Search code examples
c++visual-c++registry

Visual C++ RegGetValue() fails in program where it shouldn't


I'm making a C++ program using Visual C++ 2008 Express that gets the paths to specific apps from the registry, display a list of those that are installed, allows the user to pick one to configure, then launch the selected app.

This program is supposed to retrieve the paths to (currently) three apps by using RegGetValue (from windows.h).

While it works with Apps n°1 and 3, it fails with app n°2.

The part of the source that handles the registry is available on Pastebin: http://pastebin.com/9X2hjGqh.

I get error n°234 (ERROR_MORE_DATA) when I add a cout to get the function's return.


RegGetValue syntax:

LONG WINAPI RegGetValue(
  _In_         HKEY hkey,
  _In_opt_     LPCTSTR lpSubKey,
  _In_opt_     LPCTSTR lpValue,
  _In_opt_     DWORD dwFlags,
  _Out_opt_    LPDWORD pdwType,
  _Out_opt_    PVOID pvData,
  _Inout_opt_  LPDWORD pcbData
);

Full reference here: http://msdn.microsoft.com/en-us/library/ms724875(v=VS.85).aspx


Solution

  • One thing that stands out are all the calls where you do this:

    RegGetValue(hKey, NULL, "PATH", RRF_RT_ANY, NULL, (PVOID)&ValueBuffer, &BufferSize);
    

    Notice the last parameter is &BufferSize. This is an [in, out] parameter. You set it to the size of your buffer before going in and it changes the value to the number of characters read into the buffer on the way out. This is what the docs say about RegGetValue (and other similar Reg) functions:

    pcbData [in, out, optional] A pointer to a variable that specifies the size of the buffer pointed to by the pvData parameter, in bytes. When the function returns, this variable contains the size of the data copied to pvData.

    So when you call RegGetValue it started at 8192 (BUFFER) but after the first call it was overwritten by the the number of characters read.

    Before each RegGetValue call where you pass a &BufferSize you should do this:

    BufferSize = BUFFER
    

    As well I notice you have:

    #define BUFFER 8192
    
    char ValueBuffer[255];
    DWORD BufferSize = BUFFER;
    

    Shouldn't you be setting ValueBuffer to be at least ValueBuffer[BUFFER] instead of ValueBuffer[255]?

    As well your code as it is only supports an 8192 byte buffer. If the Value key from the registry is longer than that then it would return ERROR_MORE_DATA. I assume that your code is not anticipating anything beyond 8192. You can determine the size up front for a Value key by using RegQueryInfoKey and dynamically allocating enough space ahead of time.