#include "migshared.h" // // #defines // // // This is our version stamp. Change MEMDB_VERSION only. // #define MEMDB_VERSION L"v9 " #define VERSION_BASE_SIGNATURE L"memdb dat file " #define MEMDB_DEBUG_SIGNATURE L"debug" #define MEMDB_NODBG_SIGNATURE L"nodbg" #define VERSION_SIGNATURE VERSION_BASE_SIGNATURE MEMDB_VERSION #define DEBUG_FILE_SIGNATURE VERSION_SIGNATURE MEMDB_DEBUG_SIGNATURE #define RETAIL_FILE_SIGNATURE VERSION_SIGNATURE MEMDB_NODBG_SIGNATURE #define SIGNATURE 0xab12e87d // // We must reserve 5 bits. In a KEYSTRUCT node, 2 bits are used for AVL // balancing, 1 bit for endpoint, 1 bit for proxy nodes, and 1 bit for binary // nodes. In a hash table entry, the top 5 bits provide the hive index. // #define RESERVED_BITS 27 #define RESERVED_MASK 0xf8000000 #define OFFSET_MASK (~RESERVED_MASK) // // KEYSTRUCT flags // #define KSF_ENDPOINT 0x08000000 #define KSF_BINARY 0x40000000 #define KSF_PROXY_NODE 0x80000000 #define KSF_BALANCE_MASK 0x30000000 #define KSF_BALANCE_SHIFT 28 // bit pos of KSF_RIGHT_HEAVY #define KSF_RIGHT_HEAVY 0x10000000 #define KSF_LEFT_HEAVY 0x20000000 #define KSF_USERFLAG_MASK OFFSET_MASK // // Binary tree allocation parameters // #define ALLOC_TOLERANCE 32 #define BLOCK_SIZE 0x00010000 #define MAX_HIVE_NAME 64 #define TOKENBUCKETS 511 // // Typedefs // // // The DATABASE structure holds all pieces of information necessary // to maintain a portion of the overall memory database. There is a // root DATABASE structure that always exists (its index is zero), // and there are additional DATABASE structures for each database // the caller creates via the MemDbCreateDatabase call. Callers create // additional databases when a node is needed for temporary processing. // typedef struct { DWORD AllocSize; DWORD End; DWORD FirstLevelRoot; DWORD FirstDeleted; DWORD TokenBuckets[TOKENBUCKETS]; PBYTE Buf; WCHAR Hive[MAX_HIVE_NAME]; } DATABASE, *PDATABASE; // // Hive struct (for KSF_HIVE type) // typedef struct { DATABASE DatabaseInfo; } HIVE, *PHIVE; // // Binary block struct (for KSF_BINARY type of the key struct) // typedef struct _tagBINARYBLOCK { #ifdef DEBUG DWORD Signature; #endif DWORD Size; struct _tagBINARYBLOCK *NextPtr, *PrevPtr; DWORD OwningKey; BYTE Data[]; } BINARYBLOCK, *PBINARYBLOCK; // // KEYSTRUCT holds each piece of memdb entries. A single KEYSTRUCT // holds a portion of a key (delimited by a backslash), and the // KEYSTRUCTs are organized into a binary tree. Each KEYSTRUCT // can also contain additional binary trees. This is what makes // memdb so versitle--many relationships can be established by // formatting key strings in various ways. // typedef struct { DWORD Signature; // Offsets for data struct DWORD Left, Right; DWORD Parent; union { struct { union { DWORD dwValue; PBINARYBLOCK BinaryPtr; }; DWORD Flags; // Other properties here }; DWORD NextDeleted; // for deleted items, we keep a list of free blocks }; DWORD NextLevelRoot; DWORD PrevLevelNode; DWORD KeyToken; } KEYSTRUCT_DEBUG, *PKEYSTRUCT_DEBUG; typedef struct { // Offsets for data struct DWORD Left, Right; DWORD Parent; union { struct { union { DWORD dwValue; PBINARYBLOCK BinaryPtr; }; DWORD Flags; // Other properties here }; DWORD NextDeleted; // for deleted items, we keep a list of free blocks }; DWORD NextLevelRoot; DWORD PrevLevelNode; DWORD KeyToken; } KEYSTRUCT_RETAIL, *PKEYSTRUCT_RETAIL; typedef struct { DWORD Right; WCHAR String[]; } TOKENSTRUCT, *PTOKENSTRUCT; #ifdef DEBUG #define KEYSTRUCT KEYSTRUCT_DEBUG #define PKEYSTRUCT PKEYSTRUCT_DEBUG #else #define KEYSTRUCT KEYSTRUCT_RETAIL #define PKEYSTRUCT PKEYSTRUCT_RETAIL #endif // // Globals // extern PDATABASE g_db; extern BYTE g_SelectedDatabase; // current index of active database extern PHIVE g_HeadHive; extern CRITICAL_SECTION g_MemDbCs; #ifdef DEBUG extern BOOL g_UseDebugStructs; #endif // // memdb.c routines // PCWSTR SelectHive ( PCWSTR FullKeyStr ); BOOL PrivateMemDbSetValueA ( IN PCSTR Key, IN DWORD Val, IN DWORD SetFlags, IN DWORD ClearFlags, OUT PDWORD Offset OPTIONAL ); BOOL PrivateMemDbSetValueW ( IN PCWSTR Key, IN DWORD Val, IN DWORD SetFlags, IN DWORD ClearFlags, OUT PDWORD Offset OPTIONAL ); BOOL PrivateMemDbSetBinaryValueA ( IN PCSTR Key, IN PCBYTE BinaryData, IN DWORD DataSize, OUT PDWORD Offset OPTIONAL ); BOOL PrivateMemDbSetBinaryValueW ( IN PCWSTR Key, IN PCBYTE BinaryData, IN DWORD DataSize, OUT PDWORD Offset OPTIONAL ); // // hash.c routines // BOOL InitializeHashBlock ( VOID ); VOID FreeHashBlock ( VOID ); BOOL SaveHashBlock ( HANDLE File ); BOOL LoadHashBlock ( HANDLE File ); BOOL AddHashTableEntry ( IN PCWSTR FullString, IN DWORD Offset ); DWORD FindStringInHashTable ( IN PCWSTR FullString, OUT PBYTE DatabaseId OPTIONAL ); BOOL RemoveHashTableEntry ( IN PCWSTR FullString ); // // binval.c // PCBYTE GetKeyStructBinaryData ( PKEYSTRUCT KeyStruct ); DWORD GetKeyStructBinarySize ( PKEYSTRUCT KeyStruct ); PBINARYBLOCK AllocBinaryBlock ( IN PCBYTE Data, IN DWORD DataSize, IN DWORD OwningKey ); VOID FreeKeyStructBinaryBlock ( PKEYSTRUCT KeyStruct ); VOID FreeAllBinaryBlocks ( VOID ); BOOL LoadBinaryBlocks ( HANDLE File ); BOOL SaveBinaryBlocks ( HANDLE File ); // // bintree.c // PKEYSTRUCT GetKeyStruct ( DWORD Offset ); DWORD FindKeyStruct ( IN DWORD RootOffset, IN PCWSTR KeyName ); DWORD GetFirstOffset ( DWORD RootOffset ); DWORD GetNextOffset ( DWORD NodeOffset ); DWORD FindKey ( IN PCWSTR FullKeyPath ); DWORD FindPatternKey ( IN DWORD RootOffset, IN PCWSTR FullKeyPath, IN BOOL EndPatternAllowed ); DWORD FindKeyUsingPattern ( IN DWORD RootOffset, IN PCWSTR FullKeyPath ); DWORD FindPatternKeyUsingPattern ( IN DWORD RootOffset, IN PCWSTR FullKeyPath ); DWORD NewKey ( IN PCWSTR KeyStr, IN PCWSTR KeyStrWithHive ); VOID DeleteKey ( IN PCWSTR KeyStr, IN OUT PDWORD RootPtr, IN BOOL MustMatch ); VOID CopyValToPtr ( PKEYSTRUCT KeyStruct, PDWORD ValPtr ); VOID CopyFlagsToPtr ( PKEYSTRUCT KeyStruct, PDWORD ValPtr ); BOOL PrivateBuildKeyFromOffset ( IN DWORD StartLevel, // zero-based IN DWORD TailOffset, OUT PWSTR Buffer, OPTIONAL OUT PDWORD ValPtr, OPTIONAL OUT PDWORD UserFlagsPtr, OPTIONAL OUT PDWORD CharCount OPTIONAL ); BOOL SelectDatabase ( IN BYTE DatabaseId ); #ifdef DEBUG VOID DumpBinTreeStats ( VOID ); #else #define DumpBinTreeStats() #endif PCWSTR GetKeyToken ( IN DWORD Token );