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

331 lines
7.8 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
offsetbuf.c
Abstract:
Routines that manage the keystruct offsetbuffer
Author:
Matthew Vanderzee (mvander) 13-Aug-1999
Revision History:
--*/
#include "pch.h"
#include "memdbp.h"
//
// we store index flags in the top two bits of the UINT offsets in
// the buffer, because offsets never have a top two bits set
//
// if the user links a key, we want to mark that index, so we
// dont add it to the deleted index list. if a key is linked,
// and then deleted, we want to keep that key's index pointing
// to INVALID_OFFSET, instead of reusing the index.
//
// if a key is moved, we replace the key's original offset with
// the index of the new key's offset. then we flag that the
// offset has been redirected.
//
// if an index is marked or redirected, when that key is deleted,
// we just set the true index (the index that any redirected indices
// point to) to INVALID_OFFSET.
//
#define INDEX_FLAG_BITS 2
#define INDEX_MOVE_BITS_TO_POS(bits) (((UINT)(bits)) << (8*sizeof(UINT)-INDEX_FLAG_BITS))
#define INDEX_MARKED_FLAG INDEX_MOVE_BITS_TO_POS(0x01)
#define INDEX_REDIRECTED_FLAG INDEX_MOVE_BITS_TO_POS(0x02)
#define INDEX_FLAG_MASK INDEX_MOVE_BITS_TO_POS(0x03)
#define GET_UINT_AT_INDEX(index) (*(PUINT)(g_CurrentDatabase->OffsetBuffer.Buf + (index)))
#define SET_UINT_AT_INDEX(index, offset) ((*(PUINT)(g_CurrentDatabase->OffsetBuffer.Buf + (index)))=(offset))
#define MARK_INDEX(Index) (GET_UINT_AT_INDEX(Index) |= INDEX_MARKED_FLAG)
#define IS_INDEX_MARKED(Index) ((BOOL)(GET_UINT_AT_INDEX(Index) & INDEX_FLAG_MASK))
VOID
MarkIndexList (
IN PUINT IndexList,
IN UINT IndexListSize
)
{
BYTE CurrentDatabase;
UINT i;
CurrentDatabase = g_CurrentDatabaseIndex;
//
// iterate through whole list, switch to correct
// database, and mark list as linked.
//
for (i = 0; i < IndexListSize; i++) {
SelectDatabase (GET_DATABASE (IndexList[i]));
MARK_INDEX (GET_INDEX (IndexList[i]));
#ifdef _DEBUG
if (GET_UINT_AT_INDEX (GET_INDEX (IndexList[i])) != INVALID_OFFSET) {
MYASSERT (GetKeyStruct (GET_INDEX (IndexList[i])));
}
#endif
}
SelectDatabase (CurrentDatabase);
}
VOID
RedirectKeyIndex (
IN UINT Index,
IN UINT TargetIndex
)
/*++
Routine Description:
sets the offset at Index to TargetIndex, with INDEX_REDIRECTED_FLAG
set in the top byte. also, we mark TargetIndex, indicating it has
something redirected to it.
--*/
{
MYASSERT(!(Index & INDEX_FLAG_MASK));
MYASSERT(!(TargetIndex & INDEX_FLAG_MASK));
MYASSERT(!(GET_UINT_AT_INDEX(Index) & INDEX_REDIRECTED_FLAG));
MYASSERT(!(GET_UINT_AT_INDEX(TargetIndex) & INDEX_REDIRECTED_FLAG));
SET_UINT_AT_INDEX(Index, TargetIndex | INDEX_REDIRECTED_FLAG);
MARK_INDEX(TargetIndex);
}
UINT
pGetTrueIndex (
IN UINT Index
)
/*++
Routine Description:
takes and index and returns the true index, which is the index that
actually holds the offset of the keystruct. indexes with the
redirected flag hold the index they are redirected to.
--*/
{
MYASSERT(!(Index & INDEX_FLAG_MASK));
while (GET_UINT_AT_INDEX(Index) & INDEX_REDIRECTED_FLAG) {
Index = GET_UINT_AT_INDEX(Index) & ~INDEX_FLAG_MASK;
}
return Index;
}
UINT
KeyIndexToOffset (
IN UINT Index
)
/*++
Routine Description:
KeyIndexToOffset converts an index of a Keystruct
(in g_CurrentDatabase->OffsetBuffer) to the Keystruct's offset in the database.
Arguments:
Index - index in OffsetBuffer. must be valid
Return Value:
Offset of Keystruct.
--*/
{
MYASSERT(!(Index & INDEX_FLAG_MASK));
MYASSERT (Index <= g_CurrentDatabase->OffsetBuffer.End-sizeof(UINT));
MYASSERT (g_CurrentDatabase);
if (!g_CurrentDatabase->OffsetBuffer.Buf) {
return INVALID_OFFSET;
}
do {
Index = GET_UINT_AT_INDEX(Index);
if (Index == INVALID_OFFSET) {
return INVALID_OFFSET;
}
if (!(Index & INDEX_REDIRECTED_FLAG)) {
//
// we have found a non-redirected index, so check
// that this points to a real keystruct, and return it.
//
MYASSERT(GetKeyStructFromOffset(Index & ~INDEX_FLAG_MASK));
return Index & ~INDEX_FLAG_MASK;
}
Index &= ~INDEX_FLAG_MASK;
MYASSERT (Index <= g_CurrentDatabase->OffsetBuffer.End-sizeof(UINT));
} while (TRUE); //lint !e506
}
UINT
AddKeyOffsetToBuffer (
IN UINT Offset
)
/*++
Routine Description:
gets a space in g_CurrentDatabase->OffsetBuffer and sets it to Offset
Arguments:
Offset - value to put in buffer space
Return Value:
Index of space in g_CurrentDatabase->OffsetBuffer
--*/
{
PUINT Ptr;
MYASSERT (g_CurrentDatabase);
if (Offset & INDEX_FLAG_MASK) {
DEBUGMSG ((DBG_ERROR, "Offset to be put in list is too big, 0x%08lX", Offset));
return FALSE;
}
//
// this will check that Offset is valid and points to Keystruct
//
MYASSERT(GetKeyStructFromOffset(Offset));
if (g_CurrentDatabase->OffsetBufferFirstDeletedIndex != INVALID_OFFSET)
{
//
// if we have deleted offsets from offset list, we
// find an open index, the first of which is stored
// in g_CurrentDatabase->OffsetBufferFirstDeletedIndex. the value at
// this index in the buffer is the next open index,
// and the value at that index is the next one, etc.
//
Ptr = &GET_UINT_AT_INDEX(g_CurrentDatabase->OffsetBufferFirstDeletedIndex);
g_CurrentDatabase->OffsetBufferFirstDeletedIndex = *Ptr;
} else {
//
// otherwise, make g_CurrentDatabase->OffsetBuffer bigger to hold new offset.
//
Ptr = (PUINT) GbGrow (&g_CurrentDatabase->OffsetBuffer, sizeof(UINT));
}
*Ptr = Offset;
return (UINT)((UBINT)Ptr - (UBINT)g_CurrentDatabase->OffsetBuffer.Buf);
}
VOID
RemoveKeyOffsetFromBuffer(
IN UINT Index
)
/*++
Routine Description:
frees a space in g_CurrentDatabase->OffsetBuffer (adds to deleted index list)
Arguments:
Index - position of space to free
--*/
{
if (Index == INVALID_OFFSET) {
return;
}
MYASSERT (g_CurrentDatabase);
if (IS_INDEX_MARKED(Index)) {
//
// if index is marked, either it is redirected or something
// is linked to this index. either way, we do not want to
// reuse the index, so just set true index (not a redirected
// one) to INVALID_OFFSET.
//
SET_UINT_AT_INDEX(pGetTrueIndex(Index), INVALID_OFFSET);
} else {
//
// index not marked, so we can reuse this index by
// putting it in the deleted index list.
//
SET_UINT_AT_INDEX(Index, g_CurrentDatabase->OffsetBufferFirstDeletedIndex);
g_CurrentDatabase->OffsetBufferFirstDeletedIndex = Index;
}
}
BOOL
WriteOffsetBlock (
IN PGROWBUFFER pOffsetBuffer,
IN OUT PBYTE *Buf
)
{
MYASSERT(pOffsetBuffer);
*(((PUINT)*Buf)++) = pOffsetBuffer->End;
CopyMemory (*Buf, pOffsetBuffer->Buf, pOffsetBuffer->End);
*Buf += pOffsetBuffer->End;
return TRUE;
}
BOOL
ReadOffsetBlock (
OUT PGROWBUFFER pOffsetBuffer,
IN OUT PBYTE *Buf
)
{
UINT OffsetBufferSize;
MYASSERT(pOffsetBuffer);
ZeroMemory (pOffsetBuffer, sizeof (GROWBUFFER));
OffsetBufferSize = *(((PUINT)*Buf)++);
if (OffsetBufferSize > 0) {
if (!GbGrow(pOffsetBuffer, OffsetBufferSize)) {
return FALSE;
}
CopyMemory (pOffsetBuffer->Buf, *Buf, OffsetBufferSize);
*Buf += OffsetBufferSize;
}
return TRUE;
}
UINT GetOffsetBufferBlockSize (
IN PGROWBUFFER pOffsetBuffer
)
{
return sizeof (UINT) + pOffsetBuffer->End;
}