我正在尝试使用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;
}

上面函数的包装器,应在检查是否有效后返回创建键的句柄:
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;

要更正错误,请替换:




HKEY createdKey = NULL;

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

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

10-11 18:49