Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

hive.h File Reference

#include "hivedata.h"

Go to the source code of this file.

Defines

#define DHvCheckHive(a)
#define DHvCheckBin(h, a)
#define ROUND_UP(a, b)   ( ((ULONG)(a) + (ULONG)(b) - 1) & ~((ULONG)(b) - 1) )
#define ASSERT_LISTENTRY(ListEntry)
#define HINIT_CREATE   0
#define HINIT_MEMORY   1
#define HINIT_FILE   2
#define HINIT_MEMORY_INPLACE   3
#define HINIT_FLAT   4
#define HIVE_VOLATILE   1
#define HIVE_NOLAZYFLUSH   2
#define HIVE_HAS_BEEN_REPLACED   4
#define HvGetCell(Hive, Cell)   (((Hive)->GetCellRoutine)(Hive, Cell))
#define HvpGetHCell(Hive, Cell)

Functions

PHBIN HvpAddBin (PHHIVE Hive, ULONG NewSize, HSTORAGE_TYPE Type)
PHMAP_ENTRY HvpGetCellMap (PHHIVE Hive, HCELL_INDEX Cell)
VOID HvpFreeMap (PHHIVE Hive, PHMAP_DIRECTORY Dir, ULONG Start, ULONG End)
BOOLEAN HvpAllocateMap (PHHIVE Hive, PHMAP_DIRECTORY Dir, ULONG Start, ULONG End)
BOOLEAN HvpGrowLog1 (PHHIVE Hive, ULONG Count)
BOOLEAN HvpGrowLog2 (PHHIVE Hive, ULONG Size)
ULONG HvpHeaderCheckSum (PHBASE_BLOCK BaseBlock)
NTSTATUS HvpBuildMap (PHHIVE Hive, PVOID Image, PHCELL_INDEX TailDisplay OPTIONAL)
NTSTATUS HvpBuildMapAndCopy (PHHIVE Hive, PVOID Image, PHCELL_INDEX TailDisplay OPTIONAL)
NTSTATUS HvpInitMap (PHHIVE Hive)
VOID HvpCleanMap (PHHIVE Hive)
NTSTATUS HvpEnlistBinInMap (PHHIVE Hive, ULONG Length, PHBIN Bin, ULONG Offset, PHCELL_INDEX TailDisplay OPTIONAL)
VOID HvpFreeAllocatedBins (PHHIVE Hive)
BOOLEAN HvpDoWriteHive (PHHIVE Hive, ULONG FileType)
_CELL_DATAHvpGetCellFlat (PHHIVE Hive, HCELL_INDEX Cell)
_CELL_DATAHvpGetCellPaged (PHHIVE Hive, HCELL_INDEX Cell)
VOID HvpEnlistFreeCell (PHHIVE Hive, HCELL_INDEX Cell, ULONG Size, HSTORAGE_TYPE Type, BOOLEAN CoalesceForward, PHCELL_INDEX TailDisplay OPTIONAL)
BOOLEAN HvpEnlistFreeCells (PHHIVE Hive, PHBIN Bin, ULONG BinOffset, PHCELL_INDEX TailDisplay OPTIONAL)
VOID HvpDelistFreeCell (PHHIVE Hive, PHCELL Pcell, HSTORAGE_TYPE Type, PHCELL_INDEX TailDisplay OPTIONAL)
NTSTATUS HvInitializeHive (PHHIVE Hive, ULONG OperationType, ULONG HiveFlags, ULONG FileTypes, PVOID HiveData OPTIONAL, PALLOCATE_ROUTINE AllocateRoutine, PFREE_ROUTINE FreeRoutine, PFILE_SET_SIZE_ROUTINE FileSetSizeRoutine, PFILE_WRITE_ROUTINE FileWriteRoutine, PFILE_READ_ROUTINE FileReadRoutine, PFILE_FLUSH_ROUTINE FileFlushRoutine, ULONG Cluster, PUNICODE_STRING FileName)
BOOLEAN HvSyncHive (PHHIVE Hive)
NTSTATUS HvWriteHive (PHHIVE Hive)
NTSTATUS HvLoadHive (PHHIVE Hive, PHCELL_INDEX TailDisplay OPTIONAL)
VOID HvRefreshHive (PHHIVE Hive)
NTSTATUS HvReadInMemoryHive (PHHIVE Hive, PVOID *HiveImage)
ULONG HvCheckHive (PHHIVE Hive, PULONG Storage OPTIONAL)
ULONG HvCheckBin (PHHIVE Hive, PHBIN Bin, PULONG Storage)
BOOLEAN HvMarkCellDirty (PHHIVE Hive, HCELL_INDEX Cell)
BOOLEAN HvIsBinDirty (IN PHHIVE Hive, IN HCELL_INDEX Cell)
BOOLEAN HvMarkDirty (PHHIVE Hive, HCELL_INDEX Start, ULONG Length)
BOOLEAN HvMarkClean (PHHIVE Hive, HCELL_INDEX Start, ULONG Length)
LONG HvGetCellSize (PHHIVE Hive, PVOID Address)
HCELL_INDEX HvAllocateCell (PHHIVE Hive, ULONG NewSize, HSTORAGE_TYPE Type)
VOID HvFreeCell (PHHIVE Hive, HCELL_INDEX Cell)
HCELL_INDEX HvReallocateCell (PHHIVE Hive, HCELL_INDEX Cell, ULONG NewSize)
BOOLEAN HvIsCellAllocated (PHHIVE Hive, HCELL_INDEX Cell)
VOID HvFreeHive (PHHIVE Hive)
VOID HvFreeHivePartial (PHHIVE Hive, HCELL_INDEX Start, HSTORAGE_TYPE Type)


Define Documentation

#define ASSERT_LISTENTRY ListEntry   ) 
 

Value:

ASSERT((ListEntry)->Flink->Blink==ListEntry); \ ASSERT((ListEntry)->Blink->Flink==ListEntry);

Definition at line 58 of file hive.h.

Referenced by HvpAddBin(), and HvpDiscardBins().

#define DHvCheckBin h,
 ) 
 

Definition at line 46 of file hive.h.

Referenced by HvFreeCell().

#define DHvCheckHive  ) 
 

Definition at line 45 of file hive.h.

#define HINIT_CREATE   0
 

Definition at line 197 of file hive.h.

Referenced by CmInitSystem1(), CmpCreateTemporaryHive(), CmpInitHiveFromFile(), CmpInitializeSystemHive(), CmpLoadHiveVolatile(), EhOpenHive(), HvInitializeHive(), and MyCmpInitHiveFromFile().

#define HINIT_FILE   2
 

Definition at line 199 of file hive.h.

Referenced by CmpInitHiveFromFile(), CmpInitializeHive(), CmpLoadHiveVolatile(), CmpValidateAlternate(), CmRestoreKey(), EhOpenHive(), HvInitializeHive(), and MyCmpInitHiveFromFile().

#define HINIT_FLAT   4
 

Definition at line 201 of file hive.h.

Referenced by CmGetSystemControlValues(), and HvInitializeHive().

#define HINIT_MEMORY   1
 

Definition at line 198 of file hive.h.

Referenced by CmpInitializeHive(), CmpInitializeSystemHive(), and HvInitializeHive().

#define HINIT_MEMORY_INPLACE   3
 

Definition at line 200 of file hive.h.

Referenced by CmpInitializeHive(), and HvInitializeHive().

#define HIVE_HAS_BEEN_REPLACED   4
 

Definition at line 205 of file hive.h.

Referenced by CmReplaceKey().

#define HIVE_NOLAZYFLUSH   2
 

Definition at line 204 of file hive.h.

Referenced by CmLoadKey(), CmpDoFlushAll(), CmpRefreshHive(), CmSaveKey(), CmSaveMergedKeys(), HvMarkDirty(), and HvRefreshHive().

#define HIVE_VOLATILE   1
 

Definition at line 203 of file hive.h.

Referenced by CmGetSystemControlValues(), CmInitSystem1(), CmpAddToHiveFileList(), CmpCreateTemporaryHive(), CmpInitializeHive(), CmpInitializeHiveList(), CmpLoadHiveVolatile(), HvInitializeHive(), HvIsBinDirty(), HvMarkCellDirty(), HvMarkClean(), HvMarkDirty(), HvpAddBin(), and HvSyncHive().

#define HvGetCell Hive,
Cell   )     (((Hive)->GetCellRoutine)(Hive, Cell))
 

Definition at line 290 of file hive.h.

Referenced by CmDeleteValueKey(), CmEnumerateKey(), CmGetSystemControlValues(), CmpAddDriverToList(), CmpAddInfoAfterParseFailure(), CmpAddSubKey(), CmpAddToLeaf(), CmpAssignSecurityDescriptor(), CmpCheckKey(), CmpCheckRegistry2(), CmpCheckValueList(), CmpCopyCell(), CmpCopyKeyPartial(), CmpCopySyncTree2(), CmpCopyValue(), CmpCreateLinkNode(), CmpCreateRegistryRoot(), CmpCreateRootNode(), CmpDeleteTree(), CmpDestroyHive(), CmpDoCompareKeyName(), CmpDoCreate(), CmpDoCreateChild(), CmpDoFindSubKeyByNumber(), CmpFindControlSet(), CmpFindDrivers(), CmpFindMatchingDescriptorCell(), CmpFindNameInList(), CmpFindNLSData(), CmpFindProfileOption(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpFindSubKeyInRoot(), CmpFindTagIndex(), CmpFreeKeyBody(), CmpFreeKeyByCell(), CmpFreeKeyValues(), CmpFreeSecurityDescriptor(), CmpFreeValue(), CmpGetHiveName(), CmpGetKeySecurity(), CmpGetObjectSecurity(), CmpGetSymbolicLink(), CmpGetValueDataFromCache(), CmpGetValueKeyFromCache(), CmpGetValueListFromCache(), CmpInsertSecurityCellList(), CmpIsLoadType(), CmpLoadHiveVolatile(), CmpMarkIndexDirty(), CmpMarkKeyDirty(), CmpMarkKeyParentDirty(), CmpMarkKeyValuesDirty(), CmpMergeKeyValues(), CmpParseKey(), CmpQueryKeyData(), CmpQuerySecurityDescriptorInfo(), CmpRefreshHive(), CmpRemoveSecurityCellList(), CmpRemoveSubKey(), CmpReportNotify(), CmpSelectLeaf(), CmpSetCurrentProfile(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSortDriverList(), CmpSplitLeaf(), CmpSyncKeyValues(), CmpSyncSubKeysAfterDelete(), CmpValidateHiveSecurityDescriptors(), CmpWalkPath(), CmQueryMultipleValueKey(), CmRestoreKey(), CmSaveKey(), CmSaveMergedKeys(), CmSetValueKey(), EhCreateChild(), EhOpenHive(), EhpAttachSecurity(), and HvRefreshHive().

#define HvpGetHCell Hive,
Cell   ) 
 

Value:

( USE_OLD_CELL(Hive) ? \ CONTAINING_RECORD(HvGetCell(Hive,Cell), \ HCELL, \ u.OldCell.u.UserData) : \ CONTAINING_RECORD(HvGetCell(Hive,Cell), \ HCELL, \ u.NewCell.u.UserData))

Definition at line 292 of file hive.h.

Referenced by HvFreeCell(), HvIsCellAllocated(), and HvMarkCellDirty().

#define ROUND_UP a,
 )     ( ((ULONG)(a) + (ULONG)(b) - 1) & ~((ULONG)(b) - 1) )
 

Definition at line 49 of file hive.h.

Referenced by CmpSetValueKeyNew(), ExAllocatePool(), ExpGetProcessInformation(), HvMarkClean(), HvMarkDirty(), HvpAddBin(), HvpBuildMapAndCopy(), HvpDoWriteHive(), HvpFindNextDirtyBlock(), HvpGrowLog1(), HvpGrowLog2(), HvpInitMap(), HvpRecoverData(), HvpWriteLog(), HvWriteHive(), KeStartAllProcessors(), MmGetPageFileInformation(), MmGetVerifierInformation(), RtlCreateProcessParameters(), RtlpCopyProcString(), and RtlpCreateStack().


Function Documentation

HCELL_INDEX HvAllocateCell PHHIVE  Hive,
ULONG  NewSize,
HSTORAGE_TYPE  Type
 

Definition at line 386 of file hivecell.c.

Referenced by CmpAddSubKey(), CmpAssignSecurityDescriptor(), CmpCopyCell(), CmpCopyKeyPartial(), CmpCreateLinkNode(), CmpCreateRootNode(), CmpDoCreateChild(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), CmpSyncKeyValues(), EhCreateChild(), and EhpAttachSecurity().

