BlueMonkMN BlueMonkMN - 8 days ago 6
C++ Question

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.

Answer

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));