RegLoadKey和RegUnLoadKey - 如果句柄打开,如何强制卸载?

时间:2015-07-27 13:46:09

标签: c++ winapi registry

我有一个简单的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差得多。

0 个答案:

没有答案