00398 : 00399 00400 Allocates the space and the cell index for a new cell. 00401 00402 Arguments: 00403 00404 Hive - supplies a pointer to the hive control structure for the 00405 hive of interest 00406 00407 NewSize - size in bytes of the cell to allocate 00408 00409 Type - indicates whether Stable or Volatile storage is desired. 00410 00411 Return Value: 00412 00413 New HCELL_INDEX if success, HCELL_NIL if failure. 00414 00415 --*/ 00416 { 00417 HCELL_INDEX NewCell; 00418 00419 CMLOG(CML_MAJOR, CMS_HIVE) { 00420 KdPrint(("HvAllocateCell:\n")); 00421 KdPrint(("\tHive=%08lx NewSize=%08lx\n",Hive,NewSize)); 00422 } 00423 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00424 ASSERT(Hive->ReadOnly == FALSE); 00425 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 00426 00427 // 00428 // Make room for overhead fields and round up to HCELL_PAD boundary 00429 // 00430 if (USE_OLD_CELL(Hive)) { 00431 NewSize += FIELD_OFFSET(HCELL, u.OldCell.u.UserData); 00432 } else { 00433 NewSize += FIELD_OFFSET(HCELL, u.NewCell.u.UserData); 00434 } 00435 NewSize = ROUND_UP(NewSize, HCELL_PAD(Hive)); 00436 00437 // 00438 // Adjust the size (an easy fix for granularity) 00439 // 00440 HvpAdjustCellSize(NewSize); 00441 // 00442 // reject impossible/unreasonable values 00443 // 00444 if (NewSize > HSANE_CELL_MAX) { 00445 return HCELL_NIL; 00446 } 00447 00448 // 00449 // Do the actual storage allocation 00450 // 00451 NewCell = HvpDoAllocateCell(Hive, NewSize, Type); 00452 00453 #if DBG 00454 if (NewCell != HCELL_NIL) { 00455 ASSERT(HvIsCellAllocated(Hive, NewCell)); 00456 } 00457 #endif 00458 00459 CMLOG(CML_FLOW, CMS_HIVE) {

ULONG HvCheckBin PHHIVE  Hive,
PHBIN  Bin,
PULONG  Storage
 

Definition at line 175 of file hivechek.c.

References Bin, HBIN_NIL, Hive, HvCheckBinDebug, L, _HBIN::Size, and USE_OLD_CELL.

Referenced by HvCheckHive().

00182 : 00183 00184 Step through all of the cells in the bin. Make sure that 00185 they are consistent with each other, and with the bin header. 00186 00187 Arguments: 00188 00189 Hive - pointer to the hive control structure 00190 00191 Bin - pointer to bin to check 00192 00193 Storage - pointer to a ulong to get allocated user data size 00194 00195 Return Value: 00196 00197 0 if Bin is OK. Number of test in procedure that failed if not. 00198 00199 RANGE: 1 - 1999 00200 00201 --*/ 00202 { 00203 PHCELL p; 00204 PHCELL np; 00205 PHCELL lp; 00206 ULONG freespace = 0L; 00207 ULONG allocated = 0L; 00208 ULONG userallocated = 0L; 00209 00210 HvCheckBinDebug.Bin = Bin; 00211 HvCheckBinDebug.Status = 0; 00212 HvCheckBinDebug.CellPoint = 0; 00213 00214 // 00215 // Scan all the cells in the bin, total free and allocated, check 00216 // for impossible pointers. 00217 // 00218 p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN)); 00219 lp = p; 00220 00221 // DRAGOS: 00222 // The way allocated and freespace are computed implies the following invariants: 00223 // 1. allocated + freespace = p + p->Size - (Bin + sizeof(HBIN)). This is because p->Size is added either to allocated or to freespace. 00224 // So, assuming that allocated > Bin->Size , then 00225 // ==> p + p->Size - (Bin + sizeof(HBIN)) > Bin->Size. 00226 // ==> p + p->Size > Bin + Bin->Size + sizeof(HBIN) 00227 // ==> p + p->Size > Bin + Bin->Size 00228 // This proves that the test "NeverFail 1" (see bellow) will never fail, because when something is wrong, the test above it (namely "Fail 1") will fail 00229 // and the function will exit. 00230 // 00231 // The same logic applies to the test "NeverFail 2", so it can be removed also. 00232 // 00233 // 2. The new value of p is always calculated as p = p + p->Size. By the time this is done, the new value of p (ie. p + p->Size) is already checked against 00234 // Bin + Bin->Size (see tests "Fail 1" and "Fail 2"). So, if p > Bin + Bin->Size, either "Fail 1" or "Fail 2" will fail before asigning the new bogus value 00235 // to p. Therefore, the only possible path to exit the while loop (except a return 20 or return 40), is when p == Bin + Bin->Size. 00236 // ==> test "NeverFail 3" can be removed as it will never fail ! 00237 // 00238 // 3. Considering 1 (where p + p->Size became p) 00239 // ==> allocated + freespace = p - (Bin + sizeof(HBIN)) 00240 // But, Considering 2 (above), when the while loop exits, p = Bin + Bin->Size 00241 // ==> allocated + freespace = Bin + Bin->Size - (Bin + sizeof(HBIN)) 00242 // ==> allocated + freespace + sizeof(HBIN) = Bin->Size 00243 // This proves that test "NeverFail 4" (see bellow) will never fail as the expresion tested is always true (if the flow of execution reaches the test point). 00244 // 00245 00246 while (p < (PHCELL)((PUCHAR)Bin + Bin->Size)) { 00247 00248 // 00249 // Check last pointer 00250 // 00251 if (USE_OLD_CELL(Hive)) { 00252 if (lp == p) { 00253 if (p->u.OldCell.Last != HBIN_NIL) { 00254 KdPrint(("HvCheckBin 20: First cell has wrong last pointer\n")); 00255 KdPrint(("Bin = %08lx\n", Bin)); 00256 HvCheckBinDebug.Status = 20; 00257 HvCheckBinDebug.CellPoint = p; 00258 return 20; 00259 } 00260 } else { 00261 if ((PHCELL)(p->u.OldCell.Last + (PUCHAR)Bin) != lp) { 00262 KdPrint(("HvCheckBin 30: incorrect last pointer\n")); 00263 KdPrint(("Bin = %08lx\n", Bin)); 00264 KdPrint(("p = %08lx\n", (ULONG_PTR)p)); 00265 HvCheckBinDebug.Status = 30; 00266 HvCheckBinDebug.CellPoint = p; 00267 return 30; 00268 } 00269 } 00270 } 00271 00272 00273 // 00274 // Check size 00275 // 00276 if (p->Size < 0) { 00277 00278 // 00279 // allocated cell 00280 // 00281 00282 // DRAGOS: Fail 1 00283 // This test will alway fail prior to the failure of the bellow test 00284 // 00285 if ( ((ULONG)(p->Size * -1) > Bin->Size) || 00286 ( (PHCELL)((p->Size * -1) + (PUCHAR)p) > 00287 (PHCELL)((PUCHAR)Bin + Bin->Size) ) 00288 ) 00289 { 00290 KdPrint(("HvCheckBin 40: impossible allocation\n")); 00291 KdPrint(("Bin = %08lx\n", Bin)); 00292 HvCheckBinDebug.Status = 40; 00293 HvCheckBinDebug.CellPoint = p; 00294 return 40; 00295 } 00296 00297 allocated += (p->Size * -1); 00298 if (USE_OLD_CELL(Hive)) { 00299 userallocated += (p->Size * -1) - FIELD_OFFSET(HCELL, u.OldCell.u.UserData); 00300 } else { 00301 userallocated += (p->Size * -1) - FIELD_OFFSET(HCELL, u.NewCell.u.UserData); 00302 } 00303 00304 // 00305 // DRAGOS: NeverFail 1 00306 // This test will never fail. If a size is wrong the above test (Fail 1)will fail. We can remove this test (it's useless). 00307 // 00308 if (allocated > Bin->Size) { 00309 KdPrint(("HvCheckBin 50: allocated exceeds available\n")); 00310 KdPrint(("Bin = %08lx\n", Bin)); 00311 HvCheckBinDebug.Status = 50; 00312 HvCheckBinDebug.CellPoint = p; 00313 return 50; 00314 } 00315 00316 np = (PHCELL)((PUCHAR)p + (p->Size * -1)); 00317 00318 00319 00320 } else { 00321 00322 // 00323 // free cell 00324 // 00325 00326 // DRAGOS: Fail 2 00327 // This test will alway fail prior to the failure of the bellow test 00328 // 00329 if ( ((ULONG)p->Size > Bin->Size) || 00330 ( (PHCELL)(p->Size + (PUCHAR)p) > 00331 (PHCELL)((PUCHAR)Bin + Bin->Size) ) || 00332 (p->Size == 0) ) 00333 { 00334 KdPrint(("HvCheckBin 60: impossible free block\n")); 00335 KdPrint(("Bin = %08lx\n", Bin)); 00336 HvCheckBinDebug.Status = 60; 00337 HvCheckBinDebug.CellPoint = p; 00338 return 60; 00339 } 00340 00341 freespace = freespace + p->Size; 00342 00343 // 00344 // DRAGOS: NeverFail 2 00345 // This test will never fail. If a size is wrong the above test (Fail 2) will fail. We can remove this test (it's useless). 00346 // 00347 if (freespace > Bin->Size) { 00348 KdPrint(("HvCheckBin 70: free exceeds available\n")); 00349 KdPrint(("Bin = %08lx\n", Bin)); 00350 HvCheckBinDebug.Status = 70; 00351 HvCheckBinDebug.CellPoint = p; 00352 return 70; 00353 } 00354 00355 np = (PHCELL)((PUCHAR)p + p->Size); 00356 00357 } 00358 00359 lp = p; 00360 p = np; 00361 } 00362 00363 // DRAGOS: NeverFail 4 00364 // This test never fails. If the while loop exits, the condition tested here is always true!!! 00365 // We can remove this test (it's useless) 00366 // 00367 if ((freespace + allocated + sizeof(HBIN)) != Bin->Size) { 00368 KdPrint(("HvCheckBin 995: sizes do not add up\n")); 00369 KdPrint(("Bin = %08lx\n", Bin)); 00370 KdPrint(("freespace = %08lx ", freespace)); 00371 KdPrint(("allocated = %08lx ", allocated)); 00372 KdPrint(("size = %08lx\n", Bin->Size)); 00373 HvCheckBinDebug.Status = 995; 00374 return 995; 00375 } 00376 00377 // DRAGOS: NeverFail 3 00378 // This test never fails. The only way out of the while loop is when p == Bin + Bin->Size !!!!!!! 00379 // We can remove this test (it's useless) 00380 // 00381 if (p != (PHCELL)((PUCHAR)Bin + Bin->Size)) { 00382 KdPrint(("HvCheckBin 1000: last cell points off the end\n")); 00383 KdPrint(("Bin = %08lx\n", Bin)); 00384 HvCheckBinDebug.Status = 1000; 00385 return 1000; 00386 } 00387 00388 if (ARGUMENT_PRESENT(Storage)) { 00389 *Storage += userallocated; 00390 } 00391 return 0; 00392 } }

ULONG HvCheckHive PHHIVE  Hive,
PULONG Storage  OPTIONAL
 

Definition at line 54 of file hivechek.c.

References Bin, _HBIN::FileOffset, HBIN_SIGNATURE, HCELL_INDEX, HCELL_NIL, Hive, HMAP_BASE, HMAP_DISCARDABLE, HvCheckBin(), HvCheckHiveDebug, HvpGetCellMap(), NULL, _HBIN::Signature, _HBIN::Size, _FREE_HBIN::Size, t(), and Volatile.

Referenced by CmCheckRegistry(), and HvRefreshHive().

00060 : 00061 00062 Check the consistency of a hive. Apply CheckBin to bins, make sure 00063 all pointers in the cell map point to correct places. 00064 00065 Arguments: 00066 00067 Hive - supplies a pointer to the hive control structure for the 00068 hive of interest. 00069 00070 Storage - supplies adddress of ULONG to receive size of allocated user data 00071 00072 Return Value: 00073 00074 0 if Hive is OK. Error return indicator if not. Error value 00075 comes from one of the check procedures. 00076 00077 RANGE: 2000 - 2999 00078 00079 --*/ 00080 { 00081 HCELL_INDEX p; 00082 ULONG Length; 00083 ULONG localstorage = 0; 00084 PHMAP_ENTRY t; 00085 PHBIN Bin; 00086 ULONG i; 00087 ULONG rc; 00088 PFREE_HBIN FreeBin; 00089 00090 HvCheckHiveDebug.Hive = Hive; 00091 HvCheckHiveDebug.Status = 0; 00092 HvCheckHiveDebug.Space = (ULONG)-1; 00093 HvCheckHiveDebug.MapPoint = HCELL_NIL; 00094 HvCheckHiveDebug.BinPoint = 0; 00095 00096 p = 0; 00097 00098 00099 // 00100 // one pass for Stable space, one pass for Volatile 00101 // 00102 for (i = 0; i <= Volatile; i++) { 00103 Length = Hive->Storage[i].Length; 00104 00105 // 00106 // for each bin in the space 00107 // 00108 while (p < Length) { 00109 t = HvpGetCellMap(Hive, p); 00110 if (t == NULL) { 00111 KdPrint(("HvCheckHive:")); 00112 KdPrint(("\tBin@:%08lx invalid\n", Bin)); 00113 HvCheckHiveDebug.Status = 2005; 00114 HvCheckHiveDebug.Space = i; 00115 HvCheckHiveDebug.MapPoint = p; 00116 return 2005; 00117 } 00118 00119 00120 if ((t->BinAddress & HMAP_DISCARDABLE) == 0) { 00121 00122 Bin = (PHBIN)((t->BinAddress) & HMAP_BASE); 00123 00124 // 00125 // bin header valid? 00126 // 00127 if ( (Bin->Size > Length) || 00128 (Bin->Signature != HBIN_SIGNATURE) || 00129 (Bin->FileOffset != p) 00130 ) 00131 { 00132 KdPrint(("HvCheckHive:")); 00133 KdPrint(("\tBin@:%08lx invalid\n", Bin)); 00134 HvCheckHiveDebug.Status = 2010; 00135 HvCheckHiveDebug.Space = i; 00136 HvCheckHiveDebug.MapPoint = p; 00137 HvCheckHiveDebug.BinPoint = Bin; 00138 return 2010; 00139 } 00140 00141 // 00142 // structure inside the bin valid? 00143 // 00144 rc = HvCheckBin(Hive, Bin, &localstorage); 00145 if (rc != 0) { 00146 HvCheckHiveDebug.Status = rc; 00147 HvCheckHiveDebug.Space = i; 00148 HvCheckHiveDebug.MapPoint = p; 00149 HvCheckHiveDebug.BinPoint = Bin; 00150 return rc; 00151 } 00152 00153 p = (ULONG)p + Bin->Size; 00154 00155 } else { 00156 // 00157 // Bin is not present, skip it and advance to the next one. 00158 // 00159 FreeBin = (PFREE_HBIN)t->BlockAddress; 00160 p+=FreeBin->Size; 00161 } 00162 } 00163 00164 p = 0x80000000; // Beginning of Volatile space 00165 } 00166 00167 if (ARGUMENT_PRESENT(Storage)) { 00168 *Storage = localstorage; 00169 } 00170 return 0; 00171 }

VOID HvFreeCell PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 688 of file hivecell.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Bin, _HMAP_ENTRY::BinAddress, Cell, CML_MINOR, CMLOG, CMS_HIVE, DHvCheckBin, FALSE, _HBIN::FileOffset, HCELL_FREE_FILL, HCELL_INDEX, HCELL_TYPE_MASK, Hive, HMAP_BASE, HvGetCellType, HvpEnlistFreeCell(), HvpGetCellMap(), HvpGetHCell, HvpIsFreeNeighbor(), NULL, _HHIVE::ReadOnly, _HCELL::Size, _HBIN::Size, TRUE, _HCELL::u, USE_OLD_CELL, VALIDATE_CELL_MAP, and VOID().

Referenced by CmDeleteValueKey(), CmpAddSubKey(), CmpAssignSecurityDescriptor(), CmpCopyKeyPartial(), CmpCopyValue(), CmpCreateLinkNode(), CmpDoCreateChild(), CmpFreeKeyBody(), CmpFreeKeyByCell(), CmpFreeKeyValues(), CmpFreeSecurityDescriptor(), CmpFreeValue(), CmpMergeKeyValues(), CmpRemoveSubKey(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), and CmpSyncKeyValues().

00699 : 00700 00701 00702 Frees the storage for a cell. 00703 00704 NOTE: CALLER is expected to mark relevent data dirty, so as to 00705 allow this call to always succeed. 00706 00707 Arguments: 00708 00709 Hive - supplies a pointer to the hive control structure for the 00710 hive of interest 00711 00712 Cell - HCELL_INDEX of Cell to free. 00713 00714 Return Value: 00715 00716 FALSE - failed, presumably for want of log space. 00717 00718 TRUE - it worked 00719 00720 --*/ 00721 { 00722 PHBIN Bin; 00723 PHCELL tmp; 00724 HCELL_INDEX newfreecell; 00725 PHCELL freebase; 00726 ULONG savesize; 00727 PHCELL neighbor; 00728 ULONG Type; 00729 PHMAP_ENTRY Me; 00730 00731 00732 CMLOG(CML_MINOR, CMS_HIVE) { 00733 KdPrint(("HvFreeCell:\n")); 00734 KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell)); 00735 } 00736 ASSERT(Hive->ReadOnly == FALSE); 00737 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 00738 00739 // 00740 // Get sizes and addresses 00741 // 00742 Me = HvpGetCellMap(Hive, Cell); 00743 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Cell); 00744 Type = HvGetCellType(Cell); 00745 00746 Bin = (PHBIN)((Me->BinAddress) & HMAP_BASE); 00747 DHvCheckBin(Hive,Bin); 00748 00749 freebase = HvpGetHCell(Hive, Cell); 00750 00751 // 00752 // go do actual frees, cannot fail from this point on 00753 // 00754 ASSERT(freebase->Size < 0); 00755 freebase->Size *= -1; 00756 00757 savesize = freebase->Size; 00758 00759 // 00760 // Look for free neighbors and coalesce them. We will never travel 00761 // around this loop more than twice. 00762 // 00763 while ( 00764 HvpIsFreeNeighbor( 00765 Hive, 00766 Bin, 00767 freebase, 00768 &neighbor, 00769 Type 00770 ) == TRUE 00771 ) 00772 { 00773 00774 if (neighbor > freebase) { 00775 00776 // 00777 // Neighboring free cell is immediately above us in memory. 00778 // 00779 if (USE_OLD_CELL(Hive)) { 00780 tmp = (PHCELL)((PUCHAR)neighbor + neighbor->Size); 00781 if ( ((ULONG)((ULONG_PTR)tmp - (ULONG_PTR)Bin)) < Bin->Size) { 00782 tmp->u.OldCell.Last = (ULONG)((ULONG_PTR)freebase - (ULONG_PTR)Bin); 00783 } 00784 } 00785 freebase->Size += neighbor->Size; 00786 00787 } else { 00788 00789 // 00790 // Neighboring free cell is immediately below us in memory. 00791 // 00792 00793 if (USE_OLD_CELL(Hive)) { 00794 tmp = (PHCELL)((PUCHAR)freebase + freebase->Size); 00795 if ( ((ULONG)((ULONG_PTR)tmp - (ULONG_PTR)Bin)) < Bin->Size ) { 00796 tmp->u.OldCell.Last = (ULONG)((ULONG_PTR)neighbor - (ULONG_PTR)Bin); 00797 } 00798 } 00799 neighbor->Size += freebase->Size; 00800 freebase = neighbor; 00801 } 00802 } 00803 00804 // 00805 // freebase now points to the biggest free cell we could make, none 00806 // of which is on the free list. So put it on the list. 00807 // 00808 newfreecell = (Bin->FileOffset) + 00809 ((ULONG)((ULONG_PTR)freebase - (ULONG_PTR)Bin)) + 00810 (Type*HCELL_TYPE_MASK); 00811 00812 ASSERT(HvpGetHCell(Hive, newfreecell) == freebase); 00813 00814 #if DBG 00815 if (USE_OLD_CELL(Hive)) { 00816 RtlFillMemory( 00817 &(freebase->u.OldCell.u.UserData), 00818 (freebase->Size - FIELD_OFFSET(HCELL, u.OldCell.u.UserData)), 00819 HCELL_FREE_FILL 00820 ); 00821 } else { 00822 RtlFillMemory( 00823 &(freebase->u.NewCell.u.UserData), 00824 (freebase->Size - FIELD_OFFSET(HCELL, u.NewCell.u.UserData)), 00825 HCELL_FREE_FILL 00826 ); 00827 } 00828 #endif

VOID HvFreeHive PHHIVE  Hive  ) 
 

Definition at line 34 of file hivefree.c.

References ASSERT, _HHIVE::BaseBlock, Bin, _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, CML_BIN, CMLOG, CmpFree(), CMS_BIN_MAP, _HHIVE::DirtyAlloc, _HHIVE::DirtyVector, FALSE, _HBASE_BLOCK::FileName, _FREE_HBIN::Flags, _HHIVE::Flat, _HHIVE::Free, FREE_HBIN_DISCARDABLE, HBLOCK_SIZE, HCELL_INDEX, HCELL_TYPE_MASK, Hive, HMAP_BASE, HMAP_DISCARDABLE, HMAP_NEWALLOC, HTABLE_SLOTS, HvpFreeMap(), HvpGetCellMap(), _HBIN::MemAlloc, NULL, _HHIVE::ReadOnly, _FREE_HBIN::Size, Stable, VALIDATE_CELL_MAP, and Volatile.

Referenced by CmpDestroyTemporaryHive(), CmpInitializeHive(), CmpValidateAlternate(), CmReplaceKey(), and CmUnloadKey().

00039 : 00040 00041 Free all of the pieces of a hive. 00042 00043 Arguments: 00044 00045 Hive - supplies a pointer to hive control structure for hive to free. 00046 this structure itself will NOT be freed, but everything it 00047 points to will. 00048 00049 Return Value: 00050 00051 NONE. 00052 00053 --*/ 00054 { 00055 PHMAP_DIRECTORY Dir; 00056 PHMAP_ENTRY Me; 00057 HCELL_INDEX Address; 00058 ULONG Type; 00059 ULONG Length; 00060 PHBIN Bin; 00061 ULONG Tables; 00062 PFREE_HBIN FreeBin; 00063 00064 ASSERT(Hive->Flat == FALSE); 00065 ASSERT(Hive->ReadOnly == FALSE); 00066 ASSERT(Stable == 0); 00067 ASSERT(Volatile == 1); 00068 00069 CMLOG(CML_BIN, CMS_BIN_MAP) { 00070 KdPrint(("HvFreeHive(%ws) :\n", Hive->BaseBlock->FileName)); 00071 } 00072 // 00073 // Iterate through both types of storage 00074 // 00075 for (Type = 0; Type <= Volatile; Type++) { 00076 00077 Address = HCELL_TYPE_MASK * Type; 00078 Length = Hive->Storage[Type].Length + (HCELL_TYPE_MASK * Type); 00079 00080 if (Length > (HCELL_TYPE_MASK * Type)) { 00081 00082 // 00083 // Sweep through bin set 00084 // 00085 do { 00086 Me = HvpGetCellMap(Hive, Address); 00087 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address); 00088 if (Me->BinAddress & HMAP_DISCARDABLE) { 00089 // 00090 // hbin is either discarded or discardable, check the tombstone 00091 // 00092 FreeBin = (PFREE_HBIN)Me->BlockAddress; 00093 Address += FreeBin->Size; 00094 if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { 00095 CmpFree((PHBIN)(Me->BinAddress & HMAP_BASE), FreeBin->Size); 00096 } 00097 CmpFree(FreeBin, sizeof(FREE_HBIN)); 00098 } else { 00099 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00100 Address += Bin->MemAlloc; 00101 #if DBG 00102 // 00103 // Make sure that the next bin in the list is 00104 // actually the start of an alloc before freeing it 00105 // 00106 if (Address < Length) { 00107 Me = HvpGetCellMap(Hive, Address); 00108 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address); 00109 ASSERT(Me->BinAddress & HMAP_NEWALLOC); 00110 } 00111 #endif 00112 00113 CMLOG(CML_BIN, CMS_BIN_MAP) { 00114 if( Type == Stable ) { 00115 KdPrint(("HvFreeHive: BinAddress = 0x%08lx\t Size = 0x%lx\n", Bin, Bin->MemAlloc)); 00116 } 00117 } 00118 00119 CmpFree(Bin, Bin->MemAlloc); 00120 } 00121 00122 } while (Address < Length); 00123 00124 // 00125 // Free map table storage 00126 // 00127 ASSERT(Hive->Storage[Type].Length != (HCELL_TYPE_MASK * Type)); 00128 Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE)-1) / HTABLE_SLOTS; 00129 Dir = Hive->Storage[Type].Map; 00130 HvpFreeMap(Hive, Dir, 0, Tables); 00131 00132 if (Tables > 0) { 00133 CmpFree(Hive->Storage[Type].Map, sizeof(HMAP_DIRECTORY)); // free dir if it exists 00134 } 00135 } 00136 Hive->Storage[Type].Length = 0; 00137 } 00138 00139 CMLOG(CML_BIN, CMS_BIN_MAP) { 00140 KdPrint(("\n")); 00141 } 00142 // 00143 // Free the base block 00144 // 00145 (Hive->Free)(Hive->BaseBlock, sizeof(HBASE_BLOCK)); 00146 Hive->BaseBlock = NULL; 00147 00148 // 00149 // Free the dirty vector 00150 // 00151 if (Hive->DirtyVector.Buffer != NULL) { 00152 CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc); 00153 } 00154 00155 return; 00156 }

VOID HvFreeHivePartial PHHIVE  Hive,
HCELL_INDEX  Start,
HSTORAGE_TYPE  Type
 

Definition at line 160 of file hivefree.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, CmpFree(), CmpReleaseGlobalQuota(), _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _FREE_HBIN::Flags, _HHIVE::Flat, FREE_HBIN_DISCARDABLE, HBLOCK_SIZE, HCELL_INDEX, HCELL_TYPE_MASK, Hive, HMAP_BASE, HMAP_DISCARDABLE, HSECTOR_SIZE, HTABLE_SLOTS, HvpFreeMap(), HvpGetCellMap(), _FREE_HBIN::ListEntry, _HBIN::MemAlloc, _HHIVE::ReadOnly, RtlClearBits(), RtlNumberOfSetBits(), _FREE_HBIN::Size, Stable, Start, and VALIDATE_CELL_MAP.

Referenced by HvpTruncateBins(), and HvRefreshHive().

00167 : 00168 00169 Free the memory and associated maps for the end of a hive 00170 starting at Start. The baseblock, hive, etc will not be touched. 00171 00172 Arguments: 00173 00174 Hive - supplies a pointer to hive control structure for hive to 00175 partially free. 00176 00177 Start - HCELL_INDEX of first bin to free, will free from this 00178 bin (inclusive) to the end of the hives stable storage. 00179 00180 Type - Type of storage (Stable or Volatile) to be freed. 00181 00182 Return Value: 00183 00184 NONE. 00185 00186 --*/ 00187 { 00188 PHMAP_DIRECTORY Dir; 00189 PHMAP_ENTRY Me; 00190 HCELL_INDEX Address; 00191 ULONG StartTable; 00192 ULONG Length; 00193 PHBIN Bin; 00194 ULONG Tables; 00195 ULONG FirstBit; 00196 ULONG LastBit; 00197 PFREE_HBIN FreeBin; 00198 00199 ASSERT(Hive->Flat == FALSE); 00200 ASSERT(Hive->ReadOnly == FALSE); 00201 00202 Address = Start; 00203 Length = Hive->Storage[Type].Length; 00204 ASSERT(Address <= Length); 00205 00206 if (Address == Length) { 00207 return; 00208 } 00209 00210 // 00211 // Sweep through bin set 00212 // 00213 do { 00214 Me = HvpGetCellMap(Hive, Address + (Type*HCELL_TYPE_MASK)); 00215 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address + (Type*HCELL_TYPE_MASK)); 00216 if (Me->BinAddress & HMAP_DISCARDABLE) { 00217 FreeBin = (PFREE_HBIN)Me->BlockAddress; 00218 if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { 00219 CmpFree((PVOID)(Me->BinAddress & HMAP_BASE), FreeBin->Size); 00220 } else { 00221 // 00222 // The bin has been freed, but quota is still charged. 00223 // Since the file will now shrink, the quota must be 00224 // returned here. 00225 // 00226 CmpReleaseGlobalQuota(FreeBin->Size); 00227 } 00228 RemoveEntryList(&FreeBin->ListEntry); 00229 Address += FreeBin->Size; 00230 CmpFree(FreeBin, sizeof(FREE_HBIN)); 00231 00232 } else { 00233 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00234 00235 Address += Bin->MemAlloc; 00236 CmpFree(Bin, Bin->MemAlloc); 00237 } 00238 } while (Address < Length); 00239 00240 // 00241 // Free map table storage 00242 // 00243 Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE) - 1) / HTABLE_SLOTS; 00244 Dir = Hive->Storage[Type].Map; 00245 if (Start > 0) { 00246 StartTable = ((Start-1) / HBLOCK_SIZE) / HTABLE_SLOTS; 00247 } else { 00248 StartTable = (ULONG)-1; 00249 } 00250 HvpFreeMap(Hive, Dir, StartTable+1, Tables); 00251 00252 Hive->Storage[Type].Length = Start; 00253 00254 if (Type==Stable) { 00255 // 00256 // Clear dirty vector for data past Hive->Storage[Stable].Length 00257 // 00258 FirstBit = Start / HSECTOR_SIZE; 00259 LastBit = Hive->DirtyVector.SizeOfBitMap; 00260 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00261 RtlClearBits(&Hive->DirtyVector, FirstBit, LastBit-FirstBit); 00262 Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector); 00263 } 00264 00265 return; 00266 } }

LONG HvGetCellSize PHHIVE  Hive,
PVOID  Address
 

NTSTATUS HvInitializeHive PHHIVE  Hive,
ULONG  OperationType,
ULONG  HiveFlags,
ULONG  FileTypes,
PVOID HiveData  OPTIONAL,
PALLOCATE_ROUTINE  AllocateRoutine,
PFREE_ROUTINE  FreeRoutine,
PFILE_SET_SIZE_ROUTINE  FileSetSizeRoutine,
PFILE_WRITE_ROUTINE  FileWriteRoutine,
PFILE_READ_ROUTINE  FileReadRoutine,
PFILE_FLUSH_ROUTINE  FileFlushRoutine,
ULONG  Cluster,
PUNICODE_STRING  FileName
 

Definition at line 158 of file hiveinit.c.

References _HHIVE::Allocate, _HHIVE::Alternate, _HHIVE::BaseBlock, _HBASE_BLOCK::CheckSum, _HHIVE::Cluster, _HBASE_BLOCK::Cluster, CML_BIN, CML_MAJOR, CMLOG, CmpReleaseGlobalQuota(), CMS_BIN_MAP, CMS_INIT, _HHIVE::DirtyAlloc, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HHIVE::FileFlush, FileName, _HHIVE::FileRead, _HHIVE::FileSetSize, _HHIVE::FileWrite, _HHIVE::Flat, _HBASE_BLOCK::Format, _HHIVE::Free, _HHIVE::GetCellRoutine, HBASE_BLOCK_SIGNATURE, HBASE_FORMAT_MEMORY, HBLOCK_SIZE, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_ALTERNATE, HFILE_TYPE_LOG, HFILE_TYPE_PRIMARY, HHIVE_FREE_DISPLAY_SIZE, HHIVE_SIGNATURE, HINIT_CREATE, HINIT_FILE, HINIT_FLAT, HINIT_MEMORY, HINIT_MEMORY_INPLACE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HSECTOR_COUNT, HSECTOR_SIZE, HSYS_MAJOR, HSYS_MINOR, HTYPE_COUNT, HvLoadHive(), HvpBuildMap(), HvpBuildMapAndCopy(), HvpDoWriteHive(), HvpDumpFreeDisplay, HvpFillFileName(), HvpFreeAllocatedBins(), HvpGetCellFlat(), HvpGetCellPaged(), HvpHeaderCheckSum(), _HBASE_BLOCK::Length, _HHIVE::Log, _HHIVE::LogSize, _HBASE_BLOCK::Major, _HBASE_BLOCK::Minor, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _HHIVE::ReadOnly, _HHIVE::RefreshCount, _HBASE_BLOCK::RootCell, RtlClearAllBits(), RtlInitializeBitMap(), RtlSetAllBits(), _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HHIVE::Signature, _HBASE_BLOCK::Signature, Stable, Status, _HHIVE::StorageTypeCount, _HBASE_BLOCK::TimeStamp, TRUE, _HBASE_BLOCK::Type, _HHIVE::Version, and Volatile.

Referenced by CmGetSystemControlValues(), and CmpInitializeHive().

00175 : 00176 00177 Initialize a hive. 00178 00179 Core HHive fields are always inited. 00180 00181 File calls WILL be made BEFORE this call returns. 00182 00183 Caller is expected to create/open files and store file handles 00184 in a way that can be derived from the hive pointer. 00185 00186 Three kinds of initialization can be done, selected by OperationType: 00187 00188 HINIT_CREATE 00189 00190 Create a new hive from scratch. Will have 0 storage. 00191 [Used to do things like create HARDWARE hive and for parts 00192 of SaveKey and RestoreKey] 00193 00194 00195 HINIT_MEMORY_INPLACE 00196 00197 Build a hive control structure which allows read only 00198 access to a contiguous in-memory image of a hive. 00199 No part of the image will be copied, but a map will 00200 be made. 00201 [Used by osloader.] 00202 00203 00204 HINIT_FLAT 00205 00206 Support very limited (read-only, no checking code) operation 00207 against a hive image. 00208 00209 00210 HINIT_MEMORY 00211 00212 Create a new hive, using a hive image already in memory, 00213 at address supplied by pointer HiveData. The data will 00214 be copied. Caller is expected to free HiveData. 00215 [Used for SYSTEM hive] 00216 00217 00218 HINIT_FILE 00219 00220 Create a hive, reading its data from a file. Recovery processing 00221 via log file will be done if a log is available. If a log 00222 is recovered, flush and clear operation will proceed. 00223 00224 00225 NOTE: The HHive is not a completely opaque structure, because it 00226 is really only used by a limited set of code. Do not assume 00227 that only this routine sets all of these values. 00228 00229 00230 Arguments: 00231 00232 Hive - supplies a pointer to hive control structure to be initialized 00233 to describe this hive. 00234 00235 OperationType - specifies whether to create a new hive from scratch, 00236 from a memory image, or by reading a file from disk. 00237 00238 HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless 00239 of the types of cells allocated 00240 HIVE_NO_LAZY_FLUSH - Data in this hive is never written 00241 to disk except by an explicit FlushKey 00242 00243 FileType - HFILE_TYPE_*, HFILE_TYPE_LOG or HFILE_TYPE_ALTERNATE set 00244 up for logging or alternate support respectively. 00245 00246 HiveData - if present, supplies a pointer to an in memory image of 00247 from which to init the hive. Only useful when OperationType 00248 is set to HINIT_MEMORY. 00249 00250 AllocateRoutine - supplies a pointer to routine called to allocate 00251 memory. WILL be called before this routine returns. 00252 00253 FreeRoutine - supplies a pointer to routine called to free memory. 00254 CAN be called before this routine returns. 00255 00256 FileSetSizeRoutine - supplies a pointer to a routine used to set the 00257 size of a file. CAN be called before this 00258 routine returns. 00259 00260 FileWriteRoutine - supplies a pointer to routine called to write memory 00261 to a file. 00262 00263 FileReadRoutine - supplies a pointer to routine called to read from 00264 a file into memory. CAN be called before this 00265 routine returns. 00266 00267 FileFlushRoutine - supplies a pointer to routine called to flush a file. 00268 00269 Cluster - clustering factor in HSECTOR_SIZE units. (i.e. Size of 00270 physical sector in media / HSECTOR_SIZE. 1 for 512 byte 00271 physical sectors (or smaller), 2 for 1024, 4 for 2048, etc. 00272 (Numbers greater than 8 won't work.) 00273 00274 FileName - some path like "...\system32\config\system", last 00275 32 or so characters will be copied into baseblock 00276 (and thus to disk) as a debugging aid. May be null. 00277 00278 00279 Return Value: 00280 00281 NTSTATUS code. 00282 00283 --*/ 00284 { 00285 BOOLEAN UseForIo; 00286 PHBASE_BLOCK BaseBlock = NULL; 00287 NTSTATUS Status; 00288 NTSTATUS Status2; 00289 PVOID Image; 00290 ULONG i; 00291 PHBIN Pbin; 00292 ULONG Alignment; 00293 00294 // 00295 // this array stores the last elements in each free cell list for the stable storage 00296 // 00297 HCELL_INDEX TailDisplay[HHIVE_FREE_DISPLAY_SIZE]; 00298 00299 CMLOG(CML_MAJOR, CMS_INIT) { 00300 KdPrint(("HvInitializeHive:\n")); 00301 KdPrint(("\tHive=%08lx\n", Hive)); 00302 } 00303 00304 // 00305 // reject invalid parameter combinations 00306 // 00307 if ( (! ARGUMENT_PRESENT(HiveData)) && 00308 ((OperationType == HINIT_MEMORY) || 00309 (OperationType == HINIT_FLAT) || 00310 (OperationType == HINIT_MEMORY_INPLACE)) 00311 ) 00312 { 00313 return STATUS_INVALID_PARAMETER; 00314 } 00315 00316 if ( ! ((OperationType == HINIT_CREATE) || 00317 (OperationType == HINIT_MEMORY) || 00318 (OperationType == HINIT_MEMORY_INPLACE) || 00319 (OperationType == HINIT_FLAT) || 00320 (OperationType == HINIT_FILE)) 00321 ) 00322 { 00323 return STATUS_INVALID_PARAMETER; 00324 } 00325 00326 00327 // 00328 // static and global control values 00329 // 00330 Hive->Signature = HHIVE_SIGNATURE; 00331 00332 Hive->Allocate = AllocateRoutine; 00333 Hive->Free = FreeRoutine; 00334 Hive->FileSetSize = FileSetSizeRoutine; 00335 Hive->FileWrite = FileWriteRoutine; 00336 Hive->FileRead = FileReadRoutine; 00337 Hive->FileFlush = FileFlushRoutine; 00338 00339 Hive->Log = (BOOLEAN)((FileType == HFILE_TYPE_LOG) ? TRUE : FALSE); 00340 Hive->Alternate = (BOOLEAN)((FileType == HFILE_TYPE_ALTERNATE) ? TRUE : FALSE); 00341 00342 if ((Hive->Log || Hive->Alternate) && (HiveFlags & HIVE_VOLATILE)) { 00343 return STATUS_INVALID_PARAMETER; 00344 } 00345 00346 Hive->HiveFlags = HiveFlags; 00347 00348 if ((Cluster == 0) || (Cluster > HSECTOR_COUNT)) { 00349 return STATUS_INVALID_PARAMETER; 00350 } 00351 Hive->Cluster = Cluster; 00352 00353 Hive->RefreshCount = 0; 00354 00355 Hive->StorageTypeCount = HTYPE_COUNT; 00356 00357 00358 Hive->Storage[Volatile].Length = 0; 00359 Hive->Storage[Volatile].Map = NULL; 00360 Hive->Storage[Volatile].SmallDir = NULL; 00361 Hive->Storage[Volatile].Guard = (ULONG)-1; 00362 Hive->Storage[Volatile].FreeSummary = 0; 00363 InitializeListHead(&Hive->Storage[Volatile].FreeBins); 00364 for (i = 0; i < HHIVE_FREE_DISPLAY_SIZE; i++) { 00365 Hive->Storage[Volatile].FreeDisplay[i] = HCELL_NIL; 00366 } 00367 00368 Hive->Storage[Stable].Length = 0; 00369 Hive->Storage[Stable].Map = NULL; 00370 Hive->Storage[Stable].SmallDir = NULL; 00371 Hive->Storage[Stable].Guard = (ULONG)-1; 00372 Hive->Storage[Stable].FreeSummary = 0; 00373 InitializeListHead(&Hive->Storage[Stable].FreeBins); 00374 for (i = 0; i < HHIVE_FREE_DISPLAY_SIZE; i++) { 00375 Hive->Storage[Stable].FreeDisplay[i] = HCELL_NIL; 00376 TailDisplay[i] = HCELL_NIL; 00377 } 00378 00379 RtlInitializeBitMap(&(Hive->DirtyVector), NULL, 0); 00380 Hive->DirtyCount = 0; 00381 Hive->DirtyAlloc = 0; 00382 Hive->LogSize = 0; 00383 00384 Hive->GetCellRoutine = HvpGetCellPaged; 00385 Hive->Flat = FALSE; 00386 Hive->ReadOnly = FALSE; 00387 UseForIo = (BOOLEAN)!(Hive->HiveFlags & HIVE_VOLATILE); 00388 00389 // 00390 // new create case 00391 // 00392 if (OperationType == HINIT_CREATE) { 00393 00394 BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(sizeof(HBASE_BLOCK), UseForIo)); 00395 if (BaseBlock == NULL) { 00396 return STATUS_INSUFFICIENT_RESOURCES; 00397 } 00398 // 00399 // Make sure the buffer we got back is cluster-aligned. If not, try 00400 // harder to get an aligned buffer. 00401 // 00402 Alignment = Cluster * HSECTOR_SIZE - 1; 00403 if (((ULONG_PTR)BaseBlock & Alignment) != 0) { 00404 (Hive->Free)(BaseBlock, sizeof(HBASE_BLOCK)); 00405 BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE)); 00406 if (BaseBlock == NULL) { 00407 return STATUS_INSUFFICIENT_RESOURCES; 00408 } 00409 00410 // 00411 // Return the quota for the extra allocation, as we are not really using 00412 // it and it will not be accounted for later when we free it. 00413 // 00414 CmpReleaseGlobalQuota(PAGE_SIZE - sizeof(HBASE_BLOCK)); 00415 } 00416 00417 BaseBlock->Signature = HBASE_BLOCK_SIGNATURE; 00418 BaseBlock->Sequence1 = 1; 00419 BaseBlock->Sequence2 = 1; 00420 BaseBlock->TimeStamp.HighPart = 0; 00421 BaseBlock->TimeStamp.LowPart = 0; 00422 BaseBlock->Major = HSYS_MAJOR; 00423 BaseBlock->Minor = HSYS_MINOR; 00424 BaseBlock->Type = HFILE_TYPE_PRIMARY; 00425 BaseBlock->Format = HBASE_FORMAT_MEMORY; 00426 BaseBlock->RootCell = HCELL_NIL; 00427 BaseBlock->Length = 0; 00428 BaseBlock->Cluster = Cluster; 00429 BaseBlock->CheckSum = 0; 00430 HvpFillFileName(BaseBlock, FileName); 00431 Hive->BaseBlock = BaseBlock; 00432 Hive->Version = HSYS_MINOR; 00433 00434 return STATUS_SUCCESS; 00435 } 00436 00437 // 00438 // flat image case 00439 // 00440 if (OperationType == HINIT_FLAT) { 00441 Hive->BaseBlock = (PHBASE_BLOCK)HiveData; 00442 Hive->Version = Hive->BaseBlock->Minor; 00443 Hive->Flat = TRUE; 00444 Hive->ReadOnly = TRUE; 00445 Hive->GetCellRoutine = HvpGetCellFlat; 00446 Hive->Storage[Stable].Length = Hive->BaseBlock->Length; 00447 Hive->StorageTypeCount = 1; 00448 return STATUS_SUCCESS; 00449 } 00450 00451 // 00452 // readonly image case 00453 // 00454 if (OperationType == HINIT_MEMORY_INPLACE) { 00455 BaseBlock = (PHBASE_BLOCK)HiveData; 00456 00457 if ( (BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) || 00458 (BaseBlock->Type != HFILE_TYPE_PRIMARY) || 00459 (BaseBlock->Major != HSYS_MAJOR) || 00460 (BaseBlock->Minor > HSYS_MINOR) || 00461 (BaseBlock->Format != HBASE_FORMAT_MEMORY) || 00462 (BaseBlock->Sequence1 != BaseBlock->Sequence2) || 00463 (HvpHeaderCheckSum(BaseBlock) != 00464 (BaseBlock->CheckSum)) 00465 ) 00466 { 00467 return STATUS_REGISTRY_CORRUPT; 00468 } 00469 00470 Hive->BaseBlock = BaseBlock; 00471 Hive->Version = BaseBlock->Minor; 00472 Hive->ReadOnly = TRUE; 00473 Hive->StorageTypeCount = 1; 00474 00475 if (FileType == HFILE_TYPE_ALTERNATE) { 00476 // 00477 // Mark the baseblock with Type==HFILE_TYPE_ALTERNATE. This 00478 // case will never show up on disk, because we always flush 00479 // Type==HFILE_TYPE_PRIMARY to the alternate file. Any 00480 // baseblock with Type==HFILE_TYPE_ALTERNATE indicates that 00481 // the primary is corrupt and must be rewritten. 00482 // 00483 BaseBlock->Type=HFILE_TYPE_ALTERNATE; 00484 00485 // 00486 // baseblock has changed, recompute the checksum. 00487 // 00488 BaseBlock->CheckSum=HvpHeaderCheckSum(BaseBlock); 00489 } 00490 00491 if ( !NT_SUCCESS(HvpBuildMap( 00492 Hive, 00493 (PUCHAR)HiveData + HBLOCK_SIZE, 00494 TailDisplay 00495 ))) 00496 { 00497 return STATUS_REGISTRY_CORRUPT; 00498 } 00499 00500 // debug-only 00501 HvpDumpFreeDisplay(Hive); 00502 00503 return(STATUS_SUCCESS); 00504 } 00505 00506 // 00507 // memory copy case 00508 // 00509 if (OperationType == HINIT_MEMORY) { 00510 BaseBlock = (PHBASE_BLOCK)HiveData; 00511 00512 if ( (BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) || 00513 ((BaseBlock->Type != HFILE_TYPE_PRIMARY) && 00514 (BaseBlock->Type != HFILE_TYPE_ALTERNATE)) || 00515 (BaseBlock->Format != HBASE_FORMAT_MEMORY) || 00516 (BaseBlock->Major != HSYS_MAJOR) || 00517 (BaseBlock->Minor > HSYS_MINOR) || 00518 (HvpHeaderCheckSum(BaseBlock) != 00519 (BaseBlock->CheckSum)) 00520 ) 00521 { 00522 return STATUS_REGISTRY_CORRUPT; 00523 } 00524 00525 Hive->BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(sizeof(HBASE_BLOCK), UseForIo)); 00526 if (Hive->BaseBlock==NULL) { 00527 return(STATUS_INSUFFICIENT_RESOURCES); 00528 } 00529 // 00530 // Make sure the buffer we got back is cluster-aligned. If not, try 00531 // harder to get an aligned buffer. 00532 // 00533 Alignment = Cluster * HSECTOR_SIZE - 1; 00534 if (((ULONG_PTR)Hive->BaseBlock & Alignment) != 0) { 00535 (Hive->Free)(Hive->BaseBlock, sizeof(HBASE_BLOCK)); 00536 Hive->BaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE)); 00537 if (Hive->BaseBlock == NULL) { 00538 return (STATUS_INSUFFICIENT_RESOURCES); 00539 } 00540 } 00541 RtlCopyMemory(Hive->BaseBlock, BaseBlock, HSECTOR_SIZE); 00542 00543 Hive->Version = Hive->BaseBlock->Minor; 00544 00545 if ( !NT_SUCCESS(HvpBuildMapAndCopy(Hive, 00546 (PUCHAR)HiveData + HBLOCK_SIZE, 00547 TailDisplay))) { 00548 00549 (Hive->Free)(Hive->BaseBlock, sizeof(HBASE_BLOCK)); 00550 Hive->BaseBlock = NULL; 00551 return STATUS_REGISTRY_CORRUPT; 00552 } 00553 00554 if (BaseBlock->Type == HFILE_TYPE_ALTERNATE) { 00555 // 00556 // Note that Type==HFILE_TYPE_ALTERNATE will NEVER occur in 00557 // an on-disk image. The only way this can show up in the 00558 // baseblock is when the osloader rejects the SYSTEM hive and 00559 // successfully loads SYSTEM.ALT. When this happens, it 00560 // forces HFILE_TYPE_ALTERNATE into the in-memory image of 00561 // the baseblock. 00562 // 00563 // We've booted from SYSTEM.ALT. Mark the whole hive dirty 00564 // so everything gets flushed to SYSTEM as soon as we can 00565 // do I/O. 00566 // 00567 RtlSetAllBits(&(Hive->DirtyVector)); 00568 Hive->DirtyCount=Hive->DirtyVector.SizeOfBitMap; 00569 00570 } 00571 HvpFillFileName(Hive->BaseBlock, FileName); 00572 00573 // debug - only 00574 HvpDumpFreeDisplay(Hive); 00575 00576 return(STATUS_SUCCESS); 00577 } 00578 00579 // 00580 // file read case 00581 // 00582 if (OperationType == HINIT_FILE) { 00583 00584 CMLOG(CML_BIN, CMS_BIN_MAP) { 00585 KdPrint(("HvInitializeHive(%wZ,HINIT_FILE) :\n", FileName)); 00586 } 00587 // 00588 // get the file image (possible recovered via log) into memory 00589 // 00590 Status = HvLoadHive(Hive, TailDisplay); 00591 if ((Status != STATUS_SUCCESS) && (Status != STATUS_REGISTRY_RECOVERED)) { 00592 return Status; 00593 } 00594 00595 CMLOG(CML_BIN, CMS_BIN_MAP) { 00596 KdPrint(("\n")); 00597 } 00598 00599 if (Status == STATUS_REGISTRY_RECOVERED) { 00600 00601 // 00602 // We have a good hive, with a log, and a dirty map, 00603 // all set up. Only problem is that we need to flush 00604 // the file so the log can be cleared and new writes 00605 // posted against the hive. Since we know we have 00606 // a good log in hand, we just write the hive image. 00607 // 00608 if ( ! HvpDoWriteHive(Hive, HFILE_TYPE_PRIMARY)) { 00609 // 00610 // DRAGOS: Here we need cleanup 00611 // Clean up the bins already allocated 00612 // 00613 HvpFreeAllocatedBins( Hive ); 00614 00615 return STATUS_REGISTRY_IO_FAILED; 00616 } 00617 00618 // 00619 // If we get here, we have recovered the hive, and 00620 // written it out to disk correctly. So we clear 00621 // the log here. 00622 // 00623 RtlClearAllBits(&(Hive->DirtyVector)); 00624 Hive->DirtyCount = 0; 00625 (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, 0); 00626 Hive->LogSize = 0; 00627 } 00628 00629 // 00630 // slam debug name data into base block 00631 // 00632 HvpFillFileName(Hive->BaseBlock, FileName); 00633 00634 // debug - only 00635 HvpDumpFreeDisplay(Hive); 00636 00637 return STATUS_SUCCESS; 00638 } 00639 00640 return STATUS_INVALID_PARAMETER; 00641 }

BOOLEAN HvIsBinDirty IN PHHIVE  Hive,
IN HCELL_INDEX  Cell
 

Definition at line 200 of file hivesync.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, Cell, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyVector, FALSE, _HBIN::FileOffset, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HMAP_BASE, HSECTOR_SIZE, HvGetCellType, HvpGetCellMap(), _HHIVE::ReadOnly, _HHIVE::Signature, _HBIN::Size, TRUE, VALIDATE_CELL_MAP, and Volatile.

00207 : 00208 00209 Given a hive and a cell, checks whether the bin containing 00210 that cell has any dirty clusters or not. 00211 00212 Arguments: 00213 00214 Hive - Supplies a pointer to the hive control structure 00215 00216 Cell - Supplies the HCELL_INDEX of the Cell. 00217 00218 Return Value: 00219 00220 TRUE - Bin contains dirty data. 00221 00222 FALSE - Bin does not contain dirty data. 00223 00224 --*/ 00225 00226 { 00227 ULONG Type; 00228 PHCELL pcell; 00229 PRTL_BITMAP Bitmap; 00230 ULONG First; 00231 ULONG Last; 00232 ULONG i; 00233 PHMAP_ENTRY Map; 00234 PHBIN Bin; 00235 00236 CMLOG(CML_MINOR, CMS_IO) { 00237 KdPrint(("HvIsBinDirty:\n\t")); 00238 KdPrint(("Hive:%08lx Cell:%08lx\n", Hive, Cell)); 00239 } 00240 00241 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00242 ASSERT(Hive->ReadOnly == FALSE); 00243 00244 Type = HvGetCellType(Cell); 00245 00246 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00247 (Type == Volatile) ) 00248 { 00249 return FALSE; 00250 } 00251 00252 Bitmap = &(Hive->DirtyVector); 00253 00254 Map = HvpGetCellMap(Hive, Cell); 00255 VALIDATE_CELL_MAP(__LINE__,Map,Hive,Cell); 00256 Bin = (PHBIN)(Map->BinAddress & HMAP_BASE); 00257 First = Bin->FileOffset / HSECTOR_SIZE; 00258 Last = (Bin->FileOffset + Bin->Size - 1) / HSECTOR_SIZE; 00259 00260 for (i=First; i<=Last; i++) { 00261 if (RtlCheckBit(Bitmap, i)==1) { 00262 return(TRUE); 00263 } 00264 } 00265 return(FALSE); 00266 }

BOOLEAN HvIsCellAllocated PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 1453 of file hivecell.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, Cell, FALSE, _HHIVE::Flat, HBIN_NIL, HCELL_PAD, HCELL_TYPE_MASK, HHIVE_SIGNATURE, Hive, HMAP_BASE, HvGetCellType, HvpGetCellMap(), HvpGetHCell, NULL, Offset, _HHIVE::Signature, Size, _HCELL::Size, _HBIN::Size, TRUE, _HCELL::u, and USE_OLD_CELL.

Referenced by CmpCheckKey(), CmpCheckValueList(), CmpFindSubKeyByName(), CmpMarkIndexDirty(), CmpRemoveSubKey(), and CmpValidateHiveSecurityDescriptors().

01464 : 01465 01466 Report whether the requested cell is allocated or not. 01467 01468 Arguments: 01469 01470 Hive - containing Hive. 01471 01472 Cell - cel of interest 01473 01474 Return Value: 01475 01476 TRUE if allocated, FALSE if not. 01477 01478 --*/ 01479 { 01480 ULONG Type; 01481 PHCELL Address; 01482 PHCELL Below; 01483 PHMAP_ENTRY Me; 01484 PHBIN Bin; 01485 ULONG Offset; 01486 LONG Size; 01487 01488 01489 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 01490 01491 if (Hive->Flat == TRUE) { 01492 return TRUE; 01493 } 01494 01495 Type = HvGetCellType(Cell); 01496 01497 if ( ((Cell & ~HCELL_TYPE_MASK) > Hive->Storage[Type].Length) || // off end 01498 (Cell % HCELL_PAD(Hive) != 0) // wrong alignment 01499 ) 01500 { 01501 return FALSE; 01502 } 01503 01504 Address = HvpGetHCell(Hive, Cell); 01505 Me = HvpGetCellMap(Hive, Cell); 01506 if (Me == NULL) { 01507 return FALSE; 01508 } 01509 Bin = (PHBIN)((ULONG_PTR)(Me->BinAddress) & HMAP_BASE); 01510 Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)Bin); 01511 Size = Address->Size * -1; 01512 01513 if ( (Address->Size > 0) || // not allocated 01514 ((Offset + (ULONG)Size) > Bin->Size) || // runs off bin, or too big 01515 (Offset < sizeof(HBIN)) // pts into bin header 01516 ) 01517 { 01518 return FALSE; 01519 } 01520 01521 if (USE_OLD_CELL(Hive)) { 01522 if (Address->u.OldCell.Last != HBIN_NIL) { 01523 01524 if (Address->u.OldCell.Last > Bin->Size) { // bogus back pointer 01525 return FALSE; 01526 } 01527 01528 Below = (PHCELL)((PUCHAR)Bin + Address->u.OldCell.Last); 01529 Size = (Below->Size < 0) ? 01530 Below->Size * -1 : 01531 Below->Size; 01532 01533 if ( ((ULONG_PTR)Below + Size) != (ULONG_PTR)Address ) { // no pt back 01534 return FALSE; 01535 } 01536 } }

NTSTATUS HvLoadHive PHHIVE  Hive,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 100 of file hiveload.c.

References ASSERT, _HHIVE::BaseBlock, _HHIVE::DirtyCount, Fail, FALSE, _HHIVE::Free, HFILE_TYPE_PRIMARY, HHIVE_SIGNATURE, Hive, HvpCleanMap(), HvpFreeAllocatedBins(), HvpGetHiveHeader(), HvpGetLogHeader(), HvpReadFileImageAndBuildMap(), HvpRecoverData(), _HBASE_BLOCK::Length, _HHIVE::Log, _HBASE_BLOCK::Minor, NoMemory, NotHive, NT_SUCCESS, NTSTATUS(), NULL, _HHIVE::ReadOnly, RecoverData, RecoverHeader, _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HHIVE::Signature, TRUE, _HBASE_BLOCK::Type, and _HHIVE::Version.

Referenced by HvInitializeHive().

00106 : 00107 00108 Hive must be fully initialized, in particular, file handles 00109 must be set up. This routine is not intended for loading hives 00110 from images already in memory. 00111 00112 This routine will apply whatever fixes are available for errors 00113 in the hive image. In particular, if a log exists, and is applicable, 00114 this routine will automatically apply it. 00115 00116 ALGORITHM: 00117 00118 call HvpGetHiveHeader() 00119 00120 if (NoMemory or NoHive) 00121 return failure 00122 00123 if (RecoverData or RecoverHeader) and (no log) 00124 return falure 00125 00126 if (RecoverHeader) 00127 call HvpGetLogHeader 00128 if (fail) 00129 return failure 00130 fix up baseblock 00131 00132 Read Data 00133 00134 if (RecoverData or RecoverHeader) 00135 HvpRecoverData 00136 return STATUS_REGISTRY_RECOVERED 00137 00138 clean up sequence numbers 00139 00140 return success OR STATUS_REGISTRY_RECOVERED 00141 00142 If STATUS_REGISTRY_RECOVERED is returned, then 00143 00144 If (Log) was used, DirtyVector and DirtyCount are set, 00145 caller is expected to flush the changes (using a 00146 NEW log file) 00147 00148 Arguments: 00149 00150 Hive - supplies a pointer to the hive control structure for the 00151 hive of interest 00152 00153 TailDisplay - array containing the tail ends of the free cell lists - optional 00154 00155 Return Value: 00156 00157 STATUS: 00158 00159 STATUS_INSUFFICIENT_RESOURCES - memory alloc failure, etc 00160 STATUS_NOT_REGISTRY_FILE - bad signatures and the like 00161 STATUS_REGISTRY_CORRUPT - bad signatures in the log, 00162 bad stuff in both in alternate, 00163 inconsistent log 00164 00165 STATUS_REGISTRY_IO_FAILED - data read failed 00166 00167 STATUS_RECOVERED - successfully recovered the hive, 00168 a semi-flush of logged data 00169 is necessary. 00170 00171 STATUS_SUCCESS - it worked, no recovery needed 00172 00173 --*/ 00174 { 00175 PHBASE_BLOCK BaseBlock; 00176 ULONG result1; 00177 ULONG result2; 00178 NTSTATUS status; 00179 LARGE_INTEGER TimeStamp; 00180 ULONG FileOffset; 00181 PHBIN pbin; 00182 BOOLEAN ReadOnlyFlagCopy; 00183 00184 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00185 00186 BaseBlock = NULL; 00187 result1 = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp); 00188 00189 // 00190 // bomb out for total errors 00191 // 00192 if (result1 == NoMemory) { 00193 status = STATUS_INSUFFICIENT_RESOURCES; 00194 goto Exit1; 00195 } 00196 if (result1 == NotHive) { 00197 status = STATUS_NOT_REGISTRY_FILE; 00198 goto Exit1; 00199 } 00200 00201 00202 ReadOnlyFlagCopy = Hive->ReadOnly; 00203 // 00204 // if recovery needed, and no log, bomb out 00205 // 00206 if ( ((result1 == RecoverData) || 00207 (result1 == RecoverHeader)) ) 00208 { 00209 // 00210 // recovery needed 00211 // 00212 if(Hive->Log == FALSE) 00213 { 00214 // 00215 // no log ==> bomb out 00216 // 00217 status = STATUS_REGISTRY_CORRUPT; 00218 goto Exit1; 00219 } else { 00220 // 00221 // TRICK: simulate hive as read-only; Free cells will not 00222 // be enlisted in HvpReadFileImageAndBuildMap; Instead, they 00223 // will be enlisted in HvpRecoverData, when we are sure we have 00224 // the right info loaded up into memory 00225 // 00226 Hive->ReadOnly = TRUE; 00227 } 00228 } 00229 00230 // 00231 // need to recover header using log, so try to get it from log 00232 // 00233 if (result1 == RecoverHeader) { 00234 result2 = HvpGetLogHeader(Hive, &BaseBlock, &TimeStamp); 00235 if (result2 == NoMemory) { 00236 status = STATUS_INSUFFICIENT_RESOURCES; 00237 goto Exit1; 00238 } 00239 if (result2 == Fail) { 00240 status = STATUS_REGISTRY_CORRUPT; 00241 goto Exit1; 00242 } 00243 BaseBlock->Type = HFILE_TYPE_PRIMARY; 00244 } 00245 Hive->BaseBlock = BaseBlock; 00246 Hive->Version = Hive->BaseBlock->Minor; 00247 00248 // 00249 // at this point, we have a sane baseblock. we may or may not still 00250 // need to apply data recovery 00251 // 00252 status = HvpReadFileImageAndBuildMap(Hive,BaseBlock->Length,TailDisplay); 00253 00254 00255 // 00256 // if STATUS_REGISTRY_CORRUPT and RecoverData don't bail out, keep recovering 00257 // 00258 if( !NT_SUCCESS(status) && ((status != STATUS_REGISTRY_CORRUPT) || (result1 != RecoverData)) ) { 00259 goto Exit2; 00260 } 00261 00262 // 00263 // apply data recovery if we need it 00264 // 00265 status = STATUS_SUCCESS; 00266 if ( (result1 == RecoverHeader) || // -> implies recover data 00267 (result1 == RecoverData) ) 00268 { 00269 // 00270 // recover data will enllist the free cells as well and 00271 // will restore the original read-only state of the hive 00272 // 00273 result2 = HvpRecoverData(Hive,ReadOnlyFlagCopy,TailDisplay); 00274 if (result2 == NoMemory) { 00275 status = STATUS_INSUFFICIENT_RESOURCES; 00276 goto Exit2; 00277 } 00278 if (result2 == Fail) { 00279 status = STATUS_REGISTRY_CORRUPT; 00280 goto Exit2; 00281 } 00282 status = STATUS_REGISTRY_RECOVERED; 00283 } 00284 00285 BaseBlock->Sequence2 = BaseBlock->Sequence1; 00286 return status; 00287 00288 00289 Exit2: 00290 // 00291 // Clean up the bins already allocated 00292 // 00293 HvpFreeAllocatedBins( Hive ); 00294 00295 // 00296 // Clean up the directory table 00297 // 00298 HvpCleanMap( Hive ); 00299 00300 Exit1: 00301 if (BaseBlock != NULL) { 00302 (Hive->Free)(BaseBlock, sizeof(HBASE_BLOCK)); 00303 } 00304 00305 Hive->BaseBlock = NULL; 00306 Hive->DirtyCount = 0; 00307 return status; 00308 }

BOOLEAN HvMarkCellDirty PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 117 of file hivesync.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, Cell, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HBIN::FileOffset, HBIN_SIGNATURE, HCELL_INDEX, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HMAP_BASE, HvGetCellType, HvMarkDirty(), HvpGetCellMap(), HvpGetHCell, _HHIVE::ReadOnly, RtlNumberOfSetBits(), _HHIVE::Signature, _HBIN::Signature, Size, _HBIN::Size, _HCELL::Size, TRUE, USE_OLD_CELL, VALIDATE_CELL_MAP, and Volatile.

Referenced by CmDeleteValueKey(), CmpAddToLeaf(), CmpAssignSecurityDescriptor(), CmpCheckKey(), CmpDoCreate(), CmpInsertSecurityCellList(), CmpMarkIndexDirty(), CmpMarkKeyDirty(), CmpMarkKeyParentDirty(), CmpMarkKeyValuesDirty(), CmpSelectLeaf(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), CmSetLastWriteTimeKey(), and CmSetValueKey().

00123 : 00124 00125 Marks the data for the specified cell dirty. 00126 00127 Arguments: 00128 00129 Hive - supplies a pointer to the hive control structure for the 00130 hive of interest 00131 00132 Cell - hcell_index of cell that is being edited 00133 00134 Return Value: 00135 00136 TRUE - it worked 00137 00138 FALSE - could not allocate log space, failure! 00139 00140 --*/ 00141 { 00142 ULONG Type; 00143 ULONG Size; 00144 PHCELL pCell; 00145 PHMAP_ENTRY Me; 00146 HCELL_INDEX Base; 00147 PHBIN Bin; 00148 00149 CMLOG(CML_MINOR, CMS_IO) { 00150 KdPrint(("HvMarkCellDirty:\n\t")); 00151 KdPrint(("Hive:%08lx Cell:%08lx\n", Hive, Cell)); 00152 } 00153 00154 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00155 ASSERT(Hive->ReadOnly == FALSE); 00156 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00157 00158 Type = HvGetCellType(Cell); 00159 00160 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00161 (Type == Volatile) ) 00162 { 00163 return TRUE; 00164 } 00165 00166 pCell = HvpGetHCell(Hive,Cell); 00167 #if DBG 00168 Me = HvpGetCellMap(Hive, Cell); 00169 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Cell); 00170 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00171 ASSERT(Bin->Signature == HBIN_SIGNATURE); 00172 #endif 00173 // 00174 // If it's an old format hive, mark the entire 00175 // bin dirty, because the Last backpointers are 00176 // such a pain to deal with in the partial 00177 // alloc and free-coalescing cases. 00178 // 00179 00180 if (USE_OLD_CELL(Hive)) { 00181 Me = HvpGetCellMap(Hive, Cell); 00182 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Cell); 00183 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00184 Base = Bin->FileOffset; 00185 Size = Bin->Size; 00186 return HvMarkDirty(Hive, Base, Size); 00187 } else { 00188 if (pCell->Size < 0) { 00189 Size = -pCell->Size; 00190 } else { 00191 Size = pCell->Size; 00192 } 00193 ASSERT(Size < Bin->Size); 00194 return HvMarkDirty(Hive, Cell-FIELD_OFFSET(HCELL,u.NewCell), Size); 00195 } 00196 }

BOOLEAN HvMarkClean PHHIVE  Hive,
HCELL_INDEX  Start,
ULONG  Length
 

Definition at line 401 of file hivesync.c.

References ASSERT, BitMap, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HSECTOR_SIZE, HvGetCellType, _HHIVE::ReadOnly, ROUND_UP, RtlClearBits(), RtlNumberOfSetBits(), _HHIVE::Signature, Start, TRUE, and Volatile.

Referenced by HvpAddBin().

00408 : 00409 00410 Clears the dirty bits for a given portion of a hive. This is 00411 the inverse of HvMarkDirty, although it does not give up any 00412 file space in the primary or log that HvMarkDirty may have reserved. 00413 00414 This is a noop for Volatile address range. 00415 00416 Arguments: 00417 00418 Hive - supplies a pointer to the hive control structure for the 00419 hive of interest 00420 00421 Start - supplies a hive virtual address (i.e., an HCELL_INDEX or 00422 like form address) of the start of the area to mark dirty. 00423 00424 Length - inclusive length in bytes of area to mark dirty. 00425 00426 Return Value: 00427 00428 TRUE - it worked 00429 00430 --*/ 00431 { 00432 ULONG Type; 00433 PRTL_BITMAP BitMap; 00434 ULONG First; 00435 ULONG Last; 00436 ULONG i; 00437 ULONG Cluster; 00438 00439 CMLOG(CML_MINOR, CMS_IO) { 00440 KdPrint(("HvMarkClean:\n\t")); 00441 KdPrint(("Hive:%08lx Start:%08lx Length:%08lx\n", Hive, Start, Length)); 00442 } 00443 00444 00445 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00446 ASSERT(Hive->ReadOnly == FALSE); 00447 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00448 00449 Type = HvGetCellType(Start); 00450 00451 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00452 (Type == Volatile) ) 00453 { 00454 return TRUE; 00455 } 00456 00457 BitMap = &(Hive->DirtyVector); 00458 00459 First = Start / HSECTOR_SIZE; 00460 Last = (Start + Length - 1) / HSECTOR_SIZE; 00461 00462 Cluster = Hive->Cluster; 00463 if (Cluster > 1) { 00464 00465 // 00466 // Force Start down to base of cluster 00467 // Force End up to top of cluster 00468 // 00469 First = First & ~(Cluster - 1); 00470 Last = ROUND_UP(Last+1, Cluster) - 1; 00471 } 00472 00473 if (Last >= BitMap->SizeOfBitMap) { 00474 Last = BitMap->SizeOfBitMap-1; 00475 } 00476 00477 // 00478 // Subtract out the dirty count and 00479 // and clear the dirty bits. 00480 // 00481 for (i=First; i<=Last; i++) { 00482 if (RtlCheckBit(BitMap,i)==1) { 00483 --Hive->DirtyCount; 00484 RtlClearBits(BitMap, i, 1); 00485 } 00486 } 00487 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00488 00489 return(TRUE); 00490 }

BOOLEAN HvMarkDirty PHHIVE  Hive,
HCELL_INDEX  Start,
ULONG  Length
 

Definition at line 270 of file hivesync.c.

References ASSERT, BitMap, _HHIVE::Cluster, CML_MINOR, CMLOG, CmpLazyFlush(), CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, HHIVE_SIGNATURE, Hive, HIVE_NOLAZYFLUSH, HIVE_VOLATILE, _HHIVE::HiveFlags, HSECTOR_SIZE, HvGetCellType, HvpGrowLog1(), HvpMarkBinReadWrite, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), RtlSetBits(), _HHIVE::Signature, Start, TRUE, and Volatile.

Referenced by HvMarkCellDirty(), HvpAddBin(), and HvpRecoverData().

00277 : 00278 00279 Marks the relevent parts of a hive dirty, so that they will 00280 be flushed to backing store. 00281 00282 If Hive->Cluster is not 1, then adjacent all logical sectors 00283 in the given cluster will be forced dirty (and log space 00284 allocated for them.) This must be done here rather than in 00285 HvSyncHive so that we can know how much to grow the log. 00286 00287 This is a noop for Volatile address range. 00288 00289 NOTE: Range will not be marked dirty if operation fails. 00290 00291 Arguments: 00292 00293 Hive - supplies a pointer to the hive control structure for the 00294 hive of interest 00295 00296 Start - supplies a hive virtual address (i.e., an HCELL_INDEX or 00297 like form address) of the start of the area to mark dirty. 00298 00299 Length - inclusive length in bytes of area to mark dirty. 00300 00301 Return Value: 00302 00303 TRUE - it worked 00304 00305 FALSE - could not allocate log space, failure! 00306 00307 --*/ 00308 { 00309 ULONG Type; 00310 PRTL_BITMAP BitMap; 00311 ULONG First; 00312 ULONG Last; 00313 ULONG i; 00314 ULONG Cluster; 00315 ULONG OriginalDirtyCount; 00316 ULONG DirtySectors; 00317 BOOLEAN Result = TRUE; 00318 00319 CMLOG(CML_MINOR, CMS_IO) { 00320 KdPrint(("HvMarkDirty:\n\t")); 00321 KdPrint(("Hive:%08lx Start:%08lx Length:%08lx\n", Hive, Start, Length)); 00322 } 00323 00324 00325 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00326 ASSERT(Hive->ReadOnly == FALSE); 00327 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00328 00329 Type = HvGetCellType(Start); 00330 00331 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00332 (Type == Volatile) ) 00333 { 00334 return TRUE; 00335 } 00336 00337 00338 BitMap = &(Hive->DirtyVector); 00339 OriginalDirtyCount = Hive->DirtyCount; 00340 00341 First = Start / HSECTOR_SIZE; 00342 Last = (Start + Length - 1) / HSECTOR_SIZE; 00343 00344 Cluster = Hive->Cluster; 00345 if (Cluster > 1) { 00346 00347 // 00348 // Force Start down to base of cluster 00349 // Force End up to top of cluster 00350 // 00351 First = First & ~(Cluster - 1); 00352 Last = ROUND_UP(Last+1, Cluster) - 1; 00353 } 00354 00355 if (Last >= BitMap->SizeOfBitMap) { 00356 Last = BitMap->SizeOfBitMap-1; 00357 } 00358 00359 // 00360 // Try and grow the log enough to accomodate all the dirty sectors. 00361 // 00362 DirtySectors = 0; 00363 for (i = First; i <= Last; i++) { 00364 if (RtlCheckBit(BitMap, i)==0) { 00365 ++DirtySectors; 00366 } 00367 } 00368 if (DirtySectors != 0) { 00369 if (HvpGrowLog1(Hive, DirtySectors) == FALSE) { 00370 return(FALSE); 00371 } 00372 00373 if ((OriginalDirtyCount == 0) && (First != 0)) { 00374 Result = HvMarkDirty(Hive, 0, sizeof(HBIN)); // force header of 1st bin dirty 00375 if (Result==FALSE) { 00376 return(FALSE); 00377 } 00378 } 00379 00380 // 00381 // Log has been successfully grown, go ahead 00382 // and set the dirty bits. 00383 // 00384 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00385 Hive->DirtyCount += DirtySectors; 00386 RtlSetBits(BitMap, First, Last-First+1); 00387 } 00388 00389 // mark this bin as writable 00390 HvpMarkBinReadWrite(Hive,Start); 00391 00392 if (!(Hive->HiveFlags & HIVE_NOLAZYFLUSH)) { 00393 CmpLazyFlush(); 00394 } 00395 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00396 return(TRUE); 00397 }

PHBIN HvpAddBin PHHIVE  Hive,
ULONG  NewSize,
HSTORAGE_TYPE  Type
 

BOOLEAN HvpAllocateMap PHHIVE  Hive,
PHMAP_DIRECTORY  Dir,
ULONG  Start,
ULONG  End
 

Definition at line 853 of file hivemap.c.

References _HHIVE::Allocate, ASSERT, _HMAP_DIRECTORY::Directory, End, FALSE, Hive, NULL, Start, t(), and TRUE.

Referenced by HvpAddBin(), HvpBuildMapAndCopy(), and HvpInitMap().

00861 : 00862 00863 Sweeps through the directory Dir points to and allocates Tables. 00864 Will allocate Start-th through End-th entries, INCLUSIVE. 00865 00866 Does NOT clean up when out of memory, call HvpFreeMap to do that. 00867 Arguments: 00868 00869 Hive - supplies pointer to hive control block of interest 00870 00871 Dir - supplies address of an HMAP_DIRECTORY structure 00872 00873 Start - index of first map table pointer to allocate for 00874 00875 End - index of last map table pointer to allocate for 00876 00877 Return Value: 00878 00879 TRUE - it worked 00880 00881 FALSE - insufficient memory 00882 00883 --*/ 00884 { 00885 ULONG i; 00886 PVOID t; 00887 00888 for (i = Start; i <= End; i++) { 00889 ASSERT(Dir->Directory[i] == NULL); 00890 t = (PVOID)((Hive->Allocate)(sizeof(HMAP_TABLE), FALSE)); 00891 if (t == NULL) { 00892 return FALSE; 00893 } 00894 RtlZeroMemory(t, sizeof(HMAP_TABLE)); 00895 Dir->Directory[i] = (PHMAP_TABLE)t; 00896 } 00897 return TRUE; 00898 } }

NTSTATUS HvpBuildMap PHHIVE  Hive,
PVOID  Image,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 536 of file hivemap.c.

References Bin, CML_FLOW, CMLOG, CMS_HIVE, ErrorExit(), _HBIN::FileOffset, HBIN_SIGNATURE, HBLOCK_SIZE, Hive, HvCheckHiveDebug, HvpCleanMap(), HvpEnlistBinInMap(), HvpInitMap(), NT_SUCCESS, NTSTATUS(), Offset, _HBIN::Signature, _HBIN::Size, Stable, and Status.

Referenced by HvInitializeHive().

00543 : 00544 00545 Creates the map for the Stable storage of the hive, and inits 00546 the map for the volatile storage. 00547 00548 Following fields in hive must already be filled in: 00549 00550 Allocate, Free 00551 00552 Will initialize Storage structure of HHIVE. 00553 00554 Arguments: 00555 00556 Hive - Pointer to hive control structure to build map for. 00557 00558 Image - pointer to in memory image of the hive 00559 00560 Return Value: 00561 00562 TRUE - it worked 00563 FALSE - either hive is corrupt or no memory for map 00564 00565 --*/ 00566 { 00567 PHBIN Bin; 00568 ULONG Offset; 00569 NTSTATUS Status; 00570 ULONG Length; 00571 00572 00573 CMLOG(CML_FLOW, CMS_HIVE) { 00574 KdPrint(("HvpBuildMap:\n")); 00575 KdPrint(("\tHive=%08lx",Hive)); 00576 } 00577 00578 // 00579 // Init the map 00580 // 00581 Status = HvpInitMap(Hive); 00582 00583 if( !NT_SUCCESS(Status) ) { 00584 // 00585 // just return failure; HvpInitMap took care of cleanup 00586 // 00587 return Status; 00588 } 00589 00590 // 00591 // Fill in the map 00592 // 00593 Offset = 0; 00594 Bin = (PHBIN)Image; 00595 Length = Hive->Storage[Stable].Length; 00596 00597 while (Bin < (PHBIN)((PUCHAR)(Image) + Length)) { 00598 00599 // 00600 // Check the validity of the bin header 00601 // 00602 if ( (Bin->Size > Length) || 00603 (Bin->Size < HBLOCK_SIZE) || 00604 (Bin->Signature != HBIN_SIGNATURE) || 00605 (Bin->FileOffset != Offset)) { 00606 // 00607 // Bin is bogus 00608 // 00609 Status = STATUS_REGISTRY_CORRUPT; 00610 HvCheckHiveDebug.Hive = Hive; 00611 HvCheckHiveDebug.Status = 0xA001; 00612 HvCheckHiveDebug.Space = Length; 00613 HvCheckHiveDebug.MapPoint = Offset; 00614 HvCheckHiveDebug.BinPoint = Bin; 00615 goto ErrorExit; 00616 } 00617 00618 // 00619 // enlist this bin 00620 // 00621 Status = HvpEnlistBinInMap(Hive, Length, Bin, Offset, TailDisplay); 00622 00623 if( !NT_SUCCESS(Status) ) { 00624 goto ErrorExit; 00625 } 00626 00627 // 00628 // the next bin 00629 // 00630 Offset += Bin->Size; 00631 00632 Bin = (PHBIN)((ULONG_PTR)Bin + Bin->Size); 00633 } 00634 00635 return STATUS_SUCCESS; 00636 00637 00638 ErrorExit: 00639 // 00640 // Clean up the directory table 00641 // 00642 HvpCleanMap( Hive ); 00643 00644 return Status; 00645 }

NTSTATUS HvpBuildMapAndCopy PHHIVE  Hive,
PVOID  Image,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 47 of file hivemap.c.

References _HHIVE::Allocate, _HHIVE::BaseBlock, Bin, _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, CML_FLOW, CMLOG, CMS_HIVE, _HHIVE::DirtyAlloc, _HHIVE::DirtyVector, FALSE, _HBIN::FileOffset, _HHIVE::Free, HBIN_SIGNATURE, HBLOCK_SIZE, Hive, HMAP_NEWALLOC, HSECTOR_SIZE, HTABLE_SLOTS, HvpAllocateMap(), HvpEnlistFreeCells(), HvpFreeMap(), HvpGetCellMap(), _HBASE_BLOCK::Length, _HBIN::MemAlloc, NTSTATUS(), NULL, Offset, PAGE_SIZE, _HHIVE::ReadOnly, ROUND_UP, RtlInitializeBitMap(), _HBIN::Signature, Size, _HBIN::Size, Stable, Status, t(), TRUE, and VALIDATE_CELL_MAP.

Referenced by HvInitializeHive().

00054 : 00055 00056 Creates the map for the Stable storage of the hive, and inits 00057 the map for the volatile storage. 00058 00059 Following fields in hive must already be filled in: 00060 00061 Allocate, Free 00062 00063 Will initialize Storage structure of HHIVE. 00064 00065 The difference between this routine and HvpBuildMapAndCopy is that 00066 this routine will create a "sparse" map. As it copies the SourceImage 00067 to the newly allocated memory for the destination, it will avoid 00068 allocating space for HBINs that contain nothing but free space. The 00069 HBLOCKs in these HBINs will be marked as discarded, and HvGetCell 00070 will allocate memory for them if necessary. 00071 00072 Arguments: 00073 00074 Hive - Pointer to hive control structure to build map for. 00075 00076 Image - pointer to flat memory image of original hive. 00077 00078 Return Value: 00079 00080 TRUE - it worked 00081 FALSE - either hive is corrupt or no memory for map 00082 00083 --*/ 00084 { 00085 PHBASE_BLOCK BaseBlock; 00086 ULONG Length; 00087 ULONG MapSlots; 00088 ULONG Tables; 00089 PHMAP_TABLE t = NULL; 00090 PHMAP_DIRECTORY d = NULL; 00091 PHBIN Bin; 00092 PHBIN NewBins; 00093 PHBIN CurrentBin; 00094 ULONG Offset; 00095 ULONG_PTR Address; 00096 PHMAP_ENTRY Me; 00097 NTSTATUS Status; 00098 PULONG Vector; 00099 ULONG Size; 00100 00101 00102 CMLOG(CML_FLOW, CMS_HIVE) { 00103 KdPrint(("HvpBuildMap:\n")); 00104 KdPrint(("\tHive=%08lx",Hive)); 00105 } 00106 00107 00108 // 00109 // Compute size of data region to be mapped 00110 // 00111 BaseBlock = Hive->BaseBlock; 00112 Length = BaseBlock->Length; 00113 if ((Length % HBLOCK_SIZE) != 0 ) { 00114 Status = STATUS_REGISTRY_CORRUPT; 00115 goto ErrorExit1; 00116 } 00117 MapSlots = Length / HBLOCK_SIZE; 00118 if( MapSlots > 0 ) { 00119 Tables = (MapSlots-1) / HTABLE_SLOTS; 00120 } else { 00121 Tables = 0; 00122 } 00123 00124 Hive->Storage[Stable].Length = Length; 00125 00126 // 00127 // allocate dirty vector if one is not already present (from HvpRecoverData) 00128 // 00129 00130 if (Hive->DirtyVector.Buffer == NULL) { 00131 Vector = (PULONG)((Hive->Allocate)(ROUND_UP(Length/HSECTOR_SIZE/8,sizeof(ULONG)), TRUE)); 00132 if (Vector == NULL) { 00133 Status = STATUS_NO_MEMORY; 00134 goto ErrorExit1; 00135 } 00136 RtlZeroMemory(Vector, Length / HSECTOR_SIZE / 8); 00137 RtlInitializeBitMap(&Hive->DirtyVector, Vector, Length / HSECTOR_SIZE); 00138 Hive->DirtyAlloc = (Length/HSECTOR_SIZE/8); 00139 } 00140 00141 // 00142 // allocate and build structure for map 00143 // 00144 if (Tables == 0) { 00145 00146 // 00147 // Just 1 table, no need for directory 00148 // 00149 t = (Hive->Allocate)(sizeof(HMAP_TABLE), FALSE); 00150 if (t == NULL) { 00151 Status = STATUS_INSUFFICIENT_RESOURCES; 00152 goto ErrorExit1; 00153 } 00154 RtlZeroMemory(t, sizeof(HMAP_TABLE)); 00155 Hive->Storage[Stable].Map = 00156 (PHMAP_DIRECTORY)&(Hive->Storage[Stable].SmallDir); 00157 Hive->Storage[Stable].SmallDir = t; 00158 00159 } else { 00160 00161 // 00162 // Need directory and multiple tables 00163 // 00164 d = (PHMAP_DIRECTORY)(Hive->Allocate)(sizeof(HMAP_DIRECTORY), FALSE); 00165 if (d == NULL) { 00166 Status = STATUS_INSUFFICIENT_RESOURCES; 00167 goto ErrorExit1; 00168 } 00169 RtlZeroMemory(d, sizeof(HMAP_DIRECTORY)); 00170 00171 // 00172 // Allocate tables and fill in dir 00173 // 00174 if (HvpAllocateMap(Hive, d, 0, Tables) == FALSE) { 00175 Status = STATUS_INSUFFICIENT_RESOURCES; 00176 goto ErrorExit2; 00177 } 00178 Hive->Storage[Stable].Map = d; 00179 Hive->Storage[Stable].SmallDir = 0; 00180 } 00181 00182 // 00183 // Now we have to allocate the memory for the HBINs and fill in 00184 // the map appropriately. We are careful never to allocate less 00185 // than a page to avoid fragmenting pool. As long as the page 00186 // size is a multiple of HBLOCK_SIZE (a fairly good assumption as 00187 // long as HBLOCK_SIZE is 4k) this strategy will prevent pool 00188 // fragmentation. 00189 // 00190 // If we come across an HBIN that is entirely composed of a freed 00191 // HCELL, then we do not allocate memory, but mark its HBLOCKs in 00192 // the map as not present. HvAllocateCell will allocate memory for 00193 // the bin when it is needed. 00194 // 00195 Offset = 0; 00196 Size = 0; 00197 Bin = (PHBIN)Image; 00198 00199 while (Bin < (PHBIN)((PUCHAR)(Image) + Length)) { 00200 00201 if ( (Bin->Size > (Length-Offset)) || 00202 (Bin->Signature != HBIN_SIGNATURE) || 00203 (Bin->FileOffset != (Offset+Size)) 00204 ) 00205 { 00206 // 00207 // Bin is bogus 00208 // 00209 Status = STATUS_REGISTRY_CORRUPT; 00210 goto ErrorExit2; 00211 } 00212 00213 Size += Bin->Size; 00214 if ((Size < PAGE_SIZE) && 00215 (Size + Length - Offset > PAGE_SIZE)) { 00216 00217 // 00218 // We haven't accumulated enough bins to fill up a page 00219 // yet, and there are still bins left, so group this one 00220 // in with the next one. 00221 // 00222 Bin = (PHBIN)((ULONG_PTR)Bin + Bin->Size); 00223 00224 continue; 00225 00226 } 00227 00228 // 00229 // We now have a series of HBINs to group together in one 00230 // chunk of memory. 00231 // 00232 NewBins = (PHBIN)(Hive->Allocate)(Size, FALSE); 00233 if (NewBins==NULL) { 00234 Status = STATUS_INSUFFICIENT_RESOURCES; 00235 goto ErrorExit2; //fixfix 00236 } 00237 RtlCopyMemory(NewBins, 00238 (PUCHAR)Image+Offset, 00239 Size); 00240 NewBins->MemAlloc = Size; 00241 00242 // 00243 // create map entries for each block/page in bin 00244 // 00245 Address = (ULONG_PTR)NewBins; 00246 do { 00247 CurrentBin = (PHBIN)Address; 00248 do { 00249 Me = HvpGetCellMap(Hive, Offset); 00250 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Offset); 00251 Me->BlockAddress = Address; 00252 Me->BinAddress = (ULONG_PTR)CurrentBin; 00253 00254 if (CurrentBin == NewBins) { 00255 Me->BinAddress |= HMAP_NEWALLOC; 00256 } else { 00257 CurrentBin->MemAlloc = 0; 00258 } 00259 Address += HBLOCK_SIZE; 00260 Offset += HBLOCK_SIZE; 00261 } while ( Address < ((ULONG_PTR)CurrentBin + CurrentBin->Size )); 00262 00263 if (Hive->ReadOnly == FALSE) { 00264 00265 // 00266 // add free cells in the bin to the appropriate free lists 00267 // 00268 if ( ! HvpEnlistFreeCells(Hive, 00269 CurrentBin, 00270 CurrentBin->FileOffset, 00271 TailDisplay 00272 )) { 00273 Status = STATUS_REGISTRY_CORRUPT; 00274 goto ErrorExit2; 00275 } 00276 00277 } 00278 00279 } while ( Address < (ULONG_PTR)NewBins + Size ); 00280 00281 Bin = (PHBIN)((ULONG_PTR)Bin + Bin->Size); 00282 Size = 0; 00283 } 00284 00285 return STATUS_SUCCESS; 00286 00287 00288 ErrorExit2: 00289 if (d != NULL) { 00290 00291 // 00292 // directory was built and allocated, so clean it up 00293 // 00294 00295 HvpFreeMap(Hive, d, 0, Tables); 00296 (Hive->Free)(d, sizeof(HMAP_DIRECTORY)); 00297 } 00298 00299 ErrorExit1: 00300 return Status; 00301 }

VOID HvpCleanMap PHHIVE  Hive  ) 
 

Definition at line 751 of file hivemap.c.

References _HHIVE::Free, HBLOCK_SIZE, Hive, HTABLE_SLOTS, HvpFreeMap(), NULL, and Stable.

Referenced by HvLoadHive(), HvpBuildMap(), and HvpReadFileImageAndBuildMap().

00756 : 00757 00758 Cleans all the map allocations for the stable storage 00759 00760 Arguments: 00761 00762 Hive - Pointer to hive control structure to build map for. 00763 00764 Return Value: 00765 00766 None 00767 --*/ 00768 { 00769 ULONG Length; 00770 ULONG MapSlots; 00771 ULONG Tables; 00772 PHMAP_DIRECTORY d = NULL; 00773 00774 // 00775 // Compute MapSlots and Tables based on the Length 00776 // 00777 Length = Hive->Storage[Stable].Length; 00778 MapSlots = Length / HBLOCK_SIZE; 00779 if( MapSlots > 0 ) { 00780 Tables = (MapSlots-1) / HTABLE_SLOTS; 00781 } else { 00782 Tables = 0; 00783 } 00784 00785 if( Hive->Storage[Stable].SmallDir == 0 ) { 00786 // 00787 // directory was built and allocated, so clean it up 00788 // 00789 00790 d = Hive->Storage[Stable].Map; 00791 if( d != NULL ) { 00792 HvpFreeMap(Hive, d, 0, Tables); 00793 (Hive->Free)(d, sizeof(HMAP_DIRECTORY)); 00794 } 00795 } else { 00796 // 00797 // no directory, just a smalldir 00798 // 00799 (Hive->Free)(Hive->Storage[Stable].SmallDir, sizeof(HMAP_TABLE)); 00800 } 00801 00802 Hive->Storage[Stable].SmallDir = NULL; 00803 Hive->Storage[Stable].Map = NULL; 00804 }

VOID HvpDelistFreeCell PHHIVE  Hive,
PHCELL  Pcell,
HSTORAGE_TYPE  Type,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 1203 of file hivecell.c.

01216 : 01217 01218 Removes a free cell from its list, and clears the Summary 01219 bit for it if need be. 01220 01221 Arguments: 01222 01223 Hive - supplies a pointer to the hive control structure for the 01224 hive of interest 01225 01226 Pcell - supplies a pointer to the HCELL structure of interest 01227 01228 Type - Stable vs. Volatile 01229 01230 Return Value: 01231 01232 NONE. 01233 01234 --*/ 01235 { 01236 PHCELL_INDEX List; 01237 HCELL_INDEX Prev = HCELL_NIL; 01238 ULONG Index; 01239 01240 HvpComputeIndex(Index, Pcell->Size); 01241 List = &(Hive->Storage[Type].FreeDisplay[Index]); 01242 01243 // 01244 // Find previous cell on list 01245 // 01246 ASSERT(*List != HCELL_NIL); 01247 while (HvpGetHCell(Hive,*List) != Pcell) { 01248 Prev = *List; 01249 List = (PHCELL_INDEX)HvGetCell(Hive,*List); 01250 ASSERT(*List != HCELL_NIL); 01251 } 01252 01253 if (ARGUMENT_PRESENT(TailDisplay)) { 01254 // 01255 // This should only happen once, at boot time; Then, we want to sort the list ascedending 01256 // 01257 if( *List == TailDisplay[Index] ) { 01258 // 01259 // this cell is also the last cell on list; so it should be reset 01260 // 01261 01262 #if DBG 01263 // 01264 // consistency checks 01265 // 01266 if (USE_OLD_CELL(Hive)) { 01267 ASSERT(Pcell->u.OldCell.u.Next == HCELL_NIL); 01268 } else { 01269 ASSERT(Pcell->u.NewCell.u.Next == HCELL_NIL); 01270 } 01271 #endif 01272 01273 TailDisplay[Index] = Prev; 01274 } 01275 } 01276 01277 // 01278 // Remove Pcell from list. 01279 // 01280 if (USE_OLD_CELL(Hive)) { 01281 *List = Pcell->u.OldCell.u.Next; 01282 } else { 01283 *List = Pcell->u.NewCell.u.Next; 01284 } 01285 01286 if (Hive->Storage[Type].FreeDisplay[Index] == HCELL_NIL) { 01287 // 01288 // consistency check 01289 // 01290 ASSERT(Prev == HCELL_NIL); 01291 Hive->Storage[Type].FreeSummary &= ~(1 << Index);

BOOLEAN HvpDoWriteHive PHHIVE  Hive,
ULONG  FileType
 

Definition at line 775 of file hivesync.c.

References ASSERT, _HHIVE::BaseBlock, Bin, BitMap, _HMAP_ENTRY::BlockAddress, _HBASE_BLOCK::CheckSum, _HBASE_BLOCK::Cluster, _HHIVE::Cluster, CML_MINOR, CMLOG, CmpDoFileSetSize(), CMS_IO, Count, CMP_OFFSET_ARRAY::DataBuffer, CMP_OFFSET_ARRAY::DataLength, _HHIVE::DirtyVector, ExAllocatePool, ExFreePool(), FALSE, _HHIVE::FileFlush, CMP_OFFSET_ARRAY::FileOffset, _HHIVE::FileWrite, _HBASE_BLOCK::Format, HBASE_BLOCK_SIGNATURE, HBASE_FORMAT_MEMORY, HBLOCK_SIZE, HFILE_TYPE_LOG, HFILE_TYPE_PRIMARY, Hive, HLOG_MINSIZE, HSECTOR_SIZE, HSYS_MAJOR, HvpFindNextDirtyBlock(), HvpGetCellMap(), HvpHeaderCheckSum(), _HBASE_BLOCK::Length, _HHIVE::Log, _HHIVE::LogSize, _HBASE_BLOCK::Major, NULL, Offset, PagedPool, PCMP_OFFSET_ARRAY, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HBASE_BLOCK::Signature, Stable, _HBIN::TimeStamp, _HBASE_BLOCK::TimeStamp, TRUE, _HBASE_BLOCK::Type, and VALIDATE_CELL_MAP.

Referenced by HvInitializeHive(), HvSyncHive(), and HvWriteHive().

00781 : 00782 00783 Write dirty parts of the hive out to either its primary or alternate 00784 file. Write the header, flush, write all data, flush, update header, 00785 flush. Assume either logging or primary/alternate pairs used. 00786 00787 NOTE: TimeStamp is not set, assumption is that HvpWriteLog set 00788 that. It is only used for checking if Logs correspond anyway. 00789 00790 Arguments: 00791 00792 Hive - pointer to Hive for which dirty data is to be written. 00793 00794 FileType - indicated whether primary or alternate file should be written. 00795 00796 Return Value: 00797 00798 TRUE - it worked 00799 00800 FALSE - it failed 00801 00802 --*/ 00803 { 00804 PHBASE_BLOCK BaseBlock; 00805 ULONG Offset; 00806 PUCHAR Address; 00807 ULONG Length; 00808 BOOLEAN rc; 00809 ULONG Current; 00810 PRTL_BITMAP BitMap; 00811 PHMAP_ENTRY Me; 00812 PHBIN Bin; 00813 BOOLEAN ShrinkHive; 00814 PCMP_OFFSET_ARRAY offsetArray; 00815 CMP_OFFSET_ARRAY offsetElement; 00816 ULONG Count; 00817 ULONG SetBitCount; 00818 00819 CMLOG(CML_MINOR, CMS_IO) { 00820 KdPrint(("HvpDoWriteHive:\n\t")); 00821 KdPrint(("Hive:%08lx FileType:%08lx\n", Hive, FileType)); 00822 } 00823 00824 // 00825 // flush first, so that the filesystem structures get written to 00826 // disk if we have grown the file. 00827 // 00828 if (!(Hive->FileFlush)(Hive, FileType)) { 00829 return(FALSE); 00830 } 00831 00832 BaseBlock = Hive->BaseBlock; 00833 00834 if (BaseBlock->Length > Hive->Storage[Stable].Length) { 00835 ShrinkHive = TRUE; 00836 } else { 00837 ShrinkHive = FALSE; 00838 } 00839 00840 // 00841 // --- Write out header first time, flush --- 00842 // 00843 ASSERT(BaseBlock->Signature == HBASE_BLOCK_SIGNATURE); 00844 ASSERT(BaseBlock->Major == HSYS_MAJOR); 00845 ASSERT(BaseBlock->Format == HBASE_FORMAT_MEMORY); 00846 ASSERT(Hive->ReadOnly == FALSE); 00847 00848 00849 if (BaseBlock->Sequence1 != BaseBlock->Sequence2) { 00850 00851 // 00852 // Some previous log attempt failed, or this hive needs to 00853 // be recovered, so punt. 00854 // 00855 return FALSE; 00856 } 00857 00858 BaseBlock->Length = Hive->Storage[Stable].Length; 00859 00860 BaseBlock->Sequence1++; 00861 BaseBlock->Type = HFILE_TYPE_PRIMARY; 00862 BaseBlock->Cluster = Hive->Cluster; 00863 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 00864 00865 Offset = 0; 00866 offsetElement.FileOffset = Offset; 00867 offsetElement.DataBuffer = (PVOID) BaseBlock; 00868 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 00869 rc = (Hive->FileWrite)( 00870 Hive, 00871 FileType, 00872 &offsetElement, 00873 1, 00874 &Offset 00875 ); 00876 00877 if (rc == FALSE) { 00878 return FALSE; 00879 } 00880 if ( ! (Hive->FileFlush)(Hive, FileType)) { 00881 return FALSE; 00882 } 00883 Offset = ROUND_UP(Offset, HBLOCK_SIZE); 00884 00885 // 00886 // --- Write out dirty data (only if there is any) --- 00887 // 00888 00889 if (Hive->DirtyVector.Buffer != NULL) { 00890 // 00891 // First sector of first bin will always be dirty, write it out 00892 // with the TimeStamp value overlaid on its Link field. 00893 // 00894 BitMap = &(Hive->DirtyVector); 00895 00896 ASSERT(RtlCheckBit(BitMap, 0) == 1); 00897 ASSERT(RtlCheckBit(BitMap, (Hive->Cluster - 1)) == 1); 00898 ASSERT(sizeof(LIST_ENTRY) >= sizeof(LARGE_INTEGER)); 00899 00900 Me = HvpGetCellMap(Hive, 0); 00901 VALIDATE_CELL_MAP(__LINE__,Me,Hive,0); 00902 Address = (PUCHAR)Me->BlockAddress; 00903 Length = Hive->Cluster * HSECTOR_SIZE; 00904 Bin = (PHBIN)Address; 00905 Bin->TimeStamp = BaseBlock->TimeStamp; 00906 00907 offsetElement.FileOffset = Offset; 00908 offsetElement.DataBuffer = (PVOID) Address; 00909 offsetElement.DataLength = Length; 00910 rc = (Hive->FileWrite)( 00911 Hive, 00912 FileType, 00913 &offsetElement, 00914 1, 00915 &Offset 00916 ); 00917 ASSERT((Offset % (Hive->Cluster * HSECTOR_SIZE)) == 0); 00918 if (rc == FALSE) { 00919 return FALSE; 00920 } 00921 00922 00923 // 00924 // Write out the rest of the dirty data 00925 // 00926 Current = Hive->Cluster; // don't rewrite 1st bin or header 00927 00928 SetBitCount = RtlNumberOfSetBits(BitMap); 00929 offsetArray = 00930 (PCMP_OFFSET_ARRAY) 00931 ExAllocatePool(PagedPool, 00932 sizeof(CMP_OFFSET_ARRAY) * SetBitCount); 00933 if (offsetArray == NULL) { 00934 return FALSE; 00935 } 00936 Count = 0; 00937 00938 while (HvpFindNextDirtyBlock( 00939 Hive, 00940 BitMap, 00941 &Current, 00942 &Address, 00943 &Length, 00944 &Offset 00945 ) == TRUE) 00946 { 00947 // Gather data into array. 00948 ASSERT(Count < SetBitCount); 00949 offsetArray[Count].FileOffset = Offset; 00950 offsetArray[Count].DataBuffer = Address; 00951 offsetArray[Count].DataLength = Length; 00952 Offset += Length; 00953 Count++; 00954 ASSERT((Offset % (Hive->Cluster * HSECTOR_SIZE)) == 0); 00955 } 00956 00957 rc = (Hive->FileWrite)( 00958 Hive, 00959 FileType, 00960 offsetArray, 00961 Count, 00962 &Offset // Just an OUT parameter which returns the point 00963 // in the file after the last write. 00964 ); 00965 ExFreePool(offsetArray); 00966 if (rc == FALSE) { 00967 return FALSE; 00968 } 00969 } 00970 00971 if ( ! (Hive->FileFlush)(Hive, FileType)) { 00972 return FALSE; 00973 } 00974 00975 // 00976 // --- Write header again to report completion --- 00977 // 00978 BaseBlock->Sequence2++; 00979 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 00980 Offset = 0; 00981 00982 offsetElement.FileOffset = Offset; 00983 offsetElement.DataBuffer = (PVOID) BaseBlock; 00984 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 00985 rc = (Hive->FileWrite)( 00986 Hive, 00987 FileType, 00988 &offsetElement, 00989 1, 00990 &Offset 00991 ); 00992 if (rc == FALSE) { 00993 return FALSE; 00994 } 00995 00996 if (ShrinkHive) { 00997 // 00998 // Hive has shrunk, give up the excess space. 00999 // 01000 CmpDoFileSetSize(Hive, FileType, Hive->Storage[Stable].Length + HBLOCK_SIZE); 01001 } 01002 01003 if ( ! (Hive->FileFlush)(Hive, FileType)) { 01004 return FALSE; 01005 } 01006 01007 if ((Hive->Log) && 01008 (Hive->LogSize > HLOG_MINSIZE(Hive))) { 01009 // 01010 // Shrink log back down, reserve at least two clusters 01011 // worth of space so that if all the disk space is 01012 // consumed, there will still be enough space prereserved 01013 // to allow a minimum of registry operations so the user 01014 // can log on. 01015 // 01016 CmpDoFileSetSize(Hive, HFILE_TYPE_LOG, HLOG_MINSIZE(Hive)); 01017 Hive->LogSize = HLOG_MINSIZE(Hive); 01018 } 01019 01020 return TRUE; 01021 }

NTSTATUS HvpEnlistBinInMap PHHIVE  Hive,
ULONG  Length,
PHBIN  Bin,
ULONG  Offset,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 437 of file hivemap.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, CML_BIN, CML_FLOW, CMLOG, CMS_BIN_MAP, CMS_HIVE, ErrorExit(), FALSE, HBLOCK_SIZE, Hive, HMAP_NEWALLOC, HvCheckHiveDebug, HvpEnlistFreeCells(), HvpGetCellMap(), _HBIN::MemAlloc, NTSTATUS(), Offset, _HHIVE::ReadOnly, _HBIN::Size, Status, and VALIDATE_CELL_MAP.

Referenced by HvpBuildMap(), HvpReadFileImageAndBuildMap(), and HvpRecoverData().

00446 : 00447 00448 Creates map entries and enlist free cells for the specified bin 00449 00450 Arguments: 00451 00452 Hive - Pointer to hive control structure containing the target map 00453 00454 Length - the Length of the hive image 00455 00456 Bin - the bin to be enlisted 00457 00458 Offset - the offset within the hive file 00459 00460 TailDisplay - array containing the tail ends of the free cell lists - optional 00461 00462 Return Value: 00463 00464 STATUS_SUCCESS - it worked 00465 STATUS_REGISTRY_CORRUPT - the bin is inconsistent 00466 00467 --*/ 00468 { 00469 NTSTATUS Status; 00470 ULONG BinOffset; 00471 ULONG_PTR Address; 00472 PHMAP_ENTRY Me; 00473 00474 CMLOG(CML_FLOW, CMS_HIVE) { 00475 KdPrint(("HvpEnlistBinInMap:\n")); 00476 KdPrint(("\tHive=%08lx\t Offset=%08lx",Hive,Offset)); 00477 } 00478 00479 // 00480 // memory was allocated for this bin 00481 // 00482 Bin->MemAlloc = Bin->Size; 00483 00484 CMLOG(CML_BIN, CMS_BIN_MAP) { 00485 KdPrint(("HvpEnlistBinInMap: BinAddress = 0x%08lx\t Size = 0x%lx\n", Bin, Bin->Size)); 00486 } 00487 00488 // 00489 // create map entries for each block/page in bin 00490 // 00491 BinOffset = Offset; 00492 for (Address = (ULONG_PTR)Bin; 00493 Address < ((ULONG_PTR)Bin + Bin->Size); 00494 Address += HBLOCK_SIZE 00495 ) 00496 { 00497 Me = HvpGetCellMap(Hive, Offset); 00498 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Offset); 00499 Me->BlockAddress = Address; 00500 Me->BinAddress = (ULONG_PTR)Bin; 00501 if (Offset == BinOffset) { 00502 Me->BinAddress |= HMAP_NEWALLOC; 00503 } 00504 Offset += HBLOCK_SIZE; 00505 } 00506 00507 if (Hive->ReadOnly == FALSE) { 00508 00509 // 00510 // add free cells in the bin to the appropriate free lists 00511 // 00512 if ( ! HvpEnlistFreeCells(Hive, Bin, BinOffset,TailDisplay)) { 00513 HvCheckHiveDebug.Hive = Hive; 00514 HvCheckHiveDebug.Status = 0xA002; 00515 HvCheckHiveDebug.Space = Length; 00516 HvCheckHiveDebug.MapPoint = BinOffset; 00517 HvCheckHiveDebug.BinPoint = Bin; 00518 Status = STATUS_REGISTRY_CORRUPT; 00519 goto ErrorExit; 00520 } 00521 00522 } 00523 00524 // 00525 // logical consistency check 00526 // 00527 ASSERT(Offset == (BinOffset + Bin->Size)); 00528 00529 return STATUS_SUCCESS; 00530 00531 ErrorExit: 00532 return Status; 00533 }

VOID HvpEnlistFreeCell PHHIVE  Hive,
HCELL_INDEX  Cell,
ULONG  Size,
HSTORAGE_TYPE  Type,
BOOLEAN  CoalesceForward,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 947 of file hivecell.c.

References TRUE.

Referenced by HvFreeCell(), and HvpEnlistFreeCells().

00962 : 00963 00964 Puts the newly freed cell on the appropriate list. 00965 00966 Arguments: 00967 00968 Hive - supplies a pointer to the hive control structure for the 00969 hive of interest 00970 00971 Cell - supplies index of cell to enlist 00972 00973 Size - size of cell 00974 00975 Type - indicates whether Stable or Volatile storage is desired. 00976 00977 CoalesceForward - indicates whether we can coalesce forward or not. 00978 For the case where we have not finished scanning the hive and 00979 enlisting free cells, we do not want to coalesce forward. 00980 00981 Return Value: 00982 00983 NONE. 00984 00985 --*/ 00986 { 00987 PHCELL_INDEX Last; 00988 PHCELL_INDEX First; 00989 PHMAP_ENTRY Map; 00990 PHCELL pcell; 00991 PHCELL pcellLast; 00992 PHCELL FirstCell; 00993 ULONG Index; 00994 PHBIN Bin; 00995 HCELL_INDEX FreeCell; 00996 PFREE_HBIN FreeBin; 00997 PHBIN FirstBin; 00998 PHBIN LastBin; 00999 01000 HvpComputeIndex(Index, Size); 01001 01002 01003 First = &(Hive->Storage[Type].FreeDisplay[Index]); 01004 pcell = HvpGetHCell(Hive, Cell); 01005 ASSERT(pcell->Size > 0); 01006 ASSERT(Size == (ULONG)pcell->Size); 01007 01008 if (ARGUMENT_PRESENT(TailDisplay)) { 01009 // 01010 // This should only happen once, at boot time; Then, we want to sort the list ascedending 01011 // 01012 Last = &TailDisplay[Index]; 01013 if( *Last != HCELL_NIL ) { 01014 // 01015 // there is a last cell; insert current cell right after it. 01016 // and set the next cell pointer for the current cell to NIL 01017 // 01018 pcellLast = HvpGetHCell(Hive,*Last); 01019 ASSERT(pcellLast->Size > 0); 01020 01021 if (USE_OLD_CELL(Hive)) { 01022 pcellLast->u.OldCell.u.Next = Cell; 01023 pcell->u.OldCell.u.Next = HCELL_NIL; 01024 } else { 01025 pcellLast->u.NewCell.u.Next = Cell; 01026 pcell->u.NewCell.u.Next = HCELL_NIL; 01027 } 01028 } else { 01029 // 01030 // No Last cell; Insert it at the begining and set the last cell pointing to it as well 01031 // Sanity check: First cell should be also NIL 01032 // 01033 ASSERT( *First == HCELL_NIL ); 01034 01035 if (USE_OLD_CELL(Hive)) { 01036 pcell->u.OldCell.u.Next = *First; 01037 } else { 01038 pcell->u.NewCell.u.Next = *First; 01039 } 01040 *First = Cell; 01041 } 01042 // 01043 // The current cell becomes the last cell 01044 // 01045 *Last = Cell; 01046 } else { 01047 // 01048 // Normal case, insert the cell at the begining of the list (speed reasons). 01049 // 01050 if (USE_OLD_CELL(Hive)) { 01051 pcell->u.OldCell.u.Next = *First; 01052 } else { 01053 pcell->u.NewCell.u.Next = *First; 01054 } 01055 *First = Cell; 01056 } 01057 01058 01059 // 01060 // Check to see if this is the first cell in the bin and if the entire 01061 // bin consists just of this cell. 01062 // 01063 Map = HvpGetCellMap(Hive, Cell); 01064 VALIDATE_CELL_MAP(__LINE__,Map,Hive,Cell); 01065 Bin = (PHBIN)(Map->BinAddress & ~HMAP_NEWALLOC); 01066 if ((pcell == (PHCELL)(Bin + 1)) && 01067 (Size == Bin->Size-sizeof(HBIN))) { 01068 01069 // 01070 // We have a bin that is entirely free. But we cannot do anything with it 01071 // unless the memalloc that contains the bin is entirely free. Walk the 01072 // bins backwards until we find the first one in the alloc, then walk forwards 01073 // until we find the last one. If any of the other bins in the memalloc 01074 // are not free, bail out. 01075 // 01076 FirstBin = Bin; 01077 while (FirstBin->MemAlloc == 0) { 01078 Map=HvpGetCellMap(Hive,(FirstBin->FileOffset - HBLOCK_SIZE) + 01079 (Type * HCELL_TYPE_MASK)); 01080 VALIDATE_CELL_MAP(__LINE__,Map,Hive,(FirstBin->FileOffset - HBLOCK_SIZE) +(Type * HCELL_TYPE_MASK)); 01081 FirstBin = (PHBIN)(Map->BinAddress & HMAP_BASE); 01082 FirstCell = (PHCELL)(FirstBin+1); 01083 if ((ULONG)(FirstCell->Size) != FirstBin->Size-sizeof(HBIN)) { 01084 // 01085 // The first cell in the bin is either allocated, or not the only 01086 // cell in the HBIN. We cannot free any HBINs. 01087 // 01088 goto Done; 01089 } 01090 } 01091 01092 // 01093 // We can never discard the first bin of a hive as that always gets marked dirty 01094 // and written out. 01095 // 01096 if (FirstBin->FileOffset == 0) { 01097 goto Done; 01098 } 01099 01100 LastBin = Bin; 01101 while (LastBin->FileOffset+LastBin->Size < FirstBin->FileOffset+FirstBin->MemAlloc) { 01102 if (!CoalesceForward) { 01103 // 01104 // We are at the end of what's been built up. Just return and this 01105 // will get freed up when the next HBIN is added. 01106 // 01107 goto Done; 01108 } 01109 Map = HvpGetCellMap(Hive, (LastBin->FileOffset+LastBin->Size) + 01110 (Type * HCELL_TYPE_MASK)); 01111 VALIDATE_CELL_MAP(__LINE__,Map,Hive,(LastBin->FileOffset+LastBin->Size) + (Type * HCELL_TYPE_MASK)); 01112 01113 ASSERT(Map->BinAddress != 0); 01114 01115 LastBin = (PHBIN)(Map->BinAddress & HMAP_BASE); 01116 FirstCell = (PHCELL)(LastBin + 1); 01117 if ((ULONG)(FirstCell->Size) != LastBin->Size-sizeof(HBIN)) { 01118 // 01119 // The first cell in the bin is either allocated, or not the only 01120 // cell in the HBIN. We cannot free any HBINs. 01121 // 01122 goto Done; 01123 } 01124 } 01125 01126 // 01127 // All the bins in this alloc are freed. Coalesce all the bins into 01128 // one alloc-sized bin, then either discard the bin or mark it as 01129 // discardable. 01130 // 01131 if (FirstBin->Size != FirstBin->MemAlloc) { 01132 // 01133 // Mark the first HBLOCK of the first HBIN dirty, since 01134 // we will need to update the on disk field for the bin size 01135 // 01136 if (!HvMarkDirty(Hive, 01137 FirstBin->FileOffset + (Type * HCELL_TYPE_MASK), 01138 sizeof(HBIN) + sizeof(HCELL))) { 01139 goto Done; 01140 } 01141 01142 } 01143 01144 01145 FreeBin = (Hive->Allocate)(sizeof(FREE_HBIN), FALSE); 01146 if (FreeBin == NULL) { 01147 goto Done; 01148 } 01149 01150 // 01151 // Walk through the bins and delist each free cell 01152 // 01153 Bin = FirstBin; 01154 do { 01155 FirstCell = (PHCELL)(Bin+1); 01156 HvpDelistFreeCell(Hive, FirstCell, Type, TailDisplay); 01157 if (Bin==LastBin) { 01158 break; 01159 } 01160 Map = HvpGetCellMap(Hive, (Bin->FileOffset+Bin->Size)+ 01161 (Type * HCELL_TYPE_MASK)); 01162 VALIDATE_CELL_MAP(__LINE__,Map,Hive,(Bin->FileOffset+Bin->Size)+(Type * HCELL_TYPE_MASK)); 01163 Bin = (PHBIN)(Map->BinAddress & HMAP_BASE); 01164 01165 } while ( TRUE ); 01166 01167 // 01168 // Coalesce them all into one bin. 01169 // 01170 FirstBin->Size = FirstBin->MemAlloc; 01171 01172 FreeBin->Size = FirstBin->Size; 01173 FreeBin->FileOffset = FirstBin->FileOffset; 01174 FirstCell = (PHCELL)(FirstBin+1); 01175 FirstCell->Size = FirstBin->Size - sizeof(HBIN); 01176 if (USE_OLD_CELL(Hive)) { 01177 FirstCell->u.OldCell.Last = (ULONG)HBIN_NIL; 01178 } 01179 01180 InsertHeadList(&Hive->Storage[Type].FreeBins, &FreeBin->ListEntry); 01181 ASSERT_LISTENTRY(&FreeBin->ListEntry); 01182 ASSERT_LISTENTRY(FreeBin->ListEntry.Flink); 01183 01184 FreeCell = FirstBin->FileOffset+(Type*HCELL_TYPE_MASK); 01185 FreeBin->Flags = FREE_HBIN_DISCARDABLE; 01186 while (FreeCell-FirstBin->FileOffset < FirstBin->Size) { 01187 Map = HvpGetCellMap(Hive, FreeCell); 01188 VALIDATE_CELL_MAP(__LINE__,Map,Hive,FreeCell); 01189 if (Map->BinAddress & HMAP_NEWALLOC) { 01190 Map->BinAddress = (ULONG_PTR)FirstBin | HMAP_DISCARDABLE | HMAP_NEWALLOC; 01191 } else { 01192 Map->BinAddress = (ULONG_PTR)FirstBin | HMAP_DISCARDABLE; 01193 } 01194 Map->BlockAddress = (ULONG_PTR)FreeBin; 01195 FreeCell += HBLOCK_SIZE; 01196 } 01197 } 01198

BOOLEAN HvpEnlistFreeCells PHHIVE  Hive,
PHBIN  Bin,
ULONG  BinOffset,
PHCELL_INDEX TailDisplay  OPTIONAL
 

Definition at line 649 of file hivemap.c.

References ASSERT, Bin, FALSE, HCELL_INDEX, HCELL_PAD, Hive, HvpEnlistFreeCell(), _HBIN::Size, _HCELL::Size, Stable, and TRUE.

Referenced by HvpBuildMapAndCopy(), HvpEnlistBinInMap(), HvpRecoverData(), and HvRefreshHive().

00657 : 00658 00659 Scan through the cells in the bin, locating the free ones. 00660 Enlist them in the hive's free list set. 00661 00662 N.B. Bin MUST already be mapped when this is called. 00663 00664 Arguments: 00665 00666 Hive - pointer to hive control structure map is being built for 00667 00668 Bin - pointer to bin to enlist cells from 00669 00670 BinOffset - offset of Bin in image 00671 00672 Return Value: 00673 00674 FALSE - registry is corrupt 00675 00676 TRUE - it worked 00677 00678 --*/ 00679 { 00680 PHCELL p; 00681 ULONG celloffset; 00682 ULONG size; 00683 HCELL_INDEX cellindex; 00684 00685 // PERFNOTE -- Keep this in mind as a possible optimization for NT6. 00686 // Since now the hive is loaded in chunks of bins, we can drop the 00687 // bins that are entirely free!!!!!! 00688 // 00689 00690 // 00691 // Scan all the cells in the bin, total free and allocated, check 00692 // for impossible pointers. 00693 // 00694 celloffset = sizeof(HBIN); 00695 p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN)); 00696 00697 while (p < (PHCELL)((PUCHAR)Bin + Bin->Size)) { 00698 00699 // 00700 // if free cell, check it out, add it to free list for hive 00701 // 00702 if (p->Size >= 0) { 00703 00704 size = (ULONG)p->Size; 00705 00706 if ( (size > Bin->Size) || 00707 ( (PHCELL)(size + (PUCHAR)p) > 00708 (PHCELL)((PUCHAR)Bin + Bin->Size) ) || 00709 ((size % HCELL_PAD(Hive)) != 0) || 00710 (size == 0) ) 00711 { 00712 return FALSE; 00713 } 00714 00715 00716 // 00717 // cell is free, and is not obviously corrupt, add to free list 00718 // 00719 celloffset = (ULONG)((PUCHAR)p - (PUCHAR)Bin); 00720 cellindex = BinOffset + celloffset; 00721 00722 // 00723 // Enlist this free cell, but do not coalesce with the next free cell 00724 // as we haven't gotten that far yet. 00725 // 00726 HvpEnlistFreeCell(Hive, cellindex, size, Stable, FALSE,TailDisplay); 00727 00728 } else { 00729 00730 size = (ULONG)(p->Size * -1); 00731 00732 if ( (size > Bin->Size) || 00733 ( (PHCELL)(size + (PUCHAR)p) > 00734 (PHCELL)((PUCHAR)Bin + Bin->Size) ) || 00735 ((size % HCELL_PAD(Hive)) != 0) || 00736 (size == 0) ) 00737 { 00738 return FALSE; 00739 } 00740 00741 } 00742 00743 ASSERT(size >= 0); 00744 p = (PHCELL)((PUCHAR)p + size); 00745 } 00746 00747 return TRUE; 00748 }

VOID HvpFreeAllocatedBins PHHIVE  Hive  ) 
 

Definition at line 85 of file hiveinit.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, _HHIVE::Free, HBLOCK_SIZE, Hive, HMAP_BASE, HMAP_NEWALLOC, HTABLE_SLOTS, _HBIN::MemAlloc, Stable, and _HMAP_TABLE::Table.

Referenced by HvInitializeHive(), and HvLoadHive().

00090 : 00091 00092 Free all the bins allocated for the specified hive. 00093 It applies only to stable storage. Not all bins are allocated. 00094 Those that are not allocated have BinAddress set to 0 00095 00096 Arguments: 00097 00098 Hive - supplies a pointer to hive control structure for hive who's bin to free. 00099 00100 Return Value: 00101 00102 NONE. 00103 00104 --*/ 00105 { 00106 ULONG Length; 00107 PHBIN Bin; 00108 ULONG MapSlots; 00109 ULONG Tables; 00110 PHMAP_ENTRY Me; 00111 PHMAP_TABLE Tab; 00112 ULONG i; 00113 ULONG j; 00114 00115 // 00116 // calculate the number of tables in the map 00117 // 00118 Length = Hive->Storage[Stable].Length; 00119 MapSlots = Length / HBLOCK_SIZE; 00120 if( MapSlots > 0 ) { 00121 Tables = (MapSlots-1) / HTABLE_SLOTS; 00122 } else { 00123 Tables = 0; 00124 } 00125 00126 if( Hive->Storage[Stable].Map ) { 00127 // 00128 // iterate through the directory 00129 // 00130 for (i = 0; i <= Tables; i++) { 00131 Tab = Hive->Storage[Stable].Map->Directory[i]; 00132 00133 ASSERT(Tab); 00134 00135 // 00136 // iterate through the slots in the directory 00137 // 00138 for(j=0;j<HTABLE_SLOTS;j++) { 00139 Me = &(Tab->Table[j]); 00140 // 00141 // BinAddress non-zero means allocated bin 00142 // 00143 if( Me->BinAddress ) { 00144 if( Me->BinAddress & HMAP_NEWALLOC ) { 00145 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00146 (Hive->Free)(Bin, Bin->MemAlloc); 00147 } 00148 00149 Me->BinAddress = 0; 00150 } 00151 } 00152 } 00153 } 00154 00155 }

VOID HvpFreeMap PHHIVE  Hive,
PHMAP_DIRECTORY  Dir,
ULONG  Start,
ULONG  End
 

Definition at line 807 of file hivemap.c.

References _HMAP_DIRECTORY::Directory, End, _HHIVE::Free, HDIRECTORY_SLOTS, Hive, NULL, and Start.

Referenced by HvFreeHive(), HvFreeHivePartial(), HvpAddBin(), HvpBuildMapAndCopy(), HvpCleanMap(), and HvpInitMap().

00815 : 00816 00817 Sweeps through the directory Dir points to and frees Tables. 00818 Will free Start-th through End-th entries, INCLUSIVE. 00819 00820 Arguments: 00821 00822 Hive - supplies pointer to hive control block of interest 00823 00824 Dir - supplies address of an HMAP_DIRECTORY structure 00825 00826 Start - index of first map table pointer to clean up 00827 00828 End - index of last map table pointer to clean up 00829 00830 Return Value: 00831 00832 NONE. 00833 00834 --*/ 00835 { 00836 ULONG i; 00837 00838 if (End >= HDIRECTORY_SLOTS) { 00839 End = HDIRECTORY_SLOTS - 1; 00840 } 00841 00842 for (i = Start; i <= End; i++) { 00843 if (Dir->Directory[i] != NULL) { 00844 (Hive->Free)(Dir->Directory[i], sizeof(HMAP_TABLE)); 00845 Dir->Directory[i] = NULL; 00846 } 00847 } 00848 return; 00849 }

struct _CELL_DATA* HvpGetCellFlat PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 221 of file hivecell.c.

Referenced by HvInitializeHive().

00232 : 00233 00234 Returns the memory address for the specified Cell. Will never 00235 return failure, but may assert. Use HvIsCellAllocated to check 00236 validity of Cell. 00237 00238 This routine should never be called directly, always call it 00239 via the HvGetCell() macro. 00240 00241 This routine provides GetCell support for read only hives with 00242 single allocation flat images. Such hives do not have cell 00243 maps ("page tables"), instead, we compute addresses by 00244 arithmetic against the base image address. 00245 00246 Such hives cannot have volatile cells. 00247 00248 Arguments: 00249 00250 Hive - supplies a pointer to the hive control structure for the 00251 hive of interest 00252 00253 Cell - supplies HCELL_INDEX of cell to return address for 00254 00255 Return Value: 00256 00257 Address of Cell in memory. Assert or BugCheck if error. 00258 00259 --*/ 00260 { 00261 PUCHAR base; 00262 PHCELL pcell; 00263 00264 CMLOG(CML_FLOW, CMS_MAP) { 00265 KdPrint(("HvGetCellFlat:\n")); 00266 KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell)); 00267 } 00268 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00269 ASSERT(Cell != HCELL_NIL); 00270 ASSERT(Hive->Flat == TRUE); 00271 ASSERT(HvGetCellType(Cell) == Stable); 00272 ASSERT(Cell >= sizeof(HBIN)); 00273 ASSERT(Cell < Hive->BaseBlock->Length); 00274 ASSERT((Cell & 0x7)==0); 00275 00276 // 00277 // Address is base of Hive image + Cell 00278 // 00279 base = (PUCHAR)(Hive->BaseBlock) + HBLOCK_SIZE; 00280 pcell = (PHCELL)(base + Cell); 00281 if (USE_OLD_CELL(Hive)) { return (struct _CELL_DATA *)&(pcell->u.OldCell.u.UserData);

PHMAP_ENTRY HvpGetCellMap PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 285 of file hivecell.c.

Referenced by HvCheckHive(), HvFreeCell(), HvFreeHive(), HvFreeHivePartial(), HvIsBinDirty(), HvIsCellAllocated(), HvMarkCellDirty(), HvpAddBin(), HvpBuildMapAndCopy(), HvpCoalesceDiscardedBins(), HvpDiscardBins(), HvpDoWriteHive(), HvpEnlistBinInMap(), HvpFindNextDirtyBlock(), HvpRecoverData(), HvpTruncateBins(), and HvRefreshHive().

00296 : 00297 00298 Returns the address of the HMAP_ENTRY for the cell. 00299 00300 Arguments: 00301 00302 Hive - supplies a pointer to the hive control structure for the 00303 hive of interest 00304 00305 Cell - supplies HCELL_INDEX of cell to return map entry address for 00306 00307 Return Value: 00308 00309 Address of MAP_ENTRY in memory. NULL if no such cell or other error. 00310 00311 --*/ 00312 { 00313 ULONG Type; 00314 ULONG Table; 00315 ULONG Block; 00316 PHMAP_TABLE ptab; 00317 00318 CMLOG(CML_FLOW, CMS_MAP) { 00319 KdPrint(("HvpGetCellMapPaged:\n")); 00320 KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell)); 00321 } 00322 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00323 ASSERT(Hive->Flat == FALSE); 00324 ASSERT((Cell & (HCELL_PAD(Hive)-1))==0); 00325 00326 Type = HvGetCellType(Cell); 00327 Table = (Cell & HCELL_TABLE_MASK) >> HCELL_TABLE_SHIFT; 00328 Block = (Cell & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; 00329 00330 if ((Cell - (Type * HCELL_TYPE_MASK)) >= Hive->Storage[Type].Length) { 00331 return NULL; }

struct _CELL_DATA* HvpGetCellPaged PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 146 of file hivecell.c.

References ASSERT, ASSERT_CM_LOCK_OWNED, _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, Cell, CML_FLOW, CMLOG, CMS_MAP, FALSE, _HHIVE::Flat, HCELL_BLOCK_MASK, HCELL_BLOCK_SHIFT, HCELL_NIL, HCELL_OFFSET_MASK, HCELL_PAD, HCELL_TABLE_MASK, HCELL_TABLE_SHIFT, HCELL_TYPE_MASK, HHIVE_SIGNATURE, Hive, HMAP_BASE, HMAP_DISCARDABLE, HvGetCellType, Offset, _HHIVE::Signature, Stable, _HCELL::u, and USE_OLD_CELL.

Referenced by HvInitializeHive().

00157 : 00158 00159 Returns the memory address for the specified Cell. Will never 00160 return failure, but may assert. Use HvIsCellAllocated to check 00161 validity of Cell. 00162 00163 This routine should never be called directly, always call it 00164 via the HvGetCell() macro. 00165 00166 This routine provides GetCell support for hives with full maps. 00167 It is the normal version of the routine. 00168 00169 Arguments: 00170 00171 Hive - supplies a pointer to the hive control structure for the 00172 hive of interest 00173 00174 Cell - supplies HCELL_INDEX of cell to return address for 00175 00176 Return Value: 00177 00178 Address of Cell in memory. Assert or BugCheck if error. 00179 00180 --*/ 00181 { 00182 ULONG Type; 00183 ULONG Table; 00184 ULONG Block; 00185 ULONG Offset; 00186 PHCELL pcell; 00187 PHMAP_ENTRY Map; 00188 00189 CMLOG(CML_FLOW, CMS_MAP) { 00190 KdPrint(("HvGetCellPaged:\n")); 00191 KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell)); 00192 } 00193 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00194 ASSERT(Cell != HCELL_NIL); 00195 ASSERT(Hive->Flat == FALSE); 00196 ASSERT((Cell & (HCELL_PAD(Hive)-1))==0); 00197 ASSERT_CM_LOCK_OWNED(); 00198 #if DBG 00199 if (HvGetCellType(Cell) == Stable) { 00200 ASSERT(Cell >= sizeof(HBIN)); 00201 } else { 00202 ASSERT(Cell >= (HCELL_TYPE_MASK + sizeof(HBIN))); 00203 } 00204 #endif 00205 00206 Type = HvGetCellType(Cell); 00207 Table = (Cell & HCELL_TABLE_MASK) >> HCELL_TABLE_SHIFT; 00208 Block = (Cell & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; 00209 Offset = (Cell & HCELL_OFFSET_MASK); 00210 00211 ASSERT((Cell - (Type * HCELL_TYPE_MASK)) < Hive->Storage[Type].Length); 00212 00213 Map = &((Hive->Storage[Type].Map)->Directory[Table]->Table[Block]); 00214 ASSERT((Map->BinAddress & HMAP_BASE) != 0); 00215 ASSERT((Map->BinAddress & HMAP_DISCARDABLE) == 0); 00216 pcell = (PHCELL)((ULONG_PTR)(Map->BlockAddress) + Offset); 00217 if (USE_OLD_CELL(Hive)) { return (struct _CELL_DATA *)&(pcell->u.OldCell.u.UserData);

BOOLEAN HvpGrowLog1 PHHIVE  Hive,
ULONG  Count
 

Definition at line 495 of file hivesync.c.

References ASSERT, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, Count, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HHIVE::FileSetSize, HFILE_TYPE_LOG, Hive, HLOG_GROW, HSECTOR_SIZE, _HHIVE::Log, _HHIVE::LogSize, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), and TRUE.

Referenced by HvMarkDirty().

00501 : 00502 00503 Adjust the log for growth in the number of sectors of dirty 00504 data that are desired. 00505 00506 Arguments: 00507 00508 Hive - supplies a pointer to the hive control structure for the 00509 hive of interest 00510 00511 Count - number of additional logical sectors of log space needed 00512 00513 Return Value: 00514 00515 TRUE - it worked 00516 00517 FALSE - could not allocate log space, failure! 00518 00519 --*/ 00520 { 00521 ULONG ClusterSize; 00522 ULONG RequiredSize; 00523 ULONG tmp; 00524 00525 CMLOG(CML_MINOR, CMS_IO) { 00526 KdPrint(("HvpGrowLog1:\n\t")); 00527 KdPrint(("Hive:%08lx Count:%08lx\n", Hive, Count)); 00528 } 00529 00530 ASSERT(Hive->ReadOnly == FALSE); 00531 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00532 00533 // 00534 // If logging is off, tell caller world is OK. 00535 // 00536 if (Hive->Log == FALSE) { 00537 return TRUE; 00538 } 00539 00540 ClusterSize = Hive->Cluster * HSECTOR_SIZE; 00541 00542 tmp = Hive->DirtyVector.SizeOfBitMap / 8; // bytes 00543 tmp += sizeof(ULONG); // signature 00544 00545 RequiredSize = 00546 ClusterSize + // 1 cluster for header 00547 ROUND_UP(tmp, ClusterSize) + 00548 ((Hive->DirtyCount + Count) * HSECTOR_SIZE); 00549 00550 RequiredSize = ROUND_UP(RequiredSize, HLOG_GROW); 00551 00552 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00553 00554 if ( ! (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, RequiredSize)) { 00555 return FALSE; 00556 } 00557 00558 Hive->LogSize = RequiredSize; 00559 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00560 return TRUE; 00561 }

BOOLEAN HvpGrowLog2 PHHIVE  Hive,
ULONG  Size
 

Definition at line 565 of file hivesync.c.

References ASSERT, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HHIVE::FileSetSize, HFILE_TYPE_LOG, Hive, HLOG_GROW, HSECTOR_SIZE, _HHIVE::Log, _HHIVE::LogSize, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), Size, Stable, and TRUE.

Referenced by HvpAddBin().

00571 : 00572 00573 Adjust the log for growth in the size of the hive, in particular, 00574 account for the increased space needed for a bigger dirty vector. 00575 00576 Arguments: 00577 00578 Hive - supplies a pointer to the hive control structure for the 00579 hive of interest 00580 00581 Size - proposed growth in size in bytes. 00582 00583 Return Value: 00584 00585 TRUE - it worked 00586 00587 FALSE - could not allocate log space, failure! 00588 00589 --*/ 00590 { 00591 ULONG ClusterSize; 00592 ULONG RequiredSize; 00593 ULONG DirtyBytes; 00594 00595 CMLOG(CML_MINOR, CMS_IO) { 00596 KdPrint(("HvpGrowLog2:\n\t")); 00597 KdPrint(("Hive:%08lx Size:%08lx\n", Hive, Size)); 00598 } 00599 00600 ASSERT(Hive->ReadOnly == FALSE); 00601 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00602 00603 00604 // 00605 // If logging is off, tell caller world is OK. 00606 // 00607 if (Hive->Log == FALSE) { 00608 return TRUE; 00609 } 00610 00611 ASSERT( (Size % HSECTOR_SIZE) == 0 ); 00612 00613 ClusterSize = Hive->Cluster * HSECTOR_SIZE; 00614 00615 ASSERT( (((Hive->Storage[Stable].Length + Size) / HSECTOR_SIZE) % 8) == 0); 00616 00617 DirtyBytes = (Hive->DirtyVector.SizeOfBitMap / 8) + 00618 ((Size / HSECTOR_SIZE) / 8) + 00619 sizeof(ULONG); // signature 00620 DirtyBytes = ROUND_UP(DirtyBytes, ClusterSize); 00621 00622 RequiredSize = 00623 ClusterSize + // 1 cluster for header 00624 (Hive->DirtyCount * HSECTOR_SIZE) + 00625 DirtyBytes; 00626 00627 RequiredSize = ROUND_UP(RequiredSize, HLOG_GROW); 00628 00629 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00630 00631 if ( ! (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, RequiredSize)) { 00632 return FALSE; 00633 } 00634 00635 Hive->LogSize = RequiredSize; 00636 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00637 return TRUE; 00638 }

ULONG HvpHeaderCheckSum PHBASE_BLOCK  BaseBlock  ) 
 

Definition at line 31 of file hivesum.c.

Referenced by DoDump(), HvInitializeHive(), HvpDoWriteHive(), HvpGetHiveHeader(), HvpGetLogHeader(), and HvpWriteLog().

00036 : 00037 00038 Compute the checksum for a hive disk header. 00039 00040 Arguments: 00041 00042 BaseBlock - supplies pointer to the header to checksum 00043 00044 Return Value: 00045 00046 the check sum. 00047 00048 --*/ 00049 { 00050 ULONG sum; 00051 ULONG i; 00052 00053 sum = 0; 00054 for (i = 0; i < 127; i++) { 00055 sum ^= ((PULONG)BaseBlock)[i]; 00056 } 00057 if (sum == (ULONG)-1) { 00058 sum = (ULONG)-2; 00059 } 00060 if (sum == 0) { 00061 sum = 1; 00062 } 00063 return sum; 00064 } }

NTSTATUS HvpInitMap PHHIVE  Hive  ) 
 

Definition at line 304 of file hivemap.c.

References _HHIVE::Allocate, _HHIVE::BaseBlock, CML_FLOW, CMLOG, CMS_HIVE, _HHIVE::DirtyAlloc, _HHIVE::DirtyVector, FALSE, _HHIVE::Free, HBLOCK_SIZE, Hive, HSECTOR_SIZE, HTABLE_SLOTS, HvpAllocateMap(), HvpFreeMap(), _HBASE_BLOCK::Length, NTSTATUS(), NULL, ROUND_UP, RtlInitializeBitMap(), Stable, Status, t(), and TRUE.

Referenced by HvpBuildMap(), and HvpReadFileImageAndBuildMap().

00309 : 00310 00311 Initialize the map for the Stable Volatile storage of the hive. 00312 00313 Following fields in hive must already be filled in: 00314 00315 Allocate, Free 00316 00317 Will initialize Storage structure of HHIVE. 00318 00319 Arguments: 00320 00321 Hive - Pointer to hive control structure to build map for. 00322 00323 Return Value: 00324 00325 STATUS_SUCCESS - it worked 00326 STATUS_xxx - the errorneous status 00327 00328 --*/ 00329 { 00330 PHBASE_BLOCK BaseBlock; 00331 ULONG Length; 00332 ULONG MapSlots; 00333 ULONG Tables; 00334 PHMAP_TABLE t = NULL; 00335 PHMAP_DIRECTORY d = NULL; 00336 NTSTATUS Status; 00337 PULONG Vector; 00338 00339 00340 CMLOG(CML_FLOW, CMS_HIVE) { 00341 KdPrint(("HvpInitMap:\n")); 00342 KdPrint(("\tHive=%08lx",Hive)); 00343 } 00344 00345 // 00346 // Compute size of data region to be mapped 00347 // 00348 BaseBlock = Hive->BaseBlock; 00349 Length = BaseBlock->Length; 00350 if ((Length % HBLOCK_SIZE) != 0) { 00351 Status = STATUS_REGISTRY_CORRUPT; 00352 goto ErrorExit1; 00353 } 00354 MapSlots = Length / HBLOCK_SIZE; 00355 if( MapSlots > 0 ) { 00356 Tables = (MapSlots-1) / HTABLE_SLOTS; 00357 } else { 00358 Tables = 0; 00359 } 00360 00361 Hive->Storage[Stable].Length = Length; 00362 00363 // 00364 // allocate dirty vector if one is not already present (from HvpRecoverData) 00365 // 00366 00367 if (Hive->DirtyVector.Buffer == NULL) { 00368 Vector = (PULONG)((Hive->Allocate)(ROUND_UP(Length/HSECTOR_SIZE/8,sizeof(ULONG)), TRUE)); 00369 if (Vector == NULL) { 00370 Status = STATUS_NO_MEMORY; 00371 goto ErrorExit1; 00372 } 00373 RtlZeroMemory(Vector, Length / HSECTOR_SIZE / 8); 00374 RtlInitializeBitMap(&Hive->DirtyVector, Vector, Length / HSECTOR_SIZE); 00375 Hive->DirtyAlloc = (Length/HSECTOR_SIZE/8); 00376 } 00377 00378 // 00379 // allocate and build structure for map 00380 // 00381 if (Tables == 0) { 00382 00383 // 00384 // Just 1 table, no need for directory 00385 // 00386 t = (Hive->Allocate)(sizeof(HMAP_TABLE), FALSE); 00387 if (t == NULL) { 00388 Status = STATUS_INSUFFICIENT_RESOURCES; 00389 goto ErrorExit1; 00390 } 00391 RtlZeroMemory(t, sizeof(HMAP_TABLE)); 00392 Hive->Storage[Stable].Map = 00393 (PHMAP_DIRECTORY)&(Hive->Storage[Stable].SmallDir); 00394 Hive->Storage[Stable].SmallDir = t; 00395 00396 } else { 00397 00398 // 00399 // Need directory and multiple tables 00400 // 00401 d = (PHMAP_DIRECTORY)(Hive->Allocate)(sizeof(HMAP_DIRECTORY), FALSE); 00402 if (d == NULL) { 00403 Status = STATUS_INSUFFICIENT_RESOURCES; 00404 goto ErrorExit1; 00405 } 00406 RtlZeroMemory(d, sizeof(HMAP_DIRECTORY)); 00407 00408 // 00409 // Allocate tables and fill in dir 00410 // 00411 if (HvpAllocateMap(Hive, d, 0, Tables) == FALSE) { 00412 Status = STATUS_INSUFFICIENT_RESOURCES; 00413 goto ErrorExit2; 00414 } 00415 Hive->Storage[Stable].Map = d; 00416 Hive->Storage[Stable].SmallDir = 0; 00417 } 00418 00419 return STATUS_SUCCESS; 00420 00421 ErrorExit2: 00422 if (d != NULL) { 00423 00424 // 00425 // directory was built and allocated, so clean it up 00426 // 00427 00428 HvpFreeMap(Hive, d, 0, Tables); 00429 (Hive->Free)(d, sizeof(HMAP_DIRECTORY)); 00430 } 00431 00432 ErrorExit1: 00433 return Status; 00434 }

NTSTATUS HvReadInMemoryHive PHHIVE  Hive,
PVOID *  HiveImage
 

HCELL_INDEX HvReallocateCell PHHIVE  Hive,
HCELL_INDEX  Cell,
ULONG  NewSize
 

Definition at line 1295 of file hivecell.c.

Referenced by CmDeleteValueKey(), CmpAddToLeaf(), CmpMergeKeyValues(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyNew(), CmpSplitLeaf(), and CmRestoreKey().

01307 : 01308 01309 Grows or shrinks a cell. 01310 01311 NOTE: 01312 01313 MUST NOT FAIL if the cell is being made smaller. Can be 01314 a noop, but must work. 01315 01316 WARNING: 01317 01318 If the cell is grown, it will get a NEW and DIFFERENT HCELL_INDEX!!! 01319 01320 Arguments: 01321 01322 Hive - supplies a pointer to the hive control structure for the 01323 hive of interest 01324 01325 Cell - supplies index of cell to grow or shrink 01326 01327 NewSize - desired size of cell (this is an absolute size, not an 01328 increment or decrement.) 01329 01330 Return Value: 01331 01332 New HCELL_INDEX for cell, or HCELL_NIL if failure. 01333 01334 If return is HCELL_NIL, either old cell did not exist, or it did exist 01335 and we could not make a new one. In either case, nothing has changed. 01336 01337 If return is NOT HCELL_NIL, then it is the HCELL_INDEX for the Cell, 01338 which very probably moved. 01339 01340 --*/ 01341 { 01342 PUCHAR oldaddress; 01343 LONG oldsize; 01344 ULONG oldalloc; 01345 HCELL_INDEX NewCell; // return value 01346 PUCHAR newaddress; 01347 ULONG Type; 01348 01349 CMLOG(CML_MAJOR, CMS_HIVE) { 01350 KdPrint(("HvReallocateCell:\n")); 01351 KdPrint(("\tHive=%08lx Cell=%08lx NewSize=%08lx\n",Hive,Cell,NewSize)); 01352 } 01353 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 01354 ASSERT(Hive->ReadOnly == FALSE); 01355 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 01356 01357 // 01358 // Make room for overhead fields and round up to HCELL_PAD boundary 01359 // 01360 if (USE_OLD_CELL(Hive)) { 01361 NewSize += FIELD_OFFSET(HCELL, u.OldCell.u.UserData); 01362 } else { 01363 NewSize += FIELD_OFFSET(HCELL, u.NewCell.u.UserData); 01364 } 01365 NewSize = ROUND_UP(NewSize, HCELL_PAD(Hive)); 01366 01367 // 01368 // Adjust the size (an easy fix for granularity) 01369 // 01370 HvpAdjustCellSize(NewSize); 01371 01372 // 01373 // reject impossible/unreasonable values 01374 // 01375 if (NewSize > HSANE_CELL_MAX) { 01376 CMLOG(CML_FLOW, CMS_HIVE) { 01377 KdPrint(("\tNewSize=%08lx\n", NewSize)); 01378 } 01379 return HCELL_NIL; 01380 } 01381 01382 // 01383 // Get sizes and addresses 01384 // 01385 oldaddress = (PUCHAR)HvGetCell(Hive, Cell); 01386 oldsize = HvGetCellSize(Hive, oldaddress); 01387 ASSERT(oldsize > 0); 01388 if (USE_OLD_CELL(Hive)) { 01389 oldalloc = (ULONG)(oldsize + FIELD_OFFSET(HCELL, u.OldCell.u.UserData)); 01390 } else { 01391 oldalloc = (ULONG)(oldsize + FIELD_OFFSET(HCELL, u.NewCell.u.UserData)); 01392 } 01393 Type = HvGetCellType(Cell); 01394 01395 DHvCheckHive(Hive); 01396 01397 if (NewSize == oldalloc) { 01398 01399 // 01400 // This is a noop, return the same cell 01401 // 01402 NewCell = Cell; 01403 01404 } else if (NewSize < oldalloc) { 01405 01406 // 01407 // This is a shrink. 01408 // 01409 // PERFNOTE - IMPLEMENT THIS. Do nothing for now. 01410 // 01411 NewCell = Cell; 01412 01413 } else { 01414 01415 // 01416 // This is a grow. 01417 // 01418 01419 // 01420 // PERFNOTE - Someday we want to detect that there is a free neighbor 01421 // above us and grow into that neighbor if possible. 01422 // For now, always do the allocate, copy, free gig. 01423 // 01424 01425 // 01426 // Allocate a new block of memory to hold the cell 01427 // 01428 01429 if ((NewCell = HvpDoAllocateCell(Hive, NewSize, Type)) == HCELL_NIL) { 01430 return HCELL_NIL; 01431 } 01432 ASSERT(HvIsCellAllocated(Hive, NewCell)); 01433 newaddress = (PUCHAR)HvGetCell(Hive, NewCell); 01434 01435 // 01436 // oldaddress points to the old data block for the cell, 01437 // newaddress points to the new data block, copy the data 01438 // 01439 RtlMoveMemory(newaddress, oldaddress, oldsize); 01440 01441 // 01442 // Free the old block of memory 01443 // 01444 HvFreeCell(Hive, Cell); }

VOID HvRefreshHive PHHIVE  Hive  ) 
 

Definition at line 1584 of file hivesync.c.

References ASSERT, _HHIVE::BaseBlock, Bin, _HMAP_ENTRY::BinAddress, BitMap, _HMAP_ENTRY::BlockAddress, CmCheckRegistry(), _HHIVE::DirtyCount, _HHIVE::DirtyVector, End, FALSE, _HBIN::FileOffset, _FREE_HBIN::FileOffset, _HHIVE::FileRead, _HHIVE::FileSetSize, _CM_KEY_NODE::Flags, _FREE_HBIN::Flags, _HHIVE::Free, FREE_HBIN_DISCARDABLE, HBLOCK_SIZE, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_PRIMARY, HHIVE_FREE_DISPLAY_SIZE, Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HMAP_BASE, HMAP_DISCARDABLE, HMAP_NEWALLOC, HSECTOR_SIZE, HvCheckHive(), HvFreeHivePartial(), HvGetCell, HvpEnlistFreeCells(), HvpFindNextDirtyBlock(), HvpGetCellMap(), KeBugCheckEx(), KEY_HIVE_ENTRY, KEY_NO_DELETE, _HBASE_BLOCK::Length, List, _FREE_HBIN::ListEntry, _HBIN::MemAlloc, NULL, Offset, _CM_KEY_NODE::Parent, _HHIVE::RefreshCount, _HBASE_BLOCK::RootCell, RtlClearAllBits(), RtlClearBits(), _HBIN::Size, _FREE_HBIN::Size, Stable, Start, t(), TRUE, VALIDATE_CELL_MAP, and Volatile.

01589 : 01590 01591 Undo the last sync. We do this by reading back all data which 01592 has been marked dirty from the file into memory. Update the 01593 free list. We will then clear the dirty vector. 01594 01595 Any growth since the last sync will be discarded, and in fact, 01596 the size of the file will be set down. 01597 01598 WARNNOTE: Failure will cause a bugcheck, as we cannot 01599 keep the hive consistent if we fail part way through. 01600 01601 All I/O is done via HFILE_TYPE_PRIMARY. 01602 01603 Arguments: 01604 01605 Hive - supplies a pointer to the hive control structure for the 01606 hive of interest. 01607 01608 Return Value: 01609 01610 NONE. Either works or BugChecks. 01611 01612 --*/ 01613 { 01614 ULONG Offset; 01615 ULONG ReadLength; 01616 ULONG checkstatus; 01617 PUCHAR Address; 01618 ULONG Current; 01619 PRTL_BITMAP BitMap; 01620 BOOLEAN rc; 01621 ULONG Start; 01622 ULONG End; 01623 ULONG BitLength; 01624 HCELL_INDEX TailStart; 01625 HCELL_INDEX p; 01626 PHMAP_ENTRY t; 01627 ULONG i; 01628 PHBIN Bin; 01629 PLIST_ENTRY List; 01630 PFREE_HBIN FreeBin; 01631 PHMAP_ENTRY Map; 01632 HCELL_INDEX RootCell; 01633 PCM_KEY_NODE RootNode; 01634 HCELL_INDEX LinkCell; 01635 01636 // 01637 // this array stores the last elements in each free cell list for the stable storage 01638 // 01639 HCELL_INDEX TailDisplay[HHIVE_FREE_DISPLAY_SIZE]; 01640 01641 // 01642 // noop or assert on various uninteresting or bogus conditions 01643 // 01644 if (Hive->DirtyCount == 0) { 01645 return; 01646 } 01647 ASSERT(Hive->HiveFlags & HIVE_NOLAZYFLUSH); 01648 ASSERT(Hive->Storage[Volatile].Length == 0); 01649 01650 // 01651 // be sure the hive is not already trash 01652 // 01653 checkstatus = HvCheckHive(Hive, NULL); 01654 if (checkstatus != 0) { 01655 KeBugCheckEx(REGISTRY_ERROR,7,0,(ULONG_PTR)Hive,checkstatus); 01656 } 01657 01658 Hive->RefreshCount++; 01659 01660 // 01661 // Capture the LinkCell backpointer in the hive's root cell. We need this in case 01662 // the first bin is overwritten with what was on disk. 01663 // 01664 RootCell = Hive->BaseBlock->RootCell; 01665 RootNode = (PCM_KEY_NODE)HvGetCell(Hive, RootCell); 01666 LinkCell = RootNode->Parent; 01667 01668 // 01669 // Any bins that have been marked as discardable, but not yet flushed to 01670 // disk, are going to be overwritten with old data. Bring them back into 01671 // memory and remove their FREE_HBIN marker from the list. 01672 // 01673 List = Hive->Storage[Stable].FreeBins.Flink; 01674 while (List != &Hive->Storage[Stable].FreeBins) { 01675 01676 FreeBin = CONTAINING_RECORD(List, FREE_HBIN, ListEntry); 01677 List = List->Flink; 01678 01679 if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { 01680 for (i=0; i<FreeBin->Size; i+=HBLOCK_SIZE) { 01681 Map = HvpGetCellMap(Hive, FreeBin->FileOffset+i); 01682 VALIDATE_CELL_MAP(__LINE__,Map,Hive,FreeBin->FileOffset+i); 01683 Map->BlockAddress = (Map->BinAddress & HMAP_BASE)+i; 01684 Map->BinAddress &= ~HMAP_DISCARDABLE; 01685 } 01686 RemoveEntryList(&FreeBin->ListEntry); 01687 (Hive->Free)(FreeBin, sizeof(FREE_HBIN)); 01688 } 01689 } 01690 01691 // 01692 // OverRead base block. 01693 // 01694 Offset = 0; 01695 if ( (Hive->FileRead)( 01696 Hive, 01697 HFILE_TYPE_PRIMARY, 01698 &Offset, 01699 Hive->BaseBlock, 01700 HBLOCK_SIZE 01701 ) != TRUE) 01702 { 01703 KeBugCheckEx(REGISTRY_ERROR,7,1,0,0); 01704 } 01705 TailStart = (HCELL_INDEX)(Hive->BaseBlock->Length); 01706 01707 // 01708 // Free "tail" memory and maps for it, update hive size pointers 01709 // 01710 HvFreeHivePartial(Hive, TailStart, Stable); 01711 01712 // 01713 // Clear dirty vector for data past Hive->BaseBlock->Length 01714 // 01715 Start = Hive->BaseBlock->Length / HSECTOR_SIZE; 01716 End = Hive->DirtyVector.SizeOfBitMap; 01717 BitLength = End - Start; 01718 01719 RtlClearBits(&(Hive->DirtyVector), Start, BitLength); 01720 01721 // 01722 // Scan dirty blocks. Read contiguous blocks off disk into hive. 01723 // Stop when we get to reduced length. 01724 // 01725 BitMap = &(Hive->DirtyVector); 01726 Current = 0; 01727 while (HvpFindNextDirtyBlock( 01728 Hive, 01729 &Hive->DirtyVector, 01730 &Current, &Address, 01731 &ReadLength, 01732 &Offset 01733 )) 01734 { 01735 ASSERT(Offset < (Hive->BaseBlock->Length + sizeof(HBASE_BLOCK))); 01736 rc = (Hive->FileRead)( 01737 Hive, 01738 HFILE_TYPE_PRIMARY, 01739 &Offset, 01740 (PVOID)Address, 01741 ReadLength 01742 ); 01743 if (rc == FALSE) { 01744 KeBugCheckEx(REGISTRY_ERROR,7,2,(ULONG_PTR)&Offset,rc); 01745 } 01746 } 01747 01748 // 01749 // If we read the start of any HBINs into memory, it is likely 01750 // their MemAlloc fields are invalid. Walk through the HBINs 01751 // and write valid MemAlloc values for any HBINs whose first 01752 // sector was reread. 01753 // 01754 p=0; 01755 while (p < Hive->Storage[Stable].Length) { 01756 t = HvpGetCellMap(Hive, p); 01757 VALIDATE_CELL_MAP(__LINE__,t,Hive,p); 01758 Bin = (PHBIN)(t->BlockAddress & HMAP_BASE); 01759 01760 if ((t->BinAddress & HMAP_DISCARDABLE)==0) { 01761 if (RtlCheckBit(&Hive->DirtyVector, p / HSECTOR_SIZE)==1) { 01762 // 01763 // The first sector in the HBIN is dirty. 01764 // 01765 // Reset the BinAddress to the Block address to cover 01766 // the case where a few smaller bins have been coalesced 01767 // into a larger bin. We want the smaller bins back now. 01768 // 01769 t->BinAddress = (t->BinAddress & ~HMAP_BASE) | t->BlockAddress; 01770 01771 // Check the map to see if this is the start 01772 // of a memory allocation or not. 01773 // 01774 01775 if (t->BinAddress & HMAP_NEWALLOC) { 01776 // 01777 // Walk through the map to determine the length 01778 // of the allocation. 01779 // 01780 Bin->MemAlloc = 0; 01781 do { 01782 t = HvpGetCellMap(Hive, p+Bin->MemAlloc+HBLOCK_SIZE); 01783 Bin->MemAlloc += HBLOCK_SIZE; 01784 if (p+Bin->MemAlloc == Hive->Storage[Stable].Length) { 01785 // 01786 // Reached the end of the hive. 01787 // 01788 break; 01789 } 01790 VALIDATE_CELL_MAP(__LINE__,t,Hive,p+Bin->MemAlloc); 01791 } while ( (t->BinAddress & HMAP_NEWALLOC) == 0); 01792 01793 } else { 01794 Bin->MemAlloc = 0; 01795 } 01796 } 01797 01798 p += Bin->Size; 01799 01800 } else { 01801 FreeBin = (PFREE_HBIN)t->BlockAddress; 01802 p += FreeBin->Size; 01803 } 01804 } 01805 01806 // 01807 // be sure we haven't filled memory with trash 01808 // 01809 checkstatus = HvCheckHive(Hive, NULL); 01810 if (checkstatus != 0) { 01811 KeBugCheckEx(REGISTRY_ERROR,7,3,(ULONG_PTR)Hive,checkstatus); 01812 } 01813 01814 // 01815 // reinit the free list 01816 // 01817 for (i = 0; i < HHIVE_FREE_DISPLAY_SIZE; i++) { 01818 Hive->Storage[Stable].FreeDisplay[i] = HCELL_NIL; 01819 TailDisplay[i] = HCELL_NIL; 01820 } 01821 Hive->Storage[Stable].FreeSummary = 0; 01822 01823 // 01824 // rebuild the free list 01825 // 01826 p = 0; 01827 while (p < Hive->Storage[Stable].Length) { 01828 t = HvpGetCellMap(Hive, p); 01829 VALIDATE_CELL_MAP(__LINE__,t,Hive,p); 01830 01831 if ((t->BinAddress & HMAP_DISCARDABLE) == 0) { 01832 Bin = (PHBIN)((t->BinAddress) & HMAP_BASE); 01833 01834 if ( ! HvpEnlistFreeCells(Hive, Bin, Bin->FileOffset,TailDisplay)) { 01835 KeBugCheckEx(REGISTRY_ERROR,7,5,(ULONG_PTR)Bin,Bin->FileOffset); 01836 } 01837 01838 p = (ULONG)p + Bin->Size; 01839 } else { 01840 FreeBin = (PFREE_HBIN)t->BlockAddress; 01841 p = (ULONG)p + FreeBin->Size; 01842 } 01843 } 01844 01845 // 01846 // Finally we need to rewrite the parent field in the root hcell. This is 01847 // patched in at hive load time so the correct value could have just been 01848 // overwritten with whatever happened to be on disk. 01849 // 01850 RootNode = (PCM_KEY_NODE)HvGetCell(Hive, RootCell); 01851 RootNode->Parent = LinkCell; 01852 RootNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE; 01853 01854 01855 // 01856 // be sure the structure of the thing is OK after all this 01857 // 01858 checkstatus = CmCheckRegistry((PCMHIVE)Hive, FALSE); 01859 if (checkstatus != 0) { 01860 KeBugCheckEx(REGISTRY_ERROR,7,6,(ULONG_PTR)Hive,checkstatus); 01861 } 01862 01863 // 01864 // Clear dirty vector. 01865 // 01866 RtlClearAllBits(&(Hive->DirtyVector)); 01867 Hive->DirtyCount = 0; 01868 01869 01870 // 01871 // Adjust the file size, if this fails, ignore it, since it just 01872 // means the file is too big. 01873 // 01874 (Hive->FileSetSize)( 01875 Hive, 01876 HFILE_TYPE_PRIMARY, 01877 (Hive->BaseBlock->Length + HBLOCK_SIZE) 01878 ); 01879 01880 return; 01881 }

BOOLEAN HvSyncHive PHHIVE  Hive  ) 
 

Definition at line 647 of file hivesync.c.

References _HHIVE::Alternate, ASSERT, CML_BUGCHECK, CML_FLOW, CML_WORKER, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, DumpDirtyVector, FALSE, HFILE_TYPE_ALTERNATE, HFILE_TYPE_PRIMARY, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HvpDiscardBins(), HvpDoWriteHive(), HvpTruncateBins(), HvpWriteLog(), HvShutdownComplete, IoSetThreadHardErrorMode(), _HHIVE::Log, _HHIVE::ReadOnly, RtlClearAllBits(), _HHIVE::Signature, and TRUE.

Referenced by CmFlushKey(), CmpDoFlushAll(), CmpInitializeHiveList(), EhCloseHive(), and EhOpenHive().

00652 : 00653 00654 Force backing store to match the memory image of the Stable 00655 part of the hive's space. 00656 00657 Logs, primary, and alternate data can be written. Primary is 00658 always written. Normally either a log or an alternate, but 00659 not both, will also be written. 00660 00661 It is possible to write only the primary. 00662 00663 All dirty bits will be set clear. 00664 00665 Arguments: 00666 00667 Hive - supplies a pointer to the hive control structure for the 00668 hive of interest 00669 00670 Return Value: 00671 00672 TRUE - it worked 00673 00674 FALSE - some failure. 00675 00676 --*/ 00677 { 00678 BOOLEAN oldFlag; 00679 00680 CMLOG(CML_WORKER, CMS_IO) { 00681 KdPrint(("HvSyncHive:\n\t")); 00682 KdPrint(("Hive:%08lx\n", Hive)); 00683 } 00684 00685 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00686 ASSERT(Hive->ReadOnly == FALSE); 00687 00688 // 00689 // Punt if post shutdown 00690 // 00691 if (HvShutdownComplete) { 00692 CMLOG(CML_BUGCHECK, CMS_IO) { 00693 KdPrint(("HvSyncHive: Attempt to sync AFTER SHUTDOWN\n")); 00694 } 00695 return FALSE; 00696 } 00697 00698 // 00699 // If nothing dirty, do nothing 00700 // 00701 if (Hive->DirtyCount == 0) { 00702 return TRUE; 00703 } 00704 00705 HvpTruncateBins(Hive); 00706 00707 // 00708 // If hive is volatile, do nothing 00709 // 00710 if (Hive->HiveFlags & HIVE_VOLATILE) { 00711 return TRUE; 00712 } 00713 00714 CMLOG(CML_FLOW, CMS_IO) { 00715 KdPrint(("\tDirtyCount:%08lx\n", Hive->DirtyCount)); 00716 KdPrint(("\tDirtyVector:")); 00717 DumpDirtyVector(Hive); 00718 } 00719 00720 // 00721 // disable hard error popups, to avoid self deadlock on bogus devices 00722 // 00723 oldFlag = IoSetThreadHardErrorMode(FALSE); 00724 00725 // 00726 // Write a log. 00727 // 00728 if (Hive->Log == TRUE) { 00729 if (HvpWriteLog(Hive) == FALSE) { 00730 IoSetThreadHardErrorMode(oldFlag); 00731 return FALSE; 00732 } 00733 } 00734 00735 // 00736 // Write the primary 00737 // 00738 if (HvpDoWriteHive(Hive, HFILE_TYPE_PRIMARY) == FALSE) { 00739 IoSetThreadHardErrorMode(oldFlag); 00740 return FALSE; 00741 } 00742 00743 // 00744 // Write an alternate 00745 // 00746 if (Hive->Alternate == TRUE) { 00747 if (HvpDoWriteHive(Hive, HFILE_TYPE_ALTERNATE) == FALSE) { 00748 IoSetThreadHardErrorMode(oldFlag); 00749 return FALSE; 00750 } 00751 } 00752 00753 // 00754 // restore hard error popups mode 00755 // 00756 IoSetThreadHardErrorMode(oldFlag); 00757 00758 // 00759 // Hive was successfully written out, discard any bins marked as 00760 // discardable. 00761 // 00762 HvpDiscardBins(Hive); 00763 00764 // 00765 // Clear the dirty map 00766 // 00767 RtlClearAllBits(&(Hive->DirtyVector)); 00768 Hive->DirtyCount = 0; 00769 00770 return TRUE; 00771 }

NTSTATUS HvWriteHive PHHIVE  Hive  ) 
 

Definition at line 1433 of file hivesync.c.

References _HHIVE::Allocate, ASSERT, _HHIVE::BaseBlock, _HHIVE::Cluster, CML_BUGCHECK, CML_MAJOR, CMLOG, CmpDoFileSetSize(), CmpFree(), CmpReleaseGlobalQuota(), CMS_IO, _HHIVE::DirtyVector, FALSE, _HHIVE::Free, HFILE_TYPE_EXTERNAL, HHIVE_SIGNATURE, Hive, HSECTOR_SIZE, HvpDoWriteHive(), HvShutdownComplete, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _HHIVE::ReadOnly, ROUND_UP, RtlSetAllBits(), _HHIVE::Signature, Stable, and TRUE.

Referenced by CmpInitializeHiveList(), CmSaveKey(), and CmSaveMergedKeys().

01438 : 01439 01440 Write the hive out. Write only to the Primary file, neither 01441 logs nor alternates will be updated. The hive will be written 01442 to the HFILE_TYPE_EXTERNAL handle. 01443 01444 Intended for use in applications like SaveKey. 01445 01446 Only Stable storage will be written (as for any hive.) 01447 01448 Presumption is that layer above has set HFILE_TYPE_EXTERNAL 01449 handle to point to correct place. 01450 01451 Applying this call to an active hive will generally hose integrity 01452 measures. 01453 01454 HOW IT WORKS: 01455 01456 Make a new DirtyVector. Fill it with 1s (all dirty). 01457 Make hive point at it. We now have what looks like 01458 a completely dirty hive. 01459 01460 Call HvpWriteHive, which will write the whole thing to disk. 01461 01462 Put back DirtyVector, and free the extra one we used. 01463 01464 In failure case, force Sequence numbers in Hive and BaseBlock 01465 to match. 01466 01467 Arguments: 01468 01469 Hive - supplies a pointer to the hive control structure for the 01470 hive of interest. 01471 01472 Return Value: 01473 01474 Status. 01475 01476 --*/ 01477 { 01478 PULONG SaveDirtyVector; 01479 ULONG SaveDirtyVectorSize; 01480 PULONG AltDirtyVector; 01481 ULONG AltDirtyVectorSize; 01482 PHBASE_BLOCK SaveBaseBlock; 01483 PHBASE_BLOCK AltBaseBlock; 01484 ULONG Alignment; 01485 01486 NTSTATUS status; 01487 01488 01489 CMLOG(CML_MAJOR, CMS_IO) { 01490 KdPrint(("HvWriteHive: \n")); 01491 KdPrint(("\tHive = %08lx\n")); 01492 } 01493 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 01494 ASSERT(Hive->ReadOnly == FALSE); 01495 01496 01497 // 01498 // Punt if post shutdown 01499 // 01500 if (HvShutdownComplete) { 01501 CMLOG(CML_BUGCHECK, CMS_IO) { 01502 KdPrint(("HvWriteHive: Attempt to write hive AFTER SHUTDOWN\n")); 01503 } 01504 return STATUS_REGISTRY_IO_FAILED; 01505 } 01506 01507 // 01508 // Splice in a duplicate DirtyVector with all bits set. 01509 // 01510 SaveDirtyVector = Hive->DirtyVector.Buffer; 01511 SaveDirtyVectorSize = Hive->DirtyVector.SizeOfBitMap; 01512 SaveBaseBlock = Hive->BaseBlock; 01513 01514 AltDirtyVectorSize = (Hive->Storage[Stable].Length / HSECTOR_SIZE) / 8; 01515 AltDirtyVector = (Hive->Allocate)(ROUND_UP(AltDirtyVectorSize,sizeof(ULONG)), FALSE); 01516 if (AltDirtyVector == NULL) { 01517 status = STATUS_INSUFFICIENT_RESOURCES; 01518 goto Exit1; 01519 } 01520 Hive->DirtyVector.Buffer = AltDirtyVector; 01521 Hive->DirtyVector.SizeOfBitMap = AltDirtyVectorSize * 8; 01522 RtlSetAllBits(&(Hive->DirtyVector)); 01523 01524 // 01525 // Splice in a duplicate BaseBlock 01526 // 01527 AltBaseBlock = (Hive->Allocate)(sizeof(HBASE_BLOCK), TRUE); 01528 if (AltBaseBlock == NULL) { 01529 status = STATUS_INSUFFICIENT_RESOURCES; 01530 goto Exit2; 01531 } 01532 // 01533 // Make sure the buffer we got back is cluster-aligned. If not, try 01534 // harder to get an aligned buffer. 01535 // 01536 Alignment = Hive->Cluster * HSECTOR_SIZE - 1; 01537 if (((ULONG_PTR)AltBaseBlock & Alignment) != 0) { 01538 (Hive->Free)(AltBaseBlock, sizeof(HBASE_BLOCK)); 01539 AltBaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE)); 01540 if (AltBaseBlock == NULL) { 01541 status = STATUS_INSUFFICIENT_RESOURCES; 01542 goto Exit2; 01543 } 01544 // 01545 // Return the quota for the extra allocation, as we are not really using 01546 // it and it will not be accounted for later when we free it. 01547 // 01548 CmpReleaseGlobalQuota(PAGE_SIZE - sizeof(HBASE_BLOCK)); 01549 } 01550 01551 RtlMoveMemory(AltBaseBlock, SaveBaseBlock, HSECTOR_SIZE); 01552 Hive->BaseBlock = AltBaseBlock; 01553 01554 // 01555 // Ensure the file can be made big enough, then do the deed 01556 // 01557 status = CmpDoFileSetSize(Hive, 01558 HFILE_TYPE_EXTERNAL, 01559 Hive->Storage[Stable].Length); 01560 01561 if (NT_SUCCESS(status)) { 01562 if (!HvpDoWriteHive(Hive, HFILE_TYPE_EXTERNAL)) { 01563 status = STATUS_REGISTRY_IO_FAILED; 01564 } 01565 } 01566 01567 // 01568 // Clean up, success or failure 01569 // 01570 CmpFree(AltBaseBlock, sizeof(HBASE_BLOCK)); 01571 01572 Exit2: 01573 CmpFree(AltDirtyVector, ROUND_UP(AltDirtyVectorSize,sizeof(ULONG))); 01574 01575 Exit1: 01576 Hive->DirtyVector.Buffer = SaveDirtyVector; 01577 Hive->DirtyVector.SizeOfBitMap = SaveDirtyVectorSize; 01578 Hive->BaseBlock = SaveBaseBlock; 01579 return status; 01580 }


Generated on Sat May 15 19:44:05 2004 for test by doxygen 1.3.7