You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
751 lines
27 KiB
751 lines
27 KiB
//depot/main/Base/ntos/inc/hivedata.h#9 - integrate change 19035 (text)
|
|
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
hivedata.h
|
|
|
|
Abstract:
|
|
|
|
This module contains data structures used by the
|
|
direct memory loaded hive manager.
|
|
|
|
Author:
|
|
|
|
Dragos C. Sambotin (dragoss) 13-Jan-99
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
#ifndef __HIVE_DATA__
|
|
#define __HIVE_DATA__
|
|
|
|
//
|
|
// ===== Arbitrary Limits Imposed For Sanity =====
|
|
//
|
|
#define HSANE_CELL_MAX (1024*1024) // 1 megabyte max size for
|
|
// a single cell
|
|
|
|
|
|
//
|
|
// ===== Tuning =====
|
|
|
|
#define HBIN_THRESHOLD (HBLOCK_SIZE-512) // If less than threshold
|
|
// bytes would be left in
|
|
// bin, add another page
|
|
|
|
#define HLOG_GROW HBLOCK_SIZE // Minimum size to grow log
|
|
// by. Can set this up
|
|
// if we think it thrashes.
|
|
|
|
#define HCELL_BIG_ROUND (HBLOCK_SIZE*3) //
|
|
// If someone tries to
|
|
// allocate a very large
|
|
// cell, round it up to
|
|
// HBLOCK_SIZE. This is
|
|
// the rather arbitrary
|
|
// define for "very large"
|
|
//
|
|
//
|
|
// Never shrink the log files smaller than this, this prevents people
|
|
// from taking up all the disk space and then being unable to do
|
|
// critical registry operations (like logging on to delete some files)
|
|
//
|
|
#define HLOG_MINSIZE(Hive) \
|
|
((Hive)->Cluster * HSECTOR_SIZE * 2)
|
|
|
|
//
|
|
// ===== Basic Structures and Definitions =====
|
|
//
|
|
// These are same whether on disk or in memory.
|
|
//
|
|
|
|
//
|
|
// NOTE: Volatile == storage goes away at reboot
|
|
// Stable == Persistent == Not Volatile
|
|
//
|
|
typedef enum {
|
|
Stable = 0,
|
|
Volatile = 1
|
|
} HSTORAGE_TYPE;
|
|
|
|
#define HTYPE_COUNT 2
|
|
|
|
//
|
|
// --- HCELL_INDEX ---
|
|
//
|
|
//
|
|
// Handle to a cell -> effectively the "virtual" address of the cell,
|
|
// HvMapCell converts this to a "real" address, that is, a memory
|
|
// address. Mapping scheme is very much like that standard two level
|
|
// page table. No mappings stored in file, they are built up when
|
|
// the file is read in. (The INDEX in HCELL_INDEX is historical)
|
|
//
|
|
// Bit 31 30-21 20-12 11-0
|
|
// +----------------------------+
|
|
// | T | Table | Block | Offset |
|
|
// +----------------------------+
|
|
//
|
|
// T = Type(1)= 0 for stable ("normal") storage
|
|
// 1 for volatile storage
|
|
//
|
|
// Table(10) = Index into directory of mapping tables, selects a table.
|
|
// Each mapping table is an array of HMAP_ENTRY structures.
|
|
//
|
|
// Block(9) = Index into Table, selects an HMAP_ENTRY. HMAP_ENTRY
|
|
// contains address of area in memory that this HCELL_INDEX
|
|
// maps to. (Base of memory copy of Block)
|
|
//
|
|
// Offset(12) = Offset within page, of the Cell header for the cell
|
|
// of interest.
|
|
//
|
|
typedef ULONG HCELL_INDEX;
|
|
typedef HCELL_INDEX *PHCELL_INDEX;
|
|
|
|
#ifdef DRAGOSS_PRIVATE_DEBUG
|
|
//#undef PAGE_SIZE
|
|
//#define PAGE_SIZE 0x2000
|
|
#endif //DRAGOSS_PRIVATE_DEBUG
|
|
|
|
#define HCELL_NIL ((HCELL_INDEX)(-1))
|
|
|
|
#define HCELL_TYPE_MASK 0x80000000
|
|
#define HCELL_TYPE_SHIFT 31
|
|
|
|
#define HCELL_TABLE_MASK 0x7fe00000
|
|
#define HCELL_TABLE_SHIFT 21
|
|
|
|
#define HCELL_BLOCK_MASK 0x001ff000
|
|
#define HCELL_BLOCK_SHIFT 12
|
|
|
|
#define HCELL_OFFSET_MASK 0x00000fff
|
|
|
|
#define HBLOCK_SIZE 0x1000 // LOGICAL block size
|
|
// This is the size of one of
|
|
// the registry's logical/virtual
|
|
// pages. It has no particular
|
|
// relationship to page size
|
|
// of the machine.
|
|
|
|
#define HSECTOR_SIZE 0x200 // LOGICAL sector size
|
|
#define HSECTOR_COUNT 8 // LOGICAL sectors / LOGICAL Block
|
|
|
|
#define HSECTOR_PER_PAGE_COUNT (PAGE_SIZE / HSECTOR_SIZE) // LOGICAL sectors / Physical page
|
|
|
|
#define HTABLE_SLOTS 512 // 9 bits of address
|
|
#define HDIRECTORY_SLOTS 1024 // 10 bits of address
|
|
|
|
#define HvGetCellType(Cell) ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT))
|
|
|
|
//
|
|
// --- HCELL --- an object within the hive (A bin is filled with HCELLs)
|
|
//
|
|
// Any given item of user data must fit within a single HCELL.
|
|
// HCELLs cannot span Bins.
|
|
//
|
|
#define HCELL_PAD(Hive) ((Hive->Version>=2) ? 8 : 16)
|
|
// All cells must be at least this large,
|
|
// All allocations on this boundary
|
|
|
|
#define HCELL_ALLOCATE_FILL 0xb2 // bz -> buzz buzz (yeah, it's a stretch)
|
|
// must fill all newly allocated
|
|
// cells for security reasons
|
|
|
|
#define HCELL_FREE_FILL 0xfc // fc = HvFreeCell...
|
|
|
|
//
|
|
// Currently we support two cell formats, one with a Last backpointer (old version),
|
|
// and one without (new version)
|
|
//
|
|
// All cells in a hive must be of the same type. Version 1 hives use the old version,
|
|
// Version 2 or greater use the new version.
|
|
//
|
|
|
|
#define USE_OLD_CELL(Hive) (Hive->Version==1)
|
|
|
|
typedef struct _HCELL {
|
|
LONG Size;
|
|
union {
|
|
struct {
|
|
ULONG Last;
|
|
union {
|
|
ULONG UserData;
|
|
HCELL_INDEX Next; // offset of next element in freelist (not a FLink)
|
|
} u;
|
|
} OldCell;
|
|
|
|
struct {
|
|
union {
|
|
ULONG UserData;
|
|
HCELL_INDEX Next; // offset of next element in freelist (not a FLink)
|
|
} u;
|
|
} NewCell;
|
|
} u;
|
|
} HCELL, *PHCELL;
|
|
|
|
|
|
//
|
|
// --- HBIN --- is a contiguous set of HBLOCKs, filled with HCELLs.
|
|
//
|
|
#define HBIN_SIGNATURE 0x6e696268 // "hbin"
|
|
#define HBIN_NIL (-1)
|
|
|
|
#pragma pack(4)
|
|
typedef struct _HBIN {
|
|
ULONG Signature;
|
|
ULONG FileOffset; // Own file offset (used in checking)
|
|
ULONG Size; // Size of bin in bytes, all inclusive
|
|
ULONG Reserved1[2]; // Old FreeSpace and FreeList (from 1.0)
|
|
LARGE_INTEGER TimeStamp; // Old Link (from 1.0). Usually trash, but
|
|
// first bin has valid value used for .log
|
|
// correspondence testing, only meaningful
|
|
// on disk.
|
|
ULONG Spare; // this used to be MemAlloc. We don't use it anymore as we
|
|
// can't afford to touch the bin (it's not residing in paged-pool
|
|
// anymore, so touching it means modifying mnw pages).
|
|
// Spare is used for the ShiftFreeBins Stuff - in memory only!
|
|
|
|
//
|
|
// Cell data goes here
|
|
//
|
|
|
|
} HBIN, *PHBIN;
|
|
#pragma pack()
|
|
|
|
//
|
|
// ===== On Disk Structures =====
|
|
//
|
|
|
|
//
|
|
// NOTE: Hive storage is always allocated in units of 4K. This size
|
|
// must be used on all systems, regardless of page size, since
|
|
// the file format needs to be transportable amoung systems.
|
|
//
|
|
// NOTE: The integrity code depends on certain blocks (e.g., the
|
|
// BASE block) being at least as large as the size of a physical
|
|
// sector. (Otherwise data that should be left alone will
|
|
// be written because the FS has to block/deblock.) This means
|
|
// that the current code will not work with sectors > 4K.
|
|
//
|
|
// NOTE: A hive on disk always contains at least two blocks of storage.
|
|
// 1 block for the base block, and 1 for the minimum 1 bin.
|
|
//
|
|
// NOTE: Only modified parts of the hive get written to disk.
|
|
// This is not just for efficiency, but also to avoid risk
|
|
// of destruction of unlogged data. Dirty bits keep track
|
|
// of what has been modified, they reside in a simple
|
|
// bit map attached to the hive. One bit for each logical
|
|
// sector of 512 bytes.
|
|
//
|
|
// If the physical sector size of the machine is less than 512,
|
|
// no matter, we'll always write in clumps of 512. If the
|
|
// physical sector size is greater than 512, we'll always clump
|
|
// data together so that we log and write data
|
|
// in chunks of that size. Physical sector sizes > 4K will
|
|
// not work correctly (logging will not work right, so system
|
|
// crashes may lose data that would not otherwise be lost.)
|
|
//
|
|
|
|
|
|
//
|
|
// An on disk image of a hive looks like this:
|
|
//
|
|
// +---------------------------------------+
|
|
// | HBASE_BLOCK | 1 Hive Block == 4K
|
|
// | |
|
|
// +---------------------------------------+ <- HBLOCK_SIZE boundary
|
|
// | Bin - 1 to N 4K blocks |
|
|
// | Each contains a signature, size, and |
|
|
// | a boundary tag heap internal to |
|
|
// | itself. Once allocated lives forever |
|
|
// | and always at same file offset. |
|
|
// +---------------------------------------+ <- HBLOCK_SIZE boundary
|
|
// | Bin ... |
|
|
// +---------------------------------------+ <- HBLOCK_SIZE boundary
|
|
// ...
|
|
// +---------------------------------------+ <- HBLOCK_SIZE boundary
|
|
// | Last allocated Bin, new bins are put |
|
|
// | immediately after this one. |
|
|
// +---------------------------------------+ <- HBLOCK_SIZE boundary
|
|
//
|
|
// Hive files must allocate on HBLOCK_SIZE boundaries because they
|
|
// might be written on many different systems, and must therefore be
|
|
// set up for the largest cluster size we will support.
|
|
//
|
|
|
|
//
|
|
// The log file format is:
|
|
//
|
|
// +-------------------------------+
|
|
// | HBASE_BLOCK copy |
|
|
// +-------------------------------+ <- cluster (usually 512) bound
|
|
// | DirtyVector |
|
|
// | (length computed from length |
|
|
// | in the base block |
|
|
// | (with "DIRT" on front as a |
|
|
// | signature) |
|
|
// +-------------------------------+ <- cluster (usually 512) bound
|
|
// | Dirty Data |
|
|
// +-------------------------------+ <- cluster (usually 512) bound
|
|
// | Dirty Data |
|
|
// +-------------------------------+ <- cluster (usually 512) bound
|
|
// | ... |
|
|
// +-------------------------------+
|
|
//
|
|
// Recovery consists of reading the file in, computing which clusters
|
|
// of data are present from the dirtyvector, and where they belong in
|
|
// the hive address space. Position in file is by sequential count.
|
|
//
|
|
// Logs can allocate on cluster boundaries (physical sector size of
|
|
// host machine) because they will never be written on any machine other
|
|
// than the one that created them.
|
|
//
|
|
// For log to be valid:
|
|
//
|
|
// Signature, format, major.minor must match expected values.
|
|
// Sequence1 and Sequence2 must match.
|
|
// CheckSum must be correct.
|
|
// Signture on DirtyVector must be correct
|
|
//
|
|
// For log to be applicable:
|
|
//
|
|
// Sequence in log must match sequence in hive.
|
|
// TimeStamp in log must match TimeStamp in hive.
|
|
// Hive must be in mid-update state, or have bogus header.
|
|
//
|
|
|
|
//
|
|
// --- HBASE_BLOCK --- on disk description of the hive
|
|
//
|
|
|
|
//
|
|
// NOTE: HBASE_BLOCK must be >= the size of physical sector,
|
|
// or integrity assumptions will be violated, and crash
|
|
// recovery may not work.
|
|
//
|
|
#define HBASE_BLOCK_SIGNATURE 0x66676572 // "regf"
|
|
|
|
#define HSYS_MAJOR 1 // Must match to read at all
|
|
#define HSYS_MINOR 3
|
|
|
|
#define HSYS_WHISTLER_BETA1 4 // Whistler Beta1 hives
|
|
|
|
#define HSYS_WHISTLER 5 // normal Whistler hives
|
|
|
|
#define HSYS_MINOR_SUPPORTED HSYS_WHISTLER // Must be <= to write, always
|
|
// set up to writer's version.
|
|
|
|
|
|
|
|
#define HBASE_FORMAT_MEMORY 1 // Direct memory load case
|
|
|
|
#define HBASE_NAME_ALLOC 64 // 32 unicode chars
|
|
|
|
//
|
|
// Boot Type Loader <-> Kernel communication
|
|
//
|
|
#define HBOOT_NORMAL 0
|
|
#define HBOOT_REPAIR 1
|
|
#define HBOOT_BACKUP 2
|
|
#define HBOOT_SELFHEAL 4
|
|
|
|
#pragma pack(4)
|
|
typedef struct _HBASE_BLOCK {
|
|
ULONG Signature;
|
|
ULONG Sequence1;
|
|
ULONG Sequence2;
|
|
LARGE_INTEGER TimeStamp;
|
|
ULONG Major;
|
|
ULONG Minor;
|
|
ULONG Type; // HFILE_TYPE_[PRIMARY|LOG]
|
|
ULONG Format;
|
|
HCELL_INDEX RootCell;
|
|
ULONG Length; // Includes all but header
|
|
ULONG Cluster; // for logs only
|
|
UCHAR FileName[HBASE_NAME_ALLOC]; // filename tail
|
|
ULONG Reserved1[99];
|
|
ULONG CheckSum;
|
|
ULONG Reserved2[128*7-2]; // subtract 2 for the volatile info
|
|
ULONG BootType; // set by bootloader
|
|
ULONG BootRecover; // set to 1 by bootloader if it did hive recovery
|
|
// nobody else is using this
|
|
} HBASE_BLOCK, *PHBASE_BLOCK;
|
|
#pragma pack()
|
|
|
|
#define HLOG_HEADER_SIZE (FIELD_OFFSET(HBASE_BLOCK, Reserved2))
|
|
#define HLOG_DV_SIGNATURE 0x54524944 // "DIRT"
|
|
|
|
//
|
|
// ===== In Memory Structures =====
|
|
//
|
|
|
|
//
|
|
// In memory image of a Hive looks just like the on-disk image,
|
|
// EXCEPT that the HBIN structures can be spread throughout memory
|
|
// rather than packed together.
|
|
//
|
|
// To find an HCELL in memory, a mechanism that takes an HCELL_INDEX and
|
|
// derives a memory address from it is used. That mechanism is very
|
|
// similar to a two level hardware paging table.
|
|
//
|
|
// A bit map is used to remember which parts of the hive are dirty.
|
|
//
|
|
// An HBLOCK can be in three different states
|
|
// 1. Present in memory. BlockAddress and BinAddress are valid pointers.
|
|
// This is the normal state of an HBLOCK.
|
|
//
|
|
// 2. Discardable. The HBIN containing this HBLOCK is completely free, but
|
|
// the bin is dirty and needs to be written to the hive file before it
|
|
// can be free. This is the state we will be in if somebody frees a
|
|
// cell, causing the entire HBIN to become free. HvpEnlistFreeCell will
|
|
// transition all the HBLOCKs in the free HBIN to this state, but will
|
|
// not free their memory. After the dirty HBLOCKs are flushed to the
|
|
// file, the memory will be freed.
|
|
//
|
|
// Note that if we need to allocate more storage from an HBIN in this
|
|
// state, HvAllocateCell will simply change its state back to State 1
|
|
// and it will be usable.
|
|
//
|
|
// An HBLOCK in this state has a valid BlockAddress and BinAddress, but
|
|
// the HMAP_DISCARDABLE bit will be set.
|
|
//
|
|
// 3. Discarded. The HBIN containing this HBLOCK is completely free, and
|
|
// is not dirty (i.e. it is marked as free in the hive file as well).
|
|
// There is no memory allocated to contain this HBIN. After HvSyncHive
|
|
// writes out an HBIN that is in State 2, it frees its pool and the
|
|
// HBIN moves into this state.
|
|
//
|
|
// In order to use this HBIN, memory must be allocated to back it, and
|
|
// the HBIN and initial HCELL must be recreated. (we could re-read it
|
|
// from the hive file, but there's not much point in that since we know
|
|
// that it is entirely free, so we might as well just recreate it and
|
|
// save the disk i/o)
|
|
//
|
|
// An HBLOCK in this state has a NULL BlockAddress in the map.
|
|
// The BinAddress will contain the next HCELL in the free list, so
|
|
// we can reconstruct this when we need it.
|
|
// The HMAP_NEWALLOC bit will be set for the first HBLOCK in the HBIN.
|
|
//
|
|
|
|
//
|
|
// --- HMAP_ENTRY --- Holds memory location of HCELL
|
|
//
|
|
#define HMAP_FLAGS (0xf)
|
|
#define HMAP_BASE (~(HMAP_FLAGS))
|
|
|
|
#define HBIN_BASE(BinAddress) (BinAddress & HMAP_BASE)
|
|
#define HBIN_FLAGS(BinAddress) (BinAddress & HMAP_FLAGS)
|
|
|
|
#define HMAP_NEWALLOC 1 // the bin is the beginning of a new
|
|
// allocation. When bin is in view this
|
|
// doesn't really matter
|
|
|
|
#define HMAP_DISCARDABLE 2 // bin is discardable (i.e. is all free)
|
|
// first time when we get the chance we'll
|
|
// free it (if it is in paged pool)
|
|
|
|
#define HMAP_INVIEW 4 // bin is mapped in system cache
|
|
|
|
#define HMAP_INPAGEDPOOL 8 // bin is allocated from paged pool
|
|
|
|
|
|
#define BIN_MAP_ALLOCATION_TYPE(Me) (((Me)->BinAddress)&(HMAP_INPAGEDPOOL|HMAP_INVIEW))
|
|
|
|
#define ASSERT_BIN_INVIEW(Me) ASSERT( ((Me)->BinAddress & HMAP_INVIEW) != 0 )
|
|
#define ASSERT_BIN_INPAGEDPOOL(Me) ASSERT( ((Me)->BinAddress & HMAP_INPAGEDPOOL) != 0 )
|
|
#define ASSERT_BIN_INVALID(Me) ASSERT( ((Me)->BinAddress & (HMAP_INPAGEDPOOL|HMAP_INVIEW)) == 0 )
|
|
#define ASSERT_BIN_VALID(Me) ASSERT( ((Me)->BinAddress & (HMAP_INPAGEDPOOL|HMAP_INVIEW)) != 0 )
|
|
|
|
struct _CM_VIEW_OF_FILE; //forward
|
|
typedef struct _HMAP_ENTRY {
|
|
ULONG_PTR BlockAddress; // Low 2 bits always 0. High bits
|
|
// are memory address of HBLOCK that
|
|
// HCELL starts in, add Offset to this.
|
|
// (An HCELL can span several HBLOCKs)
|
|
//
|
|
|
|
ULONG_PTR BinAddress; // Low bit set TRUE to mark beginning
|
|
// of a new allocation.
|
|
// High bits are memory address of
|
|
// first HBLOCK in same bin.
|
|
// (A given HCELL is always contained
|
|
// in a single bin.)
|
|
|
|
// Dragos: From here start the changes!!!
|
|
struct _CM_VIEW_OF_FILE *CmView; // pointer to the view; NULL when bin is not mapped
|
|
|
|
ULONG MemAlloc; // we needed to move this from the bin header to the map, in
|
|
// order to prevent the bin from being touched
|
|
|
|
/*
|
|
We don't really need this. Left just as a comment
|
|
|
|
|
|
ULONG Flags; // tells if a bin is mapped through
|
|
// a view, is allocated from paged pool
|
|
// or is unmapped/unallocated
|
|
|
|
|
|
ULONG_PTR MappedAddress; // temporary address inside the mapped view.
|
|
|
|
*/
|
|
|
|
} HMAP_ENTRY, *PHMAP_ENTRY;
|
|
|
|
|
|
//
|
|
// --- HMAP_TABLE --- Array of MAP_ENTRYs that point to memory HBLOCKs
|
|
//
|
|
// Each HBLOCK worth of space in the Hive image has an entry in
|
|
// an HMAP_TABLE.
|
|
//
|
|
typedef struct _HMAP_TABLE {
|
|
HMAP_ENTRY Table[ HTABLE_SLOTS ];
|
|
} HMAP_TABLE, *PHMAP_TABLE;
|
|
|
|
|
|
//
|
|
// --- HMAP_DIRECTORY --- Array of pointers to HMAP_TABLEs
|
|
//
|
|
typedef struct _HMAP_DIRECTORY {
|
|
PHMAP_TABLE Directory[ HDIRECTORY_SLOTS ];
|
|
} HMAP_DIRECTORY, *PHMAP_DIRECTORY;
|
|
|
|
|
|
//
|
|
// ===== Hive Routines typedefs =====
|
|
//
|
|
struct _HHIVE; // forward
|
|
|
|
typedef
|
|
PVOID
|
|
(*PALLOCATE_ROUTINE) (
|
|
ULONG Length, // Size of new block wanted
|
|
BOOLEAN UseForIo, // TRUE if yes, FALSE if no
|
|
ULONG Tag
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(*PFREE_ROUTINE) (
|
|
PVOID MemoryBlock,
|
|
ULONG GlobalQuotaSize
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PFILE_SET_SIZE_ROUTINE) (
|
|
struct _HHIVE *Hive,
|
|
ULONG FileType,
|
|
ULONG FileSize,
|
|
ULONG OldFileSize
|
|
);
|
|
|
|
typedef struct {
|
|
ULONG FileOffset;
|
|
PVOID DataBuffer;
|
|
ULONG DataLength;
|
|
} CMP_OFFSET_ARRAY, * PCMP_OFFSET_ARRAY;
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PFILE_WRITE_ROUTINE) (
|
|
struct _HHIVE *Hive,
|
|
ULONG FileType,
|
|
PCMP_OFFSET_ARRAY offsetArray,
|
|
ULONG offsetArrayCount,
|
|
PULONG FileOffset
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PFILE_READ_ROUTINE) (
|
|
struct _HHIVE *Hive,
|
|
ULONG FileType,
|
|
PULONG FileOffset,
|
|
PVOID DataBuffer,
|
|
ULONG DataLength
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PFILE_FLUSH_ROUTINE) (
|
|
struct _HHIVE *Hive,
|
|
ULONG FileType,
|
|
PLARGE_INTEGER FileOffset,
|
|
ULONG Length
|
|
);
|
|
|
|
typedef
|
|
struct _CELL_DATA *
|
|
(*PGET_CELL_ROUTINE)(
|
|
struct _HHIVE *Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(*PRELEASE_CELL_ROUTINE)(
|
|
struct _HHIVE *Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
//
|
|
// --- HHIVE --- In memory descriptor for a hive.
|
|
//
|
|
|
|
//
|
|
// HHIVE contains pointers to service procedures, and pointers to
|
|
// map structure.
|
|
//
|
|
// NOTE: Optimization - If the size of a hive is less than what can
|
|
// be mapped with a single HMAP_TABLE (HTABLE_SLOTS * HBLOCK_SIZE,
|
|
// or 2 megabytes) there is no real HMAP_DIRECTORY. Instead,
|
|
// a single DWORD in the HHIVE acts as the 0th entry of the
|
|
// directory.
|
|
//
|
|
// NOTE: Free Storage Management - When a hive is loaded, we build up
|
|
// a display (vector) of lists of free cells. The first part
|
|
// of this vector contains lists that only hold one size cell.
|
|
// The size of cell on the list is HCELL_PAD * (ListIndex+1)
|
|
// There are 15 of these lists, so all free cells between 8 and
|
|
// 120 bytes are on these lists.
|
|
//
|
|
// The second part of this vector contains lists that hold more
|
|
// than one size cell. Each size bucket is twice the previous
|
|
// size. There are 8 of these lists, so all free cells between 136 and
|
|
// 32768 bytes are on these lists.
|
|
//
|
|
// The last list in this vector contains all cells too large to
|
|
// fit in any previous list.
|
|
//
|
|
// Example: All free cells of size 1 HCELL_PAD (8 bytes)
|
|
// are on the list at offset 0 in FreeDisplay.
|
|
//
|
|
// All free cells of size 15 HCELL_PAD (120 bytes)
|
|
// are on the list at offset 0xe.
|
|
//
|
|
// All free cells of size 16-31 HCELL_PAD (128-248 bytes)
|
|
// are on the list at offset 0xf
|
|
//
|
|
// All free cells of size 32-63 HCELL_PAD (256-506 bytes)
|
|
// are on the list at offset 0x10.
|
|
//
|
|
// All free cells of size 2048 HCELL_PAD (16384 bytes)
|
|
// OR greater, are on the list at offset 0x17.
|
|
//
|
|
// FreeSummary is a bit vector, with a bit set to true for each
|
|
// entry in FreeDisplay that is not empty.
|
|
//
|
|
|
|
#define HHIVE_SIGNATURE 0xBEE0BEE0
|
|
|
|
#define HFILE_TYPE_PRIMARY 0 // Base hive file
|
|
#define HFILE_TYPE_LOG 1 // Log (security.log)
|
|
#define HFILE_TYPE_EXTERNAL 2 // Target of savekey, etc.
|
|
#define HFILE_TYPE_MAX 3
|
|
|
|
#define HHIVE_LINEAR_INDEX 16 // All computed linear indices < HHIVE_LINEAR_INDEX are valid
|
|
#define HHIVE_EXPONENTIAL_INDEX 23 // All computed exponential indices < HHIVE_EXPONENTIAL_INDEX
|
|
// and >= HHIVE_LINEAR_INDEX are valid.
|
|
#define HHIVE_FREE_DISPLAY_SIZE 24
|
|
|
|
#define HHIVE_FREE_DISPLAY_SHIFT 3 // This must be log2 of HCELL_PAD!
|
|
#define HHIVE_FREE_DISPLAY_BIAS 7 // Add to first set bit left of cell size to get exponential index
|
|
|
|
|
|
#define FREE_HBIN_DISCARDABLE 1 // the BlockAddress in HBIN points to the real bin
|
|
|
|
typedef struct _FREE_HBIN {
|
|
LIST_ENTRY ListEntry;
|
|
ULONG Size;
|
|
ULONG FileOffset;
|
|
ULONG Flags;
|
|
} FREE_HBIN, *PFREE_HBIN;
|
|
|
|
typedef struct _FREE_DISPLAY {
|
|
ULONG RealVectorSize;
|
|
RTL_BITMAP Display;
|
|
} FREE_DISPLAY, *PFREE_DISPLAY;
|
|
|
|
typedef struct _HHIVE {
|
|
ULONG Signature;
|
|
|
|
PGET_CELL_ROUTINE GetCellRoutine;
|
|
PRELEASE_CELL_ROUTINE ReleaseCellRoutine;
|
|
|
|
PALLOCATE_ROUTINE Allocate;
|
|
PFREE_ROUTINE Free;
|
|
|
|
PFILE_SET_SIZE_ROUTINE FileSetSize;
|
|
PFILE_WRITE_ROUTINE FileWrite;
|
|
PFILE_READ_ROUTINE FileRead;
|
|
PFILE_FLUSH_ROUTINE FileFlush;
|
|
|
|
struct _HBASE_BLOCK *BaseBlock;
|
|
|
|
RTL_BITMAP DirtyVector; // only for Stable bins
|
|
ULONG DirtyCount;
|
|
ULONG DirtyAlloc; // allocated bytges for dirty vect
|
|
|
|
ULONG BaseBlockAlloc;
|
|
|
|
ULONG Cluster; // Usually 1 512 byte sector.
|
|
// Set up force writes to be
|
|
// done in larger units on
|
|
// machines with larger sectors.
|
|
// Is number of logical 512 sectors.
|
|
|
|
BOOLEAN Flat; // TRUE if FLAT
|
|
BOOLEAN ReadOnly; // TRUE if READONLY
|
|
|
|
BOOLEAN Log;
|
|
|
|
ULONG HiveFlags;
|
|
|
|
ULONG LogSize;
|
|
|
|
ULONG RefreshCount; // debugging aid
|
|
|
|
|
|
ULONG StorageTypeCount; // 1 > Number of largest valid
|
|
// type. (1 for Stable only,
|
|
// 2 for stable & volatile)
|
|
|
|
ULONG Version; // hive version, to allow supporting multiple
|
|
// formats simultaneously.
|
|
|
|
struct _DUAL {
|
|
ULONG Length;
|
|
#ifdef HV_TRACK_FREE_SPACE
|
|
ULONG FreeStorage; // how many free space.
|
|
#endif
|
|
PHMAP_DIRECTORY Map;
|
|
PHMAP_TABLE SmallDir;
|
|
ULONG Guard; // Always == -1
|
|
|
|
FREE_DISPLAY FreeDisplay[HHIVE_FREE_DISPLAY_SIZE]; // bitmap of freecells of the corresponding size
|
|
// for every HBLOCK_SIZE - bin in the hive, a bit
|
|
// is set here if a free cell of the desired size
|
|
// lies in this block
|
|
|
|
ULONG FreeSummary;
|
|
LIST_ENTRY FreeBins; // list of freed HBINs (FREE_HBIN)
|
|
|
|
} Storage[ HTYPE_COUNT ];
|
|
|
|
//
|
|
// Caller defined data goes here
|
|
//
|
|
|
|
} HHIVE, *PHHIVE;
|
|
|
|
|
|
#endif // __HIVE_DATA__
|
|
|
|
|