How to get every key and subkey from registry?
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.
#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);
}
}
}*/
}
This is a classic tree traversal problem and since you don't know how deep the sub-keys might go, the solution is recursion. Design a function that accepts a registry key and level as input. It enumerates that key's sub-keys, and for each sub-key it finds, it calls itself with that sub-key and level+1 as parameters.
Recursion is a difficult concept to wrap your mind around, but once you do, its elegance is a thing of beauty in problems like this.
精彩评论