I’m trying to write an application, where i can give a registry path, such HKLM\hardware\description\system and my application should read under system every keys name, and if there are subkeys their name too, and if there are any more subkeys then their names too and so on…
My application is working (more or less), but my problem is how to count the subkeys? For example if under system there is 2 key, a and b, and under a there is 3 more key, and under b there is 5 more, then how should i count which sublevel i am? This is important, because i have to know how to concatenate the registry path?
Here is my code so far (most of it is from msdn, but i can’t find a similar example nowhere):
#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 );
void QueryKey(HKEY hKey, wchar_t * proba );
void CutLastSubkey( wchar_t * SubKey, int howmuch);
wchar_t OriginalLocation[] = L"hardware\\description\\system";
DWORD Level = 0;
int counter = 0;
void __cdecl _tmain(void)
{
wchar_t OriginalCopy[ 512 ];
wcscpy( OriginalCopy, OriginalLocation );
test( OriginalCopy );
}
void test(wchar_t * OriginalCopy)
{
HKEY hTestKey;
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &hTestKey ) == ERROR_SUCCESS )
{
//printf("\n%ls",OriginalCopy);
QueryKey(hTestKey, OriginalCopy );
}
else printf("\nTest Failed");
RegCloseKey(hTestKey);
}
void QueryKey( HKEY hKey, wchar_t * OriginalCopy )
{
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;
TCHAR achValue[MAX_VALUE_NAME];
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,
achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime
);
if (retCode == ERROR_SUCCESS)
{
//_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
//-------------------------------------------------------------------
HKEY subkey;
Level++;
wcscat( OriginalCopy, L"\\" );
wcscat( OriginalCopy, achKey );
printf("\nNew subkey found \"%ls\" Number of subkeys: %d\n",achKey, cSubKeys);
printf("\nNew OriginalCopy \"%ls\"Level: %d\n", OriginalCopy, Level);
if( RegOpenKeyExW( HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &subkey ) == ERROR_SUCCESS )
{
counter++;
test( OriginalCopy );
RegCloseKey( subkey );
}
else printf("\n-----Querykey Failed for %ls\n",OriginalCopy );
//-------------------------------------------------------------------
}
}
}
else
{
Level--;
printf("\nNo subkeys \"%ls\" Level : %d Counter %d",OriginalCopy, Level, counter);
CutLastSubkey( OriginalCopy, 1 );
//counter--;
}
// 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);
}
}
}*/
}
void CutLastSubkey( wchar_t * SubKey, int howmuch )
{
wchar_t * pch, tmp[ 1024 ] = { 0 };
int location, i;
printf("\n\nCutlast was called with %d", howmuch);
pch = wcsrchr( SubKey,'\\' );//last occurence of \ in string
location = pch - SubKey + 1;
//printf("Last occurence of '\\' found at %d in %ls \n",location, SubKey );
location--;
SubKey[ location ] = '\0';
printf( "\n+++CutLastSubkey result :: \"%ls\"", SubKey );
if ( howmuch > 1)
{
CutLastSubkey( SubKey, Level -1 );
}
}//CutLastSubkey
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.