我有一个简单的win32应用程序,它安装了一个注册表配置单元,为它添加一个键然后卸载它。
示例如下:
#include <windows.h>
#include <iostream>
BOOL EnablePrivilege(LPCTSTR tszPrivilege, BOOL bEnable)
{
DWORD dwStatus = ERROR_SUCCESS;
HANDLE hToken;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
return FALSE;
}
if (!LookupPrivilegeValue(NULL, tszPrivilege, &tp.Privileges[0].Luid))
{
CloseHandle(hToken);
return FALSE;
}
tp.PrivilegeCount = 1;
if (bEnable)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else
{
tp.Privileges[0].Attributes = 0;
}
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
{
CloseHandle(hToken);
return FALSE;
};
CloseHandle(hToken);
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (!EnablePrivilege(SE_RESTORE_NAME, TRUE))
{
std::cout << "Enable priv failed" << std::endl;
return 1;
}
if (!EnablePrivilege(SE_BACKUP_NAME, TRUE))
{
std::cout << "Enable priv failed" << std::endl;
return 1;
}
// Load /create hive
auto err = ::RegLoadKey(HKEY_USERS, L"HiveTesting", L"Testing.hive");
if (err != ERROR_SUCCESS)
{
std::cout << "LoadKey fail " << err << std::endl;
return 1;
}
// Create a key in the loaded hive
HKEY hKey = NULL;
::RegCreateKeyEx(HKEY_USERS, L"HiveTesting\\Testing", 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0);
::RegCloseKey(hKey);
err = ::RegUnLoadKey(HKEY_USERS, L"HiveTesting");
if (err != ERROR_SUCCESS)
{
std::cout << "UnLoadKey fail " << err << std::endl;
return 1;
}
return 0;
}
除非我在注册表中查看加载的配置单元,否则这可以正常工作。这是因为regedit保持其中一个键打开的句柄。这使得RegUnLoadKey键失败,错误为5 / ERROR_ACCESS_DENIED。
但是在我的应用程序中,无论如何都必须卸载配置单元文件 - 是否有办法强制配置单元在此时卸载?我怀疑删除密钥可能会起作用,因为这会导致regedit在使用句柄时获得ERROR_KEY_DELETED。但即使这确实有效,我也不想要破坏我的所有数据。 RegSaveKey的执行情况也比RegLoad / RegUnLoad API差得多。