1

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;
}
4
  • Why can't you supply a complete program that demonstrates the problem? We can't see any declarations, or what RegTypeToStr is. You can see all of that. We cannot. Why not? Aside, why would you assign to retCode in the for loop initialiser? That's is pointless and you should enable compiler warnings so that it can tell you of the futility of it. Commented Mar 2, 2014 at 21:04
  • I added the full code I'm working on. The problem is in the very first for loop. I just can't make it work.
    – user3201639
    Commented Mar 2, 2014 at 21:07
  • The code that you added does not contain the original code in the question. It's hard to help if you post fake code. You need to get a clearer grip on things. Could you explain why you are using TEXT and _tprintf in some places but not others. Are you compiling for Unicode or MBCS? Looks very much like the latter. Commented Mar 2, 2014 at 21:11
  • Multi-byte. I want to make it work first, then take care of the rest.
    – user3201639
    Commented Mar 2, 2014 at 21:17

1 Answer 1

2

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;
12
  • And in case of (BYTE*)&data? How do I print LPBYTE types?
    – user3201639
    Commented Mar 2, 2014 at 21:28
  • @user3201639 That depends on the data type. I think I dealt with the question that you asked. Commented Mar 2, 2014 at 21:30
  • That prints only the name and type. But I also need the data, which was giving me problems. Should I make another question for that?
    – user3201639
    Commented Mar 2, 2014 at 21:33
  • The code in the question did not attempt to get the data. It was failing to get the value names and the types. Do you want me to write the rest of the program for you? I've cleared the immediate blockage. You just need to get the data now. At least you can start doing it. I'm very sorry that you don't find this helpful. Commented Mar 2, 2014 at 21:34
  • I commented the part that was getting data because it was giving me errors, that's why.
    – user3201639
    Commented Mar 2, 2014 at 21:36