Search code examples
cwinapiregistry

Error 234, more data is available, with RegQueryInfoKey and RegEnumValue


I am trying to use RegQueryInfoKey to get the longest value and data´s size and then RegEnumValue to show all the values, but I am getting the 234 error value, which means "More data is available" when I run the app.

I am also using malloc to allocate lpValueName and lpData so I can use the sizes that RegQueryInfoKey gave me.

If i set lpcchValueName to 16383, for example, the app works just fine, but it no idea why it doesn't with the lpcMaxSubKeyLen value returned by RegQueryInfoKey.

The registry key has two string values: HKCU\WinSide string values

What am I doing wrong? Apologize for all the noob errors you might see. Here is my code:

int wmain()
{
    //RegOpenKeyEx
    HKEY hKey = HKEY_CURRENT_USER;
    LPCWSTR subKey = L"WinSide";
    DWORD options = 0;
    REGSAM samDesired = KEY_QUERY_VALUE;
    HKEY hkOpenResult;

    //Opening the HKEY_CURRENT_USER\WinSide subkey
    LONG openKey = RegOpenKeyEx(hKey, subKey, options,
                            samDesired, &hkOpenResult);

    if (openKey != ERROR_SUCCESS)
        wprintf(L"Error code: %li\n", openKey);
    else
    {
        wprintf(L"Key opened!\n");

        //RegQueryInfoKey
        LPWSTR pClass = NULL;
        LPDWORD pcClass = NULL;
        LPDWORD reserved = NULL;
        DWORD numberOfSubKeys;
        LPDWORD pcMaxSubKeyLen = NULL;
        LPDWORD pcMaxClassLen = NULL;
        DWORD numberOfValues;
        DWORD longestValueName;
        DWORD longestDataComponent;
        LPDWORD securityDescriptor = NULL;
        PFILETIME pLastWriteTime = NULL;

        //Querying info from HKCU\WinSide subkey
        LONG queryInfo = RegQueryInfoKey(hkOpenResult, pClass, pcClass, reserved, &numberOfSubKeys,
                                        pcMaxSubKeyLen, pcMaxClassLen, &numberOfValues,
                                        &longestValueName, &longestDataComponent,
                                        securityDescriptor, pLastWriteTime);

        if (queryInfo != ERROR_SUCCESS)
            wprintf(L"Error code: %li\n", queryInfo);
        else
        {
            wprintf(L"Key queried!\n");
            wprintf(L"Number of values: %u\n", numberOfValues);

            //RegEnumValue
            DWORD index=0;
            DWORD sizedem = sizeof(WCHAR);
            LPWSTR nameOfValue = (LPWSTR)malloc(longestValueName * sizeof(WCHAR));
            DWORD sizeOfBufffer = longestValueName;
            DWORD typeOfDataStored;
            LPBYTE pData = (LPBYTE)malloc(longestDataComponent * sizeof(BYTE));
            DWORD sizeOfData = longestDataComponent;

            if (nameOfValue != NULL && pData != NULL)
            {
                for (index = 0; index < numberOfValues; index++)
                {
                    sizeOfBufffer = longestValueName;

                    //Enumerating values from HKCU\WinSide subkey
                    LONG enuValue = RegEnumValue(hkOpenResult, index, nameOfValue,
                        &sizeOfBufffer, NULL, &typeOfDataStored,
                        pData, &sizeOfData);

                    if (enuValue != ERROR_SUCCESS)
                        wprintf(L"Error code: %li\n", enuValue);
                    else
                    {
                        wprintf(L"Value: %s\n", (LPWSTR)pData);

                    }

                }

            }
            else
            {
                wprintf(L"Memory could not be allocated.\n");
            }       



            free(nameOfValue);
            free(pData);


        }



        RegCloseKey(hkOpenResult);
    }

    return 0;

}

This is my result:

Result

Thanks a lot!


Solution

  • your code containing many errors.

    1) LPWSTR nameOfValue = (LPWSTR)malloc(longestValueName * sizeof(WCHAR));

    really longestValueName this is

    The size does not include the terminating null character.

    so you need

    LPWSTR nameOfValue = (LPWSTR)malloc((longestValueName + 1) * sizeof(WCHAR));
    

    or (better)

    LPWSTR nameOfValue = (LPWSTR)malloc(++longestValueName * sizeof(WCHAR));
    

    then in loop, if use first variant - sizeOfBufffer = longestValueName + 1;

    or as in your code, if use ++longestValueName

    2) DWORD sizeOfData = longestDataComponent;

    you must do this in Loop, as and sizeOfBufffer = longestValueName; because sizeOfData will be changed after every RegEnumValue

    3) and you must be ready, that until you enumerate key, somebody can change key data/values - so Maximum can increase - what you got in call RegQueryInfoKey is only reasonable hint but not 100% guarantee