#include #include #include #include "windows.h" #define MSG_ERROR_VALUE_INCORRECT_SIZE "\tERROR: Value entry data has incorrect size \n\t\tValueName = %ls \n\t\tNameSize = %d \n\t\tValueType = %s \n\t\tValueSize = %d\n" #define MSG_ERROR_VALUE_NOT_NUL_TERMINATED "\tERROR: Value entry data is not NUL terminated \n\t\tValueName = %ls \n\t\tNameSize = %d \n\t\tValueType = %s\n" #define MSG_ERROR_VALUE_UNKNOWN_DATA "\tERROR: Value entry contains unknown data \n\t\tValueName = %ls \n\t\tNameSize = %d \n\t\tValueType = %#x \n\t\tValueSize = %d\n" #define MSG_ERROR_REG_ENUM_VALUE "\tERROR: RegEnumValue() failed, iValue = %d, Status = %d \n" #define MSG_ERROR_REG_OPEN_KEY_EX "\tERROR: RegOpenKeyEx() failed, Status = %d \n" #define MSG_ERROR_REG_QUERY_INFO_KEY "\tERROR: RegQueryInfoKey() failed, Status = %d \n" #define MSG_ERROR_REG_ENUM_KEY_EX "ERROR: RegEnumKeyEx() failed, \n\t Status = %d \n\t, SubKey = %d" #define MSG_ERROR_REG_CONNECT_REGISTRY "ERROR: Unable to connect to %s, Status = %d \n" #define MSG_COMPLETE_KEY_NAME "%ls\\%ls \n" VOID ExamineValueEntries( IN HKEY Key, IN LPCWSTR CompleteKeyName, IN DWORD cchMaxValueName, IN DWORD cbMaxValueData, IN DWORD cValues, IN LPCWSTR PredefinedKeyName ) { LONG Status; DWORD iValue; LPWSTR lpszValue; DWORD cchValue; DWORD dwType; PBYTE lpbData; DWORD cbData; BOOLEAN KeyNameAlreadyPrinted; // // Allocate the buffers for the value name and value data // lpszValue = ( LPWSTR )malloc( (cchMaxValueName + 1)*sizeof( WCHAR ) ); lpbData = ( LPBYTE )malloc( cbMaxValueData ); if( ( lpszValue == NULL ) || ( lpbData == NULL ) ) { printf( "ERROR: Unable to allocate memory, cchMaxValueName = %d, cbMaxValuedata = %d \n", cchMaxValueName, cbMaxValueData ); if( lpszValue != NULL ) { free( lpszValue ); } if( lpbData != NULL ) { free( lpbData ); } return; } // // Examine all value entries // KeyNameAlreadyPrinted = FALSE; for( iValue = 0; iValue < cValues; iValue++ ) { cchValue = cchMaxValueName + 1; cbData = cbMaxValueData; Status = RegEnumValueW( Key, iValue, lpszValue, &cchValue, 0, &dwType, lpbData, &cbData ); if( Status != ERROR_SUCCESS ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_REG_ENUM_VALUE, iValue, Status ); continue; } // // For debugging only // // printf( "\tValueName = %ls \n", lpszValue ); // switch( dwType ) { case REG_BINARY: if( cbData == 0 ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_BINARY", cbData ); } break; case REG_DWORD: if( cbData != sizeof( DWORD ) ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_DWORD", cbData ); } break; case REG_DWORD_BIG_ENDIAN: if( cbData != sizeof( DWORD ) ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_DWORD_BIG_ENDIAN", cbData ); } break; case REG_EXPAND_SZ: if( ( cbData != 0 ) && ( ( cbData % sizeof( WCHAR ) ) == 0 )) { if( *( ( PWCHAR )( lpbData + cbData - sizeof( WCHAR ) ) ) != ( WCHAR )'\0' ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_NOT_NUL_TERMINATED, lpszValue, cchValue, "REG_EXPAND_SZ" ); } } else { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_EXPAND_SZ", cbData ); } break; case REG_LINK: if( cbData == 0 ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_LINK", cbData ); } break; case REG_MULTI_SZ: if( ( cbData != 0 ) && ( ( cbData % sizeof( WCHAR ) ) == 0 )) { if( *( ( PWCHAR )( lpbData + cbData - sizeof( WCHAR ) ) ) != ( WCHAR )'\0' ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_NOT_NUL_TERMINATED, lpszValue, cchValue, "REG_MULTI_SZ" ); } } else { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_MULTI_SZ", cbData ); } break; case REG_NONE: if( cbData != 0 ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_NONE", cbData ); } break; case REG_RESOURCE_LIST: if( cbData == 0 ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_RESOURCE_LIST", cbData ); } break; case REG_SZ: if( ( cbData != 0 ) && ( ( cbData % sizeof( WCHAR ) ) == 0 ) ) { if( *( ( PWCHAR )( lpbData + cbData - sizeof( WCHAR ) ) ) != ( WCHAR )'\0' ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_NOT_NUL_TERMINATED, lpszValue, cchValue, "REG_SZ" ); } } else { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_SZ", cbData ); } break; case REG_FULL_RESOURCE_DESCRIPTOR: if( cbData == 0 ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_INCORRECT_SIZE, lpszValue, cchValue, "REG_FULL_RESOURCE_DESCRIPTOR", cbData ); } break; default: if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_VALUE_UNKNOWN_DATA, lpszValue, cchValue, dwType, cbData ); break; } } // // Free buffers for value name and value data // free( lpszValue ); free( lpbData ); } VOID ExamineKey( IN HKEY PredefinedKey, IN LPCWSTR ParentName, IN LPCWSTR KeyName, IN LPCWSTR PredefinedKeyName ) { LPWSTR CompleteKeyName; HKEY Key; LONG Status; WCHAR szClass[ MAX_PATH + 1 ]; DWORD cchClass; DWORD cSubKeys; DWORD cchMaxSubKey; DWORD cchMaxClass; DWORD cValues; DWORD cchMaxValueName; DWORD cbMaxValueData; DWORD cbSecurityDescriptor; FILETIME ftLastWriteTime; WCHAR szSubKeyName[ MAX_PATH + 1 ]; DWORD cchSubKeyNameLength; DWORD iSubKey; BOOLEAN KeyNameAlreadyPrinted; // // Build the complete key name // if( wcslen( ParentName ) == 0 ) { CompleteKeyName = wcsdup( KeyName ); if( CompleteKeyName == NULL ) { printf( "ERROR: wcsdup( KeyName ) failed \n" ); return; } } else { CompleteKeyName = wcsdup( ParentName ); if( CompleteKeyName == NULL ) { printf( "ERROR: wcsdup( ParentName ) failed \n" ); return; } if( wcslen( KeyName ) != 0 ) { CompleteKeyName = realloc( CompleteKeyName, ( wcslen( CompleteKeyName ) + wcslen( L"\\" ) + wcslen( KeyName ) + 1 )*sizeof( WCHAR ) ); wcscat( CompleteKeyName, L"\\" ); wcscat( CompleteKeyName, KeyName ); } } // // For debugging only // // printf( "%ls\\%ls \n", PredefinedKeyName, CompleteKeyName ); // // // Open the key // Status = RegOpenKeyExW( PredefinedKey, CompleteKeyName, 0, MAXIMUM_ALLOWED, &Key ); if( Status != ERROR_SUCCESS ) { printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); printf( MSG_ERROR_REG_OPEN_KEY_EX, Status ); free( CompleteKeyName ); return; } // // Determine the number of value entries, the maximum length of a value // entry name, the maximum data size, and the number of subkeys // cchClass = sizeof( szClass ) / sizeof( WCHAR ); Status = RegQueryInfoKeyW( Key, szClass, &cchClass, 0, &cSubKeys, &cchMaxSubKey, &cchMaxClass, &cValues, &cchMaxValueName, &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime ); if( Status != ERROR_SUCCESS ) { printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); printf( MSG_ERROR_REG_QUERY_INFO_KEY, Status ); free( CompleteKeyName ); RegCloseKey( Key ); return; } if( cValues != 0 ) { // // Examine the value entries // ExamineValueEntries( Key, CompleteKeyName, cchMaxValueName, cbMaxValueData, cValues, PredefinedKeyName ); } // // Traverse each subkey // if( cSubKeys != 0 ) { KeyNameAlreadyPrinted = FALSE; for( iSubKey = 0; iSubKey < cSubKeys; iSubKey++ ) { cchSubKeyNameLength = sizeof( szSubKeyName )/sizeof( WCHAR ); cchClass = sizeof( szClass ) / sizeof( WCHAR ); Status = RegEnumKeyExW( Key, iSubKey, szSubKeyName, &cchSubKeyNameLength, 0, NULL, NULL, &ftLastWriteTime ); if( Status != ERROR_SUCCESS ) { if( !KeyNameAlreadyPrinted ) { KeyNameAlreadyPrinted = TRUE; printf( MSG_COMPLETE_KEY_NAME, PredefinedKeyName, CompleteKeyName ); } printf( MSG_ERROR_REG_ENUM_KEY_EX, Status, iSubKey ); continue; } ExamineKey( PredefinedKey, CompleteKeyName, szSubKeyName, PredefinedKeyName ); } } RegCloseKey( Key ); free( CompleteKeyName ); } main( int argc, char* argv[] ) { DWORD i; HKEY RemoteUsers; HKEY RemoteLocalMachine; LONG Status; if( argc <= 1 ) { printf( "\n******* Examining HKEY_LOCAL_MACHINE on local machine\n\n" ); ExamineKey( HKEY_LOCAL_MACHINE, L"", L"", L"HKEY_LOCAL_MACHINE" ); printf( "\n******* Examining HKEY_USERS on local machine\n\n" ); ExamineKey( HKEY_USERS, L"", L"", L"HKEY_USERS" ); printf( "\n******* Examining HKEY_CLASSES_ROOT on local machine\n\n" ); ExamineKey( HKEY_CLASSES_ROOT, L"", L"", L"HKEY_CLASSES_ROOT" ); printf( "\n******* Examining HKEY_CURRENT_USER on local machine\n\n" ); ExamineKey( HKEY_CURRENT_USER, L"", L"", L"HKEY_CURRENT_USER" ); } else { for( i = 1; i < argc; i++ ) { // // printf( "Machine name = %s \n", argv[ i ] ); // Status = RegConnectRegistry( argv[ i ], HKEY_LOCAL_MACHINE, &RemoteLocalMachine ); if( Status != ERROR_SUCCESS ) { printf( MSG_ERROR_REG_CONNECT_REGISTRY, argv[i], Status ); continue; } Status = RegConnectRegistry( argv[ i ], HKEY_USERS, &RemoteUsers ); if( Status != ERROR_SUCCESS ) { RegCloseKey( RemoteLocalMachine ); printf( MSG_ERROR_REG_CONNECT_REGISTRY, argv[i], Status ); continue; } printf( "\n******* Examining HKEY_LOCAL_MACHINE on %s \n\n", argv[i] ); ExamineKey( RemoteLocalMachine, L"", L"", L"HKEY_LOCAL_MACHINE" ); printf( "\n******* Examining HKEY_USERS on %s \n\n", argv[i] ); ExamineKey( RemoteUsers, L"", L"", L"HKEY_USERS" ); RegCloseKey( RemoteLocalMachine ); RegCloseKey( RemoteUsers ); } } }