00001 #include "regutil.h" 00002 #include "edithive.h" 00003 00004 NTSTATUS 00005 RiInitializeRegistryFromAsciiFile( 00006 IN PUNICODE_STRING HiveName, 00007 IN PUNICODE_STRING FileName 00008 ); 00009 00010 void 00011 Usage( void ) 00012 { 00013 fprintf( stderr, "usage: HIVEINI -f hivefile [files...]\n" ); 00014 exit( 1 ); 00015 } 00016 00017 PVOID OldValueBuffer; 00018 ULONG OldValueBufferSize; 00019 00020 typedef struct _KEY_INFO { 00021 ULONG IndentAmount; 00022 UNICODE_STRING Name; 00023 HANDLE HiveHandle; 00024 HANDLE Handle; 00025 LARGE_INTEGER LastWriteTime; 00026 } KEY_INFO, *PKEY_INFO; 00027 00028 #define MAX_KEY_DEPTH 64 00029 00030 NTSTATUS 00031 RiInitializeRegistryFromAsciiFile( 00032 IN PUNICODE_STRING HiveName, 00033 IN PUNICODE_STRING FileName 00034 ) 00035 { 00036 NTSTATUS Status; 00037 REG_UNICODE_FILE UnicodeFile; 00038 PWSTR EndKey, FirstEqual, BeginValue; 00039 ULONG IndentAmount; 00040 UNICODE_STRING InputLine; 00041 UNICODE_STRING KeyName; 00042 UNICODE_STRING KeyValue; 00043 PKEY_VALUE_FULL_INFORMATION OldValueInformation; 00044 PKEY_BASIC_INFORMATION KeyInformation; 00045 UCHAR KeyInformationBuffer[ 512 ]; 00046 ULONG ResultLength; 00047 ULONG OldValueLength; 00048 PVOID ValueBuffer; 00049 ULONG ValueLength; 00050 ULONG ValueType; 00051 KEY_INFO KeyPath[ MAX_KEY_DEPTH ]; 00052 PKEY_INFO CurrentKey; 00053 ULONG KeyPathLength; 00054 OBJECT_ATTRIBUTES ObjectAttributes; 00055 UNICODE_STRING Class; 00056 ULONG Disposition; 00057 BOOLEAN UpdateKeyValue; 00058 ULONG i; 00059 HANDLE HiveHandle; 00060 HANDLE RootKey; 00061 UNICODE_STRING RootName; 00062 00063 HiveHandle = EhOpenHive(HiveName, 00064 &KeyPath[0].Handle, 00065 &KeyPath[0].Name, 00066 TYPE_SIMPLE); 00067 if (HiveHandle == NULL) { 00068 return(STATUS_OBJECT_PATH_NOT_FOUND); 00069 } 00070 KeyPath[0].Handle = (HANDLE)HCELL_NIL; 00071 00072 OldValueInformation = (PKEY_VALUE_FULL_INFORMATION)OldValueBuffer; 00073 Class.Buffer = NULL; 00074 Class.Length = 0; 00075 00076 Status = RegLoadAsciiFileAsUnicode( FileName, 00077 &UnicodeFile 00078 ); 00079 if (!NT_SUCCESS( Status )) { 00080 return( Status ); 00081 } 00082 00083 KeyPathLength = 0; 00084 while (RegGetNextLine( &UnicodeFile, &IndentAmount, &FirstEqual )) { 00085 #if 0 00086 InputLine.Buffer = UnicodeFile.BeginLine; 00087 InputLine.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)UnicodeFile.BeginLine); 00088 InputLine.MaximumLength = InputLine.Length; 00089 printf( "GetNextLine: (%02u) '%wZ'\n", IndentAmount, &InputLine ); 00090 #endif 00091 if (FirstEqual == NULL) { 00092 KeyName.Buffer = UnicodeFile.BeginLine; 00093 KeyName.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)KeyName.Buffer); 00094 KeyName.MaximumLength = (USHORT)(KeyName.Length + 1); 00095 00096 #if 0 00097 printf( "%02u %04u KeyName: %wZ\n", KeyPathLength, IndentAmount, &KeyName ); 00098 #endif 00099 CurrentKey = &KeyPath[ KeyPathLength ]; 00100 if (KeyPathLength == 0 || 00101 IndentAmount > CurrentKey->IndentAmount 00102 ) { 00103 if (KeyPathLength == MAX_KEY_DEPTH) { 00104 fprintf( stderr, 00105 "HIVEINI: %wZ key exceeded maximum depth (%u) of tree.\n", 00106 &KeyName, 00107 MAX_KEY_DEPTH 00108 ); 00109 00110 return( STATUS_UNSUCCESSFUL ); 00111 } 00112 KeyPathLength++; 00113 CurrentKey++; 00114 } 00115 else { 00116 do { 00117 CurrentKey->Handle = NULL; 00118 if (IndentAmount == CurrentKey->IndentAmount) { 00119 break; 00120 } 00121 CurrentKey--; 00122 if (--KeyPathLength == 1) { 00123 break; 00124 } 00125 } 00126 while (IndentAmount <= CurrentKey->IndentAmount); 00127 } 00128 00129 #if 0 00130 printf( " (%02u)\n", KeyPathLength ); 00131 #endif 00132 CurrentKey->Name = KeyName; 00133 CurrentKey->IndentAmount = IndentAmount; 00134 Status = EhCreateChild(HiveHandle, 00135 KeyPath[ KeyPathLength-1 ].Handle, 00136 &KeyName, 00137 &CurrentKey->Handle, 00138 &Disposition); 00139 00140 if (NT_SUCCESS( Status )) { 00141 if (DebugOutput) { 00142 fprintf( stderr, " Created key %02x %wZ (%08x)\n", 00143 CurrentKey->IndentAmount, 00144 &CurrentKey->Name, 00145 CurrentKey->Handle 00146 ); 00147 } 00148 KeyInformation = (PKEY_BASIC_INFORMATION)KeyInformationBuffer; 00149 Status = EhQueryKey( HiveHandle, 00150 CurrentKey->Handle, 00151 KeyBasicInformation, 00152 KeyInformation, 00153 sizeof( KeyInformationBuffer ), 00154 &ResultLength 00155 ); 00156 if (NT_SUCCESS( Status )) { 00157 CurrentKey->LastWriteTime = KeyInformation->LastWriteTime; 00158 } 00159 else { 00160 RtlZeroMemory( &CurrentKey->LastWriteTime, 00161 sizeof( CurrentKey->LastWriteTime ) 00162 ); 00163 00164 } 00165 00166 if (Disposition == REG_CREATED_NEW_KEY) { 00167 printf( "Created Key: " ); 00168 for (i=0; i<KeyPathLength; i++) { 00169 printf( "%wZ\\", &KeyPath[ i ].Name ); 00170 } 00171 printf( "%wZ\n", &KeyName ); 00172 } 00173 } 00174 else { 00175 fprintf( stderr, 00176 "HIVEINI: CreateKey (%wZ) relative to handle (%lx) failed - %lx\n", 00177 &KeyName, 00178 ObjectAttributes.RootDirectory, 00179 Status 00180 ); 00181 } 00182 } 00183 else { 00184 if (FirstEqual == UnicodeFile.BeginLine) { 00185 KeyName.Buffer = NULL; 00186 KeyName.Length = 0; 00187 KeyName.MaximumLength = 0; 00188 } 00189 else { 00190 EndKey = FirstEqual; 00191 while (EndKey > UnicodeFile.BeginLine && EndKey[ -1 ] <= L' ') { 00192 EndKey--; 00193 } 00194 KeyName.Buffer = UnicodeFile.BeginLine; 00195 KeyName.Length = (USHORT)((PCHAR)EndKey - (PCHAR)KeyName.Buffer); 00196 KeyName.MaximumLength = (USHORT)(KeyName.Length + 1); 00197 } 00198 00199 BeginValue = FirstEqual + 1; 00200 while (BeginValue < UnicodeFile.EndOfLine && *BeginValue <= L' ') { 00201 BeginValue++; 00202 } 00203 KeyValue.Buffer = BeginValue; 00204 KeyValue.Length = (USHORT)((PCHAR)UnicodeFile.EndOfLine - (PCHAR)BeginValue); 00205 KeyValue.MaximumLength = (USHORT)(KeyValue.Length + 1); 00206 00207 while (IndentAmount <= CurrentKey->IndentAmount) { 00208 if (DebugOutput) { 00209 fprintf( stderr, " Popping from key %02x %wZ (%08x)\n", 00210 CurrentKey->IndentAmount, 00211 &CurrentKey->Name, 00212 CurrentKey->Handle 00213 ); 00214 } 00215 CurrentKey->Handle = NULL; 00216 CurrentKey--; 00217 if (--KeyPathLength == 1) { 00218 break; 00219 } 00220 } 00221 if (DebugOutput) { 00222 fprintf( stderr, " Adding value '%wZ = %wZ' to key %02x %wZ (%08x)\n", 00223 &KeyName, 00224 &KeyValue, 00225 CurrentKey->IndentAmount, 00226 &CurrentKey->Name, 00227 CurrentKey->Handle 00228 ); 00229 } 00230 00231 if (RegGetKeyValue( &KeyValue, 00232 &UnicodeFile, 00233 &ValueType, 00234 &ValueBuffer, 00235 &ValueLength 00236 ) 00237 ) { 00238 if (ValueBuffer == NULL) { 00239 Status = EhDeleteValueKey( HiveHandle, 00240 KeyPath[ KeyPathLength+1 ].Handle, 00241 &KeyValue 00242 ); 00243 if (NT_SUCCESS( Status )) { 00244 printf( "Delete value for Key: " ); 00245 for (i=0; i<KeyPathLength; i++) { 00246 printf( "%wZ\\", &KeyPath[ i ].Name ); 00247 } 00248 printf( "%wZ\n", &KeyName ); 00249 } 00250 } 00251 else { 00252 if ( UnicodeFile.LastWriteTime.QuadPart > 00253 CurrentKey->LastWriteTime.QuadPart 00254 ) { 00255 Status = STATUS_UNSUCCESSFUL; 00256 UpdateKeyValue = TRUE; 00257 } 00258 else { 00259 Status = EhQueryValueKey( HiveHandle, 00260 CurrentKey->Handle, 00261 &KeyName, 00262 KeyValueFullInformation, 00263 OldValueInformation, 00264 OldValueBufferSize, 00265 &OldValueLength 00266 ); 00267 if (NT_SUCCESS( Status )) { 00268 UpdateKeyValue = TRUE; 00269 } 00270 else { 00271 UpdateKeyValue = FALSE; 00272 } 00273 } 00274 00275 if (!NT_SUCCESS( Status ) || 00276 OldValueInformation->Type != ValueType || 00277 OldValueInformation->DataLength != ValueLength || 00278 !RtlEqualMemory( (PCHAR)OldValueInformation + 00279 OldValueInformation->DataOffset, 00280 ValueBuffer, 00281 ValueLength ) 00282 ) { 00283 00284 Status = EhSetValueKey( HiveHandle, 00285 CurrentKey->Handle, 00286 &KeyName, 00287 0, 00288 ValueType, 00289 ValueBuffer, 00290 ValueLength 00291 ); 00292 if (NT_SUCCESS( Status )) { 00293 printf( "%s value for Key: ", 00294 UpdateKeyValue ? "Updated" : "Created" 00295 ); 00296 for (i=1; i<=KeyPathLength; i++) { 00297 printf( "%wZ\\", &KeyPath[ i ].Name ); 00298 } 00299 00300 if (KeyName.Length) { 00301 printf( "%wZ ", &KeyName ); 00302 } 00303 printf( "= '%wZ'\n", &KeyValue ); 00304 } 00305 else { 00306 fprintf( stderr, 00307 "HIVEINI: SetValueKey (%wZ) failed - %lx\n", 00308 &KeyName, 00309 Status 00310 ); 00311 } 00312 } 00313 00314 RtlFreeHeap( RtlProcessHeap(), 0, ValueBuffer ); 00315 } 00316 } 00317 else { 00318 fprintf( stderr, 00319 "HIVEINI: Invalid key (%wZ) value (%wZ)\n", &KeyName, 00320 &KeyValue 00321 ); 00322 } 00323 } 00324 } 00325 00326 EhCloseHive(HiveHandle); 00327 00328 return( Status ); 00329 } 00330 00331 00332 int 00333 __cdecl main( argc, argv ) 00334 int argc; 00335 char *argv[]; 00336 { 00337 int i; 00338 char *s; 00339 NTSTATUS Status; 00340 BOOL FileArgumentSeen; 00341 BOOL HiveArgumentSeen=FALSE; 00342 ANSI_STRING AnsiString; 00343 UNICODE_STRING DosFileName; 00344 UNICODE_STRING FileName; 00345 UNICODE_STRING DosHiveName; 00346 UNICODE_STRING HiveName; 00347 00348 OldValueBufferSize = VALUE_BUFFER_SIZE; 00349 OldValueBuffer = VirtualAlloc( NULL, OldValueBufferSize, MEM_COMMIT, PAGE_READWRITE ); 00350 if (OldValueBuffer == NULL) { 00351 fprintf( stderr, "HIVEINI: Unable to allocate value buffer.\n" ); 00352 exit( 1 ); 00353 } 00354 00355 RegInitialize(); 00356 00357 FileArgumentSeen = FALSE; 00358 HiveName.Length = HiveName.MaximumLength = 0; 00359 HiveName.Buffer = NULL; 00360 for (i=1; i<argc; i++) { 00361 s = argv[ i ]; 00362 if (*s == '-' || *s == '/') { 00363 while (*++s) { 00364 switch( tolower( *s ) ) { 00365 case 'd': 00366 DebugOutput = TRUE; 00367 break; 00368 00369 case 'f': 00370 if (++i < argc) { 00371 RtlInitAnsiString(&AnsiString, argv[i]); 00372 RtlAnsiStringToUnicodeString( &DosHiveName, 00373 &AnsiString, 00374 TRUE ); 00375 RtlDosPathNameToNtPathName_U( DosHiveName.Buffer, 00376 &HiveName, 00377 NULL, 00378 NULL ); 00379 break; 00380 } 00381 00382 default: Usage(); 00383 } 00384 } 00385 } 00386 else { 00387 FileArgumentSeen = TRUE; 00388 RtlInitAnsiString( &AnsiString, s ); 00389 Status = RtlAnsiStringToUnicodeString( &DosFileName, &AnsiString, TRUE ); 00390 if (NT_SUCCESS( Status )) { 00391 if (RtlDosPathNameToNtPathName_U( DosFileName.Buffer, 00392 &FileName, 00393 NULL, 00394 NULL 00395 ) 00396 ) { 00397 Status = RiInitializeRegistryFromAsciiFile( &HiveName, 00398 &FileName ); 00399 if (!NT_SUCCESS( Status )) { 00400 fprintf( stderr, 00401 "HIVEINI: Failed to load from %wZ - Status == %lx\n", 00402 &FileName, 00403 Status 00404 ); 00405 } 00406 } 00407 else { 00408 Status = STATUS_UNSUCCESSFUL; 00409 fprintf( stderr, 00410 "HIVEINI: Unable to map Dos Name (%wZ) to NT name\n", 00411 &DosFileName 00412 ); 00413 } 00414 } 00415 else { 00416 fprintf( stderr, 00417 "HIVEINI: Unable to convert %s to unicode - Status == %lx\n", 00418 &AnsiString, 00419 Status 00420 ); 00421 } 00422 } 00423 } 00424 00425 if (!FileArgumentSeen) { 00426 RtlInitUnicodeString( &FileName, L"\\SystemRoot\\System32\\Config\\registry.sys" ); 00427 Status = RiInitializeRegistryFromAsciiFile( &HiveName, 00428 &FileName ); 00429 if (!NT_SUCCESS( Status )) { 00430 fprintf( stderr, 00431 "HIVEINI: Failed to load from %wZ - Status == %lx\n", 00432 &FileName, 00433 Status 00434 ); 00435 } 00436 else { 00437 RtlInitUnicodeString( &FileName, L"\\SystemRoot\\System32\\Config\\registry.usr" ); 00438 Status = RiInitializeRegistryFromAsciiFile( &HiveName, 00439 &FileName ); 00440 if (!NT_SUCCESS( Status )) { 00441 fprintf( stderr, 00442 "HIVEINI: Failed to load from %wZ - Status == %lx\n", 00443 &FileName, 00444 Status 00445 ); 00446 } 00447 } 00448 } 00449 00450 return( 0 ); 00451 }