Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhiveinit.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: registry manipulation library 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org> 00005 * Copyright 2001 - 2005 Eric Kohl 00006 */ 00007 00008 #include "cmlib.h" 00009 #define NDEBUG 00010 #include <debug.h> 00011 00018 BOOLEAN CMAPI 00019 HvpVerifyHiveHeader( 00020 PHBASE_BLOCK BaseBlock) 00021 { 00022 if (BaseBlock->Signature != HV_SIGNATURE || 00023 BaseBlock->Major != HSYS_MAJOR || 00024 BaseBlock->Minor < HSYS_MINOR || 00025 BaseBlock->Type != HFILE_TYPE_PRIMARY || 00026 BaseBlock->Format != HBASE_FORMAT_MEMORY || 00027 BaseBlock->Cluster != 1 || 00028 BaseBlock->Sequence1 != BaseBlock->Sequence2 || 00029 HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum) 00030 { 00031 DPRINT1("Verify Hive Header failed: \n"); 00032 DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n", 00033 BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR); 00034 DPRINT1(" Minor: 0x%x is not >= 0x%x, Type: 0x%x and not 0x%x\n", 00035 BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, HFILE_TYPE_PRIMARY); 00036 DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n", 00037 BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster); 00038 DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n", 00039 BaseBlock->Sequence1, BaseBlock->Sequence2, 00040 HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum); 00041 return FALSE; 00042 } 00043 00044 return TRUE; 00045 } 00046 00054 VOID CMAPI 00055 HvpFreeHiveBins( 00056 PHHIVE Hive) 00057 { 00058 ULONG i; 00059 PHBIN Bin; 00060 ULONG Storage; 00061 00062 for (Storage = Stable; Storage < HTYPE_COUNT; Storage++) 00063 { 00064 Bin = NULL; 00065 for (i = 0; i < Hive->Storage[Storage].Length; i++) 00066 { 00067 if (Hive->Storage[Storage].BlockList[i].BinAddress == (ULONG_PTR)NULL) 00068 continue; 00069 if (Hive->Storage[Storage].BlockList[i].BinAddress != (ULONG_PTR)Bin) 00070 { 00071 Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress; 00072 Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress, 0); 00073 } 00074 Hive->Storage[Storage].BlockList[i].BinAddress = (ULONG_PTR)NULL; 00075 Hive->Storage[Storage].BlockList[i].BlockAddress = (ULONG_PTR)NULL; 00076 } 00077 00078 if (Hive->Storage[Storage].Length) 00079 Hive->Free(Hive->Storage[Storage].BlockList, 0); 00080 } 00081 } 00082 00092 NTSTATUS CMAPI 00093 HvpCreateHive( 00094 PHHIVE RegistryHive) 00095 { 00096 PHBASE_BLOCK BaseBlock; 00097 ULONG Index; 00098 00099 BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM); 00100 if (BaseBlock == NULL) 00101 return STATUS_NO_MEMORY; 00102 RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK)); 00103 BaseBlock->Signature = HV_SIGNATURE; 00104 BaseBlock->Major = HSYS_MAJOR; 00105 BaseBlock->Minor = HSYS_MINOR; 00106 BaseBlock->Type = HFILE_TYPE_PRIMARY; 00107 BaseBlock->Format = HBASE_FORMAT_MEMORY; 00108 BaseBlock->Cluster = 1; 00109 BaseBlock->RootCell = HCELL_NIL; 00110 BaseBlock->Length = HV_BLOCK_SIZE; 00111 BaseBlock->Sequence1 = 1; 00112 BaseBlock->Sequence2 = 1; 00113 /* FIXME: Fill in the file name */ 00114 BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock); 00115 00116 RegistryHive->BaseBlock = BaseBlock; 00117 for (Index = 0; Index < 24; Index++) 00118 { 00119 RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL; 00120 RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL; 00121 } 00122 RtlInitializeBitMap(&RegistryHive->DirtyVector, NULL, 0); 00123 00124 return STATUS_SUCCESS; 00125 } 00126 00137 NTSTATUS CMAPI 00138 HvpInitializeMemoryHive( 00139 PHHIVE Hive, 00140 PVOID ChunkBase) 00141 { 00142 SIZE_T BlockIndex; 00143 PHBIN Bin, NewBin; 00144 ULONG i; 00145 ULONG BitmapSize; 00146 PULONG BitmapBuffer; 00147 SIZE_T ChunkSize; 00148 00149 // 00150 // This hack is similar in magnitude to the US's National Debt 00151 // 00152 ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length; 00153 ((PHBASE_BLOCK)ChunkBase)->Length = HV_BLOCK_SIZE; 00154 DPRINT("ChunkSize: %lx\n", ChunkSize); 00155 00156 if (ChunkSize < sizeof(HBASE_BLOCK) || 00157 !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase)) 00158 { 00159 DPRINT1("Registry is corrupt: ChunkSize %lu < sizeof(HBASE_BLOCK) %lu, " 00160 "or HvpVerifyHiveHeader() failed\n", ChunkSize, (SIZE_T)sizeof(HBASE_BLOCK)); 00161 return STATUS_REGISTRY_CORRUPT; 00162 } 00163 00164 Hive->BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM); 00165 if (Hive->BaseBlock == NULL) 00166 { 00167 return STATUS_NO_MEMORY; 00168 } 00169 RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK)); 00170 00171 /* 00172 * Build a block list from the in-memory chunk and copy the data as 00173 * we go. 00174 */ 00175 00176 Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE) - 1; 00177 Hive->Storage[Stable].BlockList = 00178 Hive->Allocate(Hive->Storage[Stable].Length * 00179 sizeof(HMAP_ENTRY), FALSE, TAG_CM); 00180 if (Hive->Storage[Stable].BlockList == NULL) 00181 { 00182 DPRINT1("Allocating block list failed\n"); 00183 Hive->Free(Hive->BaseBlock, 0); 00184 return STATUS_NO_MEMORY; 00185 } 00186 00187 for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; ) 00188 { 00189 Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE); 00190 if (Bin->Signature != HV_BIN_SIGNATURE || 00191 (Bin->Size % HV_BLOCK_SIZE) != 0) 00192 { 00193 Hive->Free(Hive->BaseBlock, 0); 00194 Hive->Free(Hive->Storage[Stable].BlockList, 0); 00195 return STATUS_REGISTRY_CORRUPT; 00196 } 00197 00198 NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM); 00199 if (NewBin == NULL) 00200 { 00201 Hive->Free(Hive->BaseBlock, 0); 00202 Hive->Free(Hive->Storage[Stable].BlockList, 0); 00203 return STATUS_NO_MEMORY; 00204 } 00205 00206 Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin; 00207 Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin; 00208 00209 RtlCopyMemory(NewBin, Bin, Bin->Size); 00210 00211 if (Bin->Size > HV_BLOCK_SIZE) 00212 { 00213 for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++) 00214 { 00215 Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin; 00216 Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress = 00217 ((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE)); 00218 } 00219 } 00220 00221 BlockIndex += Bin->Size / HV_BLOCK_SIZE; 00222 } 00223 00224 if (HvpCreateHiveFreeCellList(Hive)) 00225 { 00226 HvpFreeHiveBins(Hive); 00227 Hive->Free(Hive->BaseBlock, 0); 00228 return STATUS_NO_MEMORY; 00229 } 00230 00231 BitmapSize = ROUND_UP(Hive->Storage[Stable].Length, 00232 sizeof(ULONG) * 8) / 8; 00233 BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE, TAG_CM); 00234 if (BitmapBuffer == NULL) 00235 { 00236 HvpFreeHiveBins(Hive); 00237 Hive->Free(Hive->BaseBlock, 0); 00238 return STATUS_NO_MEMORY; 00239 } 00240 00241 RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8); 00242 RtlClearAllBits(&Hive->DirtyVector); 00243 00244 return STATUS_SUCCESS; 00245 } 00246 00257 NTSTATUS CMAPI 00258 HvpInitializeMemoryInplaceHive( 00259 PHHIVE Hive, 00260 PVOID ChunkBase) 00261 { 00262 if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase)) 00263 { 00264 return STATUS_REGISTRY_CORRUPT; 00265 } 00266 00267 Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase; 00268 Hive->ReadOnly = TRUE; 00269 Hive->Flat = TRUE; 00270 00271 return STATUS_SUCCESS; 00272 } 00273 00274 typedef enum _RESULT 00275 { 00276 NotHive, 00277 Fail, 00278 NoMemory, 00279 HiveSuccess, 00280 RecoverHeader, 00281 RecoverData, 00282 SelfHeal 00283 } RESULT; 00284 00285 RESULT CMAPI 00286 HvpGetHiveHeader(IN PHHIVE Hive, 00287 IN PHBASE_BLOCK *HiveBaseBlock, 00288 IN PLARGE_INTEGER TimeStamp) 00289 { 00290 PHBASE_BLOCK BaseBlock; 00291 ULONG Alignment; 00292 ULONG Result; 00293 ULONG Offset = 0; 00294 ASSERT(sizeof(HBASE_BLOCK) >= (HV_BLOCK_SIZE * Hive->Cluster)); 00295 00296 /* Assume failure and allocate the buffer */ 00297 *HiveBaseBlock = 0; 00298 BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), TRUE, TAG_CM); 00299 if (!BaseBlock) return NoMemory; 00300 00301 /* Check for, and enforce, alignment */ 00302 Alignment = Hive->Cluster * HV_BLOCK_SIZE -1; 00303 if ((ULONG_PTR)BaseBlock & Alignment) 00304 { 00305 /* Free the old header */ 00306 Hive->Free(BaseBlock, 0); 00307 BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, TAG_CM); 00308 if (!BaseBlock) return NoMemory; 00309 00310 //BaseBlock->Length = PAGE_SIZE; ?? 00311 } 00312 00313 /* Clear it */ 00314 RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK)); 00315 00316 /* Now read it from disk */ 00317 Result = Hive->FileRead(Hive, 00318 HFILE_TYPE_PRIMARY, 00319 &Offset, 00320 BaseBlock, 00321 Hive->Cluster * HV_BLOCK_SIZE); 00322 00323 /* Couldn't read: assume it's not a hive */ 00324 if (!Result) return NotHive; 00325 00326 /* Do validation */ 00327 if (!HvpVerifyHiveHeader(BaseBlock)) return NotHive; 00328 00329 /* Return information */ 00330 *HiveBaseBlock = BaseBlock; 00331 *TimeStamp = BaseBlock->TimeStamp; 00332 return HiveSuccess; 00333 } 00334 00335 NTSTATUS CMAPI 00336 HvLoadHive(IN PHHIVE Hive, 00337 IN ULONG FileSize) 00338 { 00339 PHBASE_BLOCK BaseBlock = NULL; 00340 ULONG Result; 00341 LARGE_INTEGER TimeStamp; 00342 ULONG Offset = 0; 00343 PVOID HiveData; 00344 00345 /* Get the hive header */ 00346 Result = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp); 00347 switch (Result) 00348 { 00349 /* Out of memory */ 00350 case NoMemory: 00351 00352 /* Fail */ 00353 return STATUS_INSUFFICIENT_RESOURCES; 00354 00355 /* Not a hive */ 00356 case NotHive: 00357 00358 /* Fail */ 00359 return STATUS_NOT_REGISTRY_FILE; 00360 00361 /* Has recovery data */ 00362 case RecoverData: 00363 case RecoverHeader: 00364 00365 /* Fail */ 00366 return STATUS_REGISTRY_CORRUPT; 00367 } 00368 00369 /* Set default boot type */ 00370 BaseBlock->BootType = 0; 00371 00372 /* Setup hive data */ 00373 Hive->BaseBlock = BaseBlock; 00374 Hive->Version = Hive->BaseBlock->Minor; 00375 00376 /* Allocate a buffer large enough to hold the hive */ 00377 HiveData = Hive->Allocate(FileSize, TRUE, TAG_CM); 00378 if (!HiveData) return STATUS_INSUFFICIENT_RESOURCES; 00379 00380 /* Now read the whole hive */ 00381 Result = Hive->FileRead(Hive, 00382 HFILE_TYPE_PRIMARY, 00383 &Offset, 00384 HiveData, 00385 FileSize); 00386 if (!Result) return STATUS_NOT_REGISTRY_FILE; 00387 00388 /* Apply "US National Debt" hack */ 00389 ((PHBASE_BLOCK)HiveData)->Length = FileSize; 00390 00391 /* Free our base block... it's usless in this implementation */ 00392 Hive->Free(BaseBlock, 0); 00393 00394 /* Initialize the hive directly from memory */ 00395 return HvpInitializeMemoryHive(Hive, HiveData); 00396 } 00397 00429 NTSTATUS CMAPI 00430 HvInitialize( 00431 PHHIVE RegistryHive, 00432 ULONG Operation, 00433 ULONG HiveType, 00434 ULONG HiveFlags, 00435 PVOID HiveData OPTIONAL, 00436 PALLOCATE_ROUTINE Allocate, 00437 PFREE_ROUTINE Free, 00438 PFILE_SET_SIZE_ROUTINE FileSetSize, 00439 PFILE_WRITE_ROUTINE FileWrite, 00440 PFILE_READ_ROUTINE FileRead, 00441 PFILE_FLUSH_ROUTINE FileFlush, 00442 ULONG Cluster OPTIONAL, 00443 PUNICODE_STRING FileName) 00444 { 00445 NTSTATUS Status; 00446 PHHIVE Hive = RegistryHive; 00447 00448 UNREFERENCED_PARAMETER(HiveType); 00449 UNREFERENCED_PARAMETER(FileName); 00450 00451 /* 00452 * Create a new hive structure that will hold all the maintenance data. 00453 */ 00454 00455 RtlZeroMemory(Hive, sizeof(HHIVE)); 00456 00457 Hive->Allocate = Allocate; 00458 Hive->Free = Free; 00459 Hive->FileRead = FileRead; 00460 Hive->FileWrite = FileWrite; 00461 Hive->FileSetSize = FileSetSize; 00462 Hive->FileFlush = FileFlush; 00463 Hive->StorageTypeCount = HTYPE_COUNT; 00464 Hive->Cluster = 1; 00465 Hive->Version = HSYS_MINOR; 00466 Hive->HiveFlags = HiveFlags &~ HIVE_NOLAZYFLUSH; 00467 00468 switch (Operation) 00469 { 00470 case HINIT_CREATE: 00471 Status = HvpCreateHive(Hive); 00472 break; 00473 00474 case HINIT_MEMORY: 00475 Status = HvpInitializeMemoryHive(Hive, HiveData); 00476 break; 00477 00478 case HINIT_FLAT: 00479 Status = HvpInitializeMemoryInplaceHive(Hive, HiveData); 00480 break; 00481 00482 case HINIT_FILE: 00483 00484 /* Hack of doom: Cluster is actually the file size. */ 00485 Status = HvLoadHive(Hive, Cluster); 00486 if ((Status != STATUS_SUCCESS) && 00487 (Status != STATUS_REGISTRY_RECOVERED)) 00488 { 00489 /* Unrecoverable failure */ 00490 return Status; 00491 } 00492 00493 /* Check for previous damage */ 00494 if (Status == STATUS_REGISTRY_RECOVERED) ASSERT(FALSE); 00495 break; 00496 00497 default: 00498 /* FIXME: A better return status value is needed */ 00499 Status = STATUS_NOT_IMPLEMENTED; 00500 ASSERT(FALSE); 00501 } 00502 00503 if (!NT_SUCCESS(Status)) 00504 return Status; 00505 00506 if (Operation != HINIT_CREATE) CmPrepareHive(Hive); 00507 00508 return Status; 00509 } 00510 00517 VOID CMAPI 00518 HvFree( 00519 PHHIVE RegistryHive) 00520 { 00521 if (!RegistryHive->ReadOnly) 00522 { 00523 /* Release hive bitmap */ 00524 if (RegistryHive->DirtyVector.Buffer) 00525 { 00526 RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0); 00527 } 00528 00529 HvpFreeHiveBins(RegistryHive); 00530 } 00531 00532 RegistryHive->Free(RegistryHive, 0); 00533 } 00534 00535 /* EOF */ Generated on Fri May 25 2012 04:34:28 for ReactOS by
1.7.6.1
|