windows-nt/Source/XPSP1/NT/windows/winstate/cobra/utils/memdb/keydata.c
2020-09-26 16:20:57 +08:00

1302 lines
31 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
keydata.c
Abstract:
Routines that manage data for the memdb key structures.
Author:
Matthew Vanderzee (mvander) 13-Aug-1999
Revision History:
--*/
#include "pch.h"
#include "memdbp.h"
//
// KeyStruct Data Functions
//
BOOL
KeyStructSetValue (
IN UINT KeyIndex,
IN UINT Value
)
/*++
Routine Description:
sets the value for a key
Arguments:
KeyIndex - index of key
Value - value to put in key
Return Value:
TRUE if successful
--*/
{
PKEYSTRUCT KeyStruct;
KeyStruct = GetKeyStruct(KeyIndex);
MYASSERT(KeyStruct);
KeyStruct->Value = Value;
KeyStruct->DataFlags |= DATAFLAG_VALUE;
return TRUE;
}
BOOL
KeyStructSetFlags (
IN UINT KeyIndex,
IN BOOL ReplaceFlags,
IN UINT SetFlags,
IN UINT ClearFlags
)
/*++
Routine Description:
sets the flags for a key
Arguments:
KeyIndex - index of key
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:
TRUE if successful, FALSE otherwise.
--*/
{
PKEYSTRUCT KeyStruct;
KeyStruct = GetKeyStruct(KeyIndex);
MYASSERT(KeyStruct);
if (KeyStruct->DataFlags & DATAFLAG_FLAGS) {
if (ReplaceFlags) {
KeyStruct->Flags = SetFlags;
} else {
KeyStruct->Flags &= ~ClearFlags;
KeyStruct->Flags |= SetFlags;
}
} else {
KeyStruct->Flags = SetFlags;
KeyStruct->DataFlags |= DATAFLAG_FLAGS;
}
return TRUE;
}
// LINT - in the next function keystruct is thought to be possibly NULL.
// If we examine the code we'll see that this is not a possibility so...
//lint -save -e794
UINT g_TotalData = 0;
UINT
pAllocateNewDataStruct (
IN UINT DataSize,
IN UINT AltDataSize
)
/*++
Routine Description:
pAllocateNewDataStruct allocates a block of memory in the single
heap, for holding a data structure.
Arguments:
DataSize - Size of the binary data that needs to be stored here
Return Value:
An Index to the new structure.
--*/
{
UINT size;
PKEYSTRUCT keyStruct = NULL;
UINT offset;
UINT prevDel;
UINT result;
MYASSERT (g_CurrentDatabase);
size = DataSize + KEYSTRUCT_SIZE;
//
// Look for free block
//
prevDel = INVALID_OFFSET;
offset = g_CurrentDatabase->FirstKeyDeleted;
while (offset != INVALID_OFFSET) {
keyStruct = GetKeyStructFromOffset (offset);
MYASSERT (keyStruct);
if ((keyStruct->Size >= size) && (keyStruct->Size < (size + ALLOC_TOLERANCE))) {
break;
}
prevDel = offset;
offset = keyStruct->NextDeleted;
}
if (offset == INVALID_OFFSET) {
//
// We could not find one so we need to allocate a new block
//
g_TotalData ++;
offset = DatabaseAllocBlock (size + AltDataSize);
if (offset == INVALID_OFFSET) {
return INVALID_OFFSET;
}
#ifdef DEBUG
//
// if we are in debug mode, and we are using debug structs, set
// pointer normally and set Signature DWORD. if we are not using
// debug structs, then set pointer to 4 bytes below actual offset,
// so all members are shifted down.
//
if (g_UseDebugStructs) {
keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR (offset);
keyStruct->Signature = KEYSTRUCT_SIGNATURE;
} else {
keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR (offset - KEYSTRUCT_HEADER_SIZE);
}
#else
keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR(offset);
#endif
keyStruct->Size = size + AltDataSize;
} else {
//
// Delink free block if recovering free space
//
if (prevDel != INVALID_OFFSET) {
GetKeyStructFromOffset (prevDel)->NextDeleted = keyStruct->NextDeleted;
} else {
g_CurrentDatabase->FirstKeyDeleted = keyStruct->NextDeleted;
}
#ifdef DEBUG
keyStruct->KeyFlags &= ~KSF_DELETED;
#endif
}
//
// Init new block
//
keyStruct->DataSize = DataSize;
keyStruct->DataStructIndex = INVALID_OFFSET;
keyStruct->NextLevelTree = INVALID_OFFSET;
keyStruct->PrevLevelIndex = INVALID_OFFSET;
keyStruct->Flags = 0;
keyStruct->KeyFlags = KSF_DATABLOCK;
keyStruct->DataFlags = 0;
result = AddKeyOffsetToBuffer (offset);
return result;
}
//lint -restore
UINT
KeyStructAddBinaryData (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
KeyStructAddBinaryData adds a certain type of binary data to a key
if it doesn't exist yet. If it does, the function fails.
Arguments:
KeyIndex - index of key
Type - type of data
Instance - instance of data
Data - pointer to the data
DataSize - size of data
Return Value:
A valid data handle if successfull, INVALID_OFFSET otherwise.
--*/
{
PKEYSTRUCT prevStruct,dataStruct,nextStruct,keyStruct;
UINT dataIndex, prevIndex;
BOOL found = FALSE;
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
// check to see if the data is already there
dataIndex = keyStruct->DataStructIndex;
prevIndex = KeyIndex;
prevStruct = keyStruct;
while (dataIndex != INVALID_OFFSET) {
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
) {
found = TRUE;
break;
}
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
(((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
)
) {
break;
}
prevIndex = dataIndex;
prevStruct = dataStruct;
dataIndex = dataStruct->DataStructIndex;
}
if (found) {
return INVALID_OFFSET;
}
dataIndex = pAllocateNewDataStruct (DataSize, 0);
if (dataIndex == INVALID_OFFSET) {
return INVALID_OFFSET;
}
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
prevStruct = GetKeyStruct (prevIndex);
MYASSERT (prevStruct);
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
keyStruct->DataFlags |= Type;
dataStruct->DataFlags |= Type;
dataStruct->DataFlags |= Instance;
CopyMemory (dataStruct->Data, Data, DataSize);
dataStruct->DataStructIndex = prevStruct->DataStructIndex;
dataStruct->PrevLevelIndex = prevIndex;
prevStruct->DataStructIndex = dataIndex;
if (dataStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
MYASSERT (nextStruct);
nextStruct->PrevLevelIndex = dataIndex;
}
return dataIndex;
}
// LINT - in the next function keystruct is thought to be possibly NULL.
// If we examine the code we'll see that this is not a possibility so...
//lint -save -e771
UINT
KeyStructGrowBinaryData (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
KeyStructGrowBinaryData appends a certain type of binary data to a key
if it does exist. If it doesn't, the new data is added.
Arguments:
KeyIndex - index of key
Type - type of data
Instance - instance of data
Data - pointer to the data
DataSize - size of data
Return Value:
A valid data handle if successfull, INVALID_OFFSET otherwise.
--*/
{
PKEYSTRUCT prevStruct;
PKEYSTRUCT dataStruct;
PKEYSTRUCT keyStruct;
PKEYSTRUCT nextStruct;
PKEYSTRUCT newStruct;
UINT dataIndex;
UINT newIndex;
UINT prevIndex;
BOOL found = FALSE;
MYASSERT (g_CurrentDatabase);
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
// check to see if the data is already there
dataIndex = keyStruct->DataStructIndex;
prevStruct = keyStruct;
prevIndex = KeyIndex;
while (dataIndex != INVALID_OFFSET) {
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
) {
found = TRUE;
break;
}
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
(((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
)
) {
break;
}
prevStruct = dataStruct;
prevIndex = dataIndex;
dataIndex = dataStruct->DataStructIndex;
}
if ((dataIndex == INVALID_OFFSET) || (!found)) {
return KeyStructAddBinaryData (KeyIndex, Type, Instance, Data, DataSize);
}
if (dataStruct->Size >= KEYSTRUCT_SIZE + DataSize + dataStruct->DataSize) {
CopyMemory (dataStruct->Data + dataStruct->DataSize, Data, DataSize);
dataStruct->DataSize += DataSize;
return dataIndex;
} else {
newIndex = pAllocateNewDataStruct (DataSize + dataStruct->DataSize, min (dataStruct->DataSize, 65536));
if (newIndex == INVALID_OFFSET) {
return INVALID_OFFSET;
}
// now we need to reget all keystructs used so far because the database
// might have moved
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
prevStruct = GetKeyStruct (prevIndex);
MYASSERT (prevStruct);
newStruct = GetKeyStruct (newIndex);
MYASSERT (newStruct);
newStruct->DataSize = dataStruct->DataSize + DataSize;
newStruct->DataFlags = dataStruct->DataFlags;
newStruct->DataStructIndex = dataStruct->DataStructIndex;
newStruct->PrevLevelIndex = dataStruct->PrevLevelIndex;
CopyMemory (newStruct->Data, dataStruct->Data, dataStruct->DataSize);
CopyMemory (newStruct->Data + dataStruct->DataSize, Data, DataSize);
prevStruct->DataStructIndex = newIndex;
if (newStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (newStruct->DataStructIndex);
MYASSERT (nextStruct);
nextStruct->PrevLevelIndex = newIndex;
}
// now simply remove the block
//
// Donate block to free space
//
dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (dataIndex);
#ifdef DEBUG
dataStruct->KeyFlags |= KSF_DELETED;
#endif
// let's empty the keystruct (for better compression)
ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
RemoveKeyOffsetFromBuffer (dataIndex);
return newIndex;
}
}
//lint -restore
UINT
KeyStructGrowBinaryDataByIndex (
IN UINT OldIndex,
IN PCBYTE Data,
IN UINT DataSize
)
/*++
Routine Description:
KeyStructGrowBinaryDataByIndex appends a certain type of binary data to
an existing structure identified by OldIndex. The old structure is
deleted and a new one is allocated holding both old and new data.
Arguments:
OldIndex - index of data
Data - pointer to the data
DataSize - size of data
Return Value:
A valid data index if successfull, INVALID_OFFSET otherwise.
--*/
{
UINT newIndex;
PKEYSTRUCT oldStruct, newStruct, prevStruct, nextStruct;
MYASSERT (g_CurrentDatabase);
oldStruct = GetKeyStruct (OldIndex);
MYASSERT (oldStruct);
if (oldStruct->Size >= KEYSTRUCT_SIZE + DataSize + oldStruct->DataSize) {
CopyMemory (oldStruct->Data + oldStruct->DataSize, Data, DataSize);
oldStruct->DataSize += DataSize;
return OldIndex;
} else {
newIndex = pAllocateNewDataStruct (DataSize + oldStruct->DataSize, min (oldStruct->DataSize, 65536));
if (newIndex == INVALID_OFFSET) {
return INVALID_OFFSET;
}
// now we need to reget all keystructs used so far because the database
// might have moved
oldStruct = GetKeyStruct (OldIndex);
MYASSERT (oldStruct);
newStruct = GetKeyStruct (newIndex);
MYASSERT (newStruct);
newStruct->DataStructIndex = oldStruct->DataStructIndex;
newStruct->PrevLevelIndex = oldStruct->PrevLevelIndex;
newStruct->DataFlags = oldStruct->DataFlags;
CopyMemory (newStruct->Data, oldStruct->Data, oldStruct->DataSize);
CopyMemory (newStruct->Data + oldStruct->DataSize, Data, DataSize);
prevStruct = GetKeyStruct (newStruct->PrevLevelIndex);
MYASSERT (prevStruct);
prevStruct->DataStructIndex = newIndex;
if (newStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (newStruct->DataStructIndex);
MYASSERT (nextStruct);
nextStruct->PrevLevelIndex = newIndex;
}
// now simply remove the block
//
// Donate block to free space
//
oldStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (OldIndex);
#ifdef DEBUG
oldStruct->KeyFlags |= KSF_DELETED;
#endif
// let's empty the keystruct (for better compression)
ZeroMemory (oldStruct->Data, oldStruct->Size - KEYSTRUCT_SIZE);
RemoveKeyOffsetFromBuffer (OldIndex);
return newIndex;
}
}
// LINT - in the next function prevstruct is thought to be possibly not initialized.
// If we examine the code we'll see that this is not a possibility so...
//lint -save -e771
BOOL
KeyStructDeleteBinaryData (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance
)
/*++
Routine Description:
KeyStructDeleteBinaryData deletes a certain type of binary data from a key
if it exists. If it doesn't, the function will simply return success.
Arguments:
KeyIndex - index of key
Type - type of data
Instance - instance of data
Return Value:
TRUE if successfull, FALSE if not.
--*/
{
PKEYSTRUCT prevStruct, nextStruct, dataStruct, keyStruct;
UINT dataIndex, prevIndex;
BOOL found = FALSE;
UINT typeInstances = 0;
MYASSERT (g_CurrentDatabase);
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
if (!(keyStruct->DataFlags & Type)) {
// no such type of data, exiting
return TRUE;
}
// check to see if the data is already there
dataIndex = keyStruct->DataStructIndex;
prevIndex = KeyIndex;
prevStruct = keyStruct;
while (dataIndex != INVALID_OFFSET) {
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
if ((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) {
typeInstances ++;
if ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance) {
found = TRUE;
//
// now let's see if we have more instances of this binary type
//
if (dataStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
if ((nextStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) {
typeInstances ++;
}
}
break;
} else if ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance) {
break;
}
} else if ((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) {
break;
}
prevIndex = dataIndex;
prevStruct = dataStruct;
dataIndex = dataStruct->DataStructIndex;
}
if ((dataIndex == INVALID_OFFSET) || (!found)) {
return TRUE;
}
// remove the linkage
prevStruct->DataStructIndex = dataStruct->DataStructIndex;
if (dataStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
MYASSERT (nextStruct);
nextStruct->PrevLevelIndex = prevIndex;
}
// now simply remove the block
//
// Donate block to free space
//
dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (dataIndex);
#ifdef DEBUG
dataStruct->KeyFlags |= KSF_DELETED;
#endif
// let's empty the keystruct (for better compression)
ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
RemoveKeyOffsetFromBuffer (dataIndex);
//
// finally, fix the keystruct if this was the only instance of this type
//
MYASSERT (typeInstances >= 1);
if (typeInstances == 1) {
keyStruct->DataFlags &= ~Type;
}
return TRUE;
}
//lint -restore
BOOL
KeyStructDeleteBinaryDataByIndex (
IN UINT DataIndex
)
/*++
Routine Description:
KeyStructDeleteBinaryDataByIndex deletes a certain type of binary data from a key.
Arguments:
DataIndex - index of data
Return Value:
TRUE if successfull, FALSE if not.
--*/
{
PKEYSTRUCT prevStruct, nextStruct, dataStruct, keyStruct;
BYTE type = 0;
UINT typeInstances = 0;
MYASSERT (g_CurrentDatabase);
dataStruct = GetKeyStruct (DataIndex);
MYASSERT (dataStruct);
type = dataStruct->DataFlags & DATAFLAG_BINARYMASK;
typeInstances ++;
prevStruct = GetKeyStruct (dataStruct->PrevLevelIndex);
MYASSERT (prevStruct);
if ((prevStruct->DataFlags & DATAFLAG_BINARYMASK) == type) {
typeInstances ++;
}
prevStruct->DataStructIndex = dataStruct->DataStructIndex;
if (dataStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
MYASSERT (nextStruct);
if ((nextStruct->DataFlags & DATAFLAG_BINARYMASK) == type) {
typeInstances ++;
}
nextStruct->PrevLevelIndex = dataStruct->PrevLevelIndex;
}
// now simply remove the block
//
// Donate block to free space
//
dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (DataIndex);
#ifdef DEBUG
dataStruct->KeyFlags |= KSF_DELETED;
#endif
// let's empty the keystruct (for better compression)
ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
RemoveKeyOffsetFromBuffer (DataIndex);
//
// finally, fix the keystruct if this was the only instance of this type
//
MYASSERT (typeInstances >= 1);
if (typeInstances == 1) {
// first we need to find the key starting with the current database struct
keyStruct = dataStruct;
while (keyStruct->KeyFlags & KSF_DATABLOCK) {
// still a datablock
if (keyStruct->PrevLevelIndex == INVALID_OFFSET) {
// something is wrong, the first level is a datablock??
break;
}
keyStruct = GetKeyStruct (keyStruct->PrevLevelIndex);
MYASSERT (keyStruct);
}
if (!(keyStruct->KeyFlags & KSF_DATABLOCK)) {
keyStruct->DataFlags &= ~type;
}
}
return TRUE;
}
UINT
KeyStructReplaceBinaryDataByIndex (
IN UINT OldIndex,
IN PCBYTE Data,
IN UINT DataSize
)
{
UINT newIndex;
PKEYSTRUCT oldStruct, newStruct, prevStruct, nextStruct;
MYASSERT (g_CurrentDatabase);
// NTRAID#NTBUG9-153308-2000/08/01-jimschm Optimize this by keeping the current structure is big enough.
newIndex = pAllocateNewDataStruct (DataSize, 0);
if (newIndex == INVALID_OFFSET) {
return INVALID_OFFSET;
}
oldStruct = GetKeyStruct (OldIndex);
MYASSERT (oldStruct);
newStruct = GetKeyStruct (newIndex);
MYASSERT (newStruct);
newStruct->DataStructIndex = oldStruct->DataStructIndex;
newStruct->PrevLevelIndex = oldStruct->PrevLevelIndex;
newStruct->DataFlags = oldStruct->DataFlags;
CopyMemory (newStruct->Data, Data, DataSize);
prevStruct = GetKeyStruct (newStruct->PrevLevelIndex);
MYASSERT (prevStruct);
prevStruct->DataStructIndex = newIndex;
if (newStruct->DataStructIndex != INVALID_OFFSET) {
nextStruct = GetKeyStruct (newStruct->DataStructIndex);
MYASSERT (nextStruct);
nextStruct->PrevLevelIndex = newIndex;
}
// now simply remove the block
//
// Donate block to free space
//
oldStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (OldIndex);
#ifdef DEBUG
oldStruct->KeyFlags |= KSF_DELETED;
#endif
// let's empty the keystruct (for better compression)
ZeroMemory (oldStruct->Data, oldStruct->Size - KEYSTRUCT_SIZE);
RemoveKeyOffsetFromBuffer (OldIndex);
return newIndex;
}
// LINT - in the next function prevstruct is thought to be possibly not initialized.
// If we examine the code we'll see that this is not a possibility so...
//lint -save -e771
PBYTE
KeyStructGetBinaryData (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
OUT PUINT DataSize,
OUT PUINT DataIndex //OPTIONAL
)
{
PKEYSTRUCT dataStruct,keyStruct;
UINT dataIndex;
BOOL found = FALSE;
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
if (!(keyStruct->DataFlags & Type)) {
return NULL;
}
// check to see if the data is already there
dataIndex = keyStruct->DataStructIndex;
while (dataIndex != INVALID_OFFSET) {
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
) {
found = TRUE;
break;
}
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
(((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
)
) {
break;
}
dataIndex = dataStruct->DataStructIndex;
}
if ((dataIndex == INVALID_OFFSET) || (!found)) {
return NULL;
}
if (DataSize) {
*DataSize = dataStruct->DataSize;
}
if (DataIndex) {
*DataIndex = dataIndex;
}
return dataStruct->Data;
}
//lint -restore
PBYTE
KeyStructGetBinaryDataByIndex (
IN UINT DataIndex,
OUT PUINT DataSize
)
{
PKEYSTRUCT dataStruct;
dataStruct = GetKeyStruct (DataIndex);
MYASSERT (dataStruct);
if (DataSize) {
*DataSize = dataStruct->DataSize;
}
return dataStruct->Data;
}
UINT
KeyStructGetDataIndex (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance
)
/*++
Routine Description:
KeyStructGetDataIndex looks for a certain type of data and returns it's index
if it exists. If it doesn't, the function will simply return INVALID_OFFSET.
Arguments:
KeyIndex - index of key
Type - type of data
Instance - instance of data
Return Value:
A data index if successfull, INVALID_OFFSET if not.
--*/
{
PKEYSTRUCT keyStruct, dataStruct;
UINT dataIndex;
BOOL found = FALSE;
keyStruct = GetKeyStruct (KeyIndex);
MYASSERT (keyStruct);
if (!(keyStruct->DataFlags & Type)) {
return INVALID_OFFSET;
}
// check to see if we have the data there
dataIndex = keyStruct->DataStructIndex;
while (dataIndex != INVALID_OFFSET) {
dataStruct = GetKeyStruct (dataIndex);
MYASSERT (dataStruct);
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
) {
found = TRUE;
break;
}
if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
(((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
)
) {
break;
}
dataIndex = dataStruct->DataStructIndex;
}
if (!found) {
return INVALID_OFFSET;
}
return dataIndex;
}
DATAHANDLE
KeyStructAddLinkage (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
BOOL toBeAdded = TRUE;
UINT result = INVALID_OFFSET;
PUINT linkArray;
UINT linkSize;
if (!AllowDuplicates) {
//
// check to see if we already have this linkage added
//
linkArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &linkSize, &result);
if (linkArray) {
while (linkSize >= SIZEOF (UINT)) {
if (*linkArray == Linkage) {
toBeAdded = FALSE;
break;
}
linkArray ++;
linkSize -= SIZEOF (UINT);
}
}
}
if (toBeAdded) {
if (result != INVALID_OFFSET) {
result = KeyStructGrowBinaryDataByIndex (result, (PBYTE)(&Linkage), SIZEOF (UINT));
} else {
result = KeyStructGrowBinaryData (KeyIndex, Type, Instance, (PBYTE)(&Linkage), SIZEOF (UINT));
}
}
return result;
}
DATAHANDLE
KeyStructAddLinkageByIndex (
IN UINT DataIndex,
IN UINT Linkage,
IN BOOL AllowDuplicates
)
{
BOOL toBeAdded = TRUE;
UINT result = INVALID_OFFSET;
PUINT linkArray;
UINT linkSize;
if (!AllowDuplicates) {
//
// check to see if we already have this linkage added
//
linkArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &linkSize);
if (linkArray) {
while (linkSize >= SIZEOF (UINT)) {
if (*linkArray == Linkage) {
toBeAdded = FALSE;
break;
}
linkArray ++;
linkSize -= SIZEOF (UINT);
}
}
}
if (toBeAdded) {
result = KeyStructGrowBinaryDataByIndex (DataIndex, (PBYTE)(&Linkage), SIZEOF (UINT));
} else {
result = DataIndex;
}
return result;
}
BOOL
KeyStructDeleteLinkage (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
BOOL checking = TRUE;
BOOL result = FALSE;
PUINT srcArray, destArray, newArray;
UINT srcSize, newSize;
UINT dataIndex;
srcArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &srcSize, &dataIndex);
if (srcArray) {
newArray = MemDbGetMemory (srcSize);
if (newArray) {
destArray = newArray;
newSize = 0;
while (srcSize >= SIZEOF (UINT)) {
if ((*srcArray == Linkage) &&
(checking)
) {
if (FirstOnly) {
checking = FALSE;
}
} else {
*destArray = *srcArray;
newSize += SIZEOF (UINT);
destArray ++;
}
srcArray ++;
srcSize -= SIZEOF (UINT);
}
if (newSize) {
result = (KeyStructReplaceBinaryDataByIndex (dataIndex, (PBYTE)newArray, newSize) != INVALID_OFFSET);
} else {
result = KeyStructDeleteBinaryDataByIndex (dataIndex);
}
MemDbReleaseMemory (newArray);
}
}
return result;
}
BOOL
KeyStructDeleteLinkageByIndex (
IN UINT DataIndex,
IN UINT Linkage,
IN BOOL FirstOnly
)
{
BOOL checking = TRUE;
BOOL result = FALSE;
PUINT srcArray, destArray, newArray;
UINT srcSize, newSize;
srcArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &srcSize);
if (srcArray) {
newArray = MemDbGetMemory (srcSize);
if (newArray) {
destArray = newArray;
newSize = 0;
while (srcSize >= SIZEOF (UINT)) {
if ((*srcArray == Linkage) &&
(checking)
) {
if (FirstOnly) {
checking = FALSE;
}
} else {
*destArray = *srcArray;
newSize += SIZEOF (UINT);
destArray ++;
}
srcArray ++;
srcSize -= SIZEOF (UINT);
}
if (newSize) {
result = (KeyStructReplaceBinaryDataByIndex (DataIndex, (PBYTE)newArray, newSize) != INVALID_OFFSET);
} else {
result = KeyStructDeleteBinaryDataByIndex (DataIndex);
}
MemDbReleaseMemory (newArray);
}
}
return result;
}
BOOL
KeyStructTestLinkage (
IN UINT KeyIndex,
IN BYTE Type,
IN BYTE Instance,
IN KEYHANDLE Linkage
)
{
BOOL result = FALSE;
PUINT srcArray;
UINT srcSize = 0;
srcArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &srcSize, NULL);
while (srcSize >= SIZEOF (KEYHANDLE)) {
if (*srcArray == Linkage) {
result = TRUE;
break;
}
srcSize -= SIZEOF (KEYHANDLE);
srcArray++;
}
return result;
}
BOOL
KeyStructTestLinkageByIndex (
IN UINT DataIndex,
IN UINT Linkage
)
{
BOOL result = FALSE;
PUINT srcArray;
UINT srcSize;
srcArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &srcSize);
while (srcSize >= SIZEOF (UINT)) {
if (*srcArray == Linkage) {
result = TRUE;
break;
}
srcSize -= SIZEOF (UINT);
srcArray++;
}
return result;
}
BOOL
KeyStructGetValue (
IN PKEYSTRUCT KeyStruct,
OUT PUINT Value
)
{
if (!Value) {
return TRUE;
}
if (!(KeyStruct->DataFlags & DATAFLAG_VALUE)) {
//
// there is no value, but we still set output to
// zero and return TRUE
//
*Value = 0;
return TRUE;
}
*Value = KeyStruct->Value;
return TRUE;
}
BOOL
KeyStructGetFlags (
IN PKEYSTRUCT KeyStruct,
OUT PUINT Flags
)
{
if (!Flags) {
return TRUE;
}
if (!(KeyStruct->DataFlags & DATAFLAG_FLAGS)) {
//
// there are no flags, but we still set output to
// zero and return TRUE
//
*Flags = 0;
return TRUE;
}
*Flags = KeyStruct->Flags;
return TRUE;
}
VOID
KeyStructFreeAllData (
PKEYSTRUCT KeyStruct
)
/*++
Routine Description:
KeyStructFreeDataBlock frees a data block and resets the
the KSF data flags, if the key struct has a data block allocated.
--*/
{
// NTRAID#NTBUG9-153308-2000/08/01-jimschm Reimplement free routine
//KeyStructFreeData (KeyStruct);
KeyStruct->Value = 0;
KeyStruct->Flags = 0;
KeyStruct->DataFlags &= ~DATAFLAG_VALUE;
KeyStruct->DataFlags &= ~DATAFLAG_FLAGS;
}