给定的 C++ Windows API GetSecurityInfo 无效句柄

标签 c++ windows security winapi registry

我正在尝试使用 Windows API 在 Windows 10 中创建一个新的注册表项,即 RegCreateKeyEx 函数,然后使用 GetSecurityInfo 获取其 DACL。所有断言都进行得很顺利,直到我到达所说的 GetSecurityInfo 函数调用,它给出了一个无效的句柄值错误(错误 6)。我做错了什么?

这是一个更复杂的项目的一部分,所以我只会在这里给出(或者我认为是什么,但我也可以添加其余的)相关部分:

RegCreateKeyEx 的包装器,使输出更易于处理并设置遇到的任何错误:

inline extern auto RegCreateKeyEx_safe(
    _In_       const HKEY                  hKey,
    _In_       const LPCTSTR               lpSubKey,
    _Reserved_ const DWORD                 Reserved,
    _In_opt_   const LPTSTR                lpClass,
    _In_       const DWORD                 dwOptions,
    _In_       const REGSAM                samDesired,
    _In_opt_   const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _Out_      const PHKEY                 phkResult,
    _Out_opt_  const LPDWORD               lpdwDisposition)
{
    const auto result = 
        RegCreateKeyEx(
            hKey,
            lpSubKey,
            Reserved,
            lpClass,
            dwOptions,
            samDesired,
            lpSecurityAttributes,
            phkResult,
            lpdwDisposition);
    if (result != ERROR_SUCCESS)
        SetLastError(result);
    return result == ERROR_SUCCESS;
}

上述函数的包装器,在检查它是否有效后应返回创建的 key 的句柄:

inline extern auto CreateNewRegKey(
    HKEY                  hKey,
    LPCTSTR               lpSubKey,
    DWORD                 Reserved,
    LPTSTR                lpClass,
    DWORD                 dwOptions,
    REGSAM                samDesired,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    LPDWORD               lpdwDisposition)
{
    auto createdKey = static_cast<PHKEY>(malloc(sizeof HKEY));

    assert(
        RegCreateKeyEx_safe(
            hKey,
            lpSubKey,
            Reserved,
            lpClass,
            dwOptions,
            samDesired,
            lpSecurityAttributes,
            createdKey,
            lpdwDisposition));

    assert(createdKey != INVALID_HANDLE_VALUE);

    return createdKey;
}

以及 GetSecurityInfo 的包装器,与 RegCreateKey 版本相同的原因和功能:

inline extern auto GetSecurityInfo_safe(
    _In_      const HANDLE                handle,
    _In_      const SE_OBJECT_TYPE        ObjectType,
    _In_      const SECURITY_INFORMATION  SecurityInfo,
    _Out_opt_       PSID*                 ppsidOwner,
    _Out_opt_       PSID*                 ppsidGroup,
    _Out_opt_       PACL*                 ppDacl,
    _Out_opt_       PACL*                 ppSacl,
    _Out_opt_       PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
{
    const auto result =
        GetSecurityInfo(
            handle,
            ObjectType,
            SecurityInfo,
            ppsidOwner,
            ppsidGroup,
            ppDacl,
            ppSacl,
            ppSecurityDescriptor);
    if (result != ERROR_SUCCESS)
        SetLastError(result);
    return result == EXIT_SUCCESS;
}

现在调用这些函数的代码如下:

 const auto newRegKey = 
        CreateNewRegKey(
            HKEY_CURRENT_USER, 
            SUBKEY_PATH, 
            NULL, 
            nullptr, 
            REG_OPTION_NON_VOLATILE, 
            KEY_ALL_ACCESS, 
            NULL,  //securityAttributes, 
            nullptr);

    assert(
        GetSecurityInfo_safe(
            newRegKey,
            SE_REGISTRY_KEY,
            DACL_SECURITY_INFORMATION,
            NULL,
            NULL,
            oldDacl,
            NULL,
            NULL));

输出非常清楚问题出在哪里(我实现了一个稍微更冗长的断言,在检查条件后打印它,以及条件失败时的错误文本):

SUCCESS:        RegCreateKeyEx_safe( hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, createdKey, lpdwDisposition)
SUCCESS:        createdKey != INVALID_HANDLE_VALUE
FAILURE:        GetSecurityInfo_safe( newRegKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, oldDacl, NULL, NULL)

ERROR-6:        The handle is invalid.

断言:

#define _VERBOSE            (1)
#define assert(cond)        if((cond) == TRUE) \
                                { if (_VERBOSE) cout << "SUCCESS:\t" << #cond << endl; } \
                            else \
                                {cout << "FAILURE:\t" << #cond << "\n\nERROR-" << GetLastError() << ":\t" << GetLastErrorAsString() << "\n\n"; exit(EXIT_FAILURE); }

提前致谢!

最佳答案

CreateNewRegKey 函数正在返回一个指向 HKEY指针,它应该按值返回 HKEY。您将此指针传递给 GetSecurityInfo(),它需要一个 HANDLE。编译器不会注意到,因为 HANDLE 被声明为 typedef void *HANDLE;

要更正错误,请替换:

auto createdKey = static_cast<PHKEY>(malloc(sizeof HKEY));

HKEY createdKey = NULL;

并使用&createdKey调用RegCreateKeyEx_safe()来传递HKEY的地址。

关于给定的 C++ Windows API GetSecurityInfo 无效句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48009227/

相关文章:

c++ - 派生类中是否需要显式声明的析构函数?

python - 在 Python 3 中将 ascii 字符输出到标准输出

security - 将网站访问限制在一台计算机上

security - 在 Symfony 2 中保护下载链接

c++ - 需要一种方法在仅 header 库中拥有任何类型的模板化常量

c++ - 找不到此 Quicksort 代码的问题

c++ - 如何更流畅地使用<iomanip>中的setfill()?

windows - 修改 httpd.conf 以在 EasyPHP 中通过互联网提供服务

android - Mac/Windows 和 Android 之间的 WiFi-Direct 通信

python - 在 sqlite3.connect() 中使用用户输入的变量是否存在安全风险?