568 lines
12 KiB
C
568 lines
12 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1993 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
Regp.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains support for querying keys and values from the registry.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Scott B. Suhy (ScottSu) 6/1/93
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "regp.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 );
|
|||
|
|
|||
|
//
|
|||
|
// 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 );
|
|||
|
|
|||
|
//
|
|||
|
// 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;
|
|||
|
}
|