windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/common/memdb/memdb.c
2020-09-26 16:20:57 +08:00

3023 lines
71 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
memdb.c
Abstract:
A simple memory-based database for associating flags
with a string.
Author:
Jim Schmidt (jimschm) 8-Aug-1996
Revision History:
jimschm 23-Sep-1998 Expanded user flags to 24 bits (from 12 bits)
calinn 12-Dec-1997 Extended MemDbMakePrintableKey and MemDbMakeNonPrintableKey
jimschm 03-Dec-1997 Added multi-thread synchronization
jimschm 22-Oct-1997 Split into multiple source files,
added multiple memory block capability
jimschm 16-Sep-1997 Hashing: delete fix
jimschm 29-Jul-1997 Hashing, user flags added
jimschm 07-Mar-1997 Signature changes
jimschm 03-Mar-1997 PrivateBuildKeyFromOffset changes
jimschm 18-Dec-1996 Fixed deltree bug
--*/
#include "pch.h"
#include "memdbp.h"
#ifndef UNICODE
#error UNICODE required
#endif
//
// Global delcaration
//
PDATABASE g_db;
GROWLIST g_DatabaseList = GROWLIST_INIT;
BYTE g_SelectedDatabase;
PHIVE g_HeadHive;
CRITICAL_SECTION g_MemDbCs;
#ifdef DEBUG
#define FILE_SIGNATURE DEBUG_FILE_SIGNATURE
BOOL g_UseDebugStructs = TRUE;
#else
#define FILE_SIGNATURE RETAIL_FILE_SIGNATURE
#endif
//
// Private prototypes
//
INT
pCreateDatabase (
PCWSTR Name
);
BOOL
pInitializeDatabase (
OUT PDATABASE Database,
IN PCWSTR Name
);
BOOL
pFreeDatabase (
IN OUT PDATABASE Database
);
VOID
pFreeSelectedDatabase (
VOID
);
VOID
pFreeAllDatabases (
VOID
);
BOOL
pPrivateMemDbGetValueW (
IN PCWSTR KeyStr,
OUT PDWORD Value, OPTIONAL
OUT PDWORD UserFlagsPtr OPTIONAL
);
BOOL
pInitializeMemDb (
VOID
);
//
// Implementation
//
BOOL
MemDb_Entry (
IN HINSTANCE hinstDLL,
IN DWORD Reason,
IN PVOID lpv
)
/*++
Routine Description:
DllMain is called after the C runtime is initialized, and its purpose
is to initialize the globals for this process.
Arguments:
hinstDLL - (OS-supplied) Instance handle for the DLL
Reason - (OS-supplied) Type of initialization or termination
lpv - (OS-supplied) Unused
Return Value:
TRUE because DLL always initializes properly.
--*/
{
switch (Reason) {
case DLL_PROCESS_ATTACH:
if (!pInitializeMemDb()) {
return FALSE;
}
InitializeCriticalSection (&g_MemDbCs);
InitOperationTable();
break;
case DLL_PROCESS_DETACH:
pFreeAllDatabases();
FreeGrowList (&g_DatabaseList);
DeleteCriticalSection (&g_MemDbCs);
DumpBinTreeStats();
break;
}
return TRUE;
}
BOOL
pInitializeMemDb (
VOID
)
{
FreeGrowList (&g_DatabaseList);
ZeroMemory (&g_DatabaseList, sizeof (g_DatabaseList));
g_db = NULL;
if (!InitializeHashBlock()) {
return FALSE;
}
if (pCreateDatabase (L"") != 0) {
return FALSE;
}
g_SelectedDatabase = 1;
SelectDatabase (0);
return TRUE;
}
BOOL
pInitializeDatabase (
OUT PDATABASE Database,
IN PCWSTR Name
)
{
UINT u;
Database->AllocSize = BLOCK_SIZE;
Database->Buf = (PBYTE) MemAlloc (g_hHeap, 0, Database->AllocSize);
Database->End = 0;
Database->FirstLevelRoot = INVALID_OFFSET;
Database->FirstDeleted = INVALID_OFFSET;
MYASSERT (INVALID_OFFSET == 0xFFFFFFFF);
FillMemory (Database->TokenBuckets, sizeof (Database->TokenBuckets), 0xFF);
_wcssafecpy (Database->Hive, Name, MAX_HIVE_NAME);
return TRUE;
}
BOOL
pFreeDatabase (
IN OUT PDATABASE Database
)
{
if (Database->Buf) {
MemFree (g_hHeap, 0, Database->Buf);
Database->Buf = NULL;
}
Database->End = 0;
Database->FirstLevelRoot = INVALID_OFFSET;
Database->FirstDeleted = INVALID_OFFSET;
Database->Hive[0] = 0;
return TRUE;
}
INT
pCreateDatabase (
PCWSTR Name
)
{
DATABASE Database;
BYTE Index;
UINT Count;
UINT u;
//
// Does key exist already?
//
if (g_db) {
SelectDatabase (0);
if (INVALID_OFFSET != FindKeyStruct (g_db->FirstLevelRoot, Name)) {
DEBUGMSG ((DBG_WHOOPS, "Cannot create %ls because it already exists!", Name));
SetLastError (ERROR_ALREADY_EXISTS);
return -1;
}
}
//
// Scan list for a blank spot
//
Count = GrowListGetSize (&g_DatabaseList);
for (u = 0 ; u < Count ; u++) {
if (!GrowListGetItem (&g_DatabaseList, u)) {
break;
}
}
if (u < Count) {
//
// Use empty slot
//
Index = (BYTE) u;
} else if (Count < 256) {
//
// No empty slot; grow the list
//
Index = (BYTE) Count;
if (!GrowListAppend (&g_DatabaseList, NULL, 0)) {
DEBUGMSG ((DBG_WARNING, "Could not create database because GrowListAppend failed"));
return -1;
}
} else {
DEBUGMSG ((DBG_ERROR, "Cannot have more than 256 databases in memdb!"));
return -1;
}
//
// Create the database memory block
//
pInitializeDatabase (&Database, Name);
if (!GrowListSetItem (&g_DatabaseList, (UINT) Index, (PBYTE) &Database, sizeof (Database))) {
DEBUGMSG ((DBG_WARNING, "Could not create database because GrowListSetItem failed"));
pFreeDatabase (&Database);
return -1;
}
return (INT) Index;
}
VOID
pDestroySelectedDatabase (
VOID
)
{
//
// Free all resources for the database
//
pFreeSelectedDatabase ();
//
// For all databases except for the root, free the DATABASE
// structure in g_DatabaseList.
//
if (g_SelectedDatabase) {
GrowListResetItem (&g_DatabaseList, (UINT) g_SelectedDatabase);
}
}
VOID
pFreeSelectedDatabase (
VOID
)
{
//
// Free all resources used by a single database
//
if (g_db->Buf) {
MemFree (g_hHeap, 0, g_db->Buf);
}
FreeAllBinaryBlocks();
ZeroMemory (g_db, sizeof (DATABASE));
}
VOID
pFreeAllDatabases (
VOID
)
{
UINT Count;
UINT Index;
//
// Free all database blocks
//
Count = GrowListGetSize (&g_DatabaseList);
for (Index = 0 ; Index < Count ; Index++) {
if (SelectDatabase ((BYTE) Index)) {
pDestroySelectedDatabase();
}
}
//
// Free global hash table
//
FreeHashBlock();
SelectDatabase(0);
}
BOOL
SelectDatabase (
BYTE DatabaseId
)
{
PDATABASE Database;
if (g_SelectedDatabase == DatabaseId) {
return TRUE;
}
Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, (UINT) DatabaseId);
if (!Database) {
DEBUGMSG ((DBG_WHOOPS, "MemDb: Invalid database selection!"));
return FALSE;
}
g_db = Database;
g_SelectedDatabase = DatabaseId;
return TRUE;
}
PCWSTR
SelectHive (
PCWSTR FullKeyStr
)
{
UINT Count;
UINT Index;
PDATABASE Database;
PCWSTR End;
//
// Determine if root of FullKeyStr is part of a hive
//
End = wcschr (FullKeyStr, L'\\');
if (End) {
Count = GrowListGetSize (&g_DatabaseList);
for (Index = 1 ; Index < Count ; Index++) {
Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
if (Database && StringIMatchABW (Database->Hive, FullKeyStr, End)) {
//
// Match found; select the database and return the subkey
//
SelectDatabase ((BYTE) Index);
End = _wcsinc (End);
return End;
}
}
}
SelectDatabase (0);
return FullKeyStr;
}
BOOL
IsTemporaryKey (
PCWSTR FullKeyStr
)
{
UINT Count;
UINT Index;
PDATABASE Database;
PCWSTR End;
End = wcschr (FullKeyStr, L'\\');
if (!End) {
End = GetEndOfStringW (FullKeyStr);
}
Count = GrowListGetSize (&g_DatabaseList);
for (Index = 1 ; Index < Count ; Index++) {
Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
if (Database && StringIMatchABW (Database->Hive, FullKeyStr, End)) {
//
// Match found; return true
//
return TRUE;
}
}
return FALSE;
}
//
// MemDbSetValue creates or modifies KeyStr. The value of the key is changed
// when the return value is TRUE.
//
BOOL
PrivateMemDbSetValueA (
PCSTR Key,
DWORD Val,
DWORD SetFlags,
DWORD ClearFlags,
PDWORD Offset
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (Key);
if (p) {
b = PrivateMemDbSetValueW (p, Val, SetFlags, ClearFlags, Offset);
FreeConvertedStr (p);
}
return b;
}
BOOL
PrivateMemDbSetValueW (
PCWSTR Key,
DWORD Val,
DWORD SetFlags,
DWORD ClearFlags,
PDWORD Offset
)
{
DWORD KeyOffset;
PKEYSTRUCT KeyStruct;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (Key);
KeyOffset = FindKey (SubKey);
if (KeyOffset == INVALID_OFFSET) {
KeyOffset = NewKey (SubKey, Key);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
}
KeyStruct = GetKeyStruct (KeyOffset);
FreeKeyStructBinaryBlock (KeyStruct);
KeyStruct->dwValue = Val;
if (Offset) {
*Offset = KeyOffset | (g_SelectedDatabase << RESERVED_BITS);
}
KeyStruct->Flags = KeyStruct->Flags & ~(ClearFlags & KSF_USERFLAG_MASK);
KeyStruct->Flags = KeyStruct->Flags | (SetFlags & KSF_USERFLAG_MASK);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
PrivateMemDbSetBinaryValueA (
IN PCSTR Key,
IN PCBYTE Data,
IN DWORD SizeOfData,
OUT PDWORD Offset OPTIONAL
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (Key);
if (p) {
b = PrivateMemDbSetBinaryValueW (p, Data, SizeOfData, Offset);
FreeConvertedStr (p);
}
return b;
}
BOOL
PrivateMemDbSetBinaryValueW (
IN PCWSTR Key,
IN PCBYTE Data,
IN DWORD SizeOfData,
OUT PDWORD Offset OPTIONAL
)
{
DWORD KeyOffset;
PKEYSTRUCT KeyStruct;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (Key);
KeyOffset = FindKey (SubKey);
if (KeyOffset == INVALID_OFFSET) {
KeyOffset = NewKey (SubKey, Key);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
}
KeyStruct = GetKeyStruct (KeyOffset);
// Free existing buffer
FreeKeyStructBinaryBlock (KeyStruct);
// Alloc new buffer
KeyStruct->BinaryPtr = AllocBinaryBlock (Data, SizeOfData, KeyOffset);
if (!KeyStruct->BinaryPtr) {
__leave;
}
KeyStruct->Flags |= KSF_BINARY;
if (Offset) {
*Offset = KeyOffset | (g_SelectedDatabase << RESERVED_BITS);
}
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
MemDbSetValueA (
IN PCSTR KeyStr,
IN DWORD dwValue
)
{
return PrivateMemDbSetValueA (KeyStr, dwValue, 0, 0, NULL);
}
BOOL
MemDbSetValueW (
IN PCWSTR KeyStr,
IN DWORD dwValue
)
{
return PrivateMemDbSetValueW (KeyStr, dwValue, 0, 0, NULL);
}
BOOL
MemDbSetValueAndFlagsA (
IN PCSTR KeyStr,
IN DWORD dwValue,
IN DWORD SetUserFlags,
IN DWORD ClearUserFlags
)
{
return PrivateMemDbSetValueA (KeyStr, dwValue, SetUserFlags, ClearUserFlags, NULL);
}
BOOL
MemDbSetValueAndFlagsW (
IN PCWSTR KeyStr,
IN DWORD dwValue,
IN DWORD SetUserFlags,
IN DWORD ClearUserFlags
)
{
return PrivateMemDbSetValueW (KeyStr, dwValue, SetUserFlags, ClearUserFlags, NULL);
}
BOOL
MemDbSetBinaryValueA (
IN PCSTR KeyStr,
IN PCBYTE Data,
IN DWORD DataSize
)
{
return PrivateMemDbSetBinaryValueA (KeyStr, Data, DataSize, NULL);
}
BOOL
MemDbSetBinaryValueW (
IN PCWSTR KeyStr,
IN PCBYTE Data,
IN DWORD DataSize
)
{
return PrivateMemDbSetBinaryValueW (KeyStr, Data, DataSize, NULL);
}
//
// GetValue takes a full key string and returns the
// value to the caller-supplied DWORD. Value
// may be NULL to check only for existance of the
// value.
//
BOOL
pPrivateMemDbGetValueA (
IN PCSTR KeyStr,
OUT PDWORD Value, OPTIONAL
OUT PDWORD UserFlagsPtr OPTIONAL
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (KeyStr);
if (p) {
b = pPrivateMemDbGetValueW (p, Value, UserFlagsPtr);
FreeConvertedStr (p);
}
return b;
}
BOOL
pPrivateMemDbGetValueW (
IN PCWSTR KeyStr,
OUT PDWORD Value, OPTIONAL
OUT PDWORD UserFlagsPtr OPTIONAL
)
{
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyStr);
KeyOffset = FindKey (SubKey);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
CopyValToPtr (GetKeyStruct (KeyOffset), Value);
CopyFlagsToPtr (GetKeyStruct (KeyOffset), UserFlagsPtr);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
MemDbGetValueA (
IN PCSTR Key,
OUT PDWORD ValuePtr OPTIONAL
)
{
return pPrivateMemDbGetValueA (Key, ValuePtr, NULL);
}
BOOL
MemDbGetValueW (
IN PCWSTR Key,
OUT PDWORD ValuePtr OPTIONAL
)
{
return pPrivateMemDbGetValueW (Key, ValuePtr, NULL);
}
BOOL
MemDbGetValueAndFlagsA (
IN PCSTR Key,
OUT PDWORD ValuePtr, OPTIONAL
OUT PDWORD UserFlagsPtr
)
{
return pPrivateMemDbGetValueA (Key, ValuePtr, UserFlagsPtr);
}
BOOL
MemDbGetValueAndFlagsW (
IN PCWSTR Key,
OUT PDWORD ValuePtr, OPTIONAL
OUT PDWORD UserFlagsPtr
)
{
return pPrivateMemDbGetValueW (Key, ValuePtr, UserFlagsPtr);
}
PCBYTE
MemDbGetBinaryValueA (
IN PCSTR KeyStr,
OUT PDWORD DataSize OPTIONAL
)
{
PCWSTR p;
BYTE const * b = NULL;
p = ConvertAtoW (KeyStr);
if (p) {
b = MemDbGetBinaryValueW (p, DataSize);
FreeConvertedStr (p);
}
return b;
}
PCBYTE
MemDbGetBinaryValueW (
IN PCWSTR KeyStr,
OUT PDWORD DataSize OPTIONAL
)
{
DWORD KeyOffset;
PKEYSTRUCT KeyStruct;
PCWSTR SubKey;
PCBYTE Result = NULL;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyStr);
KeyOffset = FindKey (SubKey);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
KeyStruct = GetKeyStruct (KeyOffset);
if (DataSize) {
*DataSize = GetKeyStructBinarySize (KeyStruct);
}
Result = GetKeyStructBinaryData (KeyStruct);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return Result;
}
//
// GetPatternValue takes a full key string and returns the
// value to the caller-supplied DWORD. The stored value string
// is treated as a pattern, but KeyStr is not a pattern.
// The return value represents the first match found.
//
BOOL
MemDbGetPatternValueA (
IN PCSTR KeyStr,
OUT PDWORD Value
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (KeyStr);
if (p) {
b = MemDbGetPatternValueW (p, Value);
FreeConvertedStr (p);
}
return b;
}
BOOL
MemDbGetPatternValueW (
IN PCWSTR KeyStr,
OUT PDWORD Value
)
{
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyStr);
KeyOffset = FindPatternKey (g_db->FirstLevelRoot, SubKey, FALSE);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
CopyValToPtr (GetKeyStruct (KeyOffset), Value);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
//
// MemDbGetStoredEndPatternValue takes a full key string and returns the
// value to the caller-supplied DWORD. The stored value string
// is treated as a pattern, but KeyStr is not a pattern.
// The return value represents the first match found.
//
// If the last stored key segment is an asterisk, then the pattern
// is considered to match.
//
BOOL
MemDbGetStoredEndPatternValueA (
IN PCSTR KeyStr,
OUT PDWORD Value
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (KeyStr);
if (p) {
b = MemDbGetStoredEndPatternValueW (p, Value);
FreeConvertedStr (p);
}
return b;
}
BOOL
MemDbGetStoredEndPatternValueW (
IN PCWSTR KeyStr,
OUT PDWORD Value
)
{
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyStr);
KeyOffset = FindPatternKey (g_db->FirstLevelRoot, SubKey, TRUE);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
CopyValToPtr (GetKeyStruct (KeyOffset), Value);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
//
// GetValueWithPattern takes a full key string that may contain
// wildcards between the backslashes, and returns the value
// to the caller-supplied DWORD. The stored value string
// is not treated as a pattern. The return value represents
// the first match found.
//
BOOL
MemDbGetValueWithPatternA (
IN PCSTR KeyPattern,
OUT PDWORD Value
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (KeyPattern);
if (p) {
b = MemDbGetValueWithPatternW (p, Value);
FreeConvertedStr (p);
}
return b;
}
BOOL
MemDbGetValueWithPatternW (
IN PCWSTR KeyPattern,
OUT PDWORD Value
)
{
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyPattern);
KeyOffset = FindKeyUsingPattern (g_db->FirstLevelRoot, SubKey);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
CopyValToPtr (GetKeyStruct (KeyOffset), Value);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
MemDbGetPatternValueWithPatternA (
IN PCSTR KeyPattern,
OUT PDWORD Value
)
{
PCWSTR p;
BOOL b = FALSE;
p = ConvertAtoW (KeyPattern);
if (p) {
b = MemDbGetPatternValueWithPatternW (p, Value);
FreeConvertedStr (p);
}
return b;
}
BOOL
MemDbGetPatternValueWithPatternW (
IN PCWSTR KeyPattern,
OUT PDWORD Value
)
{
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
SubKey = SelectHive (KeyPattern);
KeyOffset = FindPatternKeyUsingPattern (g_db->FirstLevelRoot, SubKey);
if (KeyOffset == INVALID_OFFSET) {
__leave;
}
CopyValToPtr (GetKeyStruct (KeyOffset), Value);
b = TRUE;
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
VOID
MemDbDeleteValueA (
IN PCSTR KeyStr
)
{
PCWSTR p;
p = ConvertAtoW (KeyStr);
if (p) {
MemDbDeleteValueW (p);
FreeConvertedStr (p);
}
}
VOID
MemDbDeleteValueW (
IN PCWSTR KeyStr
)
{
PCWSTR SubKey;
EnterCriticalSection (&g_MemDbCs);
SubKey = SelectHive (KeyStr);
DeleteKey (SubKey, &g_db->FirstLevelRoot, TRUE);
LeaveCriticalSection (&g_MemDbCs);
}
VOID
MemDbDeleteTreeA (
IN PCSTR KeyStr
)
{
PCWSTR p;
p = ConvertAtoW (KeyStr);
if (p) {
MemDbDeleteTreeW (p);
FreeConvertedStr (p);
}
}
VOID
MemDbDeleteTreeW (
IN PCWSTR KeyStr
)
{
PCWSTR SubKey;
EnterCriticalSection (&g_MemDbCs);
SubKey = SelectHive (KeyStr);
DeleteKey (SubKey, &g_db->FirstLevelRoot, FALSE);
LeaveCriticalSection (&g_MemDbCs);
}
//
// Enum functions
//
BOOL
MemDbEnumFirstValueA (
OUT PMEMDB_ENUMA EnumPtr,
IN PCSTR PatternStr,
IN INT Depth,
IN DWORD Flags
)
{
BOOL b = FALSE;
PCWSTR p;
PCSTR str;
MEMDB_ENUMW enumw;
p = ConvertAtoW (PatternStr);
if (p) {
b = MemDbEnumFirstValueW (&enumw, p, Depth, Flags);
FreeConvertedStr (p);
} else {
b = FALSE;
}
if (b) {
str = ConvertWtoA (enumw.szName);
if (str) {
// ANSI struct is padded to match UNICODE
MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
CopyMemory (EnumPtr, &enumw, sizeof (MEMDB_ENUMW));
// Only the output key name needs to be converted
StringCopyA (EnumPtr->szName, str);
FreeConvertedStr (str);
} else {
b = FALSE;
}
}
return b;
}
BOOL
MemDbEnumFirstValueW (
OUT PMEMDB_ENUMW EnumPtr,
IN PCWSTR PatternStr,
IN INT Depth,
IN DWORD Flags
)
{
PCWSTR Start;
PCWSTR wstrLastWack;
PCWSTR SubPatternStr;
SubPatternStr = SelectHive (PatternStr);
//
// Init the EnumPtr struct
//
ZeroMemory (EnumPtr, sizeof (MEMDB_ENUM));
if (!Depth) {
Depth = MAX_ENUM_POS;
}
EnumPtr->Depth = Depth;
EnumPtr->Flags = Flags;
//
// If pattern has wack, locate the starting level by
// counting the number of parts that do not have
// wildcard characters.
//
Start = SubPatternStr;
while (wstrLastWack = wcschr (Start, L'\\')) {
// See if part has a wildcard character
while (Start < wstrLastWack) {
if (*Start == L'*' || *Start == L'?')
break;
Start++;
}
// If a wildcard character was found, we have to stop here
if (Start < wstrLastWack)
break;
// Otherwise, look at next part of the pattern
Start = wstrLastWack + 1;
EnumPtr->Start++;
}
EnumPtr->PosCount = 1;
EnumPtr->LastPos[0] = INVALID_OFFSET;
StringCopyW (EnumPtr->PatternStr, PatternStr);
return MemDbEnumNextValueW (EnumPtr);
}
BOOL
MemDbEnumNextValueA (
IN OUT PMEMDB_ENUMA EnumPtr
)
{
BOOL b = FALSE;
PCSTR str;
MEMDB_ENUMW enumw;
// ANSI struct is padded to match UNICODE
MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
CopyMemory (&enumw, EnumPtr, sizeof (MEMDB_ENUMW));
// ANSI output members are ignored (i.e. EnumPtr->szName)
b = MemDbEnumNextValueW (&enumw);
if (b) {
str = ConvertWtoA (enumw.szName);
if (str) {
// ANSI struct is padded to match UNICODE
MYASSERT (sizeof (MEMDB_ENUMW) == sizeof (MEMDB_ENUMA));
CopyMemory (EnumPtr, &enumw, sizeof (MEMDB_ENUMW));
// Only the output key name needs to be converted
StringCopyA (EnumPtr->szName, str);
FreeConvertedStr (str);
} else {
b = FALSE;
}
}
return b;
}
BOOL
MemDbEnumNextValueW (
IN OUT PMEMDB_ENUMW EnumPtr
)
{
// no init allowed in declarations
PKEYSTRUCT KeyStruct = NULL;
int Count;
int Level;
WCHAR PartBuf[MEMDB_MAX];
PWSTR PartStr;
PWSTR Src, Dest;
int Pos;
BOOL Wildcard;
BOOL MatchNotFound;
PCWSTR SubPatternStr;
EnterCriticalSection (&g_MemDbCs);
SubPatternStr = SelectHive (EnumPtr->PatternStr);
MatchNotFound = TRUE;
do {
Wildcard = FALSE;
//
// The following states exist upon entry:
//
// STATE DESCRIPTION
// First time through PosCount == 1, LastPos[0] == INVALID_OFFSET
//
// Not first time LastPos[PosCount - 1] == INVALID_OFFSET
// through
//
// Not first time LastPos[PosCount - 1] != INVALID_OFFSET
// through, last match
// hit the depth
// ceiling
//
// PosCount points to the current unprocessed level, or when the
// depth ceiling is reached, it points to the level of the last
// match.
//
do {
//
// Build PartStr
//
Pos = EnumPtr->PosCount - 1;
Count = Pos + 1;
// Locate start of pattern part (if it is long enough)
PartStr = PartBuf;
for (Src = (PWSTR) SubPatternStr ; Count > 1 ; Count--) {
Src = wcschr (Src, L'\\');
if (!Src) {
break;
}
Src++;
}
// Copy part from pattern to buffer
if (Src) {
Dest = PartStr;
while (*Src && *Src != L'\\') {
*Dest = *Src;
Wildcard = Wildcard || (*Dest == L'*') || (*Dest == L'?');
Dest++;
Src++;
}
// Truncate
*Dest = 0;
}
// Use asterisk when pattern is shorter than current level
else {
PartStr = L"*";
Wildcard = TRUE;
}
//
// If current level is set to invalid offset, we have not yet
// tried it.
//
if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
//
// Initialize the level
//
if (Pos == 0) {
EnumPtr->LastPos[0] = g_db->FirstLevelRoot;
} else {
KeyStruct = GetKeyStruct (EnumPtr->LastPos[Pos - 1]);
EnumPtr->LastPos[Pos] = KeyStruct->NextLevelRoot;
}
//
// If still invalid, the level is complete, and we need to
// go back.
//
if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
EnumPtr->PosCount--;
continue;
}
//
// Level ready to be processed
//
if (!Wildcard) {
//
// Use binary tree to locate this item. If no match, the pattern
// will not match anything. Otherwise, we found something to
// return.
//
EnumPtr->LastPos[Pos] = FindKeyStruct (EnumPtr->LastPos[Pos], PartStr);
if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
//
// Non-wildcard ot found. We can try going back because
// there might be a pattern at a higher level.
//
if (Pos > 0) {
PCWSTR p;
INT ParentLevel = 0;
INT LastParentLevel;
LastParentLevel = 0;
// Locate the previous pattern level
p = SubPatternStr;
while (*p && ParentLevel < Pos) {
// Locate wack, pattern or nul
while (*p && *p != L'\\') {
if (*p == L'?' || *p == L'*') {
break;
}
p++;
}
// If pattern or nul, set last pattern level
if (*p != L'\\') {
LastParentLevel = ParentLevel + 1;
// Jump to wack if not at nul
while (*p && *p != L'\\') {
p++;
}
}
// If more pattern exists, skip wack
if (p[0] && p[1]) {
MYASSERT (p[0] == L'\\');
p++;
}
ParentLevel++;
}
// Default: when no pattern, last pattern level is parent
// (Pos is zero-based while LastParentLevel is one-based)
if (!(*p)) {
LastParentLevel = Pos;
}
if (LastParentLevel) {
// Yes, a pattern does exist at a higher level
EnumPtr->PosCount = LastParentLevel;
continue;
}
}
// Pattern not found, we have exhausted all possibilities
LeaveCriticalSection (&g_MemDbCs);
return FALSE;
}
// If level is before start, keep searching forward instead
// of reporting a result.
if (EnumPtr->PosCount <= EnumPtr->Start) {
EnumPtr->PosCount++;
EnumPtr->LastPos[Pos + 1] = INVALID_OFFSET;
continue;
}
// Break out of last nested loop
break;
} else {
//
// Because of pattern, each item in the level must be examined.
// Set the pos to the first item and fall through to the pattern
// search code.
//
EnumPtr->LastPos[Pos] = GetFirstOffset (EnumPtr->LastPos[Pos]);
}
//
// Else if current level is not invalid, last time through we had a
// match and we need to increment the offset (wildcard patterns only).
//
} else {
if (Wildcard) {
EnumPtr->LastPos[Pos] = GetNextOffset (EnumPtr->LastPos[Pos]);
// If there are no more items, go back a level
if (EnumPtr->LastPos[Pos] == INVALID_OFFSET) {
EnumPtr->PosCount--;
continue;
}
}
}
//
// If we are here, it is because we are looking at a level, trying
// to find a pattern match. Loop until either a match is found,
// or we run out of items.
//
// The only exception is when the last match hit the depth ceiling
// and PartStr does not have a wildcard. In this case, we must
// reset the last pos and go back one level.
//
if (Wildcard) {
do {
// Get current key, advance, then check current key against pattern
KeyStruct = GetKeyStruct (EnumPtr->LastPos[Pos]);
if (IsPatternMatch (PartStr, GetKeyToken (KeyStruct->KeyToken)))
break;
EnumPtr->LastPos[Pos] = GetNextOffset (EnumPtr->LastPos[Pos]);
} while (EnumPtr->LastPos[Pos] != INVALID_OFFSET);
// Match found so break out of last nested loop
if (EnumPtr->LastPos[Pos] != INVALID_OFFSET)
break;
} else {
EnumPtr->LastPos[Pos] = INVALID_OFFSET;
}
//
// We ran out of items before finding a match, so it is time to
// go back up a level.
//
EnumPtr->PosCount--;
} while (EnumPtr->PosCount);
// Return if no items found
if (!EnumPtr->PosCount) {
LeaveCriticalSection (&g_MemDbCs);
return FALSE;
}
//
// A match was found. Build output string and prepare position for
// next level.
//
// Build the name of the item and get the value
EnumPtr->szName[0] = 0;
for (Level = EnumPtr->Start ; Level < EnumPtr->PosCount ; Level++) {
PWSTR namePointer = EnumPtr->szName;
KeyStruct = GetKeyStruct (EnumPtr->LastPos[Level]);
if (Level > EnumPtr -> Start) {
namePointer = _wcsappend(namePointer,L"\\");
}
_wcsappend (namePointer, GetKeyToken (KeyStruct->KeyToken));
}
MYASSERT (KeyStruct);
EnumPtr->bEndpoint = (KeyStruct->Flags & KSF_ENDPOINT) != 0;
EnumPtr->bBinary = (KeyStruct->Flags & KSF_BINARY) != 0;
EnumPtr->bProxy = (KeyStruct->Flags & KSF_PROXY_NODE) != 0;
EnumPtr->UserFlags = (KeyStruct->Flags & KSF_USERFLAG_MASK);
EnumPtr->BinaryPtr = GetKeyStructBinaryData (KeyStruct);
EnumPtr->BinarySize = GetKeyStructBinarySize (KeyStruct);
if (EnumPtr->bBinary) {
EnumPtr->dwValue = 0;
} else {
EnumPtr->dwValue = KeyStruct->dwValue;
}
EnumPtr->Offset = EnumPtr->LastPos[Pos] | (g_SelectedDatabase << RESERVED_BITS);
// Prepare position for next level
if ((EnumPtr->PosCount + 1) <= (EnumPtr->Depth + EnumPtr->Start)) {
EnumPtr->LastPos[Pos + 1] = INVALID_OFFSET;
EnumPtr->PosCount++;
}
switch (EnumPtr->Flags) {
case MEMDB_ALL_MATCHES:
MatchNotFound = FALSE;
break;
case MEMDB_ENDPOINTS_ONLY:
MatchNotFound = (KeyStruct->Flags & (KSF_ENDPOINT|KSF_PROXY_NODE)) != KSF_ENDPOINT;
break;
case MEMDB_BINARY_NODES_ONLY:
MatchNotFound = (KeyStruct->Flags & KSF_BINARY) == 0;
break;
case MEMDB_PROXY_NODES_ONLY:
MatchNotFound = (KeyStruct->Flags & KSF_PROXY_NODE) == 0;
break;
case MEMDB_ALL_BUT_PROXY:
MatchNotFound = (KeyStruct->Flags & KSF_PROXY_NODE) != 0;
break;
}
// Loop until flag match is found
} while (MatchNotFound);
LeaveCriticalSection (&g_MemDbCs);
return TRUE;
}
//
// Save and restore functions
//
BOOL
pPrivateMemDbSave (
PCWSTR FileName,
BOOL bUnicode
)
{
HANDLE FileHandle;
BOOL b = FALSE;
DWORD BytesWritten;
EnterCriticalSection (&g_MemDbCs);
__try {
SelectDatabase(0);
if (bUnicode) {
FileHandle = CreateFileW (FileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
} else {
FileHandle = CreateFileA ((PCSTR) FileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (FileHandle == INVALID_HANDLE_VALUE) {
if (bUnicode) {
DEBUGMSGW ((DBG_ERROR, "Can't open %s", FileName));
} else {
DEBUGMSGA ((DBG_ERROR, "Can't open %s", FileName));
}
__leave;
}
// entire file written in UNICODE char set
b = WriteFile (FileHandle, FILE_SIGNATURE, sizeof(FILE_SIGNATURE), &BytesWritten, NULL);
if (b) {
b = WriteFile (FileHandle, g_db, sizeof (DATABASE), &BytesWritten, NULL);
}
if (b) {
b = WriteFile (FileHandle, g_db->Buf, g_db->AllocSize, &BytesWritten, NULL);
if (BytesWritten != g_db->AllocSize)
b = FALSE;
}
if (b) {
b = SaveHashBlock (FileHandle);
}
if (b) {
b = SaveBinaryBlocks (FileHandle);
}
PushError();
CloseHandle (FileHandle);
PopError();
if (!b) {
if (bUnicode) {
DEBUGMSGW ((DBG_ERROR, "Error writing %s", FileName));
DeleteFileW (FileName);
} else {
DEBUGMSGA ((DBG_ERROR, "Error writing %s", FileName));
DeleteFileA ((PCSTR) FileName);
}
__leave;
}
MYASSERT (b == TRUE);
}
__finally {
PushError();
LeaveCriticalSection (&g_MemDbCs);
PopError();
}
return b;
}
BOOL
MemDbSaveA (
PCSTR FileName
)
{
return pPrivateMemDbSave ((PCWSTR) FileName, FALSE); // FALSE=ANSI
}
BOOL
MemDbSaveW (
PCWSTR FileName
)
{
return pPrivateMemDbSave (FileName, TRUE); // TRUE=UNICODE
}
BOOL
pPrivateMemDbLoad (
IN PCWSTR FileName,
IN BOOL bUnicode,
OUT PMEMDB_VERSION Version, OPTIONAL
IN BOOL QueryVersionOnly
)
{
HANDLE FileHandle;
BOOL b;
DWORD BytesRead;
WCHAR Buf[sizeof(FILE_SIGNATURE)];
PBYTE TempBuf = NULL;
PCWSTR VerPtr;
EnterCriticalSection (&g_MemDbCs);
if (Version) {
ZeroMemory (Version, sizeof (MEMDB_VERSION));
}
//
// Blow away existing resources
//
if (!QueryVersionOnly) {
pFreeAllDatabases();
}
//
// Load in file
//
if (*FileName && FileName) {
if (bUnicode) {
FileHandle = CreateFileW (FileName, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
} else {
FileHandle = CreateFileA ((PCSTR) FileName, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
} else {
FileHandle = INVALID_HANDLE_VALUE;
}
b = (FileHandle != INVALID_HANDLE_VALUE);
__try {
//
// Obtain the file signature
//
// NOTE: Entire file read is in UNICODE char set
//
if (b) {
b = ReadFile (FileHandle, Buf, sizeof(FILE_SIGNATURE), &BytesRead, NULL);
if (Version) {
if (StringMatchByteCountW (
VERSION_BASE_SIGNATURE,
Buf,
sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR)
)) {
Version->Valid = TRUE;
//
// Identify version number
//
VerPtr = (PCWSTR) ((PBYTE) Buf + sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR));
if (StringMatchByteCountW (
MEMDB_VERSION,
VerPtr,
sizeof (MEMDB_VERSION) - sizeof (WCHAR)
)) {
Version->CurrentVersion = TRUE;
}
Version->Version = (UINT) _wtoi (VerPtr + 1);
//
// Identify checked or free build
//
VerPtr += (sizeof (MEMDB_VERSION) / sizeof (WCHAR)) - 1;
if (StringMatchByteCountW (
MEMDB_DEBUG_SIGNATURE,
VerPtr,
sizeof (MEMDB_DEBUG_SIGNATURE) - sizeof (WCHAR)
)) {
Version->Debug = TRUE;
} else if (!StringMatchByteCountW (
VerPtr,
MEMDB_NODBG_SIGNATURE,
sizeof (MEMDB_NODBG_SIGNATURE) - sizeof (WCHAR)
)) {
Version->Valid = FALSE;
}
}
}
}
if (QueryVersionOnly) {
b = FALSE;
}
if (b) {
b = StringMatchW (Buf, FILE_SIGNATURE);
#ifdef DEBUG
//
// This code allows a debug build of memdb to work with both
// debug and retail versions of the DAT file
//
if (!b) {
if (StringMatchW (Buf, DEBUG_FILE_SIGNATURE)) {
g_UseDebugStructs = TRUE;
b = TRUE;
} else if (StringMatchW (Buf, RETAIL_FILE_SIGNATURE)) {
DEBUGMSG ((DBG_ERROR, "memdb dat file is from free build; checked version expected"));
g_UseDebugStructs = FALSE;
b = TRUE;
}
}
#else
if (!b) {
SetLastError (ERROR_BAD_FORMAT);
LOG ((LOG_WARNING, "Warning: data file could be from checked build; free version expected"));
}
#endif
}
//
// Obtain the database struct
//
if (b) {
b = ReadFile (FileHandle, (PBYTE) g_db, sizeof (DATABASE), &BytesRead, NULL);
if (BytesRead != sizeof (DATABASE)) {
b = FALSE;
SetLastError (ERROR_BAD_FORMAT);
}
}
//
// Allocate the memory block
//
if (b) {
TempBuf = (PBYTE) MemAlloc (g_hHeap, 0, g_db->AllocSize);
if (TempBuf) {
g_db->Buf = TempBuf;
TempBuf = NULL;
} else {
b = FALSE;
}
}
//
// Read the memory block
//
if (b) {
b = ReadFile (FileHandle, g_db->Buf, g_db->AllocSize, &BytesRead, NULL);
if (BytesRead != g_db->AllocSize) {
b = FALSE;
SetLastError (ERROR_BAD_FORMAT);
}
}
//
// Read the hash table
//
if (b) {
b = LoadHashBlock (FileHandle);
}
//
// Read binary blocks
//
if (b) {
b = LoadBinaryBlocks (FileHandle);
}
}
__except (TRUE) {
b = FALSE;
PushError();
LOG ((LOG_ERROR, "MemDb dat file %s could not be loaded because of an exception", FileName));
FreeAllBinaryBlocks();
PopError();
}
PushError();
if (FileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (FileHandle);
}
if (!b && !QueryVersionOnly) {
pFreeAllDatabases();
pInitializeMemDb();
}
LeaveCriticalSection (&g_MemDbCs);
PopError();
if (QueryVersionOnly) {
return TRUE;
}
return b;
}
BOOL
MemDbLoadA (
IN PCSTR FileName
)
{
return pPrivateMemDbLoad ((PCWSTR) FileName, FALSE, NULL, FALSE);
}
BOOL
MemDbLoadW (
IN PCWSTR FileName
)
{
return pPrivateMemDbLoad (FileName, TRUE, NULL, FALSE);
}
BOOL
MemDbValidateDatabase (
VOID
)
{
MEMDB_ENUMW e;
if (MemDbEnumFirstValueW (&e, L"*", 0, MEMDB_ENDPOINTS_ONLY)) {
do {
if (!pPrivateMemDbGetValueW (e.szName, NULL, NULL)) {
return FALSE;
}
} while (MemDbEnumNextValueW (&e));
}
return TRUE;
}
BOOL
MemDbCreateTemporaryKeyA (
IN PCSTR KeyName
)
{
PCWSTR KeyNameW;
BOOL b = FALSE;
KeyNameW = ConvertAtoW (KeyName);
if (KeyNameW) {
b = MemDbCreateTemporaryKeyW (KeyNameW);
FreeConvertedStr (KeyNameW);
}
return b;
}
BOOL
MemDbCreateTemporaryKeyW (
IN PCWSTR KeyName
)
{
UINT Count;
UINT Index;
PDATABASE Database;
DWORD KeyOffset;
PCWSTR SubKey;
BOOL b = FALSE;
EnterCriticalSection (&g_MemDbCs);
__try {
if (wcslen (KeyName) >= MAX_HIVE_NAME) {
SetLastError (ERROR_INVALID_PARAMETER);
__leave;
}
SubKey = SelectHive (KeyName);
KeyOffset = FindKey (SubKey);
if (KeyOffset != INVALID_OFFSET) {
SetLastError (ERROR_ALREADY_EXISTS);
__leave;
}
Count = GrowListGetSize (&g_DatabaseList);
for (Index = 1 ; Index < Count ; Index++) {
Database = (PDATABASE) GrowListGetItem (&g_DatabaseList, Index);
if (Database && StringIMatchW (Database->Hive, KeyName)) {
SetLastError (ERROR_ALREADY_EXISTS);
__leave;
}
}
b = pCreateDatabase (KeyName);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
/*++
Routine Description:
MemDbMakeNonPrintableKey converts the double-backslashe pairs in a string
to ASCII 1, a non-printable character. This allows the caller to store
properly escaped strings in MemDb.
This routine is desinged to be expanded for other types of escape
processing.
Arguments:
KeyName - Specifies the key text; receives the converted text. The DBCS
version may grow the text buffer, so the text buffer must be twice
the length of the inbound string.
Flags - Specifies the type of conversion. Currently only
MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1 is supported.
Return Value:
none
--*/
VOID
MemDbMakeNonPrintableKeyA (
IN OUT PSTR KeyName,
IN DWORD Flags
)
{
while (*KeyName) {
if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
if (_mbsnextc (KeyName) == '\\' &&
_mbsnextc (_mbsinc (KeyName)) == '\\'
) {
_setmbchar (KeyName, 1);
KeyName = _mbsinc (KeyName);
MYASSERT (_mbsnextc (KeyName) == '\\');
_setmbchar (KeyName, 1);
}
DEBUGMSG_IF ((
_mbsnextc (KeyName) == 1,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyA: Non-printable character "
"collision detected; key was damaged"
));
}
if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
if (_mbsnextc (KeyName) == '*') {
_setmbchar (KeyName, 2);
}
DEBUGMSG_IF ((
_mbsnextc (_mbsinc (KeyName)) == 2,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyA: Non-printable character "
"collision detected; key was damaged"
));
}
if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
if (_mbsnextc (KeyName) == '?') {
_setmbchar (KeyName, 3);
}
DEBUGMSG_IF ((
_mbsnextc (_mbsinc (KeyName)) == 3,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyA: Non-printable character "
"collision detected; key was damaged"
));
}
KeyName = _mbsinc (KeyName);
}
}
VOID
MemDbMakeNonPrintableKeyW (
IN OUT PWSTR KeyName,
IN DWORD Flags
)
{
while (*KeyName) {
if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
if (KeyName[0] == L'\\' && KeyName[1] == L'\\') {
KeyName[0] = 1;
KeyName[1] = 1;
KeyName++;
}
DEBUGMSG_IF ((
KeyName[0] == 1,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyW: Non-printable character "
"collision detected; key was damaged"
));
}
if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
if (KeyName[0] == L'*') {
KeyName[0] = 2;
}
DEBUGMSG_IF ((
KeyName[1] == 2,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyW: Non-printable character "
"collision detected; key was damaged"
));
}
if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
if (KeyName[0] == L'*') {
KeyName[0] = 3;
}
DEBUGMSG_IF ((
KeyName[1] == 3,
DBG_WHOOPS,
"MemDbMakeNonPrintableKeyW: Non-printable character "
"collision detected; key was damaged"
));
}
KeyName++;
}
}
/*++
Routine Description:
MemDbMakePrintableKey converts the ASCII 1 characters to backslashes,
restoring the string converted by MemDbMakeNonPrintableKey.
This routine is desinged to be expanded for other types of escape
processing.
Arguments:
KeyName - Specifies the key text; receives the converted text. The DBCS
version may grow the text buffer, so the text buffer must be twice
the length of the inbound string.
Flags - Specifies the type of conversion. Currently only
MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1 is supported.
Return Value:
none
--*/
VOID
MemDbMakePrintableKeyA (
IN OUT PSTR KeyName,
IN DWORD Flags
)
{
while (*KeyName) {
if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
if (_mbsnextc (KeyName) == 1) {
_setmbchar (KeyName, '\\');
}
}
if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
if (_mbsnextc (KeyName) == 2) {
_setmbchar (KeyName, '*');
}
}
if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
if (_mbsnextc (KeyName) == 3) {
_setmbchar (KeyName, '?');
}
}
KeyName = _mbsinc (KeyName);
}
}
VOID
MemDbMakePrintableKeyW (
IN OUT PWSTR KeyName,
IN DWORD Flags
)
{
while (*KeyName) {
if (Flags & MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1) {
if (KeyName[0] == 1) {
KeyName[0] = L'\\';
}
}
if (Flags & MEMDB_CONVERT_WILD_STAR_TO_ASCII_2) {
if (KeyName[0] == 2) {
KeyName[0] = L'*';
}
}
if (Flags & MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3) {
if (KeyName[0] == 3) {
KeyName[0] = L'?';
}
}
KeyName++;
}
}
VOID
GetFixedUserNameA (
IN OUT PSTR SrcUserBuf
)
/*++
Routine Description:
GetFixedUserName looks in memdb for the user specified in SrcUserBuf,
and if found, returns the changed name.
Arguments:
SrcUserBuf - Specifies the user to look up as returned from the Win9x
registry. Receives the user name to create on NT.
Return Value:
None.
--*/
{
CHAR EncodedName[MEMDB_MAX];
CHAR FixedName[MEMDB_MAX];
StringCopyA (EncodedName, SrcUserBuf);
MemDbMakeNonPrintableKeyA (
EncodedName,
MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1|
MEMDB_CONVERT_WILD_STAR_TO_ASCII_2|
MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3
);
if (MemDbGetEndpointValueExA (
MEMDB_CATEGORY_FIXEDUSERNAMESA,
EncodedName,
NULL,
FixedName
)) {
StringCopyA (SrcUserBuf, FixedName);
}
}
VOID
GetFixedUserNameW (
IN OUT PWSTR SrcUserBuf
)
/*++
Routine Description:
GetFixedUserName looks in memdb for the user specified in SrcUserBuf,
and if found, returns the changed name.
Arguments:
SrcUserBuf - Specifies the user to look up as returned from the Win9x
registry. Receives the user name to create on NT.
Return Value:
None.
--*/
{
WCHAR EncodedName[MEMDB_MAX];
WCHAR FixedName[MEMDB_MAX];
StringCopyW (EncodedName, SrcUserBuf);
MemDbMakeNonPrintableKeyW (
EncodedName,
MEMDB_CONVERT_DOUBLEWACKS_TO_ASCII_1|
MEMDB_CONVERT_WILD_STAR_TO_ASCII_2|
MEMDB_CONVERT_WILD_QMARK_TO_ASCII_3
);
if (MemDbGetEndpointValueExW (
MEMDB_CATEGORY_FIXEDUSERNAMESW,
EncodedName,
NULL,
FixedName
)) {
StringCopyW (SrcUserBuf, FixedName);
}
}
/*
The format of the binary file for MemDb export
DWORD Signature
DWORD Version
DWORD GlobalFlags// 0x00000001 mask for Ansi format
// 0x00000002 mask for Temporary key
BYTE Root[]; // The root of the tree (zero terminated).
struct _KEY {
WORD Flags; // 0xF000 mask for accessing the entry flags
// - 0x1000 - Mask for Key name (0 - root relative, 1 - previous key relative)
// - 0x2000 - Mask for existing data (0 - no data, 1 - some data)
// - 0x4000 - Mast for data type (0 - DWORD, 1 - binary data)
// - 0x8000 - Mast for key flags (0 - nonexistent, 1 - existent)
// 0x0FFF mask for accessing size of the entry (except the data)
BYTE Key[]; // Should be PCSTR or PCWSTR (not zero terminated)
DWORD KeyFlags; //optional (dependant on Flags).
BYTE Data[]; // optional (dependant on Flags).
// if BLOB first DWORD is the size of the BLOB
// if DWORD then has exactly 4 bytes
}
...
*/
#define MEMDB_EXPORT_SIGNATURE 0x42444D4D
#define MEMDB_EXPORT_VERSION 0x00000001
#define MEMDB_EXPORT_FLAGS_ANSI 0x00000001
#define MEMDB_EXPORT_FLAGS_TEMP_KEY 0x00000002
#define MEMDB_EXPORT_FLAGS_PREV_RELATIVE 0x1000
#define MEMDB_EXPORT_FLAGS_DATA_PRESENT 0x2000
#define MEMDB_EXPORT_FLAGS_BINARY_DATA 0x4000
#define MEMDB_EXPORT_FLAGS_FLAGS_PRESENT 0x8000
#define MEMDB_EXPORT_FLAGS_SIZE_MASK 0x0FFF
BOOL
pMemDbExportWorkerA (
IN PCSTR RootTree,
IN PCSTR FileName
)
{
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCWSTR uRootTree;
PCSTR lastWackPtr;
DWORD globalFlags;
WORD localFlags;
CHAR key[MEMDB_MAX];
DWORD keySize;
DWORD copySize;
MEMDB_ENUMA e;
WORD blobSize;
DWORD written;
fileHandle = CreateFileA (FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}
globalFlags = MEMDB_EXPORT_SIGNATURE;
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
globalFlags = MEMDB_EXPORT_VERSION;
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
globalFlags = MEMDB_EXPORT_FLAGS_ANSI;
// get the information if this key is a temporary key and set the flags if true
uRootTree = ConvertAtoW (RootTree);
if (IsTemporaryKey (uRootTree)) {
globalFlags |= MEMDB_EXPORT_FLAGS_TEMP_KEY;
}
FreeConvertedStr (uRootTree);
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
// now write the root tree
WriteFile (fileHandle, RootTree, SizeOfStringA (RootTree), &written, NULL);
MemDbBuildKeyA (key, RootTree, "*", NULL, NULL);
if (MemDbEnumFirstValueA (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
key [0] = 0;
keySize = 0;
do {
// initialize the flags
localFlags = 0;
if (e.bBinary) {
localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
localFlags |= MEMDB_EXPORT_FLAGS_BINARY_DATA;
} else {
if (e.dwValue) {
localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
}
}
if (e.UserFlags) {
localFlags |= MEMDB_EXPORT_FLAGS_FLAGS_PRESENT;
}
// let's compute the size for this blob
blobSize = sizeof (WORD); // Flags
if (keySize &&
StringIMatchByteCountA (key, e.szName, keySize - sizeof (CHAR)) &&
(e.szName [keySize - 1] == '\\')
) {
localFlags |= MEMDB_EXPORT_FLAGS_PREV_RELATIVE;
copySize = SizeOfStringA (e.szName) - keySize - sizeof (CHAR);
} else {
copySize = SizeOfStringA (e.szName) - sizeof (CHAR);
keySize = 0;
}
MYASSERT (copySize < 4096);
blobSize += (WORD) copySize;
localFlags |= blobSize;
// write the flags
WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
// write the key
WriteFile (fileHandle, ((PBYTE) e.szName) + keySize, copySize, &written, NULL);
// write the key flags if appropriate
if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
WriteFile (fileHandle, &e.UserFlags, sizeof (DWORD), &written, NULL);
}
// write the data if appropriate
if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
WriteFile (fileHandle, &e.BinarySize, sizeof (DWORD), &written, NULL);
WriteFile (fileHandle, e.BinaryPtr, e.BinarySize, &written, NULL);
} else {
WriteFile (fileHandle, &e.dwValue, sizeof (DWORD), &written, NULL);
}
}
lastWackPtr = _mbsrchr (e.szName, '\\');
if (lastWackPtr) {
keySize = ByteCountABA (e.szName, lastWackPtr) + sizeof (CHAR);
StringCopyByteCountA (key, e.szName, keySize);
} else {
keySize = 0;
}
} while (MemDbEnumNextValueA (&e));
}
localFlags = 0;
// finally write the zero terminator
WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
CloseHandle (fileHandle);
return TRUE;
}
BOOL
pMemDbExportWorkerW (
IN PCWSTR RootTree,
IN PCWSTR FileName
)
{
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCWSTR lastWackPtr;
DWORD globalFlags;
WORD localFlags;
WCHAR key[MEMDB_MAX];
DWORD keySize;
DWORD copySize;
MEMDB_ENUMW e;
WORD blobSize;
DWORD written;
fileHandle = CreateFileW (FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}
globalFlags = MEMDB_EXPORT_SIGNATURE;
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
globalFlags = MEMDB_EXPORT_VERSION;
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
// get the information if this key is a temporary key and set the flags if true
if (IsTemporaryKey (RootTree)) {
globalFlags |= MEMDB_EXPORT_FLAGS_TEMP_KEY;
}
WriteFile (fileHandle, &globalFlags, sizeof (DWORD), &written, NULL);
// now write the root tree
WriteFile (fileHandle, RootTree, SizeOfStringW (RootTree), &written, NULL);
MemDbBuildKeyW (key, RootTree, L"*", NULL, NULL);
if (MemDbEnumFirstValueW (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
key [0] = 0;
keySize = 0;
do {
// initialize the flags
localFlags = 0;
if (e.bBinary) {
localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
localFlags |= MEMDB_EXPORT_FLAGS_BINARY_DATA;
} else {
if (e.dwValue) {
localFlags |= MEMDB_EXPORT_FLAGS_DATA_PRESENT;
}
}
if (e.UserFlags) {
localFlags |= MEMDB_EXPORT_FLAGS_FLAGS_PRESENT;
}
// let's compute the size for this blob
blobSize = sizeof (WORD); // Flags
if (keySize &&
StringIMatchByteCountW (key, e.szName, keySize - sizeof (WCHAR)) &&
(e.szName [keySize - 1] == L'\\')
) {
localFlags |= MEMDB_EXPORT_FLAGS_PREV_RELATIVE;
copySize = SizeOfStringW (e.szName) - keySize - sizeof (WCHAR);
} else {
copySize = SizeOfStringW (e.szName) - sizeof (WCHAR);
keySize = 0;
}
MYASSERT (copySize < 4096);
blobSize += (WORD) copySize;
localFlags |= blobSize;
// write the flags
WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
// write the key
WriteFile (fileHandle, ((PBYTE) e.szName) + keySize, copySize, &written, NULL);
// write the key flags if appropriate
if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
WriteFile (fileHandle, &e.UserFlags, sizeof (DWORD), &written, NULL);
}
// write the data if appropriate
if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
WriteFile (fileHandle, &e.BinarySize, sizeof (DWORD), &written, NULL);
WriteFile (fileHandle, e.BinaryPtr, e.BinarySize, &written, NULL);
} else {
WriteFile (fileHandle, &e.dwValue, sizeof (DWORD), &written, NULL);
}
}
lastWackPtr = wcsrchr (e.szName, L'\\');
if (lastWackPtr) {
keySize = ByteCountABW (e.szName, lastWackPtr) + sizeof (WCHAR);
StringCopyByteCountW (key, e.szName, keySize);
} else {
keySize = 0;
}
} while (MemDbEnumNextValueW (&e));
}
localFlags = 0;
// finally write the zero terminator
WriteFile (fileHandle, &localFlags, sizeof (WORD), &written, NULL);
CloseHandle (fileHandle);
return TRUE;
}
BOOL
MemDbExportA (
IN PCSTR RootTree,
IN PCSTR FileName,
IN BOOL AnsiFormat
)
/*++
Routine Description:
MemDbExportA exports a tree in a private binary format. The format is described above.
Arguments:
RootTree - Specifies the tree to be exported
FileName - Name of the binary format file to export to.
AnsiFormat - Keys should be written in ANSI rather than in Unicode.
Return Value:
TRUE is successfull, FALSE if not.
--*/
{
PCWSTR uRootTree, uFileName;
BOOL result = TRUE;
if (AnsiFormat) {
result = pMemDbExportWorkerA (RootTree, FileName);
} else {
uRootTree = ConvertAtoW (RootTree);
uFileName = ConvertAtoW (FileName);
result = pMemDbExportWorkerW (uRootTree, uFileName);
FreeConvertedStr (uFileName);
FreeConvertedStr (uRootTree);
}
return result;
}
BOOL
MemDbExportW (
IN PCWSTR RootTree,
IN PCWSTR FileName,
IN BOOL AnsiFormat
)
/*++
Routine Description:
MemDbExportW exports a tree in a private binary format. The format is described above.
Arguments:
RootTree - Specifies the tree to be exported
FileName - Name of the binary format file to export to.
AnsiFormat - Keys should be written in ANSI rather than in Unicode.
Return Value:
TRUE is successfull, FALSE if not.
--*/
{
PCSTR aRootTree, aFileName;
BOOL result = TRUE;
if (!AnsiFormat) {
result = pMemDbExportWorkerW (RootTree, FileName);
} else {
aRootTree = ConvertWtoA (RootTree);
aFileName = ConvertWtoA (FileName);
result = pMemDbExportWorkerA (aRootTree, aFileName);
FreeConvertedStr (aFileName);
FreeConvertedStr (aRootTree);
}
return result;
}
BOOL
pMemDbImportWorkerA (
IN PBYTE FileBuffer
)
{
DWORD globalFlags;
WORD localFlags;
PCSTR rootTree;
CHAR lastKey [MEMDB_MAX];
PSTR lastKeyPtr;
CHAR node [MEMDB_MAX];
CHAR localKey [MEMDB_MAX];
DWORD flags = 0;
globalFlags = *((PDWORD) FileBuffer);
// FileBuffer will point to the tree that's imported
FileBuffer += sizeof (DWORD);
rootTree = (PCSTR) FileBuffer;
if (globalFlags & MEMDB_EXPORT_FLAGS_TEMP_KEY) {
// a temporary key was exported
MemDbCreateTemporaryKeyA ((PCSTR) FileBuffer);
}
// let's pass the string
FileBuffer = GetEndOfStringA ((PCSTR) FileBuffer) + sizeof (CHAR);
// ok from this point on we read and add all keys
lastKey [0] = 0;
localFlags = *((PWORD) FileBuffer);
while (localFlags) {
localKey [0] = 0;
StringCopyByteCountA (localKey, (PSTR)(FileBuffer + sizeof (WORD)), (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK) - sizeof (WORD) + sizeof (CHAR));
MemDbBuildKeyA (node, rootTree, (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE)?lastKey:NULL, localKey, NULL);
FileBuffer += (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK);
MYASSERT (!((localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) && (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT)));
if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
flags = *(PDWORD)FileBuffer;
FileBuffer += sizeof (DWORD);
}
if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
MemDbSetBinaryValueA (node, FileBuffer + sizeof (DWORD), *(PDWORD)FileBuffer);
FileBuffer += (*(PDWORD)FileBuffer + sizeof (DWORD));
} else {
MemDbSetValueAndFlagsA (node, *(PDWORD)FileBuffer, flags, 0);
FileBuffer += sizeof (DWORD);
}
} else {
MemDbSetValueA (node, 0);
}
if (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE) {
StringCatA (lastKey, "\\");
StringCatA (lastKey, localKey);
lastKeyPtr = _mbsrchr (lastKey, '\\');
if (lastKeyPtr) {
*lastKeyPtr = 0;
} else {
lastKey [0] = 0;
}
} else {
StringCopyA (lastKey, localKey);
lastKeyPtr = _mbsrchr (lastKey, '\\');
if (lastKeyPtr) {
*lastKeyPtr = 0;
} else {
lastKey [0] = 0;
}
}
localFlags = *((PWORD) FileBuffer);
}
return TRUE;
}
BOOL
pMemDbImportWorkerW (
IN PBYTE FileBuffer
)
{
DWORD globalFlags;
WORD localFlags;
PCWSTR rootTree;
WCHAR lastKey [MEMDB_MAX];
PWSTR lastKeyPtr;
WCHAR node [MEMDB_MAX];
WCHAR localKey [MEMDB_MAX];
DWORD flags = 0;
globalFlags = *((PDWORD) FileBuffer);
// FileBuffer will point to the tree that's imported
FileBuffer += sizeof (DWORD);
rootTree = (PCWSTR) FileBuffer;
if (globalFlags & MEMDB_EXPORT_FLAGS_TEMP_KEY) {
// a temporary key was exported
MemDbCreateTemporaryKeyW ((PCWSTR) FileBuffer);
}
// let's pass the string
FileBuffer = (PBYTE)GetEndOfStringW ((PCWSTR) FileBuffer) + sizeof (WCHAR);
// ok from this point on we read and add all keys
lastKey [0] = 0;
localFlags = *((PWORD) FileBuffer);
while (localFlags) {
localKey [0] = 0;
StringCopyByteCountW (localKey, (PWSTR)(FileBuffer + sizeof (WORD)), (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK) - sizeof (WORD) + sizeof (WCHAR));
MemDbBuildKeyW (node, rootTree, (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE)?lastKey:NULL, localKey, NULL);
FileBuffer += (localFlags & MEMDB_EXPORT_FLAGS_SIZE_MASK);
MYASSERT (!((localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) && (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT)));
if (localFlags & MEMDB_EXPORT_FLAGS_FLAGS_PRESENT) {
flags = *(PDWORD)FileBuffer;
FileBuffer += sizeof (DWORD);
}
if (localFlags & MEMDB_EXPORT_FLAGS_DATA_PRESENT) {
if (localFlags & MEMDB_EXPORT_FLAGS_BINARY_DATA) {
MemDbSetBinaryValueW (node, FileBuffer + sizeof (DWORD), *(PDWORD)FileBuffer);
FileBuffer += (*(PDWORD)FileBuffer + sizeof (DWORD));
} else {
MemDbSetValueAndFlagsW (node, *(PDWORD)FileBuffer, flags, 0);
FileBuffer += sizeof (DWORD);
}
} else {
MemDbSetValueW (node, 0);
}
if (localFlags & MEMDB_EXPORT_FLAGS_PREV_RELATIVE) {
StringCatW (lastKey, L"\\");
StringCatW (lastKey, localKey);
lastKeyPtr = wcsrchr (lastKey, L'\\');
if (lastKeyPtr) {
*lastKeyPtr = 0;
} else {
lastKey [0] = 0;
}
} else {
StringCopyW (lastKey, localKey);
lastKeyPtr = wcsrchr (lastKey, L'\\');
if (lastKeyPtr) {
*lastKeyPtr = 0;
} else {
lastKey [0] = 0;
}
}
localFlags = *((PWORD) FileBuffer);
}
return TRUE;
}
BOOL
MemDbImportA (
IN PCSTR FileName
)
/*++
Routine Description:
MemDbImportA imports a tree from a private binary format. The format is described above.
Arguments:
FileName - Name of the binary format file to import from.
Return Value:
TRUE is successfull, FALSE if not.
--*/
{
PBYTE fileBuff;
HANDLE fileHandle;
HANDLE mapHandle;
BOOL result = TRUE;
fileBuff = MapFileIntoMemoryA (FileName, &fileHandle, &mapHandle);
if (fileBuff == NULL) {
DEBUGMSGA ((DBG_ERROR, "Could not execute MemDbImport for %s", FileName));
return FALSE;
}
__try {
if (*((PDWORD) fileBuff) != MEMDB_EXPORT_SIGNATURE) {
DEBUGMSGA ((DBG_ERROR, "Unknown signature for file to import: %s", FileName));
result = FALSE;
} else {
fileBuff += sizeof (DWORD);
if (*((PDWORD) fileBuff) != MEMDB_EXPORT_VERSION) {
DEBUGMSGA ((DBG_ERROR, "Unknown version for file to import: %s", FileName));
result = FALSE;
} else {
fileBuff += sizeof (DWORD);
if (*((PDWORD) fileBuff) & MEMDB_EXPORT_FLAGS_ANSI) {
result = pMemDbImportWorkerA (fileBuff);
} else {
result = pMemDbImportWorkerW (fileBuff);
}
}
}
}
__except (1) {
DEBUGMSGA ((DBG_ERROR, "Access violation while importing: %s", FileName));
}
UnmapFile (fileBuff, mapHandle, fileHandle);
return result;
}
BOOL
MemDbImportW (
IN PCWSTR FileName
)
/*++
Routine Description:
MemDbImportW imports a tree from a private binary format. The format is described above.
Arguments:
FileName - Name of the binary format file to import from.
Return Value:
TRUE is successfull, FALSE if not.
--*/
{
PBYTE fileBuff;
HANDLE fileHandle;
HANDLE mapHandle;
BOOL result;
fileBuff = MapFileIntoMemoryW (FileName, &fileHandle, &mapHandle);
if (fileBuff == NULL) {
DEBUGMSGW ((DBG_ERROR, "Could not execute MemDbImport for %s", FileName));
return FALSE;
}
__try {
if (*((PDWORD) fileBuff) != MEMDB_EXPORT_SIGNATURE) {
DEBUGMSGW ((DBG_ERROR, "Unknown signature for file to import: %s", FileName));
result = FALSE;
} else {
fileBuff += sizeof (DWORD);
if (*((PDWORD) fileBuff) != MEMDB_EXPORT_VERSION) {
DEBUGMSGW ((DBG_ERROR, "Unknown version for file to import: %s", FileName));
result = FALSE;
} else {
fileBuff += sizeof (DWORD);
if (*((PDWORD) fileBuff) & MEMDB_EXPORT_FLAGS_ANSI) {
result = pMemDbImportWorkerA (fileBuff);
} else {
result = pMemDbImportWorkerW (fileBuff);
}
}
}
}
__except (1) {
DEBUGMSGW ((DBG_ERROR, "Access violation while importing: %s", FileName));
}
UnmapFile (fileBuff, mapHandle, fileHandle);
return result;
}
BOOL
MemDbQueryVersionA (
PCSTR FileName,
PMEMDB_VERSION Version
)
{
pPrivateMemDbLoad ((PCWSTR) FileName, FALSE, Version, TRUE);
return Version->Valid;
}
BOOL
MemDbQueryVersionW (
PCWSTR FileName,
PMEMDB_VERSION Version
)
{
pPrivateMemDbLoad (FileName, TRUE, Version, TRUE);
return Version->Valid;
}