windows-nt/Source/XPSP1/NT/windows/winstate/cobra/utils/memdb/memdb.c

5629 lines
121 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
memdb.c
Abstract:
A memory-based database for managing all kinds of data relationships.
Author:
Jim Schmidt (jimschm) 8-Aug-1996
Revision History:
jimschm 05-Oct-1999 Documentation
mvander 13-Aug-1999 many changes
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"
// PORTBUG: Make sure to pick up latest fixes in win9xupg project
//
// Includes
//
#include "memdbp.h"
#include "bintree.h"
//
// Strings
//
// None
//
// Constants
//
// None
//
// Macros
//
// None
//
// Types
//
// None
//
// Globals
//
CRITICAL_SECTION g_MemDbCs;
PMHANDLE g_MemDbPool = NULL;
static INT g_Initialized;
//
// Macro expansion list
//
// None
//
// Macro expansion definition
//
// None
//
// Code
//
/*++
Routine Description:
MemDbInitializeEx creates data structures for an initial database. Calling
this routine is required.
Arguments:
None.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
BOOL
MemDbInitializeExA (
IN PCSTR DatabasePath OPTIONAL
)
{
BOOL result = TRUE;
MYASSERT (g_Initialized >= 0);
g_Initialized++;
if (g_Initialized == 1) {
g_MemDbPool = PmCreateNamedPool ("MemDb");
if (g_MemDbPool == NULL) {
return FALSE;
}
__try {
InitializeCriticalSection (&g_MemDbCs);
} __except (EXCEPTION_CONTINUE_EXECUTION) {
// Might raise an out of memory exception, but we don't check for that in this function.
// Ignores
}
//
// If we fail, we don't automatically call MemDbTerminate, because
// there is an option to MemDbTerminate which we don't know.
//
if (!DatabasesInitializeA (DatabasePath)) {
return FALSE;
}
result = FileEnumInitialize ();
}
return result;
}
BOOL
MemDbInitializeExW (
IN PCWSTR DatabasePath OPTIONAL
)
{
BOOL result = TRUE;
MYASSERT (g_Initialized >= 0);
g_Initialized++;
if (g_Initialized == 1) {
g_MemDbPool = PmCreateNamedPool ("MemDb");
if (g_MemDbPool == NULL) {
return FALSE;
}
__try {
InitializeCriticalSection (&g_MemDbCs);
} __except (EXCEPTION_CONTINUE_EXECUTION) {
// Might raise an out of memory exception, but we don't check for that in this function.
// Ignores
}
//
// If we fail, we don't automatically call MemDbTerminate, because
// there is an option to MemDbTerminate which we don't know.
//
if (!DatabasesInitializeW (DatabasePath)) {
return FALSE;
}
result = FileEnumInitialize ();
}
return result;
}
VOID
MemDbTerminateEx (
IN BOOL EraseDatabasePath
)
/*++
Routine Description:
MemDbTerminateEx frees all resources associated with MemDb
and, optionally, removes the database directory.
This routine should be called at process termination.
Arguments:
None.
Return Value:
None.
--*/
{
MYASSERT (g_Initialized > 0);
g_Initialized--;
if (!g_Initialized) {
if (g_MemDbPool) {
PmDestroyPool (g_MemDbPool);
g_MemDbPool = NULL;
}
DatabasesTerminate (EraseDatabasePath);
DeleteCriticalSection (&g_MemDbCs);
FileEnumTerminate ();
} else if (g_Initialized < 0) {
//
// Since we call ourselves, protect callers from over-termination
//
g_Initialized = 0;
}
}
PVOID
MemDbGetMemory (
IN UINT Size
)
{
MYASSERT (g_MemDbPool);
return PmGetMemory (g_MemDbPool, Size);
}
VOID
MemDbReleaseMemory (
IN PCVOID Memory
)
{
if (Memory) {
MYASSERT (g_MemDbPool);
PmReleaseMemory (g_MemDbPool, Memory);
}
}
KEYHANDLE
MemDbAddKeyA (
IN PCSTR KeyName
)
/*++
Routine Description:
MemDbAddKey creates a memdb key that has no values, flags or any
other data. This is used to reduce the size of the database.
Arguments:
KeyName - Specifies the key to create.
Return Value:
Returns the HANDLE to the newly created key or NULL if
not successful.
--*/
{
PCWSTR keyNameW;
KEYHANDLE result = 0;
keyNameW = ConvertAtoW (KeyName);
if (keyNameW) {
result = MemDbAddKeyW (keyNameW);
FreeConvertedStr (keyNameW);
}
return result;
}
KEYHANDLE
MemDbAddKeyW (
IN PCWSTR KeyName
)
/*++
Routine Description:
MemDbAddKey creates a memdb key that has no values, flags or any
other data. This is used to reduce the size of the database.
Arguments:
KeyName - Specifies the key to create.
Return Value:
Returns the HANDLE to the newly created key or NULL if not successful.
--*/
{
UINT keyIndex;
PCWSTR subKey;
KEYHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
//
// first make sure there is no key
// with this name.
//
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex != INVALID_OFFSET) {
SetLastError (ERROR_ALREADY_EXISTS);
__leave;
}
keyIndex = NewEmptyKey (subKey);
if (keyIndex != INVALID_OFFSET) {
result = GET_EXTERNAL_INDEX (keyIndex);
SetLastError (ERROR_SUCCESS);
}
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
KEYHANDLE
MemDbSetKeyA (
IN PCSTR KeyName
)
/*++
Routine Description:
MemDbSetKey creates a memdb key that has no values, flags or any other data.
This is used to reduce the size of the database. If the key exists it will
return the handle of the existing key.
Arguments:
KeyName - Specifies the key to create.
Return Value:
Returns the HANDLE to the newly created or existent key or NULL if some error
occurs.
--*/
{
PCWSTR keyNameW;
KEYHANDLE result = 0;
keyNameW = ConvertAtoW (KeyName);
if (keyNameW) {
result = MemDbSetKeyW (keyNameW);
FreeConvertedStr (keyNameW);
}
return result;
}
KEYHANDLE
MemDbSetKeyW (
IN PCWSTR KeyName
)
/*++
Routine Description:
MemDbSetKey creates a memdb key that has no values, flags or any other data.
This is used to reduce the size of the database. If the key exists it will
return the handle of the existing key.
Arguments:
KeyName - Specifies the key to create.
Return Value:
Returns the HANDLE to the newly created or existent key or NULL if some error
occurs.
--*/
{
UINT keyIndex;
PCWSTR subKey;
KEYHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
//
// first make sure there is no key
// with this name.
//
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex != INVALID_OFFSET) {
SetLastError (ERROR_ALREADY_EXISTS);
result = GET_EXTERNAL_INDEX (keyIndex);;
__leave;
}
keyIndex = NewEmptyKey (subKey);
if (keyIndex != INVALID_OFFSET) {
result = GET_EXTERNAL_INDEX (keyIndex);;
SetLastError (ERROR_SUCCESS);
}
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteKeyA (
IN PCSTR KeyStr
)
/*++
Routine Description:
MemDbDeleteKey deletes a specific string from the database (along with all
data associated with it)
Arguments:
KeyStr - Specifies the key string to delete (i.e., foo\bar\cat)
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyStr);
if (p) {
result = MemDbDeleteKeyW (p);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbDeleteKeyW (
IN PCWSTR KeyStr
)
/*++
Routine Description:
MemDbDeleteKey deletes a specific string from the database (along with all
data associated with it)
Arguments:
KeyStr - Specifies the key string to delete (i.e., foo\bar\cat)
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
subKey = SelectHiveW (KeyStr);
if (subKey) {
result = DeleteKey (subKey, g_CurrentDatabase->FirstLevelTree, TRUE);
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
}
LeaveCriticalSection (&g_MemDbCs);
return result;
}
BOOL
MemDbDeleteKeyByHandle (
IN KEYHANDLE KeyHandle
)
/*++
Routine Description:
MemDbDeleteKeyByHandle deletes a specific key from the database
identified by the key handle. It also removes all data associated
with it.
Arguments:
KeyHandle - Key Handle identifying the key
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
dbIndex = GET_DATABASE (KeyHandle);
if (SelectDatabase (dbIndex)) {
result = PrivateDeleteKeyByIndex (GET_INDEX (KeyHandle));
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
}
LeaveCriticalSection (&g_MemDbCs);
return result;
}
BOOL
MemDbDeleteTreeA (
IN PCSTR KeyName
)
/*++
Routine Description:
MemDbDeleteTree removes an entire tree branch from the database, including
all data associated. The specified key string does not need to be
an endpoint (i.e., specifying foo\bar will cause deletion of foo\bar\cat).
Arguments:
KeyName - Specifies the key string to delete. This string cannot be empty.
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbDeleteTreeW (p);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbDeleteTreeW (
IN PCWSTR KeyName
)
/*++
Routine Description:
MemDbDeleteTree removes an entire tree branch from the database, including
all data associated. The specified key string does not need to be
an endpoint (i.e., specifying foo\bar will cause deletion of foo\bar\cat).
Arguments:
KeyName - Specifies the key string to delete. This string cannot be empty.
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
subKey = SelectHiveW (KeyName);
if (subKey) {
result = DeleteKey (subKey, g_CurrentDatabase->FirstLevelTree, FALSE);
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
}
LeaveCriticalSection (&g_MemDbCs);
return result;
}
PCSTR
MemDbGetKeyFromHandleA (
IN KEYHANDLE KeyHandle,
IN UINT StartLevel
)
/*++
Routine Description:
MemDbGetKeyFromHandle will create a key string given the key handle.
It will allocate memory from memdb's private pool to store the result.
Caller is responsible for calling MemDbReleaseMemory on the result.
This function also allow trimming from the beginning of the string.
By specifying a start level, the function will skip a number of
levels before building the string. For example, if a key handle points
to the string mycat\foo\bar, and StartLevel is 1, the function will
return foo\bar.
Arguments:
KeyHandle - Specifies the key handle that identifies the key.
StartLevel - Specifies a zero-based starting level, where zero represents
the complete string, one represents the string starting after
the first backslash, and so on.
Return Value:
A valid string (using memory allocated from memdb's private pool) if
successful, NULL otherwise.
--*/
{
PSTR result = NULL;
WCHAR wideBuffer[MEMDB_MAX];
PWSTR bufferIndex = wideBuffer;
BYTE dbIndex;
UINT chars;
PKEYSTRUCT keyStruct;
PSTR p;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return NULL;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
if (StartLevel == MEMDB_LAST_LEVEL) {
//
// Special case -- get the last level string
//
keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
if (!keyStruct) {
__leave;
}
result = MemDbGetMemory (keyStruct->KeyName[0] * 2 + 1);
p = DirectUnicodeToDbcsN (
result,
keyStruct->KeyName + 1,
keyStruct->KeyName[0] * sizeof (WCHAR)
);
*p = 0;
__leave;
}
switch (dbIndex) {
case DB_PERMANENT:
break;
case DB_TEMPORARY:
if (StartLevel == 0) {
bufferIndex [0] = L'~';
bufferIndex++;
} else {
StartLevel --;
}
break;
default:
__leave;
}
if (PrivateBuildKeyFromIndex (
StartLevel,
GET_INDEX (KeyHandle),
bufferIndex,
NULL,
NULL,
&chars
)) {
result = MemDbGetMemory (chars*2+1);
KnownSizeWtoA (result, wideBuffer);
__leave;
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
PCWSTR
MemDbGetKeyFromHandleW (
IN KEYHANDLE KeyHandle,
IN UINT StartLevel
)
/*++
Routine Description:
MemDbGetKeyFromHandle will create a key string given the key handle.
It will allocate memory from memdb's private pool to store the result.
Caller is responsible for calling MemDbReleaseMemory on the result.
This function also allow trimming from the beginning of the string.
By specifying a start level, the function will skip a number of
levels before building the string. For example, if a key handle points
to the string mycat\foo\bar, and StartLevel is 1, the function will
return foo\bar.
Arguments:
KeyHandle - Specifies the key handle that identifies the key.
StartLevel - Specifies a zero-based starting level, where zero represents
the complete string, one represents the string starting after
the first backslash, and so on.
Return Value:
A valid string (using memory allocated from memdb's private pool) if
successful, NULL otherwise.
--*/
{
PWSTR result = NULL;
WCHAR wideBuffer[MEMDB_MAX];
PWSTR bufferIndex = wideBuffer;
BYTE dbIndex;
UINT chars;
PKEYSTRUCT keyStruct;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return NULL;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
if (StartLevel == MEMDB_LAST_LEVEL) {
//
// Special case -- get the last level string
//
keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
if (!keyStruct) {
__leave;
}
chars = keyStruct->KeyName[0];
result = MemDbGetMemory ((chars + 1) * sizeof (WCHAR));
CopyMemory (result, keyStruct->KeyName + 1, chars * sizeof (WCHAR));
result[chars] = 0;
__leave;
}
switch (dbIndex) {
case DB_PERMANENT:
break;
case DB_TEMPORARY:
if (StartLevel == 0) {
bufferIndex [0] = L'~';
bufferIndex++;
} else {
StartLevel --;
}
break;
default:
__leave;
}
if (PrivateBuildKeyFromIndex (
StartLevel,
GET_INDEX (KeyHandle),
bufferIndex,
NULL,
NULL,
&chars
)) {
if (chars) {
result = MemDbGetMemory ((chars + 1) * sizeof (WCHAR));
StringCopyW (result, wideBuffer);
__leave;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetKeyFromHandleExA (
IN KEYHANDLE KeyHandle,
IN UINT StartLevel,
IN OUT PGROWBUFFER Buffer OPTIONAL
)
/*++
Routine Description:
MemDbGetKeyFromHandleEx will create a key string given the key handle.
It will use caller's grow buffer to store the result.
This function also allow trimming from the beginning of the string.
By specifying a start level, the function will skip a number of
levels before building the string. For example, if a key handle points
to the string mycat\foo\bar, and StartLevel is 1, the function will
return foo\bar.
Arguments:
KeyHandle - Specifies the key handle that identifies the key.
StartLevel - Specifies a zero-based starting level, where zero represents
the complete string, one represents the string starting after
the first backslash, and so on.
Buffer - Specifies an intialized grow buffer that may contain data.
Receives the key string, appended to data in the buffer (if
any)
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
WCHAR wideBuffer[MEMDB_MAX];
CHAR ansiBuffer[MEMDB_MAX*2];
PWSTR bufferIndex = wideBuffer;
BYTE dbIndex;
UINT chars;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
switch (dbIndex) {
case DB_PERMANENT:
break;
case DB_TEMPORARY:
if (StartLevel == 0) {
bufferIndex [0] = L'~';
bufferIndex++;
} else {
StartLevel --;
}
break;
default:
__leave;
}
if (PrivateBuildKeyFromIndex (
StartLevel,
GET_INDEX (KeyHandle),
bufferIndex,
NULL,
NULL,
&chars
)) {
if (chars) {
KnownSizeWtoA (ansiBuffer, wideBuffer);
if (Buffer) {
(void)GbCopyStringA (Buffer, ansiBuffer);
}
result = TRUE;
__leave;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetKeyFromHandleExW (
IN KEYHANDLE KeyHandle,
IN UINT StartLevel,
IN PGROWBUFFER Buffer OPTIONAL
)
/*++
Routine Description:
MemDbGetKeyFromHandleEx will create a key string given the key handle.
It will use caller's grow buffer to store the result.
This function also allow trimming from the beginning of the string.
By specifying a start level, the function will skip a number of
levels before building the string. For example, if a key handle points
to the string mycat\foo\bar, and StartLevel is 1, the function will
return foo\bar.
Arguments:
KeyHandle - Specifies the key handle that identifies the key.
StartLevel - Specifies a zero-based starting level, where zero represents
the complete string, one represents the string starting after
the first backslash, and so on.
Buffer - Specifies an intialized grow buffer that may contain data.
Receives the key string, appended to data in the buffer (if
any)
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
WCHAR wideBuffer[MEMDB_MAX];
PWSTR bufferIndex = wideBuffer;
BYTE dbIndex;
UINT chars;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
switch (dbIndex) {
case DB_PERMANENT:
break;
case DB_TEMPORARY:
if (StartLevel == 0) {
bufferIndex [0] = L'~';
bufferIndex++;
} else {
StartLevel --;
}
break;
default:
__leave;
}
if (PrivateBuildKeyFromIndex (
StartLevel,
GET_INDEX (KeyHandle),
bufferIndex,
NULL,
NULL,
&chars
)) {
if (chars) {
if (Buffer) {
(void)GbCopyStringW (Buffer, wideBuffer);
}
result = TRUE;
__leave;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
KEYHANDLE
MemDbGetHandleFromKeyA (
IN PCSTR KeyName
)
/*++
Routine Description:
MemDbGetHandleFromKey will return the key handle associated with KeyName,
if it's already added in memdb.
Arguments:
KeyName - Specifies the key to search.
Return Value:
Returns the key handle of the requested key or NULL if the key is not present.
--*/
{
PCWSTR keyNameW;
KEYHANDLE result = 0;
keyNameW = ConvertAtoW (KeyName);
if (keyNameW) {
result = MemDbGetHandleFromKeyW (keyNameW);
FreeConvertedStr (keyNameW);
}
return result;
}
KEYHANDLE
MemDbGetHandleFromKeyW (
IN PCWSTR KeyName
)
/*++
Routine Description:
MemDbGetHandleFromKey will return the key handle associated with KeyName,
if it's already added in memdb.
Arguments:
KeyName - Specifies the key to search.
Return Value:
Returns the key handle of the requested key or NULL if the key is not present.
--*/
{
UINT keyIndex;
PCWSTR subKey;
KEYHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
//
// first make sure there is a key
// with this name.
//
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (keyIndex);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
KEYHANDLE
MemDbSetValueAndFlagsExA (
IN PCSTR KeyName,
IN BOOL AlterValue,
IN UINT Value,
IN BOOL ReplaceFlags,
IN UINT SetFlags,
IN UINT ClearFlags
)
/*++
Routine Description:
MemDbSetValueAndFlagsEx creates the key if it doesn't exist and then
it sets it's value and it's flags based on the arguments.
Arguments:
KeyName - Specifies the key string (i.e., foo\bar\cat)
AlterValue - Specifies if the existing value is to be altered
Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
consider SetFlags as the replacing flags, ClearFlags will be ignored
SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
replacement flags (if ReplaceFlags is TRUE).
ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
Return Value:
the key handle for the existent or newly added key if successful, NULL
otherwise.
--*/
{
PCWSTR keyNameW;
KEYHANDLE result = 0;
keyNameW = ConvertAtoW (KeyName);
if (keyNameW) {
result = MemDbSetValueAndFlagsExW (
keyNameW,
AlterValue,
Value,
ReplaceFlags,
SetFlags,
ClearFlags
);
FreeConvertedStr (keyNameW);
}
return result;
}
KEYHANDLE
MemDbSetValueAndFlagsExW (
IN PCWSTR KeyName,
IN BOOL AlterValue,
IN UINT Value,
IN BOOL ReplaceFlags,
IN UINT SetFlags,
IN UINT ClearFlags
)
/*++
Routine Description:
MemDbSetValueAndFlagsEx creates the key if it doesn't exist and then
it sets it's value and it's flags based on the arguments.
Arguments:
KeyName - Specifies the key string (i.e., foo\bar\cat)
AlterValue - Specifies if the existing value is to be altered
Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
consider SetFlags as the replacing flags, ClearFlags will be ignored
SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
replacement flags (if ReplaceFlags is TRUE).
ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
Return Value:
the key handle for the existent or newly added key if successful, NULL
otherwise.
--*/
{
PCWSTR subKey;
KEYHANDLE result = 0;
UINT keyIndex;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
keyIndex = NewKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
}
if (AlterValue) {
if (!KeyStructSetValue (keyIndex, Value)) {
__leave;
}
}
if ((ReplaceFlags && SetFlags) ||
(!ReplaceFlags && (SetFlags || ClearFlags))
) {
if (!KeyStructSetFlags (keyIndex, ReplaceFlags, SetFlags, ClearFlags)) {
__leave;
}
}
MYASSERT (keyIndex != INVALID_OFFSET);
result = GET_EXTERNAL_INDEX (keyIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbSetValueAndFlagsByHandleEx (
IN KEYHANDLE KeyHandle,
IN BOOL AlterValue,
IN UINT Value,
IN BOOL ReplaceFlags,
IN UINT SetFlags,
IN UINT ClearFlags
)
/*++
Routine Description:
MemDbSetValueAndFlagsEx modifies value and/or flags for an existing key
identified by KeyHandle.
Arguments:
KeyHandle - Identifies an existing key
AlterValue - Specifies if the existing value is to be altered
Value - Specifies the 32-bit value associated with KeyName (only needed if AlterValue is TRUE)
ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
consider SetFlags as the replacing flags, ClearFlags will be ignored
SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
replacement flags (if ReplaceFlags is TRUE).
ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
Return Value:
the key handle for the existent or newly added key if successful, NULL
otherwise.
--*/
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
if (AlterValue) {
if (!KeyStructSetValue (GET_INDEX (KeyHandle), Value)) {
__leave;
}
}
if ((ReplaceFlags && SetFlags) ||
(!ReplaceFlags && (SetFlags || ClearFlags))
) {
if (!KeyStructSetFlags (GET_INDEX (KeyHandle), ReplaceFlags, SetFlags, ClearFlags)) {
__leave;
}
}
result = TRUE;
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetValueAndFlagsA (
IN PCSTR KeyName,
OUT PUINT Value, OPTIONAL
OUT PUINT Flags OPTIONAL
)
/*++
Routine Description:
MemDbGetValueAndFlagsA is the external entry point for querying the database
for a value and flags.
Arguments:
KeyName - Specifies the key to query (i.e., foo\bar\cat)
Value - Recieves the value associated with Key, if Key exists.
Flags - Receives the flags associated with Key, if Key exists.
Return Value:
TRUE if Key exists in the database, FALSE otherwise.
--*/
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGetValueAndFlagsW (p, Value, Flags);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbGetValueAndFlagsW (
IN PCWSTR KeyName,
OUT PUINT Value, OPTIONAL
OUT PUINT Flags OPTIONAL
)
/*++
Routine Description:
MemDbGetValueAndFlagsW is the external entry point for querying the database
for a value and flags.
Arguments:
KeyName - Specifies the key to query (i.e., foo\bar\cat)
Value - Recieves the value associated with Key, if Key exists.
Flags - Receives the flags associated with Key, if Key exists.
Return Value:
TRUE if Key exists in the database, FALSE otherwise.
--*/
{
UINT keyIndex;
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
result = TRUE;
result = result && KeyStructGetValue (GetKeyStruct (keyIndex), Value);
result = result && KeyStructGetFlags (GetKeyStruct (keyIndex), Flags);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetValueAndFlagsByHandle (
IN KEYHANDLE KeyHandle,
OUT PUINT Value, OPTIONAL
OUT PUINT Flags OPTIONAL
)
/*++
Routine Description:
MemDbGetValueAndFlagsByHandle is the external entry point for querying the database
for a value and flags based on a key handle.
Arguments:
KeyHandle - Specifies the key handle to query
Value - Recieves the value associated with Key, if KeyHandle exists.
Flags - Receives the flags associated with Key, if KeyHandle exists.
Return Value:
TRUE if KeyHandle exists in the database, FALSE otherwise.
--*/
{
BYTE dbIndex;
PKEYSTRUCT keyStruct;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
keyStruct = GetKeyStruct (GET_INDEX (KeyHandle));
if (!keyStruct) {
__leave;
}
result = TRUE;
result = result && KeyStructGetValue (keyStruct, Value);
result = result && KeyStructGetFlags (keyStruct, Flags);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbAddDataA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbAddData is the a general purpose routine for adding binary data for a key.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
PCWSTR p;
DATAHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbAddDataW (p, Type, Instance, Data, DataSize);
FreeConvertedStr (p);
}
return result;
}
DATAHANDLE
MemDbAddDataW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbAddData is the a general purpose routine for adding binary data for a key.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
UINT keyIndex;
UINT dataIndex;
PCWSTR subKey;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
keyIndex = NewKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
}
dataIndex = KeyStructAddBinaryData (keyIndex, Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbAddDataByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbAddData is the a general purpose routine for adding binary data for a key.
Arguments:
KeyHandle - Specifies the key using the key handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructAddBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbGetDataHandleA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance
)
{
PCWSTR p;
DATAHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGetDataHandleW (p, Type, Instance);
FreeConvertedStr (p);
}
return result;
}
DATAHANDLE
MemDbGetDataHandleW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex;
UINT dataIndex;
PCWSTR subKey;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
dataIndex = KeyStructGetDataIndex (keyIndex, Type, Instance);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbSetDataA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbSetData is the a general purpose routine for setting binary data for a key.
If the key does not exist, it is created. If this type of data already exists, it
is replaced
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
PCWSTR p;
DATAHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbSetDataW (p, Type, Instance, Data, DataSize);
FreeConvertedStr (p);
}
return result;
}
DATAHANDLE
MemDbSetDataW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbSetData is the a general purpose routine for setting binary data for a key.
If the key does not exist, it is created. If this type of data already exists, it
is replaced, if it doesn't, it is created.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
UINT keyIndex;
UINT dataIndex;
PCWSTR subKey;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
keyIndex = NewKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
}
KeyStructDeleteBinaryData (keyIndex, Type, Instance);
dataIndex = KeyStructAddBinaryData (keyIndex, Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbSetDataByDataHandle (
IN DATAHANDLE DataHandle,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbSetData is the a general purpose routine for replacing an existing binary data.
Arguments:
DataHandle - Specifies an existing data handle
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!DataHandle) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructReplaceBinaryDataByIndex (GET_INDEX (DataHandle), Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbSetDataByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbSetDataByKeyHandle is the a general purpose routine for setting binary data for a key.
If this type of data already exists, it is replaced, if it doesn't, it is created.
Arguments:
KeyHandle - Specifies the key using the key handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
KeyStructDeleteBinaryData (GET_INDEX (KeyHandle), Type, Instance);
dataIndex = KeyStructAddBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbGrowDataA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbGrowData is the a general purpose routine for growing binary data for a key.
If the key does not exist, it is created. If this type of data already exists, it
is growed by appending the new data, if not, it is created by adding the new data
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
PCWSTR p;
DATAHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGrowDataW (p, Type, Instance, Data, DataSize);
FreeConvertedStr (p);
}
return result;
}
DATAHANDLE
MemDbGrowDataW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbGrowData is the a general purpose routine for growing binary data for a key.
If the key does not exist, it is created. If this type of data already exists, it
is growed by appending the new data, if not, it is created by adding the new data
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
UINT keyIndex;
UINT dataIndex;
PCWSTR subKey;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
keyIndex = NewKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
}
dataIndex = KeyStructGrowBinaryData (keyIndex, Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbGrowDataByDataHandle (
IN DATAHANDLE DataHandle,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbGrowDataByDataHandle is the a general purpose routine for growing binary data for a key.
Arguments:
DataHandle - Specifies the existing binary data handle
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructGrowBinaryDataByIndex (GET_INDEX (DataHandle), Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbGrowDataByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
MemDbGrowDataByDataHandle is the a general purpose routine for growing binary
data for a key. If the data is not present it is added, if it's present, the
new data is appended.
Arguments:
KeyHandle - Specifies the key we want by it's handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Data - Specifies the address of the data to be added.
DataSize - Specifies the size of the data.
Return Value:
A valid data handle if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if (!KeyHandle) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructGrowBinaryData (GET_INDEX (KeyHandle), Type, Instance, Data, DataSize);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
PBYTE
MemDbGetDataA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetData is the a general purpose routine for retrieving existing binary
data for a key. if the key or binary data do not exist, will return NULL. The
function will allocate memory from memdb's private pool. Caller is responsible
for releasing the memory.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
DataSize - Receives the size of the data.
Return Value:
A valid memory address if function was successful, NULL otherwise. Caller must
free non-NULL return values by calling MemDbReleaseMemory.
--*/
{
PCWSTR p;
PBYTE result = NULL;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGetDataW (p, Type, Instance, DataSize);
FreeConvertedStr (p);
}
return result;
}
PBYTE
MemDbGetDataW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetData is the a general purpose routine for retrieving existing binary
data for a key. if the key or binary data do not exist, will return NULL. The
function will allocate memory from memdb's private pool. Caller is responsible
for releasing the memory.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
DataSize - Receives the size of the data.
Return Value:
A valid memory address if function was successful, NULL otherwise. Caller must
free non-NULL return values by calling MemDbReleaseMemory.
--*/
{
UINT keyIndex;
PCWSTR subKey;
PBYTE tempResult = NULL;
PBYTE result = NULL;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return NULL;
}
if (Instance > 3) {
return NULL;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
tempResult = KeyStructGetBinaryData (keyIndex, Type, Instance, &localSize, NULL);
if (tempResult) {
result = MemDbGetMemory (localSize);
if (result) {
CopyMemory (result, tempResult, localSize);
if (DataSize) {
*DataSize = localSize;
}
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
PBYTE
MemDbGetDataByDataHandle (
IN DATAHANDLE DataHandle,
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetDataByDataHandle is the a general purpose routine for retrieving
existing binary data for a key.
Arguments:
DataHandle - Specifies the data that's needed identified by the data handle
DataSize - Receives the size of the data.
Return Value:
A valid memory address if function was successful, NULL otherwise.
--*/
{
BYTE dbIndex;
PBYTE tempResult = NULL;
PBYTE result = NULL;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
tempResult = KeyStructGetBinaryDataByIndex (GET_INDEX (DataHandle), &localSize);
if (tempResult) {
result = MemDbGetMemory (localSize);
if (result) {
CopyMemory (result, tempResult, localSize);
if (DataSize) {
*DataSize = localSize;
}
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
PBYTE
MemDbGetDataByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetDataByKeyHandle is the a general purpose routine for retrieving existing binary data for a key.
Arguments:
KeyHandle - Specifies the key by it's hey handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
DataSize - Receives the size of the data.
Return Value:
A valid memory address if function was successful, NULL otherwise. Caller must
free non-NULL return values by calling MemDbReleaseMemory.
--*/
{
BYTE dbIndex;
PBYTE tempResult = NULL;
PBYTE result = NULL;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return NULL;
}
if (Instance > 3) {
return NULL;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
tempResult = KeyStructGetBinaryData (GET_INDEX (KeyHandle), Type, Instance, &localSize, NULL);
if (tempResult) {
result = MemDbGetMemory (localSize);
if (result) {
CopyMemory (result, tempResult, localSize);
if (DataSize) {
*DataSize = localSize;
}
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetDataExA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
OUT PGROWBUFFER Buffer, OPTIONAL
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetDataEx is the a general purpose routine for retrieving existing binary
data for a key. if the key or binary data do not exist, will return FALSE. The
function will use the caller supplied growbuffer to store the data.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Buffer - Specifies a grow buffer that may contain data. Receives the
stored data (appended to existing data).
DataSize - Receives the size of the data.
Return Value:
TRUE if binary data exists for the key, and was successfully stored in
Buffer, FALSE otherwise.
--*/
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGetDataExW (p, Type, Instance, Buffer, DataSize);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbGetDataExW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
OUT PGROWBUFFER Buffer, OPTIONAL
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetData is the a general purpose routine for retrieving existing binary
data for a key. if the key or binary data do not exist, will return FALSE. The
function will use the caller supplied growbuffer to store the data.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Buffer - Specifies a grow buffer that may contain data. Receives the
stored data (appended to existing data).
DataSize - Receives the size of the data.
Return Value:
TRUE if binary data exists for the key, and was successfully stored in
Buffer, FALSE otherwise.
--*/
{
UINT keyIndex;
PCWSTR subKey;
PBYTE tempResult = NULL;
PBYTE destResult = NULL;
BOOL result = FALSE;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
tempResult = KeyStructGetBinaryData (keyIndex, Type, Instance, &localSize, NULL);
if (tempResult) {
if (Buffer) {
destResult = GbGrow (Buffer, localSize);
if (destResult) {
CopyMemory (destResult, tempResult, localSize);
result = TRUE;
}
} else {
result = TRUE;
}
if (result && DataSize) {
*DataSize = localSize;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetDataByDataHandleEx (
IN DATAHANDLE DataHandle,
OUT PGROWBUFFER Buffer, OPTIONAL
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetDataByDataHandleEx is the a general purpose routine for retrieving
existing binary data for a key. The function will use the caller supplied
growbuffer to store the data.
Arguments:
DataHandle - Specifies the data that's needed identified by the data handle
Buffer - Specifies a grow buffer that may contain data. Receives the
stored data (appended to existing data).
DataSize - Receives the size of the data.
Return Value:
TRUE if binary data exists for the key, and was successfully stored in
Buffer, FALSE otherwise.
--*/
{
BYTE dbIndex;
PBYTE tempResult = NULL;
PBYTE destResult = NULL;
BOOL result = FALSE;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
tempResult = KeyStructGetBinaryDataByIndex (GET_INDEX (DataHandle), &localSize);
if (tempResult) {
if (Buffer) {
destResult = GbGrow (Buffer, localSize);
if (destResult) {
CopyMemory (destResult, tempResult, localSize);
result = TRUE;
}
} else {
result = TRUE;
}
if (result && DataSize) {
*DataSize = localSize;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbGetDataByKeyHandleEx (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
OUT PGROWBUFFER Buffer, OPTIONAL
OUT PUINT DataSize OPTIONAL
)
/*++
Routine Description:
MemDbGetDataByKeyHandle is the a general purpose routine for retrieving
existing binary data for a key. The function will use the caller supplied
growbuffer to store the data.
Arguments:
KeyHandle - Specifies the key by it's hey handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Buffer - Specifies a grow buffer that may contain data. Receives the
stored data (appended to existing data).
DataSize - Receives the size of the data.
Return Value:
TRUE if binary data exists for the key, and was successfully stored in
Buffer, FALSE otherwise.
--*/
{
BYTE dbIndex;
PBYTE tempResult = NULL;
PBYTE destResult = NULL;
BOOL result = FALSE;
UINT localSize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
tempResult = KeyStructGetBinaryData (GET_INDEX (KeyHandle), Type, Instance, &localSize, NULL);
if (tempResult) {
if (Buffer) {
destResult = GbGrow (Buffer, localSize);
if (destResult) {
CopyMemory (destResult, tempResult, localSize);
result = TRUE;
}
} else {
result = TRUE;
}
if (result && DataSize) {
*DataSize = localSize;
}
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteDataA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance
)
/*++
Routine Description:
MemDbGetData is the a general purpose routine for removing existing data for a
key. If the data does not exist the function will return TRUE anyway.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Return Value:
TRUE if function was successful, FALSE otherwise.
--*/
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbDeleteDataW (p, Type, Instance);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbDeleteDataW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance
)
/*++
Routine Description:
MemDbDeleteData is the a general purpose routine for removing existing binary
data for a key. If the data does not exist the function will return TRUE
anyway.
Arguments:
KeyName - Specifies the key string to add (i.e., foo\bar\cat)
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Return Value:
TRUE if function was successful, FALSE otherwise.
--*/
{
UINT keyIndex;
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_UNORDERED) &&
(Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
result = KeyStructDeleteBinaryData (keyIndex, Type, Instance);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteDataByDataHandle (
IN DATAHANDLE DataHandle
)
/*++
Routine Description:
MemDbGetDataByDataHandleEx is the a general purpose routine for removing
existing binary data for a key.
Arguments:
DataHandle - Specifies the data that's needed identified by the data handle
Return Value:
TRUE if successful, FALSE if not.
--*/
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructDeleteBinaryDataByIndex (GET_INDEX (DataHandle));
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteDataByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance
)
/*++
Routine Description:
MemDbGetDataByDataHandleEx is the a general purpose routine for removing
existing binary data for a key.
Arguments:
KeyHandle - Specifies the key by it's hey handle
Type - Specifies data type (DATAFLAG_UNORDERED, DATAFLAG_SINGLELINK or DATAFLAG_DOUBLELINK)
Instance - Specifies data instance (0-3)
Return Value:
TRUE if successful, FALSE if not.
--*/
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructDeleteBinaryData (GET_INDEX (KeyHandle), Type, Instance);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbAddLinkageValueA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
PCWSTR p;
DATAHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbAddLinkageValueW (p, Type, Instance, Linkage, AllowDuplicates);
FreeConvertedStr (p);
}
return result;
}
DATAHANDLE
MemDbAddLinkageValueW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
UINT keyIndex;
UINT dataIndex;
PCWSTR subKey;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
keyIndex = NewKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
}
dataIndex = KeyStructAddLinkage (keyIndex, Type, Instance, Linkage, AllowDuplicates);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbAddLinkageValueByDataHandle (
IN DATAHANDLE DataHandle,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructAddLinkageByIndex (GET_INDEX (DataHandle), Linkage, AllowDuplicates);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
DATAHANDLE
MemDbAddLinkageValueByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
BYTE dbIndex;
UINT dataIndex;
DATAHANDLE result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
dataIndex = KeyStructAddLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage, AllowDuplicates);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
result = GET_EXTERNAL_INDEX (dataIndex);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteLinkageValueA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbDeleteLinkageValueW (p, Type, Instance, Linkage, FirstOnly);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbDeleteLinkageValueW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
UINT keyIndex;
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
result = KeyStructDeleteLinkage (keyIndex, Type, Instance, Linkage, FirstOnly);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteLinkageValueByDataHandle (
IN DATAHANDLE DataHandle,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructDeleteLinkageByIndex (GET_INDEX (DataHandle), Linkage, FirstOnly);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteLinkageValueByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructDeleteLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage, FirstOnly);
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbTestLinkageValueA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage
)
{
PCWSTR p;
BOOL result = FALSE;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbTestLinkageValueW (p, Type, Instance, Linkage);
FreeConvertedStr (p);
}
return result;
}
BOOL
MemDbTestLinkageValueW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN KEYHANDLE Linkage
)
{
UINT keyIndex;
PCWSTR subKey;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
result = KeyStructTestLinkage (keyIndex, Type, Instance, Linkage);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbTestLinkageValueByDataHandle (
IN DATAHANDLE DataHandle,
IN KEYHANDLE Linkage
)
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (DataHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructTestLinkageByIndex (GET_INDEX (DataHandle), Linkage);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbTestLinkageValueByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN KEYHANDLE Linkage
)
{
BYTE dbIndex;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
result = KeyStructTestLinkage (GET_INDEX (KeyHandle), Type, Instance, Linkage);
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbAddLinkageA (
IN PCSTR KeyName1,
IN PCSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
PCWSTR p1 = NULL;
PCWSTR p2 = NULL;
BOOL result = FALSE;
p1 = ConvertAtoW (KeyName1);
p2 = ConvertAtoW (KeyName2);
if (p1 && p2) {
result = MemDbAddLinkageW (p1, p2, Type, Instance);
}
if (p1) {
FreeConvertedStr (p1);
}
if (p2) {
FreeConvertedStr (p2);
}
return result;
}
BOOL
MemDbAddLinkageW (
IN PCWSTR KeyName1,
IN PCWSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
UINT dataIndex;
PCWSTR subKey1;
PCWSTR subKey2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
keyIndex1 = FindKey (subKey1);
if (keyIndex1 == INVALID_OFFSET) {
keyIndex1 = NewKey (subKey1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
}
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
keyIndex2 = FindKey (subKey2);
if (keyIndex2 == INVALID_OFFSET) {
keyIndex2 = NewKey (subKey2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
}
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
MYASSERT (keyIndex2 != INVALID_OFFSET);
dataIndex = KeyStructAddLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2), FALSE);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
if (Type == DATAFLAG_DOUBLELINK) {
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
MYASSERT (keyIndex1 != INVALID_OFFSET);
dataIndex = KeyStructAddLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1), FALSE);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
}
result = TRUE;
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbAddLinkageByKeyHandle (
IN KEYHANDLE KeyHandle1,
IN KEYHANDLE KeyHandle2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
UINT dataIndex;
BYTE dbIndex1;
BYTE dbIndex2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex1 = GET_DATABASE (KeyHandle1);
if (!SelectDatabase (dbIndex1)) {
__leave;
}
keyIndex1 = GET_INDEX (KeyHandle1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
dbIndex2 = GET_DATABASE (KeyHandle2);
if (!SelectDatabase (dbIndex2)) {
__leave;
}
keyIndex2 = GET_INDEX (KeyHandle2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
SelectDatabase (dbIndex1);
dataIndex = KeyStructAddLinkage (keyIndex1, Type, Instance, KeyHandle2, FALSE);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
if (Type == DATAFLAG_DOUBLELINK) {
SelectDatabase (dbIndex2);
dataIndex = KeyStructAddLinkage (keyIndex2, Type, Instance, KeyHandle1, FALSE);
if (dataIndex == INVALID_OFFSET) {
__leave;
}
}
result = TRUE;
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteLinkageA (
IN PCSTR KeyName1,
IN PCSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
PCWSTR p1 = NULL;
PCWSTR p2 = NULL;
BOOL result = FALSE;
p1 = ConvertAtoW (KeyName1);
p2 = ConvertAtoW (KeyName2);
if (p1 && p2) {
result = MemDbDeleteLinkageW (p1, p2, Type, Instance);
}
if (p1) {
FreeConvertedStr (p1);
}
if (p2) {
FreeConvertedStr (p2);
}
return result;
}
BOOL
MemDbDeleteLinkageW (
IN PCWSTR KeyName1,
IN PCWSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
PCWSTR subKey1;
PCWSTR subKey2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
keyIndex1 = FindKey (subKey1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
keyIndex2 = FindKey (subKey2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
MYASSERT (keyIndex2 != INVALID_OFFSET);
result = KeyStructDeleteLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2), FALSE);
if (result && (Type == DATAFLAG_DOUBLELINK)) {
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
MYASSERT (keyIndex1 != INVALID_OFFSET);
result = KeyStructDeleteLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1), FALSE);
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbDeleteLinkageByKeyHandle (
IN KEYHANDLE KeyHandle1,
IN KEYHANDLE KeyHandle2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
BYTE dbIndex1;
BYTE dbIndex2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex1 = GET_DATABASE (KeyHandle1);
if (!SelectDatabase (dbIndex1)) {
__leave;
}
keyIndex1 = GET_INDEX (KeyHandle1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
dbIndex2 = GET_DATABASE (KeyHandle2);
if (!SelectDatabase (dbIndex2)) {
__leave;
}
keyIndex2 = GET_INDEX (KeyHandle2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
SelectDatabase (dbIndex1);
result = KeyStructDeleteLinkage (keyIndex1, Type, Instance, KeyHandle2, FALSE);
if (result && (Type == DATAFLAG_DOUBLELINK)) {
SelectDatabase (dbIndex2);
result = KeyStructDeleteLinkage (keyIndex2, Type, Instance, KeyHandle1, FALSE);
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbTestLinkageA (
IN PCSTR KeyName1,
IN PCSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
PCWSTR p1 = NULL;
PCWSTR p2 = NULL;
BOOL result = FALSE;
p1 = ConvertAtoW (KeyName1);
p2 = ConvertAtoW (KeyName2);
if (p1 && p2) {
result = MemDbTestLinkageW (p1, p2, Type, Instance);
}
if (p1) {
FreeConvertedStr (p1);
}
if (p2) {
FreeConvertedStr (p2);
}
return result;
}
BOOL
MemDbTestLinkageW (
IN PCWSTR KeyName1,
IN PCWSTR KeyName2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
PCWSTR subKey1;
PCWSTR subKey2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
keyIndex1 = FindKey (subKey1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
keyIndex2 = FindKey (subKey2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
subKey1 = SelectHiveW (KeyName1);
if (!subKey1) {
__leave;
}
MYASSERT (keyIndex2 != INVALID_OFFSET);
result = KeyStructTestLinkage (keyIndex1, Type, Instance, GET_EXTERNAL_INDEX (keyIndex2));
if (result && (Type == DATAFLAG_DOUBLELINK)) {
subKey2 = SelectHiveW (KeyName2);
if (!subKey2) {
__leave;
}
MYASSERT (keyIndex1 != INVALID_OFFSET);
result = KeyStructTestLinkage (keyIndex2, Type, Instance, GET_EXTERNAL_INDEX (keyIndex1));
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
MemDbTestLinkageByKeyHandle (
IN KEYHANDLE KeyHandle1,
IN KEYHANDLE KeyHandle2,
IN BYTE Type,
IN BYTE Instance
)
{
UINT keyIndex1;
UINT keyIndex2;
BYTE dbIndex1;
BYTE dbIndex2;
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return FALSE;
}
if (Instance > 3) {
return FALSE;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex1 = GET_DATABASE (KeyHandle1);
if (!SelectDatabase (dbIndex1)) {
__leave;
}
keyIndex1 = GET_INDEX (KeyHandle1);
if (keyIndex1 == INVALID_OFFSET) {
__leave;
}
dbIndex2 = GET_DATABASE (KeyHandle2);
if (!SelectDatabase (dbIndex2)) {
__leave;
}
keyIndex2 = GET_INDEX (KeyHandle2);
if (keyIndex2 == INVALID_OFFSET) {
__leave;
}
SelectDatabase (dbIndex1);
result = KeyStructTestLinkage (keyIndex1, Type, Instance, KeyHandle2);
if (result && (Type == DATAFLAG_DOUBLELINK)) {
SelectDatabase (dbIndex2);
result = KeyStructTestLinkage (keyIndex2, Type, Instance, KeyHandle1);
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
KEYHANDLE
MemDbGetLinkageA (
IN PCSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT LinkageIndex
)
{
PCWSTR p = NULL;
KEYHANDLE result = 0;
p = ConvertAtoW (KeyName);
if (p) {
result = MemDbGetLinkageW (p, Type, Instance, LinkageIndex);
FreeConvertedStr (p);
}
return result;
}
KEYHANDLE
MemDbGetLinkageW (
IN PCWSTR KeyName,
IN BYTE Type,
IN BYTE Instance,
IN UINT LinkageIndex
)
{
UINT keyIndex;
PCWSTR subKey;
KEYHANDLE result = 0;
PUINT linkArray;
UINT linkArraySize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (KeyName);
if (!subKey) {
__leave;
}
keyIndex = FindKey (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
linkArraySize = 0;
linkArray = (PUINT)KeyStructGetBinaryData (keyIndex, Type, Instance, &linkArraySize, NULL);
linkArraySize = linkArraySize / SIZEOF(UINT);
if (linkArraySize <= LinkageIndex) {
__leave;
}
result = linkArray [LinkageIndex];
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
KEYHANDLE
MemDbGetLinkageByKeyHandle (
IN KEYHANDLE KeyHandle,
IN BYTE Type,
IN BYTE Instance,
IN UINT LinkageIndex
)
{
UINT keyIndex;
BYTE dbIndex;
KEYHANDLE result = 0;
PUINT linkArray;
UINT linkArraySize;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
if ((Type != DATAFLAG_SINGLELINK) &&
(Type != DATAFLAG_DOUBLELINK)
) {
return result;
}
if (Instance > 3) {
return result;
}
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
keyIndex = GET_INDEX (KeyHandle);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
linkArray = (PUINT)KeyStructGetBinaryData (keyIndex, Type, Instance, &linkArraySize, NULL);
linkArraySize = linkArraySize / SIZEOF(UINT);
if (linkArraySize <= LinkageIndex) {
__leave;
}
result = linkArray [LinkageIndex];
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
pCheckEnumConditions (
IN UINT KeyIndex,
IN PMEMDB_ENUMW MemDbEnum
)
{
PKEYSTRUCT keyStruct;
UINT index;
PWSTR segPtr, segEndPtr;
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
if (keyStruct->KeyFlags & KSF_ENDPOINT) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_ENDPOINTS)) {
return FALSE;
}
MemDbEnum->EndPoint = TRUE;
} else {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_NONENDPOINTS)) {
return FALSE;
}
MemDbEnum->EndPoint = FALSE;
}
if (keyStruct->DataFlags & DATAFLAG_UNORDERED) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_UNORDERED)) {
return FALSE;
}
}
if (keyStruct->DataFlags & DATAFLAG_SINGLELINK) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_SINGLELINK)) {
return FALSE;
}
}
if (keyStruct->DataFlags & DATAFLAG_DOUBLELINK) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_DOUBLELINK)) {
return FALSE;
}
}
if (keyStruct->DataFlags & DATAFLAG_VALUE) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_VALUE)) {
return FALSE;
}
MemDbEnum->Value = keyStruct->Value;
} else {
MemDbEnum->Value = 0;
}
if (keyStruct->DataFlags & DATAFLAG_FLAGS) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_FLAGS)) {
return FALSE;
}
MemDbEnum->Flags = keyStruct->Flags;
} else {
MemDbEnum->Flags = 0;
}
if (!keyStruct->DataFlags) {
if (!(MemDbEnum->EnumFlags & ENUMFLAG_EMPTY)) {
return FALSE;
}
}
if (MemDbEnum->BeginLevel != ENUMLEVEL_LASTLEVEL) {
if (MemDbEnum->CurrentLevel - 1 < MemDbEnum->BeginLevel) {
return FALSE;
}
if (MemDbEnum->CurrentLevel - 1 > MemDbEnum->EndLevel) {
return FALSE;
}
}
MYASSERT (KeyIndex != INVALID_OFFSET);
MemDbEnum->KeyHandle = GET_EXTERNAL_INDEX (KeyIndex);
index = 0;
segPtr = MemDbEnum->KeyNameCopy;
MemDbEnum->FullKeyName[0] = 0;
MemDbEnum->KeyName[0] = 0;
while (segPtr) {
segEndPtr = wcschr (segPtr, L'\\');
if (segEndPtr) {
*segEndPtr = 0;
}
index ++;
if (index > 1) {
StringCatW (MemDbEnum->FullKeyName, L"\\");
StringCatW (MemDbEnum->FullKeyName, segPtr);
} else {
switch (g_CurrentDatabaseIndex) {
case DB_PERMANENT:
StringCopyW (MemDbEnum->FullKeyName, segPtr);
break;
case DB_TEMPORARY:
StringCopyW (MemDbEnum->FullKeyName, L"~");
StringCatW (MemDbEnum->FullKeyName, segPtr);
break;
default:
StringCopyW (MemDbEnum->FullKeyName, segPtr);
}
}
if (MemDbEnum->BeginLevel == ENUMLEVEL_LASTLEVEL) {
if (index >= MemDbEnum->CurrentLevel) {
//this is the last segment, copy it to the
//partial key
StringCopyW (MemDbEnum->KeyName, segPtr);
}
} else {
if (index > MemDbEnum->BeginLevel) {
//copy the current segment in partial key
if ((index - 1) == MemDbEnum->BeginLevel) {
if (index == 1) {
switch (g_CurrentDatabaseIndex) {
case DB_PERMANENT:
StringCopyW (MemDbEnum->KeyName, segPtr);
break;
case DB_TEMPORARY:
StringCopyW (MemDbEnum->KeyName, L"~");
StringCatW (MemDbEnum->KeyName, segPtr);
break;
default:
StringCopyW (MemDbEnum->KeyName, segPtr);
}
} else {
StringCopyW (MemDbEnum->KeyName, segPtr);
}
} else {
StringCatW (MemDbEnum->KeyName, L"\\");
StringCatW (MemDbEnum->KeyName, segPtr);
}
}
}
if (segEndPtr) {
segPtr = segEndPtr + 1;
*segEndPtr = L'\\';
} else {
segPtr = NULL;
}
if (index >= MemDbEnum->CurrentLevel) {
// no more segments to copy
break;
}
}
return TRUE;
}
VOID
pAddKeyToEnumStruct (
IN OUT PMEMDB_ENUMW MemDbEnum,
IN PCWSTR KeyName
)
{
PCWSTR lastName;
PWSTR endPtr;
lastName = MemDbEnum->KeyNameCopy;
if (lastName) {
MemDbEnum->KeyNameCopy = JoinTextExW (g_MemDbPool, lastName, L"\\", NULL, KeyName[0] + 1, &endPtr);
StringPasCopyConvertFrom (endPtr, KeyName);
MemDbReleaseMemory ((PBYTE)lastName);
} else {
MemDbEnum->KeyNameCopy = (PWSTR)MemDbGetMemory ((KeyName[0] + 1) * SIZEOF(WCHAR));
StringPasCopyConvertFrom ((PWSTR)MemDbEnum->KeyNameCopy, KeyName);
}
// NTRAID#NTBUG9-153308-2000/08/01-jimschm this way of doing it will fill out the pool very fast.
// need to find a way to release first and allocate after that.
}
VOID
pDeleteLastKeyFromEnumStruct (
IN OUT PMEMDB_ENUMW MemDbEnum
)
{
PWSTR lastWackPtr;
lastWackPtr = wcsrchr (MemDbEnum->KeyNameCopy, L'\\');
if (lastWackPtr) {
*lastWackPtr = 0;
} else {
MemDbReleaseMemory (MemDbEnum->KeyNameCopy);
MemDbEnum->KeyNameCopy = NULL;
}
}
BOOL
pMemDbEnumNextW (
IN OUT PMEMDB_ENUMW MemDbEnum
)
{
BOOL shouldReturn = FALSE;
BOOL result = FALSE;
BOOL patternMatch = TRUE;
BOOL goOn = TRUE;
BOOL patternFound;
UINT treeEnumContext;
UINT treeEnumNode;
UINT tempKeyIndex;
PKEYSTRUCT tempKeyStruct;
PBYTE gbAddress;
UINT minLevel;
UINT internalLevel;
while (!shouldReturn) {
if (MemDbEnum->EnumerationMode) {
result = FALSE;
minLevel = MemDbEnum->CurrentLevel;
internalLevel = MemDbEnum->CurrentLevel;
if (MemDbEnum->TreeEnumLevel == MemDbEnum->TreeEnumBuffer.End) {
patternMatch = FALSE;
while (!patternMatch) {
if (MemDbEnum->TreeEnumBuffer.End) {
goOn = TRUE;
while (goOn) {
// we are in the middle of some tree enumeration
// let's get back the context and continue
if (MemDbEnum->TreeEnumBuffer.End == 0) {
// we can't back out any more, we're done
break;
}
MemDbEnum->TreeEnumBuffer.End -= (SIZEOF(UINT)+SIZEOF(UINT));
if (MemDbEnum->TreeEnumLevel > MemDbEnum->TreeEnumBuffer.End) {
MemDbEnum->TreeEnumLevel = MemDbEnum->TreeEnumBuffer.End;
}
minLevel --;
if (MemDbEnum->CurrentLevel > minLevel) {
MemDbEnum->CurrentLevel = minLevel;
}
if (internalLevel > minLevel) {
internalLevel = minLevel;
}
pDeleteLastKeyFromEnumStruct (MemDbEnum);
treeEnumContext = *((PUINT) (MemDbEnum->TreeEnumBuffer.Buf+MemDbEnum->TreeEnumBuffer.End + SIZEOF(UINT)));
tempKeyIndex = BinTreeEnumNext (&treeEnumContext);
if (tempKeyIndex != INVALID_OFFSET) {
minLevel ++;
internalLevel ++;
goOn = FALSE;
// put them in the grow buffer
gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
if (gbAddress) {
*((PUINT) (gbAddress)) = tempKeyIndex;
*((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
}
tempKeyStruct = GetKeyStruct (tempKeyIndex);
MYASSERT (tempKeyStruct);
pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
treeEnumNode = tempKeyStruct->NextLevelTree;
while ((treeEnumNode != INVALID_OFFSET) &&
(internalLevel - 1 <= MemDbEnum->EndLevel)
) {
tempKeyIndex = BinTreeEnumFirst (treeEnumNode, &treeEnumContext);
if (tempKeyIndex != INVALID_OFFSET) {
minLevel ++;
internalLevel ++;
// put them in the grow buffer
gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
if (gbAddress) {
*((PUINT) (gbAddress)) = tempKeyIndex;
*((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
}
tempKeyStruct = GetKeyStruct (tempKeyIndex);
MYASSERT (tempKeyStruct);
pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
treeEnumNode = tempKeyStruct->NextLevelTree;
} else {
treeEnumNode = INVALID_OFFSET;
}
}
}
}
} else {
// we are about to start the tree enumeration
// let's start the enumeration and push the
// context data in our buffer
treeEnumNode = MemDbEnum->CurrentIndex;
while ((treeEnumNode != INVALID_OFFSET) &&
(internalLevel <= MemDbEnum->EndLevel)
) {
tempKeyIndex = BinTreeEnumFirst (treeEnumNode, &treeEnumContext);
if (tempKeyIndex != INVALID_OFFSET) {
minLevel ++;
internalLevel ++;
// put them in the grow buffer
gbAddress = GbGrow (&(MemDbEnum->TreeEnumBuffer), SIZEOF(UINT)+SIZEOF(UINT));
if (gbAddress) {
*((PUINT) (gbAddress)) = tempKeyIndex;
*((PUINT) (gbAddress+SIZEOF(UINT))) = treeEnumContext;
}
tempKeyStruct = GetKeyStruct (tempKeyIndex);
MYASSERT (tempKeyStruct);
pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
treeEnumNode = tempKeyStruct->NextLevelTree;
} else {
treeEnumNode = INVALID_OFFSET;
}
}
}
if (MemDbEnum->TreeEnumBuffer.End == 0) {
// we can't back out any more, we're done
break;
}
if (MemDbEnum->PatternStruct.PatternMatch) {
MYASSERT (MemDbEnum->PatternStruct.Data);
patternMatch =
MemDbEnum->PatternStruct.PatternMatch (
MemDbEnum->PatternStruct.Data,
MemDbEnum->KeyNameCopy
);
} else {
patternMatch = IsPatternMatchW (
MemDbEnum->PatternCopy,
MemDbEnum->KeyNameCopy
);
}
}
}
if (MemDbEnum->TreeEnumLevel == MemDbEnum->TreeEnumBuffer.End) {
break;
}
MYASSERT (MemDbEnum->TreeEnumLevel < MemDbEnum->TreeEnumBuffer.End);
// now implement segment by segment enumeration because we
// just created a full key that matches the pattern
MemDbEnum->CurrentLevel ++;
shouldReturn = pCheckEnumConditions (
*((PUINT) (MemDbEnum->TreeEnumBuffer.Buf+MemDbEnum->TreeEnumLevel)),
MemDbEnum
);
MemDbEnum->TreeEnumLevel += (SIZEOF(UINT)+SIZEOF(UINT));
result = TRUE;
} else {
result = FALSE;
if (!MemDbEnum->PatternEndPtr) {
//we are done, no more segments
break;
}
MemDbEnum->PatternPtr = MemDbEnum->PatternEndPtr;
MemDbEnum->PatternEndPtr = wcschr (MemDbEnum->PatternPtr, L'\\');
if (MemDbEnum->PatternEndPtr) {
*MemDbEnum->PatternEndPtr = 0;
}
if (MemDbEnum->PatternStruct.PatternFind) {
patternFound =
MemDbEnum->PatternStruct.PatternFind (
MemDbEnum->PatternPtr
);
} else {
patternFound = (wcschr (MemDbEnum->PatternPtr, L'*') ||
wcschr (MemDbEnum->PatternPtr, L'?')
);
}
if (patternFound) {
MemDbEnum->EnumerationMode = TRUE;
if (MemDbEnum->PatternEndPtr) {
*MemDbEnum->PatternEndPtr = L'\\';
MemDbEnum->PatternEndPtr++;
}
} else {
tempKeyIndex = FindKeyStructInTree (
MemDbEnum->CurrentIndex,
MemDbEnum->PatternPtr,
FALSE
);
if (tempKeyIndex == INVALID_OFFSET) {
// we are done, the segment we look for does not exist
break;
}
tempKeyStruct = GetKeyStruct (tempKeyIndex);
MYASSERT (tempKeyStruct);
pAddKeyToEnumStruct (MemDbEnum, tempKeyStruct->KeyName);
MemDbEnum->CurrentIndex = tempKeyStruct->NextLevelTree;
MemDbEnum->CurrentLevel ++;
if (MemDbEnum->PatternEndPtr) {
*MemDbEnum->PatternEndPtr = L'\\';
MemDbEnum->PatternEndPtr++;
}
patternMatch = IsPatternMatchW (
MemDbEnum->PatternCopy,
MemDbEnum->KeyNameCopy
);
shouldReturn = patternMatch && pCheckEnumConditions (
tempKeyIndex,
MemDbEnum
);
result = TRUE;
}
}
}
return result;
}
BOOL
RealMemDbEnumFirstExW (
IN OUT PMEMDB_ENUMW MemDbEnum,
IN PCWSTR EnumPattern,
IN UINT EnumFlags,
IN UINT BeginLevel,
IN UINT EndLevel,
IN PMEMDB_PATTERNSTRUCTW PatternStruct OPTIONAL
)
{
BOOL result = FALSE;
PCWSTR subPattern;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
subPattern = SelectHiveW (EnumPattern);
if (!subPattern) {
__leave;
}
ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMW));
MemDbEnum->CurrentDatabaseIndex = GetCurrentDatabaseIndex ();
MemDbEnum->EnumFlags = EnumFlags;
MemDbEnum->PatternCopy = DuplicateTextExW (g_MemDbPool, subPattern, 0, NULL);
if (!MemDbEnum->PatternCopy) {
__leave;
}
MemDbEnum->PatternPtr = MemDbEnum->PatternCopy;
MemDbEnum->PatternEndPtr = MemDbEnum->PatternPtr;
MemDbEnum->CurrentIndex = g_CurrentDatabase->FirstLevelTree;
MemDbEnum->BeginLevel = BeginLevel;
if (MemDbEnum->BeginLevel == ENUMLEVEL_LASTLEVEL) {
MemDbEnum->EndLevel = ENUMLEVEL_ALLLEVELS;
} else {
MemDbEnum->EndLevel = EndLevel;
if (MemDbEnum->EndLevel < MemDbEnum->BeginLevel) {
MemDbEnum->EndLevel = MemDbEnum->BeginLevel;
}
}
MemDbEnum->CurrentLevel = 0;
if (PatternStruct) {
MemDbEnum->PatternStruct.PatternFind = PatternStruct->PatternFind;
MemDbEnum->PatternStruct.PatternMatch = PatternStruct->PatternMatch;
MemDbEnum->PatternStruct.Data = PatternStruct->Data;
}
result = pMemDbEnumNextW (MemDbEnum);
if (!result) {
MemDbAbortEnumW (MemDbEnum);
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
RealMemDbEnumFirstExA (
IN OUT PMEMDB_ENUMA MemDbEnum,
IN PCSTR EnumPattern,
IN UINT EnumFlags,
IN UINT BeginLevel,
IN UINT EndLevel,
IN PMEMDB_PATTERNSTRUCTW PatternStruct OPTIONAL
)
{
BOOL result = FALSE;
PCWSTR unicodeStr;
unicodeStr = ConvertAtoW (EnumPattern);
if (!unicodeStr) {
return FALSE;
}
result = RealMemDbEnumFirstExW (
&(MemDbEnum->UnicodeEnum),
unicodeStr,
EnumFlags,
BeginLevel,
EndLevel,
PatternStruct
);
if (result) {
KnownSizeWtoA (MemDbEnum->FullKeyName, MemDbEnum->UnicodeEnum.FullKeyName);
KnownSizeWtoA (MemDbEnum->KeyName, MemDbEnum->UnicodeEnum.KeyName);
MemDbEnum->Value = MemDbEnum->UnicodeEnum.Value;
MemDbEnum->Flags = MemDbEnum->UnicodeEnum.Flags;
MemDbEnum->KeyHandle = MemDbEnum->UnicodeEnum.KeyHandle;
MemDbEnum->EndPoint = MemDbEnum->UnicodeEnum.EndPoint;
}
FreeConvertedStr (unicodeStr);
return result;
}
BOOL
RealMemDbEnumNextW (
IN OUT PMEMDB_ENUMW MemDbEnum
)
{
BOOL result = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
if (!SelectDatabase (MemDbEnum->CurrentDatabaseIndex)) {
__leave;
}
result = pMemDbEnumNextW (MemDbEnum);
if (!result) {
MemDbAbortEnumW (MemDbEnum);
}
}
__finally {
LeaveCriticalSection (&g_MemDbCs);
}
return result;
}
BOOL
RealMemDbEnumNextA (
IN OUT PMEMDB_ENUMA MemDbEnum
)
{
BOOL result = FALSE;
result = RealMemDbEnumNextW (&(MemDbEnum->UnicodeEnum));
if (result) {
KnownSizeWtoA (MemDbEnum->FullKeyName, MemDbEnum->UnicodeEnum.FullKeyName);
KnownSizeWtoA (MemDbEnum->KeyName, MemDbEnum->UnicodeEnum.KeyName);
MemDbEnum->Value = MemDbEnum->UnicodeEnum.Value;
MemDbEnum->Flags = MemDbEnum->UnicodeEnum.Flags;
MemDbEnum->KeyHandle = MemDbEnum->UnicodeEnum.KeyHandle;
MemDbEnum->EndPoint = MemDbEnum->UnicodeEnum.EndPoint;
}
return result;
}
BOOL
MemDbAbortEnumW (
IN OUT PMEMDB_ENUMW MemDbEnum
)
{
if (MemDbEnum->KeyNameCopy) {
MemDbReleaseMemory (MemDbEnum->KeyNameCopy);
}
if (MemDbEnum->PatternCopy) {
MemDbReleaseMemory (MemDbEnum->PatternCopy);
}
GbFree (&(MemDbEnum->TreeEnumBuffer));
ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMW));
return TRUE;
}
BOOL
MemDbAbortEnumA (
IN OUT PMEMDB_ENUMA MemDbEnum
)
{
MemDbAbortEnumW (&(MemDbEnum->UnicodeEnum));
ZeroMemory (MemDbEnum, SIZEOF (MEMDB_ENUMA));
return TRUE;
}
BOOL
MemDbSetInsertionOrderedA (
IN PCSTR Key
)
/*++
Routine Description:
MemDbSetInsertionOrderedA sets the enumeration order of the children of Key
to be in the order they were inserted.
Arguments:
Key - key to make insertion ordered
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PCWSTR unicodeKey;
BOOL b = FALSE;
unicodeKey = ConvertAtoW (Key);
if (unicodeKey) {
b = MemDbSetInsertionOrderedW (unicodeKey);
FreeConvertedStr (unicodeKey);
}
return b;
}
BOOL
MemDbSetInsertionOrderedW (
IN PCWSTR Key
)
/*++
Routine Description:
MemDbSetInsertionOrderedW sets the enumeration order of the children of Key
to be in the order they were inserted.
Arguments:
Key - key to make insertion ordered
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
UINT keyIndex;
PCWSTR subKey;
BOOL b = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return b;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
subKey = SelectHiveW (Key);
if (!subKey) {
__leave;
}
keyIndex = FindKeyStruct (subKey);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
b = KeyStructSetInsertionOrdered(GetKeyStruct(keyIndex));
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
MemDbSetInsertionOrderedByKeyHandle (
IN KEYHANDLE KeyHandle
)
/*++
Routine Description:
MemDbSetInsertionOrderedByKeyHandle sets the enumeration order of the children of
KeyHandle to be in the order they were inserted.
Arguments:
KeyHandle - Specifies the key using the key handle
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
BYTE dbIndex;
BOOL b = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return b;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
b = KeyStructSetInsertionOrdered (GetKeyStruct(GET_INDEX (KeyHandle)));
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
BOOL
MemDbMoveKeyHandleToEnd (
IN KEYHANDLE KeyHandle
)
{
BYTE dbIndex;
UINT keyIndex;
PKEYSTRUCT keyStruct;
UINT parentIndex;
PKEYSTRUCT parentKeyStruct;
UINT treeOffset;
BOOL b = FALSE;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return b;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
__try {
dbIndex = GET_DATABASE (KeyHandle);
if (!SelectDatabase (dbIndex)) {
__leave;
}
keyIndex = GET_INDEX (KeyHandle);
if (keyIndex == INVALID_OFFSET) {
__leave;
}
keyStruct = GetKeyStruct (keyIndex);
if (!keyStruct) {
__leave;
}
parentIndex = keyStruct->PrevLevelIndex;
if (parentIndex == INVALID_OFFSET) {
__leave;
}
parentKeyStruct = GetKeyStruct (parentIndex);
if (!parentKeyStruct) {
__leave;
}
if (!KeyStructSetInsertionOrdered (parentKeyStruct)) {
__leave;
}
// reloading key struct and parent key struct
keyStruct = GetKeyStruct (keyIndex);
if (!keyStruct) {
__leave;
}
parentKeyStruct = GetKeyStruct (parentIndex);
if (!parentKeyStruct) {
__leave;
}
treeOffset = parentKeyStruct->NextLevelTree;
if (treeOffset == INVALID_OFFSET) {
__leave;
}
if (!BinTreeDeleteNode (treeOffset, keyStruct->KeyName, NULL)) {
__leave;
}
if (!BinTreeAddNode (treeOffset, keyIndex)) {
__leave;
}
b = TRUE;
}
__finally {
#ifdef DEBUG
if (g_DatabaseCheckLevel) {
CheckDatabase (g_DatabaseCheckLevel);
}
#endif
LeaveCriticalSection (&g_MemDbCs);
}
return b;
}
PCBYTE
MemDbGetDatabaseAddress (
VOID
)
{
PCBYTE result = NULL;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
if (SelectDatabase(0)) {
result = g_CurrentDatabase->Buf;
}
LeaveCriticalSection (&g_MemDbCs);
return result;
}
UINT
MemDbGetDatabaseSize (
VOID
)
/*++
Routine Description:
MemDbGetDatabaseSize returns the size of the permanent database
Arguments:
None.
Return Value:
The size of the permanent database.
--*/
{
UINT result = 0;
if (!g_Initialized) {
DEBUGMSG ((DBG_ERROR, "MemDb is not initialized"));
return result;
}
MYASSERT (g_MemDbPool);
EnterCriticalSection (&g_MemDbCs);
if (SelectDatabase(0)) {
result = g_CurrentDatabase->End;
}
LeaveCriticalSection (&g_MemDbCs);
return result;
}
#ifdef DEBUG
BOOL
MemDbCheckDatabase(
UINT Level
)
/*++
Routine Description:
MemDbCheckDatabase enumerates the entire database and verifies that each
enumerated key can be found in the hash table.
Arguments:
Level - Specifies database check level
Return Value:
TRUE if the database is valid, FALSE otherwise.
--*/
{
MYASSERT (g_MemDbPool);
return (CheckDatabase(Level) && CheckLevel(g_CurrentDatabase->FirstLevelTree, INVALID_OFFSET));
}
#endif