31 out of 107 rated this helpful - Rate this topic

RegQueryValueEx function

Applies to: desktop apps only

Retrieves the type and data for the specified value name associated with an open registry key.

To ensure that any string values (REG_SZ, REG_MULTI_SZ, and REG_EXPAND_SZ) returned are null-terminated, use the RegGetValue function.

Syntax

LONG WINAPI RegQueryValueEx(
  __in         HKEY hKey,
  __in_opt     LPCTSTR lpValueName,
  __reserved   LPDWORD lpReserved,
  __out_opt    LPDWORD lpType,
  __out_opt    LPBYTE lpData,
  __inout_opt  LPDWORD lpcbData
);

Parameters

hKey [in]

A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right. For more information, see Registry Key Security and Access Rights.

This handle is returned by the RegCreateKeyEx, RegCreateKeyTransacted, RegOpenKeyEx, or RegOpenKeyTransacted function. It can also be one of the following predefined keys:

HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_PERFORMANCE_DATA
HKEY_PERFORMANCE_NLSTEXT
HKEY_PERFORMANCE_TEXT
HKEY_USERS
lpValueName [in, optional]

The name of the registry value.

If lpValueName is NULL or an empty string, "", the function retrieves the type and data for the key's unnamed or default value, if any.

If lpValueName specifies a value that is not in the registry, the function returns ERROR_FILE_NOT_FOUND.

Keys do not automatically have an unnamed or default value. Unnamed values can be of any type. For more information, see Registry Element Size Limits.

lpReserved

This parameter is reserved and must be NULL.

lpType [out, optional]

A pointer to a variable that receives a code indicating the type of data stored in the specified value. For a list of the possible type codes, see Registry Value Types. The lpType parameter can be NULL if the type code is not required.

lpData [out, optional]

A pointer to a buffer that receives the value's data. This parameter can be NULL if the data is not required.

lpcbData [in, out, optional]

A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter, in bytes. When the function returns, this variable contains the size of the data copied to lpData.

The lpcbData parameter can be NULL only if lpData is NULL.

If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, this size includes any terminating null character or characters unless the data was stored without them. For more information, see Remarks.

If the buffer specified by lpData parameter is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of the lpData buffer are undefined.

If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS and stores the size of the data, in bytes, in the variable pointed to by lpcbData. This enables an application to determine the best way to allocate a buffer for the value's data.

If hKey specifies HKEY_PERFORMANCE_DATA and the lpData buffer is not large enough to contain all of the returned data, RegQueryValueEx returns ERROR_MORE_DATA and the value returned through the lpcbData parameter is undefined. This is because the size of the performance data can change from one call to the next. In this case, you must increase the buffer size and call RegQueryValueEx again passing the updated buffer size in the lpcbData parameter. Repeat this until the function succeeds. You need to maintain a separate variable to keep track of the buffer size, because the value returned by lpcbData is unpredictable.

If the lpValueName registry value does not exist, RegQueryValueEx returns ERROR_FILE_NOT_FOUND and the value returned through the lpcbData parameter is undefined.

Return value

If the function succeeds, the return value is ERROR_SUCCESS.

If the function fails, the return value is a system error code.

If the lpData buffer is too small to receive the data, the function returns ERROR_MORE_DATA.

If the lpValueName registry value does not exist, the function returns ERROR_FILE_NOT_FOUND.

Remarks

An application typically calls RegEnumValue to determine the value names and then RegQueryValueEx to retrieve the data for the names.

If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with the proper terminating null characters. Therefore, even if the function returns ERROR_SUCCESS, the application should ensure that the string is properly terminated before using it; otherwise, it may overwrite a buffer. (Note that REG_MULTI_SZ strings should have two terminating null characters.) One way an application can ensure that the string is properly terminated is to use RegGetValue, which adds terminating null characters if needed.

If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, and the ANSI version of this function is used (either by explicitly calling RegQueryValueExA or by not defining UNICODE before including the Windows.h file), this function converts the stored Unicode string to an ANSI string before copying it to the buffer pointed to by lpData.

When calling the RegQueryValueEx function with hKey set to the HKEY_PERFORMANCE_DATA handle and a value string of a specified object, the returned data structure sometimes has unrequested objects. Do not be surprised; this is normal behavior. When calling the RegQueryValueEx function, you should always expect to walk the returned data structure to look for the requested object.

Note that operations that access certain registry keys are redirected. For more information, see Registry Virtualization and 32-bit and 64-bit Application Data in the Registry.

Examples

Ensure that you reinitialize the value pointed to by the lpcbData parameter each time you call this function. This is very important when you call this function in a loop, as in the following code example.


#include <windows.h>
#include <malloc.h>
#include <stdio.h>

#define TOTALBYTES    8192
#define BYTEINCREMENT 4096

