/*++ Copyright (c) 1996 Microsoft Corporation Module Name: memdbp.h Abstract: internal functions for memdb operations Author: Matthew Vanderzee (mvander) 13-Aug-1999 Revision History: --*/ // // Constants // #define INVALID_OFFSET (~((UINT)0)) // // database types // #define DB_NOTHING 0x00 #define DB_PERMANENT 0x01 #define DB_TEMPORARY 0x02 #ifdef DEBUG #define PTR_WAS_INVALIDATED(x) (x=NULL) #else #define PTR_WAS_INVALIDATED(x) #endif // // signatures for different memory structures. // #define KEYSTRUCT_SIGNATURE ('K'+('E'<<8)+('E'<<16)+('Y'<<24)) #define DATABLOCK_SIGNATURE ('B'+('L'<<8)+('O'<<16)+('K'<<24)) #define NODESTRUCT_SIGNATURE ('N'+('O'<<8)+('D'<<16)+('E'<<24)) #define BINTREE_SIGNATURE ('T'+('R'<<8)+('E'<<16)+('E'<<24)) #define LISTELEM_SIGNATURE ('L'+('I'<<8)+('S'<<16)+('T'<<24)) #define MEMDB_VERBOSE 0 // // KEYSTRUCT flags // #define KSF_ENDPOINT 0x01 #define KSF_DATABLOCK 0x02 // // we only need this flag for easier checking // of keys, in FindKeyStructInDatabase() // #ifdef DEBUG #define KSF_DELETED 0x04 #endif // // database allocation parameters // #define ALLOC_TOLERANCE 32 #define MAX_HIVE_NAME 64 // // Typedefs // typedef struct { UINT Size; UINT End; UINT FreeHead; PBYTE Buf; } MEMDBHASH, *PMEMDBHASH; // // // The DATABASE structure holds all pieces of information necessary // to maintain a portion of the overall memory database. There are // two DATABASE structures, a permanent and a temporary one. // typedef struct { UINT AllocSize; UINT End; UINT FirstLevelTree; UINT FirstKeyDeleted; // this stores the Offset of the key, not the Index UINT FirstBinTreeDeleted; UINT FirstBinTreeNodeDeleted; UINT FirstBinTreeListElemDeleted; BOOL AllocFailed; PMEMDBHASH HashTable; GROWBUFFER OffsetBuffer; UINT OffsetBufferFirstDeletedIndex; BYTE Buf[]; } DATABASE, *PDATABASE; // // Globals - defined in database.c // extern PDATABASE g_CurrentDatabase; extern BYTE g_CurrentDatabaseIndex; extern CRITICAL_SECTION g_MemDbCs; #ifdef DEBUG extern BOOL g_UseDebugStructs; #endif #define OFFSET_TO_PTR(Offset) (g_CurrentDatabase->Buf+(Offset)) #define PTR_TO_OFFSET(Ptr) (UINT)((UBINT)(Ptr)-(UBINT)(g_CurrentDatabase->Buf)) // // GET_EXTERNAL_INDEX converts an internal index and converts it to a key or data handle (has database number as top byte). // GET_DATABASE takes a key or data handle and returns the database number byte // GET_INDEX takes a key or data handle and returns the index without the database number // #define GET_EXTERNAL_INDEX(Index) ((Index) | ((UINT)(g_CurrentDatabaseIndex) << (8*sizeof(UINT)-8))) #define GET_DATABASE(Index) ((BYTE)((Index) >> (8*sizeof(UINT)-8))) #define GET_INDEX(Index) ((Index) & (INVALID_OFFSET>>8)) // // a KEYSTRUCT holds each piece of a memdb entry. 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 versatile--many relationships can be established by // formatting key strings in various ways. // // when changing offset of KeyName in KEYSTRUCT (by adding new members // or resizing or reordering, etc) be sure to change constant in // GetDataStr macro below (currently (3*sizeof(UINT)+4)). typedef struct { #ifdef DEBUG DWORD Signature; #endif union { UINT Value; // value of key UINT DataSize; // size of the actual data (if this is a data structure UINT NextDeleted; // for deleted items, we keep a list of free blocks }; UINT Flags; // key flags UINT DataStructIndex; // offset of Data structure holding the binary data UINT NextLevelTree; // offset of bintree holding next level keystructs UINT PrevLevelIndex; // index of previous level keystruct UINT Size; // size of block (maybe not all of it is used) BYTE KeyFlags; BYTE DataFlags; union { WCHAR KeyName[]; // name of key (just this level, not full key) BYTE Data[]; // Binary data stored in this keystruct }; } KEYSTRUCT, *PKEYSTRUCT; #define KEYSTRUCT_SIZE_MAIN ((WORD)(5*sizeof(UINT) + sizeof(UINT) + 2*sizeof(BYTE))) #ifdef DEBUG #define KEYSTRUCT_HEADER_SIZE sizeof(DWORD) #define KEYSTRUCT_SIZE (KEYSTRUCT_SIZE_MAIN + \ (WORD)(g_UseDebugStructs ? KEYSTRUCT_HEADER_SIZE : 0)) #else #define KEYSTRUCT_SIZE KEYSTRUCT_SIZE_MAIN #endif // // GetDataStr is used by the bintree.c functions to get // the data string inside a data element, to be used for // ordering in the tree. For us, the data type is // a KeyStruct. // #define GetDataStr(DataIndex) ((PWSTR)(OFFSET_TO_PTR(KeyIndexToOffset(DataIndex)+KEYSTRUCT_SIZE))) // // hash.c routines // PMEMDBHASH CreateHashBlock ( VOID ); VOID FreeHashBlock ( IN PMEMDBHASH pHashTable ); BOOL ReadHashBlock ( IN PMEMDBHASH pHashTable, IN OUT PBYTE *Buf ); BOOL WriteHashBlock ( IN PMEMDBHASH pHashTable, IN OUT PBYTE *Buf ); UINT GetHashTableBlockSize ( IN PMEMDBHASH pHashTable ); BOOL AddHashTableEntry ( IN PMEMDBHASH pHashTable, IN PCWSTR FullString, IN UINT Offset ); UINT FindStringInHashTable ( IN PMEMDBHASH pHashTable, IN PCWSTR FullString ); BOOL RemoveHashTableEntry ( IN PMEMDBHASH pHashTable, IN PCWSTR FullString ); // // memdbfile.c // BOOL SetSizeOfFile ( HANDLE hFile, LONGLONG Size ); PBYTE MapFileFromHandle ( HANDLE hFile, PHANDLE hMap ); #define UnmapFileFromHandle(Buf, hMap) UnmapFile(Buf, hMap, INVALID_HANDLE_VALUE) // // database.c // BOOL DatabasesInitializeA ( IN PCSTR DatabasePath OPTIONAL ); BOOL DatabasesInitializeW ( IN PCWSTR DatabasePath OPTIONAL ); PCSTR DatabasesGetBasePath ( VOID ); VOID DatabasesTerminate ( IN BOOL EraseDatabasePath ); BOOL SizeDatabaseBuffer ( IN BYTE DatabaseIndex, IN UINT NewSize ); UINT DatabaseAllocBlock ( IN UINT Size ); BOOL SelectDatabase ( IN BYTE DatabaseIndex ); PCWSTR SelectHiveW ( IN PCWSTR FullKeyStr ); BYTE GetCurrentDatabaseIndex ( VOID ); #ifdef DEBUG BOOL CheckDatabase ( IN UINT Level ); #endif // // offsetbuf.c // VOID RedirectKeyIndex ( IN UINT Index, IN UINT TargetIndex ); UINT KeyIndexToOffset ( IN UINT Index ); UINT AddKeyOffsetToBuffer( IN UINT Offset ); VOID RemoveKeyOffsetFromBuffer( IN UINT Index ); VOID MarkIndexList ( PUINT IndexList, UINT IndexListSize ); BOOL ReadOffsetBlock ( OUT PGROWBUFFER pOffsetBuffer, IN OUT PBYTE *Buf ); BOOL WriteOffsetBlock ( IN PGROWBUFFER pOffsetBuffer, IN OUT PBYTE *Buf ); UINT GetOffsetBufferBlockSize ( IN PGROWBUFFER pOffsetBuffer ); // // pastring.c // Pascal-style string: wide characters, first char // is number of characters, no null-termination // typedef WCHAR * PPASTR; typedef WCHAR const * PCPASTR; // // these convert a WSTR in place from null-terminated // to Pascal-style strings // PPASTR StringPasConvertTo (PWSTR str); PWSTR StringPasConvertFrom (PPASTR str); // // these convert a WSTR from null-terminated // to Pascal-style strings in new string buffer // PPASTR StringPasCopyConvertTo (PPASTR str1, PCWSTR str2); PWSTR StringPasCopyConvertFrom (PWSTR str1, PCPASTR str2); PPASTR StringPasCopy (PPASTR str1, PCPASTR str2); UINT StringPasCharCount (PCPASTR str); INT StringPasCompare (PCPASTR str1, PCPASTR str2); BOOL StringPasMatch (PCPASTR str1, PCPASTR str2); INT StringPasICompare (PCPASTR str1, PCPASTR str2); BOOL StringPasIMatch (PCPASTR str1, PCPASTR str2); // // keystrct.c // #ifdef DEBUG PKEYSTRUCT GetKeyStructFromOffset ( UINT Offset ); PKEYSTRUCT GetKeyStruct ( UINT Index ); #else #define GetKeyStructFromOffset(Offset) ((Offset==INVALID_OFFSET) ? \ NULL : \ (PKEYSTRUCT)OFFSET_TO_PTR(Offset)) #define GetKeyStruct(Index) ((Index==INVALID_OFFSET) ? \ NULL : \ GetKeyStructFromOffset(KeyIndexToOffset(Index))) #endif UINT GetFirstIndex ( IN UINT TreeOffset, OUT PUINT pTreeEnum ); UINT GetNextIndex ( IN OUT PUINT pTreeEnum ); UINT NewKey ( IN PCWSTR KeyStr ); UINT NewEmptyKey ( IN PCWSTR KeyStr ); BOOL PrivateDeleteKeyByIndex ( IN UINT Index ); BOOL DeleteKey ( IN PCWSTR KeyStr, IN UINT TreeOffset, IN BOOL MustMatch ); BOOL PrivateBuildKeyFromIndex ( IN UINT StartLevel, // zero-based IN UINT TailIndex, OUT PWSTR Buffer, OPTIONAL OUT PUINT ValPtr, OPTIONAL OUT PUINT UserFlagsPtr, OPTIONAL OUT PUINT SizeInChars OPTIONAL ); BOOL KeyStructSetInsertionOrdered ( IN PKEYSTRUCT Key ); UINT KeyStructGetChildCount ( IN PKEYSTRUCT pKey ); UINT FindKeyStructInTree ( IN UINT TreeOffset, IN PWSTR KeyName, IN BOOL IsPascalString ); #ifdef DEBUG BOOL CheckLevel(UINT TreeOffset, UINT PrevLevelIndex ); #endif // // keyfind.c // UINT FindKeyStruct( IN PCWSTR Key ); UINT FindKey ( IN PCWSTR FullKeyPath ); UINT FindKeyStructUsingTreeOffset ( IN UINT TreeOffset, IN OUT PUINT pTreeEnum, IN PCWSTR KeyStr ); #ifdef DEBUG BOOL FindKeyStructInDatabase( UINT KeyOffset ); #endif // // keydata.c // BOOL KeyStructSetValue ( IN UINT KeyIndex, IN UINT Value ); BOOL KeyStructSetFlags ( IN UINT KeyIndex, IN BOOL ReplaceFlags, IN UINT SetFlags, IN UINT ClearFlags ); UINT KeyStructAddBinaryData ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, IN PCBYTE Data, IN UINT DataSize ); UINT KeyStructGrowBinaryData ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, IN PCBYTE Data, IN UINT DataSize ); UINT KeyStructGrowBinaryDataByIndex ( IN UINT OldIndex, IN PCBYTE Data, IN UINT DataSize ); BOOL KeyStructDeleteBinaryData ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance ); BOOL KeyStructDeleteBinaryDataByIndex ( IN UINT DataIndex ); UINT KeyStructReplaceBinaryDataByIndex ( IN UINT OldIndex, IN PCBYTE Data, IN UINT DataSize ); PBYTE KeyStructGetBinaryData ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, OUT PUINT DataSize, OUT PUINT DataIndex //OPTIONAL ); PBYTE KeyStructGetBinaryDataByIndex ( IN UINT DataIndex, OUT PUINT DataSize ); UINT KeyStructGetDataIndex ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance ); DATAHANDLE KeyStructAddLinkage ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, IN UINT Linkage, IN BOOL AllowDuplicates ); DATAHANDLE KeyStructAddLinkageByIndex ( IN UINT DataIndex, IN UINT Linkage, IN BOOL AllowDuplicates ); BOOL KeyStructDeleteLinkage ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, IN UINT Linkage, IN BOOL FirstOnly ); BOOL KeyStructDeleteLinkageByIndex ( IN UINT DataIndex, IN UINT Linkage, IN BOOL FirstOnly ); BOOL KeyStructTestLinkage ( IN UINT KeyIndex, IN BYTE Type, IN BYTE Instance, IN KEYHANDLE Linkage ); BOOL KeyStructTestLinkageByIndex ( IN UINT DataIndex, IN UINT Linkage ); BOOL KeyStructGetValue ( IN PKEYSTRUCT KeyStruct, OUT PUINT Value ); BOOL KeyStructGetFlags ( IN PKEYSTRUCT KeyStruct, OUT PUINT Flags ); VOID KeyStructFreeAllData ( PKEYSTRUCT KeyStruct ); // // bintree.c // #ifdef DEBUG // // violating code hiding for easier debugging. // (only database.c should see bintree functions) // UINT BinTreeGetSizeOfStruct( DWORD Signature ); BOOL BinTreeFindStructInDatabase( DWORD Sig, UINT Offset ); #endif