696 lines
15 KiB
C
696 lines
15 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
memdbex.c
|
|
|
|
Abstract:
|
|
|
|
Extensions to use the memdb tree like a relational database
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 2-Dec-1996
|
|
|
|
Revision History:
|
|
|
|
jimschm 23-Sep-1998 Expanded user flags to 24 bits (from
|
|
12 bits), removed AnsiFromUnicode
|
|
jimschm 21-Oct-1997 Cleaned up a little
|
|
marcw 09-Apr-1997 Added MemDbGetOffset* functions.
|
|
jimschm 17-Jan-1997 All string params can be NULL now
|
|
jimschm 18-Dec-1996 Added GetEndpointValue functions
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "memdbp.h"
|
|
|
|
VOID
|
|
MemDbBuildKeyA (
|
|
OUT PSTR Buffer,
|
|
IN PCSTR Category,
|
|
IN PCSTR Item,
|
|
IN PCSTR Field,
|
|
IN PCSTR Data
|
|
)
|
|
{
|
|
PSTR p;
|
|
static CHAR Wack[] = "\\";
|
|
|
|
p = Buffer;
|
|
*p = 0;
|
|
|
|
if (Category)
|
|
p = _mbsappend (p, Category);
|
|
if (Item) {
|
|
if (p != Buffer)
|
|
p = _mbsappend (p, Wack);
|
|
|
|
p = _mbsappend (p, Item);
|
|
}
|
|
if (Field) {
|
|
if (p != Buffer)
|
|
p = _mbsappend (p, Wack);
|
|
|
|
p = _mbsappend (p, Field);
|
|
}
|
|
if (Data) {
|
|
if (p != Buffer)
|
|
p = _mbsappend (p, Wack);
|
|
|
|
p = _mbsappend (p, Data);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
MemDbBuildKeyW (
|
|
OUT PWSTR Buffer,
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item,
|
|
IN PCWSTR Field,
|
|
IN PCWSTR Data
|
|
)
|
|
{
|
|
PWSTR p;
|
|
static WCHAR Wack[] = L"\\";
|
|
|
|
p = Buffer;
|
|
*p = 0;
|
|
|
|
if (Category)
|
|
p = _wcsappend (p, Category);
|
|
if (Item) {
|
|
if (p != Buffer)
|
|
p = _wcsappend (p, Wack);
|
|
|
|
p = _wcsappend (p, Item);
|
|
}
|
|
if (Field) {
|
|
if (p != Buffer)
|
|
p = _wcsappend (p, Wack);
|
|
|
|
p = _wcsappend (p, Field);
|
|
}
|
|
if (Data) {
|
|
if (p != Buffer)
|
|
p = _wcsappend (p, Wack);
|
|
|
|
p = _wcsappend (p, Data);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbSetValueExA (
|
|
IN PCSTR Category,
|
|
IN PCSTR Item, OPTIONAL
|
|
IN PCSTR Field, OPTIONAL
|
|
IN PCSTR Data, OPTIONAL
|
|
IN DWORD Val,
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
CHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyA (Key, Category, Item, Field, Data);
|
|
|
|
return PrivateMemDbSetValueA (Key, Val, 0, 0, Offset);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbSetValueExW (
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item, OPTIONAL
|
|
IN PCWSTR Field, OPTIONAL
|
|
IN PCWSTR Data, OPTIONAL
|
|
IN DWORD Val,
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
WCHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyW (Key, Category, Item, Field, Data);
|
|
|
|
return PrivateMemDbSetValueW (Key, Val, 0, 0, Offset);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbSetBinaryValueExA (
|
|
IN PCSTR Category,
|
|
IN PCSTR Item, OPTIONAL
|
|
IN PCSTR Field, OPTIONAL
|
|
IN PCBYTE BinaryData,
|
|
IN DWORD DataSize,
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
CHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyA (Key, Category, Item, Field, NULL);
|
|
|
|
return PrivateMemDbSetBinaryValueA (Key, BinaryData, DataSize, Offset);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbSetBinaryValueExW (
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item, OPTIONAL
|
|
IN PCWSTR Field, OPTIONAL
|
|
IN PCBYTE BinaryData,
|
|
IN DWORD DataSize,
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
WCHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyW (Key, Category, Item, Field, NULL);
|
|
|
|
return PrivateMemDbSetBinaryValueW (Key, BinaryData, DataSize, Offset);
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
MemDbBuildKeyFromOffset and MemDbBuildKeyFromOffsetEx create a key
|
|
string given the offset to the key, copying the string into the
|
|
supplied buffer. If a value pointer or user flag pointer is
|
|
provided, it is filled with the value or flag stored at the offset.
|
|
|
|
These functions 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 an offset points
|
|
to the string mycat\foo\bar, and StartLevel is 1, the function will
|
|
return foo\bar in Buffer.
|
|
|
|
Arguments:
|
|
|
|
Offset - Specifies the offset to the key as returned by MemDbSetValueEx.
|
|
|
|
Buffer - Specifies a MEMDB_MAX buffer.
|
|
|
|
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.
|
|
|
|
ValPtr - Specifies a variable that receives the value stored for the key
|
|
|
|
Return Value:
|
|
|
|
TRUE if the offset is valid and the function completed successfully, or
|
|
FALSE if the offset is not valid or an internal memory corruption was detected.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
MemDbBuildKeyFromOffsetA (
|
|
IN DWORD Offset,
|
|
OUT PSTR Buffer, OPTIONAL
|
|
IN DWORD StartLevel,
|
|
OUT PDWORD ValPtr OPTIONAL
|
|
)
|
|
{
|
|
WCHAR WideBuffer[MEMDB_MAX];
|
|
BOOL b;
|
|
|
|
b = MemDbBuildKeyFromOffsetW (
|
|
Offset,
|
|
WideBuffer,
|
|
StartLevel,
|
|
ValPtr
|
|
);
|
|
|
|
if (b) {
|
|
KnownSizeWtoA (Buffer, WideBuffer);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
MemDbBuildKeyFromOffsetW (
|
|
IN DWORD Offset,
|
|
OUT PWSTR Buffer, OPTIONAL
|
|
IN DWORD StartLevel,
|
|
OUT PDWORD ValPtr OPTIONAL
|
|
)
|
|
{
|
|
return MemDbBuildKeyFromOffsetExW (
|
|
Offset,
|
|
Buffer,
|
|
NULL,
|
|
StartLevel,
|
|
ValPtr,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
MemDbBuildKeyFromOffset and MemDbBuildKeyFromOffsetEx create a key
|
|
string given the offset to the key, copying the string into the
|
|
supplied buffer. If a value pointer or user flag pointer is
|
|
provided, it is filled with the value or flag stored at the offset.
|
|
|
|
These functions 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 an offset points
|
|
to the string mycat\foo\bar, and StartLevel is 1, the function will
|
|
return foo\bar in Buffer.
|
|
|
|
Arguments:
|
|
|
|
Offset - Specifies the offset to the key as returned by MemDbSetValueEx.
|
|
|
|
Buffer - Specifies a MEMDB_MAX buffer.
|
|
|
|
BufferLen - Receives the length of the string in characters, excluding the
|
|
terminating nul. If caller is using this for buffer allocation
|
|
size, double BufferLen.
|
|
|
|
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.
|
|
|
|
ValPtr - Specifies a variable that receives the value stored for the key
|
|
|
|
UserFlagPtr - Specifies a variable that receives the user flags stored for the
|
|
key
|
|
|
|
Return Value:
|
|
|
|
TRUE if the offset is valid and the function completed successfully, or
|
|
FALSE if the offset is not valid or an internal memory corruption was detected.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
MemDbBuildKeyFromOffsetExA (
|
|
IN DWORD Offset,
|
|
OUT PSTR Buffer, OPTIONAL
|
|
OUT PDWORD BufferLen, OPTIONAL
|
|
IN DWORD StartLevel,
|
|
OUT PDWORD ValPtr, OPTIONAL
|
|
OUT PDWORD UserFlagPtr OPTIONAL
|
|
)
|
|
{
|
|
WCHAR WideBuffer[MEMDB_MAX];
|
|
BOOL b;
|
|
|
|
b = MemDbBuildKeyFromOffsetExW (
|
|
Offset,
|
|
WideBuffer,
|
|
BufferLen,
|
|
StartLevel,
|
|
ValPtr,
|
|
UserFlagPtr
|
|
);
|
|
|
|
if (b) {
|
|
KnownSizeWtoA (Buffer, WideBuffer);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
MemDbBuildKeyFromOffsetExW (
|
|
IN DWORD Offset,
|
|
OUT PWSTR Buffer, OPTIONAL
|
|
OUT PDWORD BufferLen, OPTIONAL
|
|
IN DWORD StartLevel,
|
|
OUT PDWORD ValPtr, OPTIONAL
|
|
OUT PDWORD UserFlagPtr OPTIONAL
|
|
)
|
|
{
|
|
PWSTR p,s;
|
|
BYTE newDb = (BYTE) (Offset >> RESERVED_BITS);
|
|
|
|
if (Offset == INVALID_OFFSET) {
|
|
return FALSE;
|
|
}
|
|
|
|
SelectDatabase (newDb);
|
|
|
|
p = Buffer;
|
|
|
|
if (newDb != 0) {
|
|
if (StartLevel == 0) {
|
|
|
|
if (Buffer) {
|
|
s = g_db->Hive;
|
|
while (*s) {
|
|
*p++ = *s++;
|
|
}
|
|
*p++ = L'\\';
|
|
}
|
|
}
|
|
else {
|
|
StartLevel --;
|
|
}
|
|
}
|
|
|
|
return PrivateBuildKeyFromOffset (
|
|
StartLevel,
|
|
Offset & OFFSET_MASK,
|
|
p,
|
|
ValPtr,
|
|
UserFlagPtr,
|
|
BufferLen
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbEnumItemsA (
|
|
OUT PMEMDB_ENUMA pEnum,
|
|
IN PCSTR Category
|
|
)
|
|
{
|
|
CHAR Pattern[MEMDB_MAX];
|
|
|
|
if (!Category)
|
|
return FALSE;
|
|
|
|
wsprintfA (Pattern, "%s\\*", Category);
|
|
return MemDbEnumFirstValueA (pEnum, Pattern, MEMDB_THIS_LEVEL_ONLY, NO_FLAGS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbEnumItemsW (
|
|
OUT PMEMDB_ENUMW pEnum,
|
|
IN PCWSTR Category
|
|
)
|
|
{
|
|
WCHAR Pattern[MEMDB_MAX];
|
|
|
|
if (!Category)
|
|
return FALSE;
|
|
|
|
wsprintfW (Pattern, L"%s\\*", Category);
|
|
return MemDbEnumFirstValueW (pEnum, Pattern, MEMDB_THIS_LEVEL_ONLY, NO_FLAGS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbEnumFieldsA (
|
|
OUT PMEMDB_ENUMA pEnum,
|
|
IN PCSTR Category,
|
|
IN PCSTR Item OPTIONAL
|
|
)
|
|
{
|
|
CHAR Pattern[MEMDB_MAX];
|
|
|
|
if (!Category)
|
|
return MemDbEnumItemsA (pEnum, Item);
|
|
|
|
if (!Item)
|
|
return MemDbEnumItemsA (pEnum, Category);
|
|
|
|
wsprintfA (Pattern, "%s\\%s\\*", Category, Item);
|
|
return MemDbEnumFirstValueA (pEnum, Pattern, MEMDB_THIS_LEVEL_ONLY, NO_FLAGS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbEnumFieldsW (
|
|
OUT PMEMDB_ENUMW pEnum,
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item OPTIONAL
|
|
)
|
|
{
|
|
WCHAR Pattern[MEMDB_MAX];
|
|
|
|
if (!Category)
|
|
return MemDbEnumItemsW (pEnum, Item);
|
|
|
|
if (!Item)
|
|
return MemDbEnumItemsW (pEnum, Category);
|
|
|
|
wsprintfW (Pattern, L"%s\\%s\\*", Category, Item);
|
|
return MemDbEnumFirstValueW (pEnum, Pattern, MEMDB_THIS_LEVEL_ONLY, NO_FLAGS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetValueExA (
|
|
OUT PMEMDB_ENUMA pEnum,
|
|
IN PCSTR Category,
|
|
IN PCSTR Item, OPTIONAL
|
|
IN PCSTR Field OPTIONAL
|
|
)
|
|
{
|
|
CHAR Pattern[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyA (Pattern, Category, Item, Field, NULL);
|
|
if (*Pattern) {
|
|
AppendWackA (Pattern);
|
|
}
|
|
StringCatA (Pattern, "*");
|
|
|
|
return MemDbEnumFirstValueA (pEnum, Pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetValueExW (
|
|
OUT PMEMDB_ENUMW pEnum,
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item, OPTIONAL
|
|
IN PCWSTR Field OPTIONAL
|
|
)
|
|
{
|
|
WCHAR Pattern[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyW (Pattern, Category, Item, Field, NULL);
|
|
if (*Pattern) {
|
|
AppendWackW (Pattern);
|
|
}
|
|
StringCatW (Pattern, L"*");
|
|
|
|
return MemDbEnumFirstValueW (pEnum, Pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
MemDbGetEndpointValueA (
|
|
IN PCSTR Pattern,
|
|
IN PCSTR Item, OPTIONAL // used as the first variable arg to wsprintfA
|
|
OUT PSTR Buffer
|
|
)
|
|
{
|
|
CHAR Path[MEMDB_MAX];
|
|
MEMDB_ENUMA memdb_enum;
|
|
|
|
if (!Pattern) {
|
|
if (!Item)
|
|
return FALSE;
|
|
|
|
StringCopyA (Path, Item);
|
|
}
|
|
else {
|
|
if (!Item)
|
|
StringCopyA (Path, Pattern);
|
|
else
|
|
wsprintfA (Path, Pattern, Item);
|
|
}
|
|
|
|
if (!MemDbEnumFirstValueA (&memdb_enum, Path,
|
|
MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
|
|
Buffer[0] = 0;
|
|
return FALSE;
|
|
}
|
|
StringCopyA (Buffer, memdb_enum.szName);
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetEndpointValueW (
|
|
IN PCWSTR Pattern,
|
|
IN PCWSTR Item, OPTIONAL
|
|
OUT PWSTR Buffer
|
|
)
|
|
{
|
|
WCHAR Path[MEMDB_MAX];
|
|
MEMDB_ENUMW memdb_enum;
|
|
|
|
if (!Pattern) {
|
|
if (!Item)
|
|
return FALSE;
|
|
|
|
StringCopyW (Path, Item);
|
|
}
|
|
else {
|
|
if (!Item)
|
|
StringCopyW (Path, Pattern);
|
|
else
|
|
wsprintfW (Path, Pattern, Item);
|
|
}
|
|
|
|
if (!MemDbEnumFirstValueW (&memdb_enum, Path,
|
|
MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
|
|
Buffer[0] = 0;
|
|
return FALSE;
|
|
}
|
|
StringCopyW (Buffer, memdb_enum.szName);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetEndpointValueExA (
|
|
IN PCSTR Category,
|
|
IN PCSTR Item, OPTIONAL
|
|
IN PCSTR Field, OPTIONAL
|
|
OUT PSTR Buffer
|
|
)
|
|
{
|
|
CHAR Path[MEMDB_MAX];
|
|
MEMDB_ENUMA memdb_enum;
|
|
|
|
MemDbBuildKeyA (Path, Category, Item, Field, NULL);
|
|
if (*Path) {
|
|
AppendWackA (Path);
|
|
}
|
|
StringCatA (Path, "*");
|
|
|
|
|
|
if (!MemDbEnumFirstValueA (&memdb_enum, Path,
|
|
MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
|
|
Buffer[0] = 0;
|
|
return FALSE;
|
|
}
|
|
strcpy (Buffer, memdb_enum.szName);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
MemDbGetEndpointValueExW (
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item, OPTIONAL
|
|
IN PCWSTR Field, OPTIONAL
|
|
OUT PWSTR Buffer
|
|
)
|
|
{
|
|
WCHAR Path[MEMDB_MAX];
|
|
MEMDB_ENUMW memdb_enum;
|
|
|
|
MemDbBuildKeyW (Path, Category, Item, Field, NULL);
|
|
if (*Path) {
|
|
AppendWackW (Path);
|
|
}
|
|
StringCatW (Path, L"*");
|
|
|
|
if (!MemDbEnumFirstValueW (&memdb_enum, Path,
|
|
MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
|
|
Buffer[0] = 0;
|
|
return FALSE;
|
|
}
|
|
StringCopyW (Buffer, memdb_enum.szName);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetOffsetW(
|
|
IN PCWSTR Key,
|
|
OUT PDWORD Offset
|
|
)
|
|
{
|
|
BOOL b;
|
|
DWORD keyOffset;
|
|
|
|
keyOffset = FindKey (Key);
|
|
if (keyOffset == INVALID_OFFSET) {
|
|
b = FALSE;
|
|
}
|
|
else {
|
|
b = TRUE;
|
|
*Offset = keyOffset;
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetOffsetA (
|
|
IN PCSTR Key,
|
|
OUT PDWORD Offset
|
|
)
|
|
{
|
|
|
|
PCWSTR wstr;
|
|
BOOL b;
|
|
|
|
wstr = ConvertAtoW (Key);
|
|
if (wstr) {
|
|
b = MemDbGetOffsetW (wstr,Offset);
|
|
FreeConvertedStr (wstr);
|
|
}
|
|
else {
|
|
b = FALSE;
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetOffsetExW (
|
|
IN PCWSTR Category,
|
|
IN PCWSTR Item, OPTIONAL
|
|
IN PCWSTR Field, OPTIONAL
|
|
IN PCWSTR Data, OPTIONAL
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
WCHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyW(Key,Category,Item,Field,Data);
|
|
|
|
return MemDbGetOffsetW(Key,Offset);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MemDbGetOffsetExA (
|
|
IN PCSTR Category,
|
|
IN PCSTR Item, OPTIONAL
|
|
IN PCSTR Field, OPTIONAL
|
|
IN PCSTR Data, OPTIONAL
|
|
OUT PDWORD Offset OPTIONAL
|
|
)
|
|
{
|
|
CHAR Key[MEMDB_MAX];
|
|
|
|
MemDbBuildKeyA(Key,Category,Item,Field,Data);
|
|
|
|
return MemDbGetOffsetA(Key,Offset);
|
|
}
|
|
|
|
|
|
|
|
|