如何删除注册表中拙劣的符号链接

How to delete botched symbolic links in the registry

本文关键字:符号链接 注册表 何删除 删除      更新时间:2023-10-16

我正在对注册表进行一些编辑原型,以创建一个从一个区域到另一个区域的符号链接。我使用了以下代码:

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("%dn"), 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("%dn"), 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);

现在我有 2 个问题。

  1. 我无法删除在软件下创建的 MyKey 值。
  2. 尝试将 SymbolicLinkValue 写入 MyKey 时,即使以管理员身份运行时,我也会收到访问被拒绝错误。

我需要帮助清理我的注册表并使此代码正常工作。

我在 http://www.codeproject.com/Articles/11973/Registry-Symbolic-Links 找到了解决我所有问题的代码。

这是它用于删除表示符号链接的注册表项的代码:

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

我上面的代码在创建链接时遇到了一些问题。这些更正的行使其工作:

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

上述用于链接创建的代码将非常适合HKEY_LOCAL_MACHINE,如果您的路径具有不同的键,请使用以下内容

//HKEY_USERS
TCHAR target[] = _T("\Registry\USER\SOFTWARE\MyKey");
//HKEY_LOCAL_MACHINE
TCHAR target[] = _T("\Registry\MACHINE\SOFTWARE\MyKey");
//HKEY_CURRENT_USER
TCHAR target[] = _T("\Registry\USER\CurrentUser\SOFTWARE\MyKey");

我没有足够的业力来称赞......但是 AFAIK 您不能在符号链接上使用普通的 RegKeyDelete。使用符号链接标志创建密钥时,窗口会将容器标记为符号链接,并且将在目标上执行所有进一步的操作。我认为用户模式没有足够的粒度来指定您希望在符号链接的针尖容器而不是目标上完成操作。

您可以调用 ZwOpenKey 并为其提供一个具有 OBJ_OPENLINK 标志的OBJECT_ATTRIBUTES结构

如果将设置了此标志的对象句柄传递给 打开对象,如果对象是符号链接对象,则例程 应该打开符号链接对象本身,而不是对象 符号链接引用的(这是默认行为)。

然后,您可以使用该句柄执行所需的任何操作。