498 lines
17 KiB
C
498 lines
17 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <memory.h>
|
||
|
#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 );
|
||
|
}
|
||
|
}
|
||
|
}
|