给出了C ++ windows API GetSecurityInfo无效句柄

问题描述 投票:1回答:1

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

先感谢您!

c++ windows security winapi registry
1个回答
3
投票

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

要更正错误,请更正:

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

HKEY createdKey = NULL;

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

© www.soinside.com 2019 - 2024. All rights reserved.