754 lines
13 KiB
C
754 lines
13 KiB
C
/*++
|
|
|
|
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
|