【问题标题】:C++ windows API GetSecurityInfo invalid handle given给定的 C++ windows API GetSecurityInfo 无效句柄
【发布时间】:2018-06-09 02:31:06
【问题描述】:

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

提前谢谢你!

【问题讨论】:

  • 这个包装器有什么意义? SetLastError 这里不需要 - Reg api 只返回错误代码而不是 true/false,这确实更好的设计和易于使用
  • @RbMm 需要它们,因为代码是更复杂项目的一部分,并且一致性使得使用更大的代码库变得更加容易:)
  • 使用返回错误代码的函数 - 比使用返回真/假并设置最后一个错误的函数容易得多
  • Windwes API 中的一些函数使用“经典”方式返回错误代码,而其他函数返回 winapi BOOL,没有内在的一致性,所以我不得不自己破解它。

标签: c++ windows security winapi registry


【解决方案1】:

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

要更正错误替换:

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

HKEY createdKey = NULL;

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

【讨论】:

  • 谢谢!我试图强迫自己主要/只使用指针、自动变量等以获得更好的感觉,所以我实际上通过在 GetSecurityInfo 函数调用中取消引用 newRegKey 来修复它:GetSecurityInfo_safe( *newRegKey, SE_REGISTRY_KEY, ... 但我不会注意到没有您的帮助,再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 2019-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多