00001 /*++ 00002 00003 Copyright (c) 1999 Microsoft Corporation 00004 00005 Module Name: 00006 00007 hivedata.h 00008 00009 Abstract: 00010 00011 This module contains data structures used by the 00012 direct memory loaded hive manager. 00013 00014 Author: 00015 00016 Dragos C. Sambotin (dragoss) 13-Jan-99 00017 00018 Revision History: 00019 00020 00021 00022 --*/ 00023 00024 #ifndef __HIVE_DATA__ 00025 #define __HIVE_DATA__ 00026 00027 // 00028 // ===== Arbitrary Limits Imposed For Sanity ===== 00029 // 00030 #define HSANE_CELL_MAX (1024*1024) // 1 megabyte max size for 00031 // a single cell 00032 00033 00034 // 00035 // ===== Tuning ===== 00036 00037 #define HBIN_THRESHOLD (HBLOCK_SIZE-512) // If less than threshold 00038 // bytes would be left in 00039 // bin, add another page 00040 00041 #define HLOG_GROW HBLOCK_SIZE // Minimum size to grow log 00042 // by. Can set this up 00043 // if we think it thrashes. 00044 00045 #define HCELL_BIG_ROUND (HBLOCK_SIZE*3) // 00046 // If someone tries to 00047 // allocate a very large 00048 // cell, round it up to 00049 // HBLOCK_SIZE. This is 00050 // the rather arbitrary 00051 // define for "very large" 00052 // 00053 // 00054 // Never shrink the log files smaller than this, this prevents people 00055 // from sucking up all the disk space and then being unable to do 00056 // critical registry operations (like logging on to delete some files) 00057 // 00058 #define HLOG_MINSIZE(Hive) \ 00059 ((Hive)->Cluster * HSECTOR_SIZE * 2) 00060 00061 // 00062 // ===== Basic Structures and Definitions ===== 00063 // 00064 // These are same whether on disk or in memory. 00065 // 00066 00067 // 00068 // NOTE: Volatile == storage goes away at reboot 00069 // Stable == Persistent == Not Volatile 00070 // 00071 typedef enum { 00072 Stable = 0, 00073 Volatile = 1 00074 } HSTORAGE_TYPE; 00075 00076 #define HTYPE_COUNT 2 00077 00078 // 00079 // --- HCELL_INDEX --- 00080 // 00081 // 00082 // Handle to a cell -> effectively the "virtual" address of the cell, 00083 // HvMapCell converts this to a "real" address, that is, a memory 00084 // address. Mapping scheme is very much like that standard two level 00085 // page table. No mappings stored in file, they are built up when 00086 // the file is read in. (The INDEX in HCELL_INDEX is historical) 00087 // 00088 // Bit 31 30-21 20-12 11-0 00089 // +----------------------------+ 00090 // | T | Table | Block | Offset | 00091 // +----------------------------+ 00092 // 00093 // T = Type(1)= 0 for stable ("normal") storage 00094 // 1 for volatile storage 00095 // 00096 // Table(10) = Index into directory of mapping tables, selects a table. 00097 // Each mapping table is an array of HMAP_ENTRY structures. 00098 // 00099 // Block(9) = Index into Table, selects an HMAP_ENTRY. HMAP_ENTRY 00100 // contains address of area in memory that this HCELL_INDEX 00101 // maps to. (Base of memory copy of Block) 00102 // 00103 // Offset(12) = Offset within page, of the Cell header for the cell 00104 // of interest. 00105 // 00106 typedef ULONG HCELL_INDEX; 00107 typedef HCELL_INDEX *PHCELL_INDEX; 00108 00109 #define HCELL_NIL ((HCELL_INDEX)(-1)) 00110 00111 #define HCELL_TYPE_MASK 0x80000000 00112 #define HCELL_TYPE_SHIFT 31 00113 00114 #define HCELL_TABLE_MASK 0x7fe00000 00115 #define HCELL_TABLE_SHIFT 21 00116 00117 #define HCELL_BLOCK_MASK 0x001ff000 00118 #define HCELL_BLOCK_SHIFT 12 00119 00120 #define HCELL_OFFSET_MASK 0x00000fff 00121 00122 #define HBLOCK_SIZE 0x1000 // LOGICAL block size 00123 // This is the size of one of 00124 // the registry's logical/virtual 00125 // pages. It has no particular 00126 // relationship to page size 00127 // of the machine. 00128 00129 #define HSECTOR_SIZE 0x200 // LOGICAL sector size 00130 #define HSECTOR_COUNT 8 // LOGICAL sectors / LOGICAL Block 00131 00132 #define HTABLE_SLOTS 512 // 9 bits of address 00133 #define HDIRECTORY_SLOTS 1024 // 10 bits of address 00134 00135 #define HvGetCellType(Cell) ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT)) 00136 00137 // 00138 // --- HCELL --- an object within the hive (A bin is filled with HCELLs) 00139 // 00140 // Any given item of user data must fit within a single HCELL. 00141 // HCELLs cannot span Bins. 00142 // 00143 #define HCELL_PAD(Hive) ((Hive->Version>=2) ? 8 : 16) 00144 // All cells must be at least this large, 00145 // All allocations on this boundary 00146 00147 #define HCELL_ALLOCATE_FILL 0xb2 // bz -> buzz buzz (yeah, it's a stretch) 00148 // must fill all newly allocated 00149 // cells for security reasons 00150 00151 #define HCELL_FREE_FILL 0xfc // fc = HvFreeCell... 00152 00153 // 00154 // Currently we support two cell formats, one with a Last backpointer (old version), 00155 // and one without (new version) 00156 // 00157 // All cells in a hive must be of the same type. Version 1 hives use the old version, 00158 // Version 2 or greater use the new version. 00159 // 00160 00161 #define USE_OLD_CELL(Hive) (Hive->Version==1) 00162 00163 typedef struct _HCELL { 00164 LONG Size; 00165 union { 00166 struct { 00167 ULONG Last; 00168 union { 00169 ULONG UserData; 00170 HCELL_INDEX Next; // offset of next element in freelist (not a FLink) 00171 } u; 00172 } OldCell; 00173 00174 struct { 00175 union { 00176 ULONG UserData; 00177 HCELL_INDEX Next; // offset of next element in freelist (not a FLink) 00178 } u; 00179 } NewCell; 00180 } u; 00181 } HCELL, *PHCELL; 00182 00183 00184 // 00185 // --- HBIN --- is a contiguous set of HBLOCKs, filled with HCELLs. 00186 // 00187 #define HBIN_SIGNATURE 0x6e696268 // "hbin" 00188 #define HBIN_NIL (-1) 00189 00190 #pragma pack(4) 00191 typedef struct _HBIN { 00192 ULONG Signature; 00193 ULONG FileOffset; // Own file offset (used in checking) 00194 ULONG Size; // Size of bin in bytes, all inclusive 00195 ULONG Reserved1[2]; // Old FreeSpace and FreeList (from 1.0) 00196 LARGE_INTEGER TimeStamp; // Old Link (from 1.0). Usually trash, but 00197 // first bin has valid value used for .log 00198 // correspondence testing, only meaningful 00199 // on disk. 00200 ULONG MemAlloc; // if non 0, this is first bin of allocation 00201 // and this is it's size. else, middle 00202 // bin of an allocation. MEMORY ONLY, 00203 // field on disk has no meaning. 00204 00205 // 00206 // Cell data goes here 00207 // 00208 00209 } HBIN, *PHBIN; 00210 #pragma pack() 00211 00212 // 00213 // ===== On Disk Structures ===== 00214 // 00215 00216 // 00217 // NOTE: Hive storage is always allocated in units of 4K. This size 00218 // must be used on all systems, regardless of page size, since 00219 // the file format needs to be transportable amoung systems. 00220 // 00221 // NOTE: The integrity code depends on certain blocks (e.g., the 00222 // BASE block) being at least as large as the size of a physical 00223 // sector. (Otherwise data that should be left alone will 00224 // be written because the FS has to block/deblock.) This means 00225 // that the current code will not work with sectors > 4K. 00226 // 00227 // NOTE: A hive on disk always contains at least two blocks of storage. 00228 // 1 block for the base block, and 1 for the minimum 1 bin. 00229 // 00230 // NOTE: Only modified parts of the hive get written to disk. 00231 // This is not just for efficiency, but also to avoid risk 00232 // of destruction of unlogged data. Dirty bits keep track 00233 // of what has been modified, they reside in a simple 00234 // bit map attached to the hive. One bit for each logical 00235 // sector of 512 bytes. 00236 // 00237 // If the physical sector size of the machine is less than 512, 00238 // no matter, we'll always write in clumps of 512. If the 00239 // physical sector size is greater than 512, we'll always clump 00240 // data together so that we log and write data 00241 // in chunks of that size. Physical sector sizes > 4K will 00242 // not work correctly (logging will not work right, so system 00243 // crashes may lose data that would not otherwise be lost.) 00244 // 00245 00246 00247 // 00248 // An on disk image of a hive looks like this: 00249 // 00250 // +---------------------------------------+ 00251 // | HBASE_BLOCK | 1 Hive Block == 4K 00252 // | | 00253 // +---------------------------------------+ <- HBLOCK_SIZE boundary 00254 // | Bin - 1 to N 4K blocks | 00255 // | Each contains a signature, size, and | 00256 // | a boundary tag heap internal to | 00257 // | itself. Once allocated lives forever | 00258 // | and always at same file offset. | 00259 // +---------------------------------------+ <- HBLOCK_SIZE boundary 00260 // | Bin ... | 00261 // +---------------------------------------+ <- HBLOCK_SIZE boundary 00262 // ... 00263 // +---------------------------------------+ <- HBLOCK_SIZE boundary 00264 // | Last allocated Bin, new bins are put | 00265 // | immediately after this one. | 00266 // +---------------------------------------+ <- HBLOCK_SIZE boundary 00267 // 00268 // Hive files must allocate on HBLOCK_SIZE boundaries because they 00269 // might be written on many different systems, and must therefore be 00270 // set up for the largest cluster size we will support. 00271 // 00272 00273 // 00274 // The log file format is: 00275 // 00276 // +-------------------------------+ 00277 // | HBASE_BLOCK copy | 00278 // +-------------------------------+ <- cluster (usually 512) bound 00279 // | DirtyVector | 00280 // | (length computed from length | 00281 // | in the base block | 00282 // | (with "DIRT" on front as a | 00283 // | signature) | 00284 // +-------------------------------+ <- cluster (usually 512) bound 00285 // | Dirty Data | 00286 // +-------------------------------+ <- cluster (usually 512) bound 00287 // | Dirty Data | 00288 // +-------------------------------+ <- cluster (usually 512) bound 00289 // | ... | 00290 // +-------------------------------+ 00291 // 00292 // Recovery consists of reading the file in, computing which clusters 00293 // of data are present from the dirtyvector, and where they belong in 00294 // the hive address space. Position in file is by sequential count. 00295 // 00296 // Logs can allocate on cluster boundaries (physical sector size of 00297 // host machine) because they will never be written on any machine other 00298 // than the one that created them. 00299 // 00300 // For log to be valid: 00301 // 00302 // Signature, format, major.minor must match expected values. 00303 // Sequence1 and Sequence2 must match. 00304 // CheckSum must be correct. 00305 // Signture on DirtyVector must be correct 00306 // 00307 // For log to be applicable: 00308 // 00309 // Sequence in log must match sequence in hive. 00310 // TimeStamp in log must match TimeStamp in hive. 00311 // Hive must be in mid-update state, or have bogus header. 00312 // 00313 00314 // 00315 // --- HBASE_BLOCK --- on disk description of the hive 00316 // 00317 00318 // 00319 // NOTE: HBASE_BLOCK must be >= the size of physical sector, 00320 // or integrity assumptions will be violated, and crash 00321 // recovery may not work. 00322 // 00323 #define HBASE_BLOCK_SIGNATURE 0x66676572 // "regf" 00324 00325 #define HSYS_MAJOR 1 // Must match to read at all 00326 #define HSYS_MINOR 3 // Must be <= to write, always 00327 // set up to writer's version. 00328 00329 #define HBASE_FORMAT_MEMORY 1 // Direct memory load case 00330 00331 #define HBASE_NAME_ALLOC 64 // 32 unicode chars 00332 00333 #pragma pack(4) 00334 typedef struct _HBASE_BLOCK { 00335 ULONG Signature; 00336 ULONG Sequence1; 00337 ULONG Sequence2; 00338 LARGE_INTEGER TimeStamp; 00339 ULONG Major; 00340 ULONG Minor; 00341 ULONG Type; // HFILE_TYPE_[PRIMARY|LOG] 00342 ULONG Format; 00343 HCELL_INDEX RootCell; 00344 ULONG Length; // Includes all but header 00345 ULONG Cluster; // for logs only 00346 UCHAR FileName[HBASE_NAME_ALLOC]; // filename tail 00347 ULONG Reserved1[99]; 00348 ULONG CheckSum; 00349 ULONG Reserved2[128*7]; 00350 } HBASE_BLOCK, *PHBASE_BLOCK; 00351 #pragma pack() 00352 00353 #define HLOG_HEADER_SIZE (FIELD_OFFSET(HBASE_BLOCK, Reserved2)) 00354 #define HLOG_DV_SIGNATURE 0x54524944 // "DIRT" 00355 00356 // 00357 // ===== In Memory Structures ===== 00358 // 00359 00360 // 00361 // In memory image of a Hive looks just like the on-disk image, 00362 // EXCEPT that the HBIN structures can be spread throughout memory 00363 // rather than packed together. 00364 // 00365 // To find an HCELL in memory, a mechanism that takes an HCELL_INDEX and 00366 // derives a memory address from it is used. That mechanism is very 00367 // similar to a two level hardware paging table. 00368 // 00369 // A bit map is used to remember which parts of the hive are dirty. 00370 // 00371 // An HBLOCK can be in three different states 00372 // 1. Present in memory. BlockAddress and BinAddress are valid pointers. 00373 // This is the normal state of an HBLOCK. 00374 // 00375 // 2. Discardable. The HBIN containing this HBLOCK is completely free, but 00376 // the bin is dirty and needs to be written to the hive file before it 00377 // can be free. This is the state we will be in if somebody frees a 00378 // cell, causing the entire HBIN to become free. HvpEnlistFreeCell will 00379 // transition all the HBLOCKs in the free HBIN to this state, but will 00380 // not free their memory. After the dirty HBLOCKs are flushed to the 00381 // file, the memory will be freed. 00382 // 00383 // Note that if we need to allocate more storage from an HBIN in this 00384 // state, HvAllocateCell will simply change its state back to State 1 00385 // and it will be usable. 00386 // 00387 // An HBLOCK in this state has a valid BlockAddress and BinAddress, but 00388 // the HMAP_DISCARDABLE bit will be set. 00389 // 00390 // 3. Discarded. The HBIN containing this HBLOCK is completely free, and 00391 // is not dirty (i.e. it is marked as free in the hive file as well). 00392 // There is no memory allocated to contain this HBIN. After HvSyncHive 00393 // writes out an HBIN that is in State 2, it frees its pool and the 00394 // HBIN moves into this state. 00395 // 00396 // In order to use this HBIN, memory must be allocated to back it, and 00397 // the HBIN and initial HCELL must be recreated. (we could re-read it 00398 // from the hive file, but there's not much point in that since we know 00399 // that it is entirely free, so we might as well just recreate it and 00400 // save the disk i/o) 00401 // 00402 // An HBLOCK in this state has a NULL BlockAddress in the map. 00403 // The BinAddress will contain the next HCELL in the free list, so 00404 // we can reconstruct this when we need it. 00405 // The HMAP_NEWALLOC bit will be set for the first HBLOCK in the HBIN. 00406 // 00407 00408 // 00409 // --- HMAP_ENTRY --- Holds memory location of HCELL 00410 // 00411 #define HMAP_FLAGS (3) 00412 #define HMAP_BASE (~3) 00413 #define HMAP_NEWALLOC 1 00414 #define HMAP_DISCARDABLE 2 00415 00416 typedef struct _HMAP_ENTRY { 00417 ULONG_PTR BlockAddress; // Low 2 bits always 0. High bits 00418 // are memory address of HBLOCK that 00419 // HCELL starts in, add Offset to this. 00420 // (An HCELL can span several HBLOCKs) 00421 // 00422 00423 ULONG_PTR BinAddress; // Low bit set TRUE to mark beginning 00424 // of a new allocation. 00425 // High bits are memory address of 00426 // first HBLOCK in same bin. 00427 // (A given HCELL is always contained 00428 // in a single bin.) 00429 } HMAP_ENTRY, *PHMAP_ENTRY; 00430 00431 00432 // 00433 // --- HMAP_TABLE --- Array of MAP_ENTRYs that point to memory HBLOCKs 00434 // 00435 // Each HBLOCK worth of space in the Hive image has an entry in 00436 // an HMAP_TABLE. 00437 // 00438 typedef struct _HMAP_TABLE { 00439 HMAP_ENTRY Table[ HTABLE_SLOTS ]; 00440 } HMAP_TABLE, *PHMAP_TABLE; 00441 00442 00443 // 00444 // --- HMAP_DIRECTORY --- Array of pointers to HMAP_TABLEs 00445 // 00446 typedef struct _HMAP_DIRECTORY { 00447 PHMAP_TABLE Directory[ HDIRECTORY_SLOTS ]; 00448 } HMAP_DIRECTORY, *PHMAP_DIRECTORY; 00449 00450 00451 // 00452 // ===== Hive Routines typedefs ===== 00453 // 00454 struct _HHIVE; // forward 00455 00456 typedef 00457 PVOID 00458 (*PALLOCATE_ROUTINE) ( 00459 ULONG Length, // Size of new block wanted 00460 BOOLEAN UseForIo // TRUE if yes, FALSE if no 00461 ); 00462 00463 typedef 00464 VOID 00465 (*PFREE_ROUTINE) ( 00466 PVOID MemoryBlock, 00467 ULONG GlobalQuotaSize 00468 ); 00469 00470 typedef 00471 BOOLEAN 00472 (*PFILE_SET_SIZE_ROUTINE) ( 00473 struct _HHIVE *Hive, 00474 ULONG FileType, 00475 ULONG FileSize 00476 ); 00477 00478 typedef struct { 00479 ULONG FileOffset; 00480 PVOID DataBuffer; 00481 ULONG DataLength; 00482 } CMP_OFFSET_ARRAY, * PCMP_OFFSET_ARRAY; 00483 00484 typedef 00485 BOOLEAN 00486 (*PFILE_WRITE_ROUTINE) ( 00487 struct _HHIVE *Hive, 00488 ULONG FileType, 00489 PCMP_OFFSET_ARRAY offsetArray, 00490 ULONG offsetArrayCount, 00491 PULONG FileOffset 00492 ); 00493 00494 typedef 00495 BOOLEAN 00496 (*PFILE_READ_ROUTINE) ( 00497 struct _HHIVE *Hive, 00498 ULONG FileType, 00499 PULONG FileOffset, 00500 PVOID DataBuffer, 00501 ULONG DataLength 00502 ); 00503 00504 typedef 00505 BOOLEAN 00506 (*PFILE_FLUSH_ROUTINE) ( 00507 struct _HHIVE *Hive, 00508 ULONG FileType 00509 ); 00510 00511 typedef 00512 struct _CELL_DATA * 00513 (*PGET_CELL_ROUTINE)( 00514 struct _HHIVE *Hive, 00515 HCELL_INDEX Cell 00516 ); 00517 00518 // 00519 // --- HHIVE --- In memory descriptor for a hive. 00520 // 00521 00522 // 00523 // HHIVE contains pointers to service procedures, and pointers to 00524 // map structure. 00525 // 00526 // NOTE: Optimization - If the size of a hive is less than what can 00527 // be mapped with a single HMAP_TABLE (HTABLE_SLOTS * HBLOCK_SIZE, 00528 // or 2 megabytes) there is no real HMAP_DIRECTORY. Instead, 00529 // a single DWORD in the HHIVE acts as the 0th entry of the 00530 // directory. 00531 // 00532 // NOTE: Free Storage Management - When a hive is loaded, we build up 00533 // a display (vector) of lists of free cells. The first part 00534 // of this vector contains lists that only hold one size cell. 00535 // The size of cell on the list is HCELL_PAD * (ListIndex+1) 00536 // There are 15 of these lists, so all free cells between 8 and 00537 // 120 bytes are on these lists. 00538 // 00539 // The second part of this vector contains lists that hold more 00540 // than one size cell. Each size bucket is twice the previous 00541 // size. There are 8 of these lists, so all free cells between 136 and 00542 // 32768 bytes are on these lists. 00543 // 00544 // The last list in this vector contains all cells too large to 00545 // fit in any previous list. 00546 // 00547 // Example: All free cells of size 1 HCELL_PAD (8 bytes) 00548 // are on the list at offset 0 in FreeDisplay. 00549 // 00550 // All free cells of size 15 HCELL_PAD (120 bytes) 00551 // are on the list at offset 0xe. 00552 // 00553 // All free cells of size 16-31 HCELL_PAD (128-248 bytes) 00554 // are on the list at offset 0xf 00555 // 00556 // All free cells of size 32-63 HCELL_PAD (256-506 bytes) 00557 // are on the list at offset 0x10. 00558 // 00559 // All free cells of size 2048 HCELL_PAD (16384 bytes) 00560 // OR greater, are on the list at offset 0x17. 00561 // 00562 // FreeSummary is a bit vector, with a bit set to true for each 00563 // entry in FreeDisplay that is not empty. 00564 // 00565 00566 #define HHIVE_SIGNATURE 0xBEE0BEE0 00567 00568 #define HFILE_TYPE_PRIMARY 0 // Base hive file 00569 #define HFILE_TYPE_ALTERNATE 1 // Alternate (e.g. system.alt) 00570 #define HFILE_TYPE_LOG 2 // Log (security.log) 00571 #define HFILE_TYPE_EXTERNAL 3 // Target of savekey, etc. 00572 #define HFILE_TYPE_MAX 4 00573 00574 #define HHIVE_LINEAR_INDEX 16 // All computed linear indices < HHIVE_LINEAR_INDEX are valid 00575 #define HHIVE_EXPONENTIAL_INDEX 23 // All computed exponential indices < HHIVE_EXPONENTIAL_INDEX 00576 // and >= HHIVE_LINEAR_INDEX are valid. 00577 #define HHIVE_FREE_DISPLAY_SIZE 24 00578 00579 #define HHIVE_FREE_DISPLAY_SHIFT 3 // This must be log2 of HCELL_PAD! 00580 #define HHIVE_FREE_DISPLAY_BIAS 7 // Add to first set bit left of cell size to get exponential index 00581 00582 00583 #define FREE_HBIN_DISCARDABLE 1 00584 00585 typedef struct _FREE_HBIN { 00586 LIST_ENTRY ListEntry; 00587 ULONG Size; 00588 ULONG FileOffset; 00589 ULONG Flags; 00590 } FREE_HBIN, *PFREE_HBIN; 00591 00592 typedef struct _HHIVE { 00593 ULONG Signature; 00594 00595 PGET_CELL_ROUTINE GetCellRoutine; 00596 00597 PALLOCATE_ROUTINE Allocate; 00598 PFREE_ROUTINE Free; 00599 00600 PFILE_SET_SIZE_ROUTINE FileSetSize; 00601 PFILE_WRITE_ROUTINE FileWrite; 00602 PFILE_READ_ROUTINE FileRead; 00603 PFILE_FLUSH_ROUTINE FileFlush; 00604 00605 struct _HBASE_BLOCK *BaseBlock; 00606 00607 RTL_BITMAP DirtyVector; // only for Stable bins 00608 ULONG DirtyCount; 00609 ULONG DirtyAlloc; // allocated bytges for dirty vect 00610 ULONG Cluster; // Usually 1 512 byte sector. 00611 // Set up force writes to be 00612 // done in larger units on 00613 // machines with larger sectors. 00614 // Is number of logical 512 sectors. 00615 00616 BOOLEAN Flat; // TRUE if FLAT 00617 BOOLEAN ReadOnly; // TRUE if READONLY 00618 00619 BOOLEAN Log; 00620 BOOLEAN Alternate; 00621 00622 ULONG HiveFlags; 00623 00624 ULONG LogSize; 00625 00626 ULONG RefreshCount; // debugging aid 00627 00628 00629 ULONG StorageTypeCount; // 1 > Number of largest valid 00630 // type. (1 for Stable only, 00631 // 2 for stable & volatile) 00632 00633 ULONG Version; // hive version, to allow supporting multiple 00634 // formats simultaneously. 00635 00636 struct _DUAL { 00637 ULONG Length; 00638 PHMAP_DIRECTORY Map; 00639 PHMAP_TABLE SmallDir; 00640 ULONG Guard; // Always == -1 00641 00642 HCELL_INDEX FreeDisplay[HHIVE_FREE_DISPLAY_SIZE]; 00643 ULONG FreeSummary; 00644 LIST_ENTRY FreeBins; // list of freed HBINs (FREE_HBIN) 00645 00646 } Storage[ HTYPE_COUNT ]; 00647 00648 // 00649 // Caller defined data goes here 00650 // 00651 00652 } HHIVE, *PHHIVE; 00653 00654 00655 #endif // __HIVE_DATA__ 00656 00657