652 lines
14 KiB
C
652 lines
14 KiB
C
/*++
|
||
|
||
Copyright (c) 1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Registry.c
|
||
|
||
Abstract:
|
||
|
||
This module contains support for querying keys and values from the registry.
|
||
|
||
Author:
|
||
|
||
David J. Gilman (davegi) 27-Nov-1992
|
||
Gregg R. Acheson (GreggA) 6-Mar-1994
|
||
|
||
Environment:
|
||
|
||
User Mode
|
||
|
||
--*/
|
||
|
||
#include "winmsd.h"
|
||
#include "registry.h"
|
||
|
||
//
|
||
//*** Debug Support.
|
||
//
|
||
|
||
#if DBG
|
||
|
||
#define DbgRegSuccess( exp ) \
|
||
((( exp ) == ERROR_SUCCESS ) \
|
||
? ( VOID ) 0 \
|
||
: (( VOID )DebugPrintfW( \
|
||
TEXT( "*** Assertion Failed : %s (%d)\nin file %hs at line %d\n" ), \
|
||
TEXT( #exp ), \
|
||
( exp ), \
|
||
__FILE__, \
|
||
__LINE__ \
|
||
), DebugBreak ( )));
|
||
|
||
VOID
|
||
DbgValidateRegistryValue(
|
||
IN HREGKEY Handle,
|
||
IN LPVALUE Value,
|
||
IN LONG RegSuccess
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate some assumptions about the queried (enumerated) registry values.
|
||
|
||
Arguments:
|
||
|
||
Handle - Supplies the HREGKEY whose values is to be validated.
|
||
Value - Supplies a pointer to the VALUE object to be validated.
|
||
RegSuccess - Supplies the result of the last registry call.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
if( RegSuccess == ERROR_SUCCESS ) {
|
||
|
||
//
|
||
// Check the validity of the handle.
|
||
//
|
||
|
||
DbgPointerAssert( Handle );
|
||
DbgAssert( CheckSignature( Handle ));
|
||
|
||
if( Handle->Type == REG_SZ ) {
|
||
|
||
//
|
||
// Catch offenders of the REG_SZ rule.
|
||
//
|
||
|
||
DbgAssert((( LPTSTR ) Handle->Data )[( Handle->CurrentSize / sizeof( TCHAR )) - 1] == TEXT( '\0' ));
|
||
}
|
||
|
||
|
||
if( Handle->Values != NULL ) {
|
||
|
||
//
|
||
// Check the validity of the value.
|
||
//
|
||
|
||
DbgPointerAssert( Value );
|
||
|
||
//
|
||
// Make sure value types are consistent between what the registry
|
||
// has and what the caller expects.
|
||
//
|
||
|
||
DbgAssert( Handle->Type == Value->Type );
|
||
}
|
||
}
|
||
}
|
||
|
||
#else // ! DBG
|
||
|
||
#define DbgRegSuccess( x )
|
||
|
||
#define DbgValidateRegistryValue( h, v, r )
|
||
|
||
#endif // DBG
|
||
|
||
BOOL
|
||
CloseRegistryKey(
|
||
IN HREGKEY Handle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Close an HREGKEY by freeing all local and system resources.
|
||
|
||
Arguments:
|
||
|
||
Handle - Supplies the HREGKEY to close.
|
||
|
||
Return Value:
|
||
|
||
BOOL - Returns TRUE if the key was succesfully closed.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG RegSuccess;
|
||
|
||
//
|
||
// Check the validity of the supplied handle.
|
||
//
|
||
|
||
DbgPointerAssert( Handle );
|
||
DbgAssert( CheckSignature( Handle ));
|
||
if(( Handle == NULL ) || ( ! CheckSignature( Handle ))) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Reset the currrency index.
|
||
//
|
||
|
||
Handle->CurrentValue = 0;
|
||
|
||
//
|
||
// Free the data buffer, the value name buffer, and the subkey name buffer.
|
||
// Note that return values aren't checked since CloseRegistryKey could have
|
||
// been called by OpenRegistryKey with an incomplete HREGKEY object.
|
||
//
|
||
|
||
FreeMemory( Handle->Data );
|
||
FreeObject( Handle->ValueName );
|
||
FreeObject( Handle->Subkey );
|
||
|
||
//
|
||
// Close the key.
|
||
//
|
||
|
||
RegSuccess = RegCloseKey( Handle->hKey );
|
||
DbgRegSuccess( RegSuccess );
|
||
|
||
//
|
||
// If we're remote, close the remote registry
|
||
//
|
||
|
||
if( _fIsRemote &&
|
||
( Handle->ParentHandle == HKEY_LOCAL_MACHINE ||
|
||
Handle->ParentHandle == HKEY_USERS ) ) {
|
||
|
||
RegSuccess = RegCloseKey( Handle->RemoteKey );
|
||
DbgRegSuccess( RegSuccess );
|
||
}
|
||
|
||
//
|
||
// Free the key.
|
||
//
|
||
|
||
FreeObject( Handle );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
HREGKEY
|
||
OpenRegistryKey(
|
||
IN LPKEY Key
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Open the supplied Registry key in preparation for querying each value in
|
||
the supplied key's values table.
|
||
|
||
Arguments:
|
||
|
||
Key - Supplies a key description whose table of values will be
|
||
queried.
|
||
Return Value:
|
||
|
||
HREGKEY - Returns a handle which in turn can be passed to
|
||
QueryRegistryValue.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
LONG RegSuccess;
|
||
LPKEY OpenedKey;
|
||
TCHAR Class[ MAX_PATH ];
|
||
DWORD ClassLength;
|
||
DWORD MaxClass;
|
||
DWORD Values;
|
||
DWORD SecurityDescriptor;
|
||
FILETIME LastWriteTime;
|
||
|
||
DbgPointerAssert( Key );
|
||
|
||
//
|
||
// If we are remote, and it's a key we can open remotely,
|
||
// Open the remote registry.
|
||
//
|
||
|
||
if( _fIsRemote &&
|
||
( Key->ParentHandle == HKEY_LOCAL_MACHINE ||
|
||
Key->ParentHandle == HKEY_USERS ) ) {
|
||
|
||
RegSuccess = RegConnectRegistry(
|
||
_lpszSelectedComputer,
|
||
Key->ParentHandle,
|
||
&Key->RemoteKey );
|
||
|
||
DbgRegSuccess( RegSuccess );
|
||
|
||
if( RegSuccess != ERROR_SUCCESS ) {
|
||
return FALSE;
|
||
}
|
||
|
||
DbgAssert( Key->RemoteKey );
|
||
|
||
if( Key->RemoteKey ) {
|
||
|
||
Key->ParentHandle = Key->RemoteKey;
|
||
|
||
} else {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
}
|
||
|
||
//
|
||
// Attempt to open the supplied key.
|
||
//
|
||
|
||
RegSuccess = RegOpenKeyEx(
|
||
Key->ParentHandle,
|
||
Key->Name,
|
||
0,
|
||
KEY_READ,
|
||
&Key->hKey
|
||
);
|
||
DbgRegSuccess( RegSuccess );
|
||
if( RegSuccess != ERROR_SUCCESS ) {
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Set the key's signature so that CloseRegistryKey will work correctly if
|
||
// called due to an error condition.
|
||
//
|
||
|
||
SetSignature( Key );
|
||
|
||
//
|
||
// Attempt to query the number of values and the size of the largest
|
||
// value's data.
|
||
//
|
||
|
||
ClassLength = sizeof( Class );
|
||
RegSuccess = RegQueryInfoKey(
|
||
Key->hKey,
|
||
Class,
|
||
&ClassLength,
|
||
NULL,
|
||
&Key->Subkeys,
|
||
&Key->SubkeyLength,
|
||
&MaxClass,
|
||
&Values,
|
||
&Key->ValueNameLength,
|
||
&Key->Size,
|
||
&SecurityDescriptor,
|
||
&LastWriteTime
|
||
);
|
||
DbgRegSuccess( RegSuccess );
|
||
if( RegSuccess != ERROR_SUCCESS ) {
|
||
Success = CloseRegistryKey( Key );
|
||
DbgAssert( Success );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// If the caller did not specify the specific values to find, setup to find
|
||
// them all.
|
||
//
|
||
|
||
if( Key->CountOfValues == 0 ) {
|
||
|
||
Key->CountOfValues = Values;
|
||
|
||
Key->ValueNameLength += sizeof( TCHAR );
|
||
Key->ValueName = AllocateObject( TCHAR, Key->ValueNameLength );
|
||
DbgPointerAssert( Key->ValueName );
|
||
if( Key->ValueName == NULL ) {
|
||
Success = CloseRegistryKey( Key );
|
||
DbgAssert( Success );
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
Key->Data = AllocateMemory( BYTE, Key->Size );
|
||
DbgPointerAssert( Key->Data );
|
||
if( Key->Data == NULL ) {
|
||
Success = CloseRegistryKey( Key );
|
||
DbgAssert( Success );
|
||
return NULL;
|
||
}
|
||
|
||
Key->SubkeyLength += sizeof( TCHAR );
|
||
Key->Subkey = AllocateObject( TCHAR, Key->SubkeyLength );
|
||
DbgPointerAssert( Key->Subkey );
|
||
if( Key->Subkey == NULL ) {
|
||
Success = CloseRegistryKey( Key );
|
||
DbgAssert( Success );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// There is no current sub-key so initialize its length and index to zero.
|
||
//
|
||
|
||
Key->CurrentSubkeyLength = 0;
|
||
Key->CurrentSubkey = 0;
|
||
|
||
//
|
||
// No data in the buffer.
|
||
//
|
||
|
||
Key->CurrentSize = 0;
|
||
|
||
//
|
||
// No name in the buffer.
|
||
//
|
||
|
||
Key->CurrentValueNameLength = 0;
|
||
|
||
//
|
||
// First value to query.
|
||
//
|
||
|
||
Key->CurrentValue = 0;
|
||
|
||
//
|
||
// Make the key a dynamic object.
|
||
//
|
||
|
||
OpenedKey = AllocateObject( KEY, 1 );
|
||
DbgPointerAssert( OpenedKey );
|
||
if( OpenedKey == NULL ) {
|
||
Success = CloseRegistryKey( Key );
|
||
DbgAssert( Success );
|
||
}
|
||
CopyMemory( OpenedKey, Key, sizeof( KEY ));
|
||
SetSignature( OpenedKey );
|
||
|
||
return ( HREGKEY ) OpenedKey;
|
||
}
|
||
|
||
BOOL
|
||
QueryNextValue(
|
||
IN HREGKEY Handle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Return the data for the next value referenced by the supplied Registry
|
||
key handle.
|
||
|
||
Arguments:
|
||
|
||
Handle - Supplies the handle for the key whose next value is being queried.
|
||
|
||
Return Value:
|
||
|
||
BOOL - Returns TRUE if the value was succesfully queried.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG RegSuccess;
|
||
LPVALUE Value;
|
||
|
||
//
|
||
// Check the validity of the supplied handle.
|
||
//
|
||
|
||
DbgPointerAssert( Handle );
|
||
DbgAssert( CheckSignature( Handle ));
|
||
if(( Handle == NULL ) || ( ! CheckSignature( Handle ))) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Assume that there are no more values.
|
||
//
|
||
|
||
RegSuccess = ! ERROR_SUCCESS;
|
||
Value = NULL;
|
||
|
||
//
|
||
// If there are still more values of interest.
|
||
//
|
||
|
||
if( Handle->CurrentValue < Handle->CountOfValues ) {
|
||
|
||
//
|
||
// If the caller did not ask for specific values.
|
||
//
|
||
|
||
if( Handle->Values == NULL ) {
|
||
|
||
Handle->CurrentValueNameLength = Handle->ValueNameLength;
|
||
Handle->CurrentSize = Handle->Size;
|
||
RegSuccess = RegEnumValue(
|
||
Handle->hKey,
|
||
Handle->CurrentValue,
|
||
Handle->ValueName,
|
||
&Handle->CurrentValueNameLength,
|
||
NULL,
|
||
&Handle->Type,
|
||
Handle->Data,
|
||
&Handle->CurrentSize
|
||
);
|
||
} else {
|
||
|
||
//
|
||
// The caller asked for specific values.
|
||
//
|
||
|
||
//
|
||
// Get a pointer to the current value.
|
||
//
|
||
|
||
Value = &Handle->Values[ Handle->CurrentValue ];
|
||
|
||
//
|
||
// Save the supplied value type so that it can be validated below.
|
||
//
|
||
|
||
Handle->Type = Value->Type;
|
||
|
||
//
|
||
// Get the value's data...
|
||
//
|
||
|
||
Handle->CurrentSize = Handle->Size;
|
||
RegSuccess = RegQueryValueEx(
|
||
Handle->hKey,
|
||
Value->Name,
|
||
NULL,
|
||
&Value->Type,
|
||
Handle->Data,
|
||
&Handle->CurrentSize
|
||
);
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// There are no more values.
|
||
//
|
||
|
||
RegSuccess = ! ERROR_SUCCESS;
|
||
|
||
}
|
||
|
||
//
|
||
// Validate some assumptions.
|
||
//
|
||
|
||
DbgValidateRegistryValue( Handle, Value, RegSuccess );
|
||
|
||
//
|
||
// Regardless as to the success of the value query (enumeration)
|
||
// increment the current value index.
|
||
//
|
||
|
||
Handle->CurrentValue++;
|
||
|
||
//
|
||
// Return the results of the query (enumeration).
|
||
//
|
||
|
||
return ( RegSuccess == ERROR_SUCCESS )
|
||
? TRUE
|
||
: FALSE;
|
||
}
|
||
|
||
HREGKEY
|
||
QueryNextSubkey(
|
||
IN HREGKEY Handle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Return the data for the next value referenced by the supplied Registry
|
||
key handle.
|
||
|
||
Arguments:
|
||
|
||
Handle - Supplies the handle for the key whose next value is being queried.
|
||
|
||
Return Value:
|
||
|
||
BOOL - Returns TRUE if the value was succesfully queried.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG RegSuccess;
|
||
FILETIME LastWrite;
|
||
|
||
//
|
||
// Check the validity of the supplied handle.
|
||
//
|
||
|
||
DbgPointerAssert( Handle );
|
||
DbgAssert( CheckSignature( Handle ));
|
||
if(( Handle == NULL ) || ( ! CheckSignature( Handle ))) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Assume that there are no more subkeys.
|
||
//
|
||
|
||
RegSuccess = ! ERROR_SUCCESS;
|
||
|
||
//
|
||
// If there are still more subkeys...
|
||
//
|
||
|
||
if( Handle->CurrentSubkey < Handle->Subkeys ) {
|
||
|
||
Handle->CurrentSubkeyLength = Handle->SubkeyLength;
|
||
RegSuccess = RegEnumKeyEx(
|
||
Handle->hKey,
|
||
Handle->CurrentSubkey,
|
||
Handle->Subkey,
|
||
&Handle->CurrentSubkeyLength,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&LastWrite
|
||
);
|
||
DbgRegSuccess( RegSuccess );
|
||
if( RegSuccess != ERROR_SUCCESS ) {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// If the subkey was succesfully enumerated, increment the current
|
||
// subkey index, open a new key and return a new HREGKEY.
|
||
//
|
||
|
||
if( RegSuccess == ERROR_SUCCESS ) {
|
||
|
||
HREGKEY hRegKey;
|
||
|
||
MakeKey( Subkey, Handle->hKey, Handle->Subkey, Handle->CountOfValues, Handle->Values );
|
||
|
||
hRegKey = OpenRegistryKey( &Subkey );
|
||
DbgHandleAssert( hRegKey );
|
||
if( hRegKey == NULL ) {
|
||
return NULL;
|
||
}
|
||
|
||
Handle->CurrentSubkey++;
|
||
|
||
return hRegKey;
|
||
}
|
||
|
||
//
|
||
// No more keys or some other failure.
|
||
//
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
LONG
|
||
QueryValue(
|
||
IN HKEY Key,
|
||
IN LPWSTR pszKeyValue,
|
||
IN LPBYTE *lpValueBuffer
|
||
)
|
||
{
|
||
DWORD err = FALSE;
|
||
DWORD cb = MAX_REG_VALUE;
|
||
LPBYTE lpValue;
|
||
|
||
lpValue = (LPBYTE) LocalAlloc(LPTR, cb);
|
||
|
||
if ( lpValue )
|
||
{
|
||
|
||
err = RegQueryValueEx(Key, pszKeyValue, 0, 0, lpValue, &cb);
|
||
|
||
if (err == ERROR_MORE_DATA)
|
||
{
|
||
LocalFree(lpValue);
|
||
lpValue = (LPBYTE) LocalAlloc(LPTR, cb);
|
||
err = RegQueryValueEx(Key, pszKeyValue, 0, 0, lpValue, &cb);
|
||
}
|
||
|
||
}
|
||
|
||
*lpValueBuffer = lpValue;
|
||
|
||
return(err);
|
||
|
||
}
|
||
|
||
|
||
|