303 lines
7.7 KiB
C
303 lines
7.7 KiB
C
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
regdmp.c
|
|
|
|
Abstract:
|
|
|
|
Utility to display all or part of the registry in a format that
|
|
is suitable for input to the REGINI program.
|
|
|
|
REGDMP [KeyPath]
|
|
|
|
Will ennumerate and dump out the subkeys and values of KeyPath,
|
|
and then apply itself recursively to each subkey it finds.
|
|
|
|
Handles all value types (e.g. REG_???) defined in ntregapi.h
|
|
|
|
Default KeyPath if none specified is \Registry
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 12-Mar-92
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "regutil.h"
|
|
|
|
BOOL
|
|
DumpValues(
|
|
HKEY KeyHandle,
|
|
PWSTR KeyName,
|
|
ULONG Depth
|
|
);
|
|
|
|
void
|
|
DumpKeys(
|
|
HKEY ParentKeyHandle,
|
|
PWSTR KeyName,
|
|
PWSTR FullPath,
|
|
ULONG Depth
|
|
);
|
|
|
|
BOOLEAN SummaryOutput;
|
|
|
|
BOOL
|
|
CtrlCHandler(
|
|
IN ULONG CtrlType
|
|
)
|
|
{
|
|
RTDisconnectFromRegistry( &RegistryContext );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
int
|
|
__cdecl
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
ULONG n;
|
|
char *s;
|
|
LONG Error;
|
|
PWSTR RegistryPath;
|
|
|
|
InitCommonCode( CtrlCHandler,
|
|
"REGDMP",
|
|
"[-s] [-o outputWidth] registryPath",
|
|
"-s specifies summary output. Value names, type and first line of data\n"
|
|
"\n"
|
|
"registryPath specifies where to start dumping.\n"
|
|
"\n"
|
|
"If REGDMP detects any REG_SZ or REG_EXPAND_SZ that is missing the\n"
|
|
"trailing null character, it will prefix the value string with the\n"
|
|
"following text: (*** MISSING TRAILING NULL CHARACTER ***)\n"
|
|
"The REGFIND tool can be used to clean these up, as this is a common\n"
|
|
"programming error.\n"
|
|
);
|
|
|
|
RegistryPath = NULL;
|
|
while (--argc) {
|
|
s = *++argv;
|
|
if (*s == '-' || *s == '/') {
|
|
while (*++s) {
|
|
switch( tolower( *s ) ) {
|
|
case 'f':
|
|
FullPathOutput = TRUE;
|
|
break;
|
|
|
|
case 's':
|
|
SummaryOutput = TRUE;
|
|
break;
|
|
|
|
default:
|
|
CommonSwitchProcessing( &argc, &argv, *s );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (RegistryPath == NULL) {
|
|
RegistryPath = GetArgAsUnicode( s );
|
|
}
|
|
else {
|
|
Usage( "May only specify one registry path to dump", 0 );
|
|
}
|
|
}
|
|
|
|
Error = RTConnectToRegistry( MachineName,
|
|
HiveFileName,
|
|
HiveRootName,
|
|
Win95Path,
|
|
Win95UserPath,
|
|
&RegistryPath,
|
|
&RegistryContext
|
|
);
|
|
if (Error != NO_ERROR) {
|
|
FatalError( "Unable to access registry specifed (%u)", Error, 0 );
|
|
}
|
|
|
|
DumpKeys( RegistryContext.HiveRootHandle, RegistryPath, RegistryPath, 0 );
|
|
|
|
RTDisconnectFromRegistry( &RegistryContext );
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
DumpKeys(
|
|
HKEY ParentKeyHandle,
|
|
PWSTR KeyName,
|
|
PWSTR FullPath,
|
|
ULONG Depth
|
|
)
|
|
{
|
|
LONG Error;
|
|
HKEY KeyHandle;
|
|
ULONG SubKeyIndex;
|
|
WCHAR SubKeyName[ MAX_PATH ];
|
|
ULONG SubKeyNameLength;
|
|
WCHAR ComputeFullPath[ MAX_PATH ];
|
|
FILETIME LastWriteTime;
|
|
BOOL AnyValues;
|
|
|
|
Error = RTOpenKey( &RegistryContext,
|
|
ParentKeyHandle,
|
|
KeyName,
|
|
MAXIMUM_ALLOWED,
|
|
REG_OPTION_OPEN_LINK,
|
|
&KeyHandle
|
|
);
|
|
|
|
if (Error != NO_ERROR) {
|
|
if (Depth == 0) {
|
|
FatalError( "Unable to open key '%ws' (%u)\n",
|
|
(ULONG_PTR)KeyName,
|
|
(ULONG)Error
|
|
);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Print name of node we are about to dump out
|
|
//
|
|
|
|
if (!FullPathOutput) {
|
|
|
|
RTFormatKeyName( (PREG_OUTPUT_ROUTINE)fprintf, stdout, Depth * IndentMultiple, KeyName );
|
|
RTFormatKeySecurity( (PREG_OUTPUT_ROUTINE)fprintf, stdout, KeyHandle, NULL );
|
|
printf( "\n" );
|
|
}
|
|
|
|
//
|
|
// Print out node's values
|
|
//
|
|
if (FullPathOutput)
|
|
AnyValues = DumpValues( KeyHandle, FullPath, 0 );
|
|
else
|
|
DumpValues( KeyHandle, KeyName, Depth + 1 );
|
|
|
|
//
|
|
// Enumerate node's children and apply ourselves to each one
|
|
//
|
|
|
|
for (SubKeyIndex = 0; TRUE; SubKeyIndex++) {
|
|
SubKeyNameLength = sizeof( SubKeyName ) / sizeof(WCHAR);
|
|
Error = RTEnumerateKey( &RegistryContext,
|
|
KeyHandle,
|
|
SubKeyIndex,
|
|
&LastWriteTime,
|
|
&SubKeyNameLength,
|
|
SubKeyName
|
|
);
|
|
|
|
if (Error != NO_ERROR) {
|
|
if (Error != ERROR_NO_MORE_ITEMS && Error != ERROR_ACCESS_DENIED) {
|
|
fprintf( stderr,
|
|
"RTEnumerateKey( %ws ) failed (%u), skipping\n",
|
|
KeyName,
|
|
Error
|
|
);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (FullPathOutput) {
|
|
|
|
wcscpy(ComputeFullPath, FullPath);
|
|
wcscat(ComputeFullPath, L"\\");
|
|
wcscat(ComputeFullPath, SubKeyName);
|
|
}
|
|
|
|
DumpKeys( KeyHandle, SubKeyName, ComputeFullPath, Depth + 1 );
|
|
}
|
|
|
|
if (FullPathOutput) {
|
|
if (SubKeyIndex == 0) {
|
|
if (!AnyValues) {
|
|
fprintf(stdout, "%ws\n", FullPath );
|
|
}
|
|
}
|
|
}
|
|
|
|
RTCloseKey( &RegistryContext, KeyHandle );
|
|
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
DumpValues(
|
|
HKEY KeyHandle,
|
|
PWSTR KeyName,
|
|
ULONG Depth
|
|
)
|
|
{
|
|
LONG Error;
|
|
DWORD ValueIndex;
|
|
DWORD ValueType;
|
|
DWORD ValueNameLength;
|
|
WCHAR ValueName[ MAX_PATH ];
|
|
DWORD ValueDataLength;
|
|
|
|
for (ValueIndex = 0; TRUE; ValueIndex++) {
|
|
ValueType = REG_NONE;
|
|
ValueNameLength = sizeof( ValueName ) / sizeof( WCHAR );
|
|
ValueDataLength = OldValueBufferSize;
|
|
Error = RTEnumerateValueKey( &RegistryContext,
|
|
KeyHandle,
|
|
ValueIndex,
|
|
&ValueType,
|
|
&ValueNameLength,
|
|
ValueName,
|
|
&ValueDataLength,
|
|
OldValueBuffer
|
|
);
|
|
if (Error == NO_ERROR) {
|
|
|
|
if (FullPathOutput) {
|
|
fprintf(stdout, "%ws -> ", KeyName );
|
|
}
|
|
|
|
RTFormatKeyValue( OutputWidth,
|
|
(PREG_OUTPUT_ROUTINE)fprintf,
|
|
stdout,
|
|
SummaryOutput,
|
|
Depth * IndentMultiple,
|
|
ValueName,
|
|
ValueDataLength,
|
|
ValueType,
|
|
OldValueBuffer
|
|
);
|
|
}
|
|
else
|
|
if (Error == ERROR_NO_MORE_ITEMS) {
|
|
if (ValueIndex == 0) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
else {
|
|
if (DebugOutput) {
|
|
fprintf( stderr,
|
|
"RTEnumerateValueKey( %ws ) failed (%u)\n",
|
|
KeyName,
|
|
Error
|
|
);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|