890 lines
20 KiB
C
890 lines
20 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
memdbfile.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
file operations for memdb saving/loading/exporting/importing
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Jim Schmidt (jimschm) 8-Aug-1996
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
mvander 13-Aug-1999 split from memdb.c
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "memdbp.h"
|
||
|
|
||
|
//
|
||
|
// This is our version stamp. Change MEMDB_VERSION_STAMP only.
|
||
|
//
|
||
|
|
||
|
#define MEMDB_VERSION_STAMP 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_STAMP
|
||
|
#define DEBUG_FILE_SIGNATURE VERSION_SIGNATURE MEMDB_DEBUG_SIGNATURE
|
||
|
#define RETAIL_FILE_SIGNATURE VERSION_SIGNATURE MEMDB_NODBG_SIGNATURE
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#define FILE_SIGNATURE DEBUG_FILE_SIGNATURE
|
||
|
#else
|
||
|
#define FILE_SIGNATURE RETAIL_FILE_SIGNATURE
|
||
|
#endif
|
||
|
|
||
|
PBYTE
|
||
|
MapFileFromHandle (
|
||
|
HANDLE hFile,
|
||
|
PHANDLE hMap
|
||
|
)
|
||
|
{
|
||
|
MYASSERT(hMap);
|
||
|
if (!hFile || hFile == INVALID_HANDLE_VALUE) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
*hMap = CreateFileMappingA (
|
||
|
hFile,
|
||
|
NULL,
|
||
|
PAGE_READWRITE,
|
||
|
0,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if (*hMap == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return MapViewOfFile (*hMap, FILE_MAP_WRITE, 0, 0, 0);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SetSizeOfFile (
|
||
|
HANDLE hFile,
|
||
|
LONGLONG Size
|
||
|
)
|
||
|
{
|
||
|
LONG a;
|
||
|
LONG b;
|
||
|
PLONG sizeHi;
|
||
|
|
||
|
a = (LONG) Size;
|
||
|
b = (LONG) (SHIFTRIGHT32(Size));
|
||
|
if (b) {
|
||
|
sizeHi = &b;
|
||
|
} else {
|
||
|
sizeHi = NULL;
|
||
|
}
|
||
|
|
||
|
if (SetFilePointer (hFile, a, sizeHi, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!SetEndOfFile (hFile)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
WriteBlocks (
|
||
|
IN OUT PBYTE *Buf,
|
||
|
IN PMEMDBHASH pHashTable,
|
||
|
IN PGROWBUFFER pOffsetBuffer
|
||
|
)
|
||
|
{
|
||
|
MYASSERT(Buf);
|
||
|
MYASSERT(pHashTable);
|
||
|
MYASSERT(pOffsetBuffer);
|
||
|
|
||
|
if (!WriteHashBlock (pHashTable, Buf)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!WriteOffsetBlock (pOffsetBuffer, Buf)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
ReadBlocks (
|
||
|
IN OUT PBYTE *Buf,
|
||
|
OUT PMEMDBHASH *ppHashTable,
|
||
|
OUT PGROWBUFFER pOffsetBuffer
|
||
|
)
|
||
|
{
|
||
|
MYASSERT(Buf);
|
||
|
MYASSERT(ppHashTable);
|
||
|
MYASSERT(pOffsetBuffer);
|
||
|
|
||
|
//
|
||
|
// fill hash block
|
||
|
//
|
||
|
if (!*ppHashTable) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!ReadHashBlock (*ppHashTable, Buf)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!ReadOffsetBlock (pOffsetBuffer, Buf)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
pPrivateMemDbSave (
|
||
|
PCSTR FileName
|
||
|
)
|
||
|
{
|
||
|
HANDLE FileHandle = NULL;
|
||
|
HANDLE hMap = INVALID_HANDLE_VALUE;
|
||
|
PBYTE Buf = NULL;
|
||
|
PBYTE MapPtr = NULL;
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
EnterCriticalSection (&g_MemDbCs);
|
||
|
|
||
|
__try {
|
||
|
|
||
|
if (!SelectDatabase (DB_PERMANENT)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// now we resize file to fit everything in it.
|
||
|
//
|
||
|
FileHandle = BfCreateFileA (FileName);
|
||
|
|
||
|
if (!FileHandle) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (!SetSizeOfFile (
|
||
|
FileHandle,
|
||
|
(LONGLONG)(sizeof (FILE_SIGNATURE)) +
|
||
|
g_CurrentDatabase->AllocSize +
|
||
|
GetHashTableBlockSize (g_CurrentDatabase->HashTable) +
|
||
|
GetOffsetBufferBlockSize (&g_CurrentDatabase->OffsetBuffer)
|
||
|
)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Buf = MapFileFromHandle (FileHandle, &hMap);
|
||
|
|
||
|
if (Buf == NULL) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
MapPtr = Buf;
|
||
|
|
||
|
CopyMemory (Buf, FILE_SIGNATURE, sizeof (FILE_SIGNATURE));
|
||
|
|
||
|
Buf += sizeof (FILE_SIGNATURE);
|
||
|
|
||
|
CopyMemory (Buf, g_CurrentDatabase, g_CurrentDatabase->AllocSize);
|
||
|
|
||
|
Buf += g_CurrentDatabase->AllocSize;
|
||
|
|
||
|
if (!WriteBlocks (
|
||
|
&Buf,
|
||
|
g_CurrentDatabase->HashTable,
|
||
|
&g_CurrentDatabase->OffsetBuffer
|
||
|
)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
result = TRUE;
|
||
|
}
|
||
|
__finally {
|
||
|
|
||
|
UnmapFile (MapPtr, hMap, FileHandle);
|
||
|
|
||
|
PushError();
|
||
|
|
||
|
// lint is not familiar with __finally so...
|
||
|
if (!result) { //lint !e774
|
||
|
if (FileHandle) {
|
||
|
CloseHandle (FileHandle);
|
||
|
}
|
||
|
|
||
|
DeleteFileA (FileName);
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection (&g_MemDbCs);
|
||
|
|
||
|
PopError();
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbSaveA (
|
||
|
PCSTR FileName
|
||
|
)
|
||
|
{
|
||
|
return pPrivateMemDbSave (FileName); // TRUE=UNICODE
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbSaveW (
|
||
|
PCWSTR FileName
|
||
|
)
|
||
|
{
|
||
|
PCSTR p;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
p = ConvertWtoA (FileName);
|
||
|
if (p) {
|
||
|
b = pPrivateMemDbSave (p);
|
||
|
FreeConvertedStr (p);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
pPrivateMemDbLoad (
|
||
|
IN PCSTR AnsiFileName,
|
||
|
IN PCWSTR UnicodeFileName,
|
||
|
OUT PMEMDB_VERSION Version, OPTIONAL
|
||
|
IN BOOL QueryVersionOnly
|
||
|
)
|
||
|
{
|
||
|
HANDLE FileHandle = NULL;
|
||
|
HANDLE hMap = INVALID_HANDLE_VALUE;
|
||
|
WCHAR FileSig[sizeof(FILE_SIGNATURE)];
|
||
|
PCWSTR VerPtr;
|
||
|
UINT DbSize;
|
||
|
PMEMDBHASH pHashTable;
|
||
|
PBYTE Buf = NULL;
|
||
|
PBYTE SavedBuf = NULL;
|
||
|
PCSTR databaseLocation = NULL;
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
|
||
|
EnterCriticalSection (&g_MemDbCs);
|
||
|
|
||
|
__try {
|
||
|
__try {
|
||
|
|
||
|
if (Version) {
|
||
|
ZeroMemory (Version, sizeof (MEMDB_VERSION));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Blow away existing resources
|
||
|
//
|
||
|
|
||
|
if (!QueryVersionOnly) {
|
||
|
databaseLocation = DuplicatePathStringA (DatabasesGetBasePath (), 0);
|
||
|
DatabasesTerminate (FALSE);
|
||
|
DatabasesInitializeA (databaseLocation);
|
||
|
FreePathStringA (databaseLocation);
|
||
|
|
||
|
if (!SelectDatabase (DB_PERMANENT)) {
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (AnsiFileName) {
|
||
|
Buf = MapFileIntoMemoryA (AnsiFileName, &FileHandle, &hMap);
|
||
|
} else {
|
||
|
Buf = MapFileIntoMemoryW (UnicodeFileName, &FileHandle, &hMap);
|
||
|
}
|
||
|
|
||
|
if (Buf == NULL) {
|
||
|
__leave;
|
||
|
}
|
||
|
SavedBuf = Buf;
|
||
|
|
||
|
//
|
||
|
// Obtain the file signature
|
||
|
//
|
||
|
// NOTE: Entire file read is in UNICODE char set
|
||
|
//
|
||
|
|
||
|
CopyMemory (FileSig, Buf, sizeof(FILE_SIGNATURE));
|
||
|
|
||
|
if (Version) {
|
||
|
if (StringMatchByteCountW (
|
||
|
VERSION_BASE_SIGNATURE,
|
||
|
FileSig,
|
||
|
sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR)
|
||
|
)) {
|
||
|
|
||
|
Version->Valid = TRUE;
|
||
|
|
||
|
//
|
||
|
// Identify version number
|
||
|
//
|
||
|
|
||
|
VerPtr = (PCWSTR) ((PBYTE)FileSig + sizeof (VERSION_BASE_SIGNATURE) - sizeof (WCHAR));
|
||
|
|
||
|
if (StringMatchByteCountW (
|
||
|
MEMDB_VERSION_STAMP,
|
||
|
VerPtr,
|
||
|
sizeof (MEMDB_VERSION_STAMP) - sizeof (WCHAR)
|
||
|
)) {
|
||
|
Version->CurrentVersion = TRUE;
|
||
|
}
|
||
|
|
||
|
Version->Version = (UINT) _wtoi (VerPtr + 1);
|
||
|
|
||
|
//
|
||
|
// Identify checked or free build
|
||
|
//
|
||
|
|
||
|
VerPtr += (sizeof (MEMDB_VERSION_STAMP) / 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) {
|
||
|
|
||
|
if (!StringMatchW (FileSig, FILE_SIGNATURE)) {
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (StringMatchW (FileSig, DEBUG_FILE_SIGNATURE)) {
|
||
|
|
||
|
g_UseDebugStructs = TRUE;
|
||
|
|
||
|
} else if (StringMatchW (FileSig, RETAIL_FILE_SIGNATURE)) {
|
||
|
|
||
|
DEBUGMSG ((DBG_ERROR, "memdb dat file is from free build; checked version expected"));
|
||
|
g_UseDebugStructs = FALSE;
|
||
|
|
||
|
} else {
|
||
|
#endif
|
||
|
SetLastError (ERROR_BAD_FORMAT);
|
||
|
LOG ((LOG_WARNING, "Warning: data file could be from checked build; free version expected"));
|
||
|
__leave;
|
||
|
#ifdef DEBUG
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
Buf += sizeof(FILE_SIGNATURE);
|
||
|
DbSize = *((PUINT)Buf);
|
||
|
|
||
|
//
|
||
|
// resize the database. SizeDatabaseBuffer also fixes g_CurrentDatabase
|
||
|
// and other global variables, so we dont have to worry.
|
||
|
//
|
||
|
if (!SizeDatabaseBuffer(g_CurrentDatabaseIndex, DbSize)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
MYASSERT (g_CurrentDatabase);
|
||
|
|
||
|
//
|
||
|
// save hashtable pointer (which points to hashtable created
|
||
|
// in InitializeDatabases (above)), then load database, then
|
||
|
// fix hashtable pointer.
|
||
|
//
|
||
|
pHashTable = g_CurrentDatabase->HashTable;
|
||
|
CopyMemory (g_CurrentDatabase, Buf, DbSize);
|
||
|
g_CurrentDatabase->HashTable = pHashTable;
|
||
|
Buf += DbSize;
|
||
|
|
||
|
if (!ReadBlocks (
|
||
|
&Buf,
|
||
|
&g_CurrentDatabase->HashTable,
|
||
|
&g_CurrentDatabase->OffsetBuffer
|
||
|
)) {
|
||
|
__leave;
|
||
|
}
|
||
|
result = TRUE;
|
||
|
}
|
||
|
|
||
|
UnmapFile (SavedBuf, hMap, FileHandle);
|
||
|
|
||
|
}
|
||
|
__except (TRUE) {
|
||
|
result = FALSE;
|
||
|
PushError();
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (AnsiFileName) {
|
||
|
LOGA ((LOG_ERROR, "MemDb dat file %s could not be loaded because of an exception", AnsiFileName));
|
||
|
} else {
|
||
|
LOGW ((LOG_ERROR, "MemDb dat file %s could not be loaded because of an exception", UnicodeFileName));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
PopError();
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
|
||
|
PushError();
|
||
|
|
||
|
if (!result && !QueryVersionOnly) {
|
||
|
databaseLocation = DuplicatePathStringA (DatabasesGetBasePath (), 0);
|
||
|
DatabasesTerminate (FALSE);
|
||
|
DatabasesInitializeA (databaseLocation);
|
||
|
FreePathStringA (databaseLocation);
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection (&g_MemDbCs);
|
||
|
|
||
|
PopError();
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbLoadA (
|
||
|
IN PCSTR FileName
|
||
|
)
|
||
|
{
|
||
|
|
||
|
return pPrivateMemDbLoad (FileName, NULL, NULL, FALSE);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbLoadW (
|
||
|
IN PCWSTR FileName
|
||
|
)
|
||
|
{
|
||
|
return pPrivateMemDbLoad (NULL, FileName, NULL, FALSE);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbQueryVersionA (
|
||
|
PCSTR FileName,
|
||
|
PMEMDB_VERSION Version
|
||
|
)
|
||
|
{
|
||
|
BOOL b;
|
||
|
|
||
|
b = pPrivateMemDbLoad (FileName, NULL, Version, TRUE);
|
||
|
|
||
|
return b ? Version->Valid : FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbQueryVersionW (
|
||
|
PCWSTR FileName,
|
||
|
PMEMDB_VERSION Version
|
||
|
)
|
||
|
{
|
||
|
pPrivateMemDbLoad (NULL, FileName, Version, TRUE);
|
||
|
return Version->Valid;
|
||
|
}
|
||
|
|
||
|
/* format for binary file export
|
||
|
|
||
|
DWORD Signature
|
||
|
|
||
|
UINT Version
|
||
|
|
||
|
UINT GlobalFlags// 0x00000001 mask for Ansi format
|
||
|
// 0x00000002 mask for debug mode
|
||
|
|
||
|
//
|
||
|
// each _KEY block is followed by its children,
|
||
|
// and each of those is followed by its children,
|
||
|
// etc., so it is easy to recurse to gather
|
||
|
// the whole tree.
|
||
|
//
|
||
|
|
||
|
struct _KEY {
|
||
|
|
||
|
#if (GlobalFlags & MEMDB_EXPORT_FLAGS_DEBUG)
|
||
|
WORD DebugSig // signature for each keystruct block.
|
||
|
#endif
|
||
|
WORD StructSize; // total number of bytes including this member
|
||
|
WORD NameSize; // total number of bytes in Key[]
|
||
|
WORD DataSize; // total number of bytes in Data[]
|
||
|
WORD NumChildren // number of children, whose data structures will follow
|
||
|
// this one (though not necessarily one after another, if
|
||
|
// any of them have children themselves)
|
||
|
BYTE Key[]; // Should be PCSTR or PCWSTR (not zero terminated).
|
||
|
// the first key in the exported file will have the full
|
||
|
// key path as its key name.
|
||
|
BYTE Data[]; // block of data pieces, all in same format as in datablock.c
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
#define MEMDB_EXPORT_SIGNATURE ('M'+('D'<<8)+('B'<<16)+('X'<<24))
|
||
|
// NTRAID#NTBUG9-153308-2000/08/01-jimschm reenable the line below when implementing export and import functions
|
||
|
//#define MEMDB_EXPORT_DEBUG_SIG ('K'+('Y'<<8))
|
||
|
#define MEMDB_EXPORT_VERSION 0x00000003
|
||
|
#define MEMDB_EXPORT_FLAGS_ANSI 0x00000001
|
||
|
#define MEMDB_EXPORT_FLAGS_DEBUG 0x00000002
|
||
|
|
||
|
// NTRAID#NTBUG9-153308-2000/08/01-jimschm Implement the function and remove lint comments
|
||
|
//lint -save -e713 -e715
|
||
|
BOOL
|
||
|
pMemDbExportWorker (
|
||
|
IN HANDLE FileHandle,
|
||
|
IN UINT KeyIndex,
|
||
|
IN BOOL AnsiFormat,
|
||
|
IN PCWSTR FullKeyPath
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
exports a key to a file, and then recurses through
|
||
|
that key's children.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileHandle - already opened handle to write to
|
||
|
|
||
|
KeyIndex - index of key to write
|
||
|
|
||
|
AnsiFormat - if TRUE, then FullKeyPath (above) and KeyName
|
||
|
(below) are actually ANSI strings (not unicode).
|
||
|
|
||
|
FullKeyPath - only used for first keystruct to be written
|
||
|
to file. it specifies the full path of the root key.
|
||
|
for all others, this argument should be NULL.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful, FALSE otherwise.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
//lint -restore
|
||
|
|
||
|
BOOL
|
||
|
pMemDbExport (
|
||
|
IN PCWSTR RootTree,
|
||
|
IN PCSTR FileName,
|
||
|
IN BOOL AnsiFormat
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
exports a MemDb tree to a file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RootTree - full key path of the top level key to write
|
||
|
to the file.
|
||
|
|
||
|
FileName - file to write to.
|
||
|
|
||
|
AnsiFormat - if TRUE, then RootTree and FileName are
|
||
|
actually ANSI strings (not unicode).
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful, FALSE otherwise.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HANDLE FileHandle = NULL;
|
||
|
UINT Flags;
|
||
|
DWORD written;
|
||
|
UINT RootIndex = INVALID_OFFSET;
|
||
|
PCWSTR SubRootTreeW, RootTreeW;
|
||
|
BOOL b;
|
||
|
|
||
|
if (AnsiFormat) {
|
||
|
//
|
||
|
// if we are in ansi mode, everything is ANSI strings,
|
||
|
// but we still need unicode string for SelectHiveW ()
|
||
|
//
|
||
|
RootTreeW = ConvertAtoW ((PCSTR)RootTree);
|
||
|
|
||
|
if (!RootTreeW) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
RootTreeW = RootTree;
|
||
|
}
|
||
|
SubRootTreeW = SelectHiveW (RootTreeW);
|
||
|
|
||
|
if (SubRootTreeW) {
|
||
|
RootIndex = FindKeyStruct (SubRootTreeW);
|
||
|
}
|
||
|
|
||
|
if (AnsiFormat) {
|
||
|
FreeConvertedStr(RootTreeW);
|
||
|
}
|
||
|
|
||
|
if (RootIndex == INVALID_OFFSET) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
FileHandle = BfCreateFileA (FileName);
|
||
|
|
||
|
if (!FileHandle) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Flags = MEMDB_EXPORT_SIGNATURE;
|
||
|
WriteFile (FileHandle, &Flags, sizeof (DWORD), &written, NULL);
|
||
|
|
||
|
Flags = MEMDB_EXPORT_VERSION;
|
||
|
WriteFile (FileHandle, &Flags, sizeof (UINT), &written, NULL);
|
||
|
|
||
|
Flags = AnsiFormat ? MEMDB_EXPORT_FLAGS_ANSI : 0;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Flags |= MEMDB_EXPORT_FLAGS_DEBUG;
|
||
|
#endif
|
||
|
WriteFile (FileHandle, &Flags, sizeof (UINT), &written, NULL);
|
||
|
|
||
|
//
|
||
|
// write root index key and all children to file.
|
||
|
//
|
||
|
b = pMemDbExportWorker(FileHandle, RootIndex, AnsiFormat, RootTree);
|
||
|
|
||
|
|
||
|
//
|
||
|
// finally write the zero terminator
|
||
|
//
|
||
|
Flags = 0;
|
||
|
WriteFile (FileHandle, &Flags, sizeof (WORD), &written, NULL);
|
||
|
|
||
|
CloseHandle (FileHandle);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbExportA (
|
||
|
IN PCSTR RootTree,
|
||
|
IN PCSTR FileName,
|
||
|
IN BOOL AnsiFormat
|
||
|
)
|
||
|
{
|
||
|
PCWSTR p;
|
||
|
BOOL b;
|
||
|
|
||
|
if (!AnsiFormat) {
|
||
|
|
||
|
p = ConvertAtoW (RootTree);
|
||
|
|
||
|
if (!p) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = pMemDbExport (p, FileName, FALSE);
|
||
|
|
||
|
FreeConvertedStr (p);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
b = pMemDbExport ((PCWSTR)RootTree, FileName, TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MemDbExportW (
|
||
|
IN PCWSTR RootTree,
|
||
|
IN PCWSTR FileName,
|
||
|
IN BOOL AnsiFormat
|
||
|
)
|
||
|
{
|
||
|
PCSTR p, FileNameA;
|
||
|
BOOL b;
|
||
|
|
||
|
FileNameA = ConvertWtoA (FileName);
|
||
|
|
||
|
if (!FileNameA) {
|
||
|
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (AnsiFormat) {
|
||
|
|
||
|
p = ConvertWtoA (RootTree);
|
||
|
|
||
|
if (!p) {
|
||
|
|
||
|
FreeConvertedStr (FileNameA);
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
b = pMemDbExport ((PCWSTR)p, FileNameA, TRUE);
|
||
|
|
||
|
FreeConvertedStr (p);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
b = pMemDbExport (RootTree, FileNameA, FALSE);
|
||
|
|
||
|
}
|
||
|
|
||
|
FreeConvertedStr (FileNameA);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
// NTRAID#NTBUG9-153308-2000/08/01-jimschm Implement the function and remove lint comments
|
||
|
//lint -save -e713 -e715
|
||
|
BOOL
|
||
|
pMemDbImportWorker (
|
||
|
IN PBYTE *FileBuffer,
|
||
|
IN BOOL AnsiFormat,
|
||
|
IN BOOL DebugMode,
|
||
|
IN BOOL ExportRoot
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
imports a key from a file, and then recurses through
|
||
|
that key's children.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileBuffer - pointer to a memory pointer, which should
|
||
|
initially point to the beginning of the
|
||
|
memory-mapped file to read. this will be updated
|
||
|
as the function runs
|
||
|
|
||
|
AnsiFormat - TRUE if the file is in ANSI mode (determined
|
||
|
by file header)
|
||
|
|
||
|
DebugMode - TRUE if the file is in debug mode (determined
|
||
|
by file header)
|
||
|
|
||
|
ExportRoot - TRUE if this is the first call to this function
|
||
|
for a file (the name of the first keystruct in a file
|
||
|
is the full key path for that keystruct, all other keys
|
||
|
in the file have only the relative name).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful, FALSE otherwise.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
//lint -restore
|
||
|
|
||
|
BOOL
|
||
|
MemDbImportA (
|
||
|
IN PCSTR FileName
|
||
|
)
|
||
|
{
|
||
|
PCWSTR FileNameW;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
FileNameW = ConvertAtoW (FileName);
|
||
|
|
||
|
if (FileNameW) {
|
||
|
b = MemDbImportW (FileNameW);
|
||
|
FreeConvertedStr (FileNameW);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
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, BufferPtr;
|
||
|
HANDLE fileHandle;
|
||
|
HANDLE mapHandle;
|
||
|
BOOL b = FALSE;
|
||
|
UINT Flags;
|
||
|
|
||
|
fileBuff = MapFileIntoMemoryW (FileName, &fileHandle, &mapHandle);
|
||
|
if (fileBuff == NULL) {
|
||
|
DEBUGMSGW ((DBG_ERROR, "Could not execute MemDbImport for %s", FileName));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
BufferPtr = fileBuff;
|
||
|
if (*((PDWORD) BufferPtr) != MEMDB_EXPORT_SIGNATURE) {
|
||
|
DEBUGMSGW ((DBG_ERROR, "Unknown signature for file to import: %s", FileName));
|
||
|
b = FALSE;
|
||
|
} else {
|
||
|
BufferPtr += sizeof (DWORD);
|
||
|
|
||
|
if (*((PUINT) BufferPtr) != MEMDB_EXPORT_VERSION) {
|
||
|
|
||
|
DEBUGMSGW ((DBG_ERROR, "Unknown or outdated version for file to import: %s", FileName));
|
||
|
b = FALSE;
|
||
|
} else {
|
||
|
BufferPtr += sizeof (UINT);
|
||
|
Flags = *((PUINT) BufferPtr);
|
||
|
BufferPtr += sizeof (UINT);
|
||
|
|
||
|
b = pMemDbImportWorker (
|
||
|
&BufferPtr,
|
||
|
Flags & MEMDB_EXPORT_FLAGS_ANSI,
|
||
|
Flags & MEMDB_EXPORT_FLAGS_DEBUG,
|
||
|
TRUE
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (1) {
|
||
|
DEBUGMSGW ((DBG_ERROR, "Access violation while importing: %s", FileName));
|
||
|
}
|
||
|
|
||
|
UnmapFile (fileBuff, mapHandle, fileHandle);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|