开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