I'm trying to create a new registry key in Windows 10 using the Windows API, namely the RegCreateKeyEx
function, and then get its DACL using GetSecurityInfo
. All the asserts go smoothly until i get to said GetSecurityInfo
function call, which gives an invalid handle value error(error 6). What am I doing wrong?
This is part of a more elaborate project so I will only give the(or what I think it is, but i can add the rest too) relevant part here:
A wrapper to RegCreateKeyEx
to make the output easier to work with and set any errors encountered:
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;
}
A wrapper to the above function that should return a handle to the created key after checking if it is valid:
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;
}
And a wrapper for GetSecurityInfo
, same reason and functionality as the RegCreateKey
version:
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;
}
Now the code calling these functions is as follows:
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));
The output is pretty clear on where the issue is(I implemented a slightly more verbose assert that after checking the condition, it prints it, along with the error text in case the condition failed):
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.
The assert:
#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); }
Thank you in advance!
The function CreateNewRegKey
is returning a pointer to an HKEY
where it should return HKEY
by value. You pass this pointer to GetSecurityInfo()
which expects a HANDLE
instead. The compiler won't notice because HANDLE
is declared as typedef void *HANDLE;
.
To correct the error replace:
auto createdKey = static_cast<PHKEY>(malloc(sizeof HKEY));
with
HKEY createdKey = NULL;
and call RegCreateKeyEx_safe()
with &createdKey
to pass the address of the HKEY
.