Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

549 lines
10 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
binvals.c
Abstract:
Routines to manage binary blocks associated with memdb keys.
Author:
Jim Schmidt (jimschm) 8-Aug-1996
Revision History:
Jim Schmidt (jimschm) 21-Oct-1997 Split from memdb.c
--*/
#include "pch.h"
#include "memdbp.h"
#ifndef UNICODE
#error UNICODE required
#endif
static PBINARYBLOCK g_FirstBlockPtr = NULL;
//
// Implementation
//
PBYTE
pGetBinaryData (
IN PBINARYBLOCK BlockPtr
)
/*++
Routine Description:
pGetBinaryData returns a pointer to the data portion of a
BINARYBLOCK struct.
Arguments:
BlockPtr - A pointer to a BINARYBLOCK struct.
Return Value:
A pointer to the binary data of BlockPtr, or NULL if BlockPtr
is invalid.
--*/
{
#ifdef DEBUG
// Verify checked block is valid
if (BlockPtr && BlockPtr->Signature != SIGNATURE) {
DEBUGMSG ((
DBG_ERROR,
"Signature of %x is invalid, can't get binary data",
g_FirstBlockPtr
));
return NULL;
}
#endif
if (!BlockPtr) {
return NULL;
}
return BlockPtr->Data;
}
DWORD
pGetBinaryDataSize (
IN PBINARYBLOCK BlockPtr
)
{
#ifdef DEBUG
// Verify checked block is valid
if (BlockPtr && BlockPtr->Signature != SIGNATURE) {
DEBUGMSG ((
DBG_ERROR,
"Signature of %x is invalid, can't get binary data",
g_FirstBlockPtr
));
return 0;
}
#endif
if (!BlockPtr) {
return 0;
}
return BlockPtr->Size - sizeof (BINARYBLOCK);
}
PCBYTE
GetKeyStructBinaryData (
PKEYSTRUCT KeyStruct
)
{
if (!KeyStruct || !(KeyStruct->Flags & KSF_BINARY)) {
return NULL;
}
return pGetBinaryData (KeyStruct->BinaryPtr);
}
DWORD
GetKeyStructBinarySize (
PKEYSTRUCT KeyStruct
)
{
if (!KeyStruct || !(KeyStruct->Flags & KSF_BINARY)) {
return 0;
}
return pGetBinaryDataSize (KeyStruct->BinaryPtr);
}
PBINARYBLOCK
pGetFirstBinaryBlock (
VOID
)
/*++
Routine Description:
pGetFristBinaryBlock returns a pointer to the first allocated
BINARYBLOCK struct, or NULL if no structs are allocated. This
routine is used with pGetNextBinaryBlock to walk all allocated
blocks.
Arguments:
none
Return Value:
A pointer to the the first allocated BINARYBLOCK struct, or NULL
if there are no structs allocated.
--*/
{
#ifdef DEBUG
// Verify checked block is valid
if (g_FirstBlockPtr && g_FirstBlockPtr->Signature != SIGNATURE) {
DEBUGMSG ((DBG_ERROR, "First binary block %x signature is invalid", g_FirstBlockPtr));
return NULL;
}
#endif
return g_FirstBlockPtr;
}
PBINARYBLOCK
pGetNextBinaryBlock (
IN PBINARYBLOCK BlockPtr
)
/*++
Routine Description:
pGetNextBinaryBlock returns a pointer to the next allocated
BINARYBLOCK struct, or NULL if no more blocks are allocated.
Arguments:
BlockPtr - The non-NULL return value of pGetFirstBinaryBlock or
pGetNextBinaryBlock
Return Value:
A pointer to the next BINARYBLOCK struct, or NULL if no more blocks
are allocated.
--*/
{
if (!BlockPtr) {
return NULL;
}
#ifdef DEBUG
// Verify checked block is valid
if (BlockPtr->NextPtr && BlockPtr->NextPtr->Signature != SIGNATURE) {
DEBUGMSG ((DBG_ERROR, "Binary block %x signature is invalid", BlockPtr->NextPtr));
return NULL;
}
#endif
return BlockPtr->NextPtr;
}
PBINARYBLOCK
AllocBinaryBlock (
IN PCBYTE Data,
IN DWORD DataSize,
IN DWORD OwningKey
)
/*++
Routine Description:
AllocBinaryBlock returns a pointer to an initialized BINARYBLOCK
structure, or NULL if the structure could not be allocated. If
the structure is allocated, Data is copied to the newly allocated
block. Call pFreeBinaryBlock to clean up this allocation.
Arguments:
Data - A pointer to a block of binary data to be copied into
the newly allocated structure
DataSize - The number of bytes to copy (may be zero)
OwningKey - The offset of the key who owns the data block
Return Value:
A pointer to the binary block structure, or NULL if it could not
be allocated.
--*/
{
PBINARYBLOCK BlockPtr;
DWORD AllocSize;
AllocSize = DataSize + sizeof (BINARYBLOCK);
BlockPtr = (PBINARYBLOCK) MemAlloc (g_hHeap, 0, AllocSize);
if (!BlockPtr) {
// DataSize must be bigger than 2G
OutOfMemory_Terminate();
}
//
// Initialize block struct
//
if (DataSize) {
CopyMemory (BlockPtr->Data, Data, DataSize);
}
BlockPtr->Size = AllocSize;
BlockPtr->OwningKey = OwningKey;
#ifdef DEBUG
BlockPtr->Signature = SIGNATURE;
#endif
//
// Link block to list of allocated blocks
//
BlockPtr->NextPtr = g_FirstBlockPtr;
if (g_FirstBlockPtr) {
g_FirstBlockPtr->PrevPtr = BlockPtr;
}
g_FirstBlockPtr = BlockPtr;
BlockPtr->PrevPtr = NULL;
//
// Return
//
return BlockPtr;
}
VOID
pFreeBinaryBlock (
PBINARYBLOCK BlockPtr,
BOOL Delink
)
/*++
Routine Description:
pFreeBinaryBlock frees memory allocated for a binary block and optionally
delinks it from the allocation list.
Arguments:
BlockPtr - A pointer to the block to delete
Delink - TRUE if structure should be delinked from allocation list,
or FALSE if the allocation list does not need to be maintained
Return Value:
none
--*/
{
if (!BlockPtr) {
return;
}
#ifdef DEBUG
if (BlockPtr->Signature != SIGNATURE) {
DEBUGMSG ((DBG_ERROR, "Can't free block %x because signature is invalid", BlockPtr));
return;
}
#endif
if (Delink) {
#ifdef DEBUG
if (BlockPtr->PrevPtr && BlockPtr->PrevPtr->Signature != SIGNATURE) {
DEBUGMSG ((DBG_ERROR, "Can't free block %x because prev block (%x) signature is invalid", BlockPtr, BlockPtr->PrevPtr));
return;
}
if (BlockPtr->NextPtr && BlockPtr->NextPtr->Signature != SIGNATURE) {
DEBUGMSG ((DBG_ERROR, "Can't free block %x because next block (%x) signature is invalid", BlockPtr, BlockPtr->NextPtr));
return;
}
#endif
if (BlockPtr->PrevPtr) {
BlockPtr->PrevPtr->NextPtr = BlockPtr->NextPtr;
} else {
g_FirstBlockPtr = BlockPtr->NextPtr;
}
if (BlockPtr->NextPtr) {
BlockPtr->NextPtr->PrevPtr = BlockPtr->PrevPtr;
}
}
MemFree (g_hHeap, 0, BlockPtr);
}
VOID
FreeKeyStructBinaryBlock (
PKEYSTRUCT KeyStruct
)
/*++
Routine Description:
FreeKeyStructBinaryBlock frees a binary block and resets the
KSF_BINARY flag, if the key struct has a binary block allocated.
Arguments:
none
Return Value:
none
--*/
{
if (KeyStruct->Flags & KSF_BINARY) {
pFreeBinaryBlock (KeyStruct->BinaryPtr, TRUE);
KeyStruct->BinaryPtr = NULL;
KeyStruct->Flags &= ~KSF_BINARY;
}
}
VOID
FreeAllBinaryBlocks (
VOID
)
/*++
Routine Description:
FreeAllBinaryBlocks removes all memory associated with binary
blocks. This function is used for final cleanup.
Arguments:
none
Return Value:
none
--*/
{
PBINARYBLOCK NextBlockPtr;
while (g_FirstBlockPtr) {
NextBlockPtr = g_FirstBlockPtr->NextPtr;
pFreeBinaryBlock (g_FirstBlockPtr, FALSE);
g_FirstBlockPtr = NextBlockPtr;
}
}
BOOL
LoadBinaryBlocks (
HANDLE File
)
{
BOOL b;
DWORD Count;
DWORD Owner = 0;
DWORD Size;
DWORD Read;
DWORD d;
PBYTE TempBuf = NULL;
PBINARYBLOCK NewBlock;
b = ReadFile (File, &Count, sizeof (DWORD), &Read, NULL);
if (b && Count) {
//
// Alloc binary objects
//
for (d = 0 ; b && d < Count ; d++) {
// Get Size and Owner
b = ReadFile (File, &Size, sizeof (DWORD), &Read, NULL);
if (Size > BLOCK_SIZE * 32) {
b = FALSE;
}
if (b) {
b = ReadFile (File, &Owner, sizeof (DWORD), &Read, NULL);
}
// Alloc a temporary buffer to read in data
if (b) {
TempBuf = (PBYTE) MemAlloc (g_hHeap, 0, Size);
b = ReadFile (File, TempBuf, Size, &Read, NULL);
// If data read OK, create binary block object
if (b) {
NewBlock = AllocBinaryBlock (TempBuf, Size, Owner);
if (!NewBlock) {
b = FALSE;
} else {
// Link owner to new memory location
MYASSERT (GetKeyStruct (Owner)->Flags & KSF_BINARY);
GetKeyStruct(Owner)->BinaryPtr = NewBlock;
}
}
MemFree (g_hHeap, 0, TempBuf);
TempBuf = NULL;
}
}
}
if (TempBuf) {
MemFree (g_hHeap, 0, TempBuf);
}
return b;
}
BOOL
SaveBinaryBlocks (
HANDLE File
)
{
BOOL b;
DWORD Count;
DWORD Size;
PBINARYBLOCK BinaryPtr;
DWORD Written;
//
// Count the binary objects
//
BinaryPtr = pGetFirstBinaryBlock();
Count = 0;
while (BinaryPtr) {
Count++;
BinaryPtr = pGetNextBinaryBlock (BinaryPtr);
}
//
// Write count to disk
//
b = WriteFile (File, &Count, sizeof (DWORD), &Written, NULL);
if (b) {
//
// Write the binary objects
//
BinaryPtr = pGetFirstBinaryBlock();
while (b && BinaryPtr) {
//
// Format per object:
//
// Size (DWORD)
// Owner (DWORD)
// Data (Size)
//
Size = pGetBinaryDataSize (BinaryPtr);
b = WriteFile (File, &Size, sizeof (DWORD), &Written, NULL);
if (b) {
b = WriteFile (File, &BinaryPtr->OwningKey, sizeof (DWORD), &Written, NULL);
}
if (b && Size) {
b = WriteFile (File, pGetBinaryData (BinaryPtr), Size, &Written, NULL);
if (Written != Size) {
b = FALSE;
}
}
BinaryPtr = pGetNextBinaryBlock(BinaryPtr);
}
}
return b;
}