2020-09-30 17:12:29 +02:00

652 lines
14 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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);
}