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