void main()
{
    DWORD BufferSize = TOTALBYTES;
    DWORD cbData;
    DWORD dwRet;

    PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
    cbData = BufferSize;

    printf("\nRetrieving the data...");

    dwRet = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
                             TEXT("Global"),
                             NULL,
                             NULL,
                             (LPBYTE) PerfData,
                             &cbData );
    while( dwRet == ERROR_MORE_DATA )
    {
        // Get a buffer that is big enough.

        BufferSize += BYTEINCREMENT;
        PerfData = (PPERF_DATA_BLOCK) realloc( PerfData, BufferSize );
        cbData = BufferSize;

        printf(".");
        dwRet = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
                         TEXT("Global"),
                         NULL,
                         NULL,
                         (LPBYTE) PerfData,
                         &cbData );
    }
    if( dwRet == ERROR_SUCCESS )
        printf("\n\nFinal buffer size is %d\n", BufferSize);
    else printf("\nRegQueryValueEx failed (%d)\n", dwRet);
}


Requirements

Minimum supported client

Windows 2000 Professional

Minimum supported server

Windows 2000 Server

Header

Winreg.h (include Windows.h)

Library

Advapi32.lib

DLL

Advapi32.dll

Unicode and ANSI names

RegQueryValueExW (Unicode) and RegQueryValueExA (ANSI)

See also

ExpandEnvironmentStrings
RegCreateKeyEx
RegEnumKeyEx
RegEnumValue
RegGetValue
Registry Functions
Registry Overview
RegOpenKeyEx
RegQueryInfoKey

 

 

Send comments about this topic to Microsoft

Build date: 3/6/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Bug in Windows Vista
If you get an ERROR_NO_ACCESS from this function the most probable reason is that lpData is not a valid pointer.

This may happen when you pass for example a DWORD by value instead of it's address.

But there is another possible reason for ERROR_NO_ACCESS returned from RegSetValueEx which is a bug in at least Windows Vista:

When lpValueName points to a location within a memory that has been allocated via GlobalAlloc(GMEM_FIXED...) you get this error, too.
The solution is to copy the String to a local String on the stack.
Good example code
Some example snippets (reading a DWORD, String, etc.) can be found here: http://guidepc.altervista.org/windows/api/functions/regqueryvalueex.html $0$0 $0 $0(note that the type of hr is HRESULT).$0
Note for Visual Basic
$0When querying for a string value in VB, you may need to use the alternate function declaration found here: http://guidepc.altervista.org/windows/api/functions/regqueryvalueex.html.$0
howto read from HK_CurrentUser of currently logged in user, from within a service
Hi,

I have a software, that comprise of a regular user process and a service.

The process writes some data to HK_CurrentUser.

In the service I try to read those data from HK_CurrentUser.


That does not work !    The reason is:
    The regular user process runs as the user that is currently logged in.
    The service runs as admin.


Now my question:
    How can I read from within the service, out of the HK_CurrentUser branch that belongs to the currentyl logged in user?



Thanks in advance for you help.
unicode registry functions need the string pointers aligned on 16bit boundary
unicode registry functions like RegOpenKeyEx,RegCreateKeyEx,RegQueryValueEx need the LPCTSTR parameters aligned on a 16bit boundary otherwise error 998 is returned.

solution:

// ensure 16bit aligned string if unicode
#ifdef UNICODE
in_KeyPath = EnsureAlignedString(in_KeyPath, lv_PathBuf, 256);
#endif

// open subkey
if (RegOpenKeyEx(in_hBaseKey, in_KeyPath, 0, KEY_QUERY_VALUE, &lv_hKey) != 0)
return FALSE;

where:

TCHAR *EnsureAlignedString(TCHAR *in_Str, TCHAR *in_Buf, INT in_MaxLen)
{
// registry calls needs unicode strings to be aligned on 16bit boundaries
if ((INT)in_Str & 1)
{
// alignment is needed, copy to aligned buffer
tstrncpyeos(in_Buf, in_Str, in_MaxLen-1);

// use the buffer
return in_Buf;
}
else
{
// already aligned
return in_Str;
}
}

--
[Raymond Chen (MSFT)] Alignment requirements are implied by the data type LPCWSTR. If unaligned data were permitted, then it would have been declared as UNALIGNED. This requirement applies to all functions which take Unicode strings, not just registry functions.
C++ Example
I'm not sure why the C++ sample code is expanding the BufferSize by BYTEINCREMENT in the sample code. Since cbData should contain the number of bytes required when RegQueryValueEx returns ERROR_MORE_DATA, why not just realloc PerfData to the actual number of bytes required rather than expanding the buffer piecemeal inside a loop?
IF Key Doesnt exists

RegQueryValueEx will create the registry key if its not present right? Can i get a function which queries for a registry key and takes the value only if the key is present? Else it will take the default value specified by me.

[Noelle Mallory - MSFT] Please post questions to the MSDN Forums at http://forums.microsoft.com/msdn. You will likely get a quicker response through the forum than through the Community Content.

Termination of REG_xxx_SZ with \0
Note: RegQueryValueEx will append a missing \0 for type REG_xxx_SZ if there is room, but it will leave it non-terminated if there is no room.
If the value doesn't exist
Returns ERROR_FILE_NOT_FOUND if the value doesn't exist.