windows-nt/Source/XPSP1/NT/base/ntos/config/utils/hiveini.c
2020-09-26 16:20:57 +08:00

452 lines
16 KiB
C

#include "regutil.h"
#include "edithive.h"
NTSTATUS
RiInitializeRegistryFromAsciiFile(
IN PUNICODE_STRING HiveName,
IN PUNICODE_STRING FileName
);
void
Usage( void )
{
fprintf( stderr, "usage: HIVEINI -f hivefile [files...]\n" );
exit( 1 );
}
PVOID OldValueBuffer;
ULONG OldValueBufferSize;
typedef struct _KEY_INFO {
ULONG IndentAmount;
UNICODE_STRING Name;
HANDLE HiveHandle;
HANDLE Handle;
LARGE_INTEGER LastWriteTime;
} KEY_INFO, *PKEY_INFO;
#define MAX_KEY_DEPTH 64
NTSTATUS
RiInitializeRegistryFromAsciiFile(
IN PUNICODE_STRING HiveName,
IN PUNICODE_STRING FileName
)
{
NTSTATUS Status;
REG_UNICODE_FILE UnicodeFile;
PWSTR EndKey, FirstEqual, BeginValue;
ULONG IndentAmount;
UNICODE_STRING InputLine;
UNICODE_STRING KeyName;
UNICODE_STRING KeyValue;
PKEY_VALUE_FULL_INFORMATION OldValueInformation;
PKEY_BASIC_INFORMATION KeyInformation;
UCHAR KeyInformationBuffer[ 512 ];
ULONG ResultLength;
ULONG OldValueLength;
PVOID ValueBuffer;
ULONG ValueLength;
ULONG ValueType;
KEY_INFO KeyPath[ MAX_KEY_DEPTH ];
PKEY_INFO CurrentKey;
ULONG KeyPathLength;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING Class;
ULONG Disposition;
BOOLEAN UpdateKeyValue;
ULONG i;
HANDLE HiveHandle;
HANDLE RootKey;
UNICODE_STRING RootName;
HiveHandle = EhOpenHive(HiveName,
&KeyPath[0].Handle,
&KeyPath[0].Name,
TYPE_SIMPLE);
if (HiveHandle == NULL) {
return(STATUS_OBJECT_PATH_NOT_FOUND);
}
KeyPath[0].Handle = (HANDLE)HCELL_NIL;
OldValueInformation = (PKEY_VALUE_FULL_INFORMATION)OldValueBuffer;
Class.Buffer = NULL;
Class.Length = 0;
Status = RegLoadAsciiFileAsUnicode( FileName,
&UnicodeFile
);
if (!NT_SUCCESS( Status )) {
return( Status );
}
KeyPathLength = 0;
while (RegGetNextLine( &UnicodeFile, &IndentAmount, &FirstEqual )) {
#if 0
InputLine.Buffer = UnicodeFile.BeginLine;
InputLine.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)UnicodeFile.BeginLine);
InputLine.MaximumLength = InputLine.Length;
printf( "GetNextLine: (%02u) '%wZ'\n", IndentAmount, &InputLine );
#endif
if (FirstEqual == NULL) {
KeyName.Buffer = UnicodeFile.BeginLine;
KeyName.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)KeyName.Buffer);
KeyName.MaximumLength = (USHORT)(KeyName.Length + 1);
#if 0
printf( "%02u %04u KeyName: %wZ\n", KeyPathLength, IndentAmount, &KeyName );
#endif
CurrentKey = &KeyPath[ KeyPathLength ];
if (KeyPathLength == 0 ||
IndentAmount > CurrentKey->IndentAmount
) {
if (KeyPathLength == MAX_KEY_DEPTH) {
fprintf( stderr,
"HIVEINI: %wZ key exceeded maximum depth (%u) of tree.\n",
&KeyName,
MAX_KEY_DEPTH
);
return( STATUS_UNSUCCESSFUL );
}
KeyPathLength++;
CurrentKey++;
}
else {
do {
CurrentKey->Handle = NULL;
if (IndentAmount == CurrentKey->IndentAmount) {
break;
}
CurrentKey--;
if (--KeyPathLength == 1) {
break;
}
}
while (IndentAmount <= CurrentKey->IndentAmount);
}
#if 0
printf( " (%02u)\n", KeyPathLength );
#endif
CurrentKey->Name = KeyName;
CurrentKey->IndentAmount = IndentAmount;
Status = EhCreateChild(HiveHandle,
KeyPath[ KeyPathLength-1 ].Handle,
&KeyName,
&CurrentKey->Handle,
&Disposition);
if (NT_SUCCESS( Status )) {
if (DebugOutput) {
fprintf( stderr, " Created key %02x %wZ (%08x)\n",
CurrentKey->IndentAmount,
&CurrentKey->Name,
CurrentKey->Handle
);
}
KeyInformation = (PKEY_BASIC_INFORMATION)KeyInformationBuffer;
Status = EhQueryKey( HiveHandle,
CurrentKey->Handle,
KeyBasicInformation,
KeyInformation,
sizeof( KeyInformationBuffer ),
&ResultLength
);
if (NT_SUCCESS( Status )) {
CurrentKey->LastWriteTime = KeyInformation->LastWriteTime;
}
else {
RtlZeroMemory( &CurrentKey->LastWriteTime,
sizeof( CurrentKey->LastWriteTime )
);
}
if (Disposition == REG_CREATED_NEW_KEY) {
printf( "Created Key: " );
for (i=0; i<KeyPathLength; i++) {
printf( "%wZ\\", &KeyPath[ i ].Name );
}
printf( "%wZ\n", &KeyName );
}
}
else {
fprintf( stderr,
"HIVEINI: CreateKey (%wZ) relative to handle (%lx) failed - %lx\n",
&KeyName,
ObjectAttributes.RootDirectory,
Status
);
}
}
else {
if (FirstEqual == UnicodeFile.BeginLine) {
KeyName.Buffer = NULL;
KeyName.Length = 0;
KeyName.MaximumLength = 0;
}
else {
EndKey = FirstEqual;
while (EndKey > UnicodeFile.BeginLine && EndKey[ -1 ] <= L' ') {
EndKey--;
}
KeyName.Buffer = UnicodeFile.BeginLine;
KeyName.Length = (USHORT)((PCHAR)EndKey - (PCHAR)KeyName.Buffer);
KeyName.MaximumLength = (USHORT)(KeyName.Length + 1);
}
BeginValue = FirstEqual + 1;
while (BeginValue < UnicodeFile.EndOfLine && *BeginValue <= L' ') {
BeginValue++;
}
KeyValue.Buffer = BeginValue;
KeyValue.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)BeginValue);
KeyValue.MaximumLength = (USHORT)(KeyValue.Length + 1);
while (IndentAmount <= CurrentKey->IndentAmount) {
if (DebugOutput) {
fprintf( stderr, " Popping from key %02x %wZ (%08x)\n",
CurrentKey->IndentAmount,
&CurrentKey->Name,
CurrentKey->Handle
);
}
CurrentKey->Handle = NULL;
CurrentKey--;
if (--KeyPathLength == 1) {
break;
}
}
if (DebugOutput) {
fprintf( stderr, " Adding value '%wZ = %wZ' to key %02x %wZ (%08x)\n",
&KeyName,
&KeyValue,
CurrentKey->IndentAmount,
&CurrentKey->Name,
CurrentKey->Handle
);
}
if (RegGetKeyValue( &KeyValue,
&UnicodeFile,
&ValueType,
&ValueBuffer,
&ValueLength
)
) {
if (ValueBuffer == NULL) {
Status = EhDeleteValueKey( HiveHandle,
KeyPath[ KeyPathLength+1 ].Handle,
&KeyValue
);
if (NT_SUCCESS( Status )) {
printf( "Delete value for Key: " );
for (i=0; i<KeyPathLength; i++) {
printf( "%wZ\\", &KeyPath[ i ].Name );
}
printf( "%wZ\n", &KeyName );
}
}
else {
if ( UnicodeFile.LastWriteTime.QuadPart >
CurrentKey->LastWriteTime.QuadPart
) {
Status = STATUS_UNSUCCESSFUL;
UpdateKeyValue = TRUE;
}
else {
Status = EhQueryValueKey( HiveHandle,
CurrentKey->Handle,
&KeyName,
KeyValueFullInformation,
OldValueInformation,
OldValueBufferSize,
&OldValueLength
);
if (NT_SUCCESS( Status )) {
UpdateKeyValue = TRUE;
}
else {
UpdateKeyValue = FALSE;
}
}
if (!NT_SUCCESS( Status ) ||
OldValueInformation->Type != ValueType ||
OldValueInformation->DataLength != ValueLength ||
!RtlEqualMemory( (PCHAR)OldValueInformation +
OldValueInformation->DataOffset,
ValueBuffer,
ValueLength )
) {
Status = EhSetValueKey( HiveHandle,
CurrentKey->Handle,
&KeyName,
0,
ValueType,
ValueBuffer,
ValueLength
);
if (NT_SUCCESS( Status )) {
printf( "%s value for Key: ",
UpdateKeyValue ? "Updated" : "Created"
);
for (i=1; i<=KeyPathLength; i++) {
printf( "%wZ\\", &KeyPath[ i ].Name );
}
if (KeyName.Length) {
printf( "%wZ ", &KeyName );
}
printf( "= '%wZ'\n", &KeyValue );
}
else {
fprintf( stderr,
"HIVEINI: SetValueKey (%wZ) failed - %lx\n",
&KeyName,
Status
);
}
}
RtlFreeHeap( RtlProcessHeap(), 0, ValueBuffer );
}
}
else {
fprintf( stderr,
"HIVEINI: Invalid key (%wZ) value (%wZ)\n", &KeyName,
&KeyValue
);
}
}
}
EhCloseHive(HiveHandle);
return( Status );
}
int
__cdecl main( argc, argv )
int argc;
char *argv[];
{
int i;
char *s;
NTSTATUS Status;
BOOL FileArgumentSeen;
BOOL HiveArgumentSeen=FALSE;
ANSI_STRING AnsiString;
UNICODE_STRING DosFileName;
UNICODE_STRING FileName;
UNICODE_STRING DosHiveName;
UNICODE_STRING HiveName;
OldValueBufferSize = VALUE_BUFFER_SIZE;
OldValueBuffer = VirtualAlloc( NULL, OldValueBufferSize, MEM_COMMIT, PAGE_READWRITE );
if (OldValueBuffer == NULL) {
fprintf( stderr, "HIVEINI: Unable to allocate value buffer.\n" );
exit( 1 );
}
RegInitialize();
FileArgumentSeen = FALSE;
HiveName.Length = HiveName.MaximumLength = 0;
HiveName.Buffer = NULL;
for (i=1; i<argc; i++) {
s = argv[ i ];
if (*s == '-' || *s == '/') {
while (*++s) {
switch( tolower( *s ) ) {
case 'd':
DebugOutput = TRUE;
break;
case 'f':
if (++i < argc) {
RtlInitAnsiString(&AnsiString, argv[i]);
RtlAnsiStringToUnicodeString( &DosHiveName,
&AnsiString,
TRUE );
RtlDosPathNameToNtPathName_U( DosHiveName.Buffer,
&HiveName,
NULL,
NULL );
break;
}
default: Usage();
}
}
}
else {
FileArgumentSeen = TRUE;
RtlInitAnsiString( &AnsiString, s );
Status = RtlAnsiStringToUnicodeString( &DosFileName, &AnsiString, TRUE );
if (NT_SUCCESS( Status )) {
if (RtlDosPathNameToNtPathName_U( DosFileName.Buffer,
&FileName,
NULL,
NULL
)
) {
Status = RiInitializeRegistryFromAsciiFile( &HiveName,
&FileName );
if (!NT_SUCCESS( Status )) {
fprintf( stderr,
"HIVEINI: Failed to load from %wZ - Status == %lx\n",
&FileName,
Status
);
}
}
else {
Status = STATUS_UNSUCCESSFUL;
fprintf( stderr,
"HIVEINI: Unable to map Dos Name (%wZ) to NT name\n",
&DosFileName
);
}
}
else {
fprintf( stderr,
"HIVEINI: Unable to convert %s to unicode - Status == %lx\n",
&AnsiString,
Status
);
}
}
}
if (!FileArgumentSeen) {
RtlInitUnicodeString( &FileName, L"\\SystemRoot\\System32\\Config\\registry.sys" );
Status = RiInitializeRegistryFromAsciiFile( &HiveName,
&FileName );
if (!NT_SUCCESS( Status )) {
fprintf( stderr,
"HIVEINI: Failed to load from %wZ - Status == %lx\n",
&FileName,
Status
);
}
else {
RtlInitUnicodeString( &FileName, L"\\SystemRoot\\System32\\Config\\registry.usr" );
Status = RiInitializeRegistryFromAsciiFile( &HiveName,
&FileName );
if (!NT_SUCCESS( Status )) {
fprintf( stderr,
"HIVEINI: Failed to load from %wZ - Status == %lx\n",
&FileName,
Status
);
}
}
}
return( 0 );
}