Question

I am trying to print info about registry. My problem is in the first for loop.

I can't get it to print dataType and data correctly.

Also, adding them in the same print will crash the program or not print correctly.

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

void EnumerateValues(HKEY hKey, DWORD numValues)
{
 DWORD dwIndex = 0;
    LPSTR valueName = new CHAR[64];
 DWORD valNameLen;
 DWORD dataType;
 DWORD data;
 DWORD dataSize;

    for (int i = 0; i < numValues; i++)
 {
  RegEnumValue(hKey,
     dwIndex,
     valueName,
     &valNameLen,
     NULL,
     &dataType,
     (BYTE*)&data,
     &dataSize);

  dwIndex++;

_tprintf(TEXT("(%d) %s %d\n"), i+1, valueName, dataType); 
      // printf("Code: 0x%08X\n", data);

 }
}


void EnumerateSubKeys(HKEY RootKey, char* subKey, unsigned int tabs = 0) 
{
 HKEY hKey;
    DWORD cSubKeys;        //Used to store the number of Subkeys
    DWORD maxSubkeyLen;    //Longest Subkey name length
    DWORD cValues;        //Used to store the number of Subkeys
    DWORD maxValueLen;    //Longest Subkey name length
    DWORD retCode;        //Return values of calls

 RegOpenKeyEx(RootKey, subKey, 0, KEY_ALL_ACCESS, &hKey);

    RegQueryInfoKey(hKey,            // key handle
                    NULL,            // buffer for class name
                    NULL,            // size of class string
                    NULL,            // reserved
                    &cSubKeys,        // number of subkeys
                    &maxSubkeyLen,    // longest subkey length
                    NULL,            // longest class string 
                    &cValues,        // number of values for this key 
                    &maxValueLen,    // longest value name 
                    NULL,            // longest value data 
                    NULL,            // security descriptor 
                    NULL);            // last write time

    if(cSubKeys>0)
 {
        char currentSubkey[MAX_PATH];

        for(int i=0;i < cSubKeys;i++){
   DWORD currentSubLen=MAX_PATH;

            retCode=RegEnumKeyEx(hKey,    // Handle to an open/predefined key
            i,                // Index of the subkey to retrieve.
            currentSubkey,            // buffer to receives the name of the subkey
            &currentSubLen,            // size of that buffer
            NULL,                // Reserved
            NULL,                // buffer for class string 
            NULL,                // size of that buffer
            NULL);                // last write time

            if(retCode==ERROR_SUCCESS)
   {
                for (int i = 0; i < tabs; i++)
                    printf("\t");
                printf("(%d) %s\n", i+1, currentSubkey);

                char* subKeyPath = new char[currentSubLen + strlen(subKey)];
                sprintf(subKeyPath, "%s\\%s", subKey, currentSubkey);
    EnumerateSubKeys(RootKey, subKeyPath, (tabs + 1));
   }
  }
 }
    else
 {
  EnumerateValues(hKey, cValues);
 }

 RegCloseKey(hKey); 
}


int main()
{
    EnumerateSubKeys(HKEY_CURRENT_USER,"SOFTWARE\\Dropbox");
   getchar();
    return 0;
}
Was it helpful?

Solution

Your call to RegEnumValue is incorrect. It has the following problems:

  1. You are expected to initialise valNameLen before calling the function.
  2. You are expected to initialise dataSize before calling the function.
  3. You fail to check the return value of RegEnumValue and thus assume that the function succeeds. And in fact it fails because you of the aforementioned errors.

Let's ignore the value for now, since that's much more complex. Let's just try and enumerate the names of the values. That code would look like this:

void EnumerateValues(HKEY hKey, DWORD numValues)
{
    for (DWORD dwIndex = 0; dwIndex < numValues; dwIndex++)
    {
        char valueName[64];
        DWORD valNameLen = sizeof(valueName);
        DWORD dataType;
        DWORD dataSize = 0;
        DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
            NULL, &dataType, NULL, &dataSize);
        if (retval == ERROR_SUCCESS)
        {
            printf("(%d) %s %d\n", dwIndex+1, valueName, dataType);
        }
        else
        {
            // handle error
        }
    }
}

Note also that I stopped using a dynamically allocated character array as your code did. Your code leaked that array. Obviously if you need to cope with arbitrarily large value names, then you would need to use dynamically allocated arrays.

As for extracting the data, that's a bigger task that I don't believe is in the scope of this question. You need special code for each individual data type.

For instance, to read a REG_SZ you would use code like this:

char *data = new char [dataSize+1];
data[dataSize] = '\0';
valNameLen = sizeof(valueName);
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
    NULL, NULL, (LPBYTE)data, &dataSize);
if (retval == ERROR_SUCCESS)
{
    printf("(%d) %s %d %s\n", dwIndex+1, valueName, dataType, data);
}
else
{
    // handle error
}
delete[] data;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top