Determine Path to Registry Key from Hkey Handle in C++

Determine path to registry key from HKEY handle in C++

Use LoadLibrary and NtQueryKey exported function as in the following code snippet.

#include <windows.h>
#include <string>

typedef LONG NTSTATUS;

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif

#ifndef STATUS_BUFFER_TOO_SMALL
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#endif

std::wstring GetKeyPathFromKKEY(HKEY key)
{
std::wstring keyPath;
if (key != NULL)
{
HMODULE dll = LoadLibrary(L"ntdll.dll");
if (dll != NULL) {
typedef DWORD (__stdcall *NtQueryKeyType)(
HANDLE KeyHandle,
int KeyInformationClass,
PVOID KeyInformation,
ULONG Length,
PULONG ResultLength);

NtQueryKeyType func = reinterpret_cast<NtQueryKeyType>(::GetProcAddress(dll, "NtQueryKey"));

if (func != NULL) {
DWORD size = 0;
DWORD result = 0;
result = func(key, 3, 0, 0, &size);
if (result == STATUS_BUFFER_TOO_SMALL)
{
size = size + 2;
wchar_t* buffer = new (std::nothrow) wchar_t[size/sizeof(wchar_t)]; // size is in bytes
if (buffer != NULL)
{
result = func(key, 3, buffer, size, &size);
if (result == STATUS_SUCCESS)
{
buffer[size / sizeof(wchar_t)] = L'\0';
keyPath = std::wstring(buffer + 2);
}

delete[] buffer;
}
}
}

FreeLibrary(dll);
}
}
return keyPath;
}

int _tmain(int argc, _TCHAR* argv[])
{
HKEY key = NULL;
LONG ret = ERROR_SUCCESS;

ret = RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft", &key);
if (ret == ERROR_SUCCESS)
{
wprintf_s(L"Key path for %p is '%s'.", key, GetKeyPathFromKKEY(key).c_str());
RegCloseKey(key);
}

return 0;
}

This will print the key path on the console:

Key path for 00000FDC is
'\REGISTRY\MACHINE\SOFTWARE\Microsoft'.

How to extract hive and registry name from registry key

If I understand you correctly, you just want to split the string "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Firefox" into substrings "HKEY_LOCAL_MACHINE" and "SOFTWARE\Mozilla\Firefox". There are no Win32 API functions for that exact purpose, but you can use the find() and substr() methods of C++'s std::wstring class, eg:

#include <string>

std::wstring keyname = ...; // "HKEY_LOCAL_MACHINE\\SOFTWARE\\Mozilla\\Firefox"

std::wstring::size_type pos = keyname.find(L'\\');
if (pos != std::wstring::npos)
{
std::wstring root = keyname.substr(0, pos);
std::wstring key = keyname.substr(pos+1);
// use root and key as needed...
}

Alternative, you can use std::wistringstream and std::getline():

#include <string>
#include <sstream>

std::wstring keyname = ...; // "HKEY_LOCAL_MACHINE\\SOFTWARE\\Mozilla\\Firefox"
std::wstring root, key;

std::wistringstream iss(keyname);
if (std::getline(iss, root, L'\\') && std::getline(iss, key))
{
// use root and key as needed...
}

How to get every key and subkey from registry?

The first thing to do is get rid of those globals; they're just complicating things. With recursion you want everything on the stack. The code below fixes your problem.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

void test( wchar_t * OriginalCopy, DWORD Level );
void QueryKey(HKEY hKey, const wchar_t * proba, DWORD Level );

int counter = 0;

void __cdecl _tmain(void)
{

test( L"hardware\\description\\system", 0);

}

void test(wchar_t * OriginalCopy, DWORD Level)
{
HKEY hTestKey;

if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, (LPCWSTR)OriginalCopy, 0, KEY_READ, &hTestKey ) == ERROR_SUCCESS )
{
//printf("\n%ls",OriginalCopy);
QueryKey(hTestKey, OriginalCopy, Level );
}
else printf("\nTest Failed");
RegCloseKey(hTestKey);

}

void QueryKey( HKEY hKey, const wchar_t * OriginalCopy, DWORD Level )
{
//printf("\n1. OriginalCopy: %ls Level %d", OriginalCopy, Level );

TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time

DWORD i, retCode;

DWORD cchValue = MAX_VALUE_NAME;

// Get the class name and the value count.
retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time

// Enumerate the subkeys, until RegEnumKeyEx fails.

if (cSubKeys)
{
//printf( "\nNumber of subkeys: %d\n", cSubKeys);

for (i=0; i<cSubKeys; i++)
{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyExW(hKey,
i,
(LPWSTR)achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime
);

if (retCode == ERROR_SUCCESS)
{
//_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
//-------------------------------------------------------------------
HKEY subkey;

wchar_t NewCopy[MAX_PATH];
wcscpy( NewCopy, OriginalCopy );
wcscat( NewCopy, L"\\" );
wcscat( NewCopy, (const wchar_t *)achKey);
//printf("\nNew subkey found \"%ls\" Number of subkeys: %d\n",achKey, cSubKeys);
printf("\nNew OriginalCopy \"%ls\"Level: %d\n", NewCopy, Level);

if ( RegOpenKeyExW( HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &subkey ) == ERROR_SUCCESS )
{
counter++;
test( NewCopy, Level+1 );
RegCloseKey( subkey );
}
else printf("\n-----Querykey Failed for %ls\n",OriginalCopy );

//-------------------------------------------------------------------
}
}
}

// Enumerate the key values.

/*if (cValues)
{
printf( "\nNumber of values: %d\n", cValues);

for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue( hKey,
i,
achValue,
&cchValue,
NULL,
NULL,
NULL,
NULL
);

if (retCode == ERROR_SUCCESS )
{
_tprintf(TEXT("(%d) %s\n"), i+1, achValue);
}
}
}*/
}

How to get registry Key name from an open Key Handle in Perl?

Browsing through the source, it doesn't look like Win32::Registry will let you take the handle and get back to the Key. I see three ways around this:

  1. Maintain a list of returned objects from Open and the path to them yourself.
  2. Hack the module (subclass it, change the source) to do #1 for you.
  3. Or extend the Win32::Registry API to do what's shown in this stackoverflow answer: Determine path to registry key from HKEY handle in C++

Invoking RegCloseKey on a predefined registry key handle

The MSDN doc for the RegOpenKey function infers that you would only want to call RegCloseKey on a handle which you've programmatically created.

...If the key is not one of the predefined registry keys, call the RegCloseKey function after you have finished using the handle.



Related Topics



Leave a reply



Submit