Search code examples
c++winapiregistry

How to delete botched symbolic links in the registry


I'm prototyping some edits to the registry to create a symbolic link from one area to another. I've used the following code:

HKEY hkFS;
HKEY hkSOFTWARE;
DWORD dwDisposition;
LSTATUS result;
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), 0,
         KEY_CREATE_SUB_KEY , &hkSOFTWARE);
if (result == 0) {
   result = RegOpenKeyEx(hkSOFTWARE, _T("MyKey"), REG_OPTION_OPEN_LINK,
            KEY_WRITE | KEY_CREATE_LINK | KEY_WOW64_64KEY, &hkFS);
   if (result != ERROR_SUCCESS) {
      _tprintf(_T("%d\n"), result);
      result = RegCreateKeyEx(hkSOFTWARE, _T("MyKey"), 0, NULL,
               REG_OPTION_CREATE_LINK,
               KEY_WRITE | KEY_CREATE_LINK | KEY_WOW64_64KEY,
               NULL, &hkFS, &dwDisposition);
      _tprintf(_T("%d\n"), result);
   }
   if (result == ERROR_SUCCESS) {
      //result = ZwDeleteKey(hkFS);
      TCHAR target[] = _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MyKey");
      result = RegSetValueEx(hkFS, _T("SymbolicLinkValue"), 0, REG_SZ,
               (const BYTE const *)target, sizeof(target));
      if (result != ERROR_SUCCESS) {
         TCHAR msg[256];
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, result, 0, msg,
                       sizeof(msg) / sizeof(TCHAR), NULL);
         _tprintf(_T("Failed to write SymbolicLinkValue: %s"), msg);
      }
      RegCloseKey(hkFS);
   }
   else {
      TCHAR msg[256];
      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, result, 0, msg,
                    sizeof(msg) / sizeof(TCHAR), NULL);
      _putts(msg);
   }
}
else {
   TCHAR msg[256];
   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, result, 0, msg,
                 sizeof(msg) / sizeof(TCHAR), NULL);
   _tprintf(_T("Error opening SOFTWARE: %s"), msg);
}
RegCloseKey(hkSOFTWARE);

And now I have 2 problems.

  1. I cannot delete the MyKey values that have been created under SOFTWARE.
  2. I get Access Denied errors when attempting to write SymbolicLinkValue to MyKey, even when running as administrator.

I need help cleaning up my registry and making this code work.


Solution

  • I found code at http://www.codeproject.com/Articles/11973/Registry-Symbolic-Links that solved all my problems.

    This is the code it uses to delete a registry key representing a symbolic link:

    typedef LONG NTSTATUS;
    
    #if !defined(_NTSYSTEM_)
    #define NTSYSAPI     DECLSPEC_IMPORT
    #else
    #define NTSYSAPI
    #endif
    
    NTSYSAPI
    NTSTATUS
    NTAPI
    ZwDeleteKey(
        IN HANDLE KeyHandle
        );
    
    typedef NTSYSAPI NTSTATUS  (NTAPI *ZW_DELETE_KEY_PROTO)(HANDLE);
    static LONG DynZwDeleteKey(HKEY hKey)
    {
        LONG lStatus = ERROR_SUCCESS;
        HMODULE hNTDll = LoadLibraryW( L"ntdll.dll" );
        if (hNTDll)
        {
          ZW_DELETE_KEY_PROTO lpfnZwDeleteKey =  (ZW_DELETE_KEY_PROTO)GetProcAddress(hNTDll, "ZwDeleteKey");
          if (lpfnZwDeleteKey)
            lStatus = lpfnZwDeleteKey(hKey);
          else
            lStatus = GetLastError();
    
          VERIFY(FreeLibrary(hNTDll));
        }
        else
            lStatus = GetLastError();
    
        return lStatus;
    }
    

    And my code above had a couple problems in creating the link. These corrected lines make it work:

    result = RegCreateKeyEx(hkSOFTWARE, _T("MyKey"), 0, NULL,
             REG_OPTION_CREATE_LINK,
             KEY_ALL_ACCESS | KEY_CREATE_LINK | KEY_WOW64_64KEY,
             NULL, &hkFS, &dwDisposition);
    

    ...

    result = RegSetValueExW(hkFS, L"SymbolicLinkValue", 0, REG_LINK,
             (const BYTE const *)target, lstrlen(target) * sizeof(WCHAR));