/*++ 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; }