VOID HvFreeHivePartial( PHHIVE Hive, HCELL_INDEX Start, HSTORAGE_TYPE Type ) /*++ Routine Description: Free the memory and associated maps for the end of a hive starting at Start. The baseblock, hive, etc will not be touched. Arguments: Hive - supplies a pointer to hive control structure for hive to partially free. Start - HCELL_INDEX of first bin to free, will free from this bin (inclusive) to the end of the hives stable storage. Type - Type of storage (Stable or Volatile) to be freed. Return Value: NONE. --*/ { PHMAP_DIRECTORY Dir; PHMAP_ENTRY Me; HCELL_INDEX Address; ULONG StartTable; ULONG Length; PHBIN Bin; ULONG Tables; ULONG FirstBit; ULONG LastBit; PFREE_HBIN FreeBin; ASSERT(Hive->Flat == FALSE); ASSERT(Hive->ReadOnly == FALSE); Address = Start; Length = Hive->Storage[Type].Length; ASSERT(Address <= Length); if (Address == Length) { return; } // // Sweep through bin set // do { Me = HvpGetCellMap(Hive, Address + (Type*HCELL_TYPE_MASK)); VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address + (Type*HCELL_TYPE_MASK)); if (Me->BinAddress & HMAP_DISCARDABLE) { FreeBin = (PFREE_HBIN)Me->BlockAddress; if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { CmpFree((PVOID)HBIN_BASE(Me->BinAddress), FreeBin->Size); } else { // // The bin has been freed, but quota is still charged. // Since the file will now shrink, the quota must be // returned here. // if( Me->BinAddress & HMAP_INPAGEDPOOL) { // // we charge quota only for bins in paged-pool // CmpReleaseGlobalQuota(FreeBin->Size); } } RemoveEntryList(&FreeBin->ListEntry); Address += FreeBin->Size; CmpFree(FreeBin, sizeof(FREE_HBIN)); } else { Bin = (PHBIN)HBIN_BASE(Me->BinAddress); Address += HvpGetBinMemAlloc(Hive,Bin,Type); if( Me->BinAddress & HMAP_INPAGEDPOOL && HvpGetBinMemAlloc(Hive,Bin,Type) ) { // // free the bin only if it is allocated from paged pool // CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type)); } } } while (Address < Length); // // Free map table storage // Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE) - 1) / HTABLE_SLOTS; Dir = Hive->Storage[Type].Map; if (Start > 0) { StartTable = ((Start-1) / HBLOCK_SIZE) / HTABLE_SLOTS; } else { StartTable = (ULONG)-1; } HvpFreeMap(Hive, Dir, StartTable+1, Tables); // // update hysteresis (eventually queue work item) // if( Type == Stable) { CmpUpdateSystemHiveHysteresis(Hive,(Start&(~HCELL_TYPE_MASK)),Hive->Storage[Type].Length); } Hive->Storage[Type].Length = (Start&(~HCELL_TYPE_MASK)); if (Type==Stable) { // // Clear dirty vector for data past Hive->Storage[Stable].Length // FirstBit = Start / HSECTOR_SIZE; LastBit = Hive->DirtyVector.SizeOfBitMap; ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); RtlClearBits(&Hive->DirtyVector, FirstBit, LastBit-FirstBit); Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector); } HvpAdjustHiveFreeDisplay(Hive,Hive->Storage[Type].Length,Type); return; }
VOID HvFreeHive( PHHIVE Hive ) /*++ Routine Description: Free all of the pieces of a hive. Arguments: Hive - supplies a pointer to hive control structure for hive to free. this structure itself will NOT be freed, but everything it points to will. Return Value: NONE. --*/ { PHMAP_DIRECTORY Dir; PHMAP_ENTRY Me; HCELL_INDEX Address; ULONG Type; ULONG Length; PHBIN Bin; ULONG Tables; PFREE_HBIN FreeBin; ASSERT(Hive->Flat == FALSE); ASSERT(Hive->ReadOnly == FALSE); ASSERT(Stable == 0); ASSERT(Volatile == 1); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive(%ws) :\n", Hive->BaseBlock->FileName)); // // Iterate through both types of storage // for (Type = 0; Type <= Volatile; Type++) { Address = HCELL_TYPE_MASK * Type; Length = Hive->Storage[Type].Length + (HCELL_TYPE_MASK * Type); if( Hive->Storage[Type].Map && (Length > (HCELL_TYPE_MASK * Type)) ) { // // Sweep through bin set // do { Me = HvpGetCellMap(Hive, Address); VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address); if (Me->BinAddress & HMAP_DISCARDABLE) { // // hbin is either discarded or discardable, check the tombstone // FreeBin = (PFREE_HBIN)Me->BlockAddress; Address += FreeBin->Size; if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { CmpFree((PHBIN)HBIN_BASE(Me->BinAddress), FreeBin->Size); } else if(Me->BinAddress & HMAP_INPAGEDPOOL) { // // The bin has been freed, but quota is still charged. // Since the hive is being freed, the quota must be // returned here. // CmpReleaseGlobalQuota(FreeBin->Size); } CmpFree(FreeBin, sizeof(FREE_HBIN)); } else { if( Me->BinAddress & HMAP_INPAGEDPOOL ) { ASSERT( Me->BinAddress & HMAP_INPAGEDPOOL ); Bin = (PHBIN)HBIN_BASE(Me->BinAddress); Address += HvpGetBinMemAlloc(Hive,Bin,Type); #if DBG if( Type == Stable ) { CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive: BinAddress = 0x%p\t Size = 0x%lx\n", Bin, HvpGetBinMemAlloc(Hive,Bin,Type))); } #endif // // free the actual bin only if it is allocated from paged pool // if(HvpGetBinMemAlloc(Hive,Bin,Type)) { CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type)); } } else { // // bin was mapped into view; advance carefully // Address += HBLOCK_SIZE; } } } while (Address < Length); // // Free map table storage // ASSERT(Hive->Storage[Type].Length != (HCELL_TYPE_MASK * Type)); Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE)-1) / HTABLE_SLOTS; Dir = Hive->Storage[Type].Map; HvpFreeMap(Hive, Dir, 0, Tables); if (Tables > 0) { CmpFree(Hive->Storage[Type].Map, sizeof(HMAP_DIRECTORY)); // free dir if it exists } } Hive->Storage[Type].Length = 0; } CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n")); // // Free the base block // (Hive->Free)(Hive->BaseBlock,Hive->BaseBlockAlloc); Hive->BaseBlock = NULL; // // Free the dirty vector // if (Hive->DirtyVector.Buffer != NULL) { CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc); } HvpFreeHiveFreeDisplay(Hive); LogHiveFree(Hive); return; }
ULONG HvCheckHive( PHHIVE Hive, PULONG Storage OPTIONAL ) /*++ Routine Description: Check the consistency of a hive. Apply CheckBin to bins, make sure all pointers in the cell map point to correct places. Arguments: Hive - supplies a pointer to the hive control structure for the hive of interest. Storage - supplies adddress of ULONG to receive size of allocated user data Return Value: 0 if Hive is OK. Error return indicator if not. Error value comes from one of the check procedures. RANGE: 2000 - 2999 --*/ { HCELL_INDEX p; ULONG Length; ULONG localstorage = 0; PHMAP_ENTRY t; PHBIN Bin; ULONG i; ULONG rc; PFREE_HBIN FreeBin; HvCheckHiveDebug.Hive = Hive; HvCheckHiveDebug.Status = 0; HvCheckHiveDebug.Space = (ULONG)-1; HvCheckHiveDebug.MapPoint = HCELL_NIL; HvCheckHiveDebug.BinPoint = 0; p = 0; // // one pass for Stable space, one pass for Volatile // for (i = 0; i <= Volatile; i++) { Length = Hive->Storage[i].Length; // // for each bin in the space // while (p < Length) { t = HvpGetCellMap(Hive, p); if (t == NULL) { KdPrint(("HvCheckHive:")); KdPrint(("\tBin@:%08lx invalid\n", Bin)); HvCheckHiveDebug.Status = 2005; HvCheckHiveDebug.Space = i; HvCheckHiveDebug.MapPoint = p; return 2005; } if ((t->BinAddress & HMAP_DISCARDABLE) == 0) { Bin = (PHBIN)((t->BinAddress) & HMAP_BASE); // // bin header valid? // if ( (Bin->Size > Length) || (Bin->Signature != HBIN_SIGNATURE) || (Bin->FileOffset != p) ) { KdPrint(("HvCheckHive:")); KdPrint(("\tBin@:%08lx invalid\n", Bin)); HvCheckHiveDebug.Status = 2010; HvCheckHiveDebug.Space = i; HvCheckHiveDebug.MapPoint = p; HvCheckHiveDebug.BinPoint = Bin; return 2010; } // // structure inside the bin valid? // rc = HvCheckBin(Hive, Bin, &localstorage); if (rc != 0) { HvCheckHiveDebug.Status = rc; HvCheckHiveDebug.Space = i; HvCheckHiveDebug.MapPoint = p; HvCheckHiveDebug.BinPoint = Bin; return rc; } p = (ULONG)p + Bin->Size; } else { // // Bin is not present, skip it and advance to the next one. // FreeBin = (PFREE_HBIN)t->BlockAddress; p+=FreeBin->Size; } } p = 0x80000000; // Beginning of Volatile space } if (ARGUMENT_PRESENT(Storage)) { *Storage = localstorage; } return 0; }