windows-nt/Source/XPSP1/NT/drivers/wdm/input/client/hidtest/debug.c
2020-09-26 16:20:57 +08:00

451 lines
11 KiB
C

#define __DEBUG_C__
#ifndef DEBUG
#define DEBUG
#endif
/*****************************************************************************
/* Debug include files
/*****************************************************************************/
#include <stdio.h>
#include "debug.h"
/*****************************************************************************
/* Local debug macro definitions
/*****************************************************************************/
#define SIGNATURE_SIZE 2
#define HEADER_SIGNATURE 'rdHM'
#define FOOTER_SIGNATURE 'rtFM'
#define MEMFILL_VALUE 0xCC
#define MEMORY_TRAP(msg) TRAP(TRAP_LEVEL_4, msg)
/*****************************************************************************
/* Data types local to debug
/*****************************************************************************/
typedef struct {
LIST_ENTRY ListEntry;
PCHAR FileName;
ULONG LineNumber;
BOOL IsValid;
ULONG BufferSize;
ULONG Signature[SIGNATURE_SIZE];
} ALLOCHEADER, *PALLOCHEADER;
typedef struct {
ULONG Signature[SIGNATURE_SIZE];
} ALLOCFOOTER, *PALLOCFOOTER;
typedef enum {
MEM_ALLOC_NO_ERROR, MEM_ALLOC_HEADER_OVERFLOW,
MEM_ALLOC_INVALID_HEADER, MEM_ALLOC_ALREADY_FREED,
MEM_ALLOC_FOOTER_OVERFLOW
} MEM_ALLOC_STATUS, *PMEM_ALLOC_STATUS;
/*****************************************************************************
/* Global debug data variables
/*****************************************************************************/
INT Debug_TrapLevel = TRAP_LEVEL_1;
BOOL Debug_TrapOn = FALSE;
static INT Debug_ListCount = 0;
/*****************************************************************************
/* Local debug data variables
/*****************************************************************************/
static LIST_ENTRY Debug_AllocList = { &Debug_AllocList, &Debug_AllocList };
/*****************************************************************************
/* Local debug function declarations
/*****************************************************************************/
BOOL
Debug_IsEmptyList(
IN PLIST_ENTRY ListHead
);
VOID
Debug_InsertIntoListAtTail(
IN OUT PLIST_ENTRY ListHead,
IN OUT PLIST_ENTRY NewEntry
);
PLIST_ENTRY
Debug_RemoveHeadOfList(
IN PLIST_ENTRY ListHead
);
VOID
Debug_RemoveListEntry(
IN PLIST_ENTRY OldEntry
);
/*****************************************************************************
/* Global debug function definitions
/*****************************************************************************/
HGLOBAL __cdecl
Debug_Alloc(
IN PCHAR FileName,
IN ULONG LineNumber,
IN DWORD AllocSize
)
{
INT Index;
DWORD BytesToAllocate;
PALLOCHEADER NewBuffer;
PALLOCFOOTER BufferFooter;
BytesToAllocate = sizeof(ALLOCHEADER) + sizeof(ALLOCFOOTER) + AllocSize;
NewBuffer = (PALLOCHEADER) GlobalAlloc(GPTR, BytesToAllocate);
if (NULL != NewBuffer) {
/*
// Initialize the header structure
*/
NewBuffer -> FileName = FileName;
NewBuffer -> LineNumber = LineNumber;
NewBuffer -> IsValid = TRUE;
NewBuffer -> BufferSize = AllocSize;
for (Index = 0; Index < SIGNATURE_SIZE; Index++)
NewBuffer -> Signature[Index] = HEADER_SIGNATURE;
/*
// Insert the new allocation block into the list of allocation blocks
*/
Debug_InsertIntoListAtTail(&Debug_AllocList,
&(NewBuffer -> ListEntry)
);
/*
// Increment to the pointer that will get returned to the user and
// initialize that to the fill value
*/
NewBuffer++;
FillMemory(NewBuffer, AllocSize, MEMFILL_VALUE);
/*
// Initialize the footer on the memory block
*/
BufferFooter = (PALLOCFOOTER) (((PCHAR) NewBuffer) + AllocSize);
for (Index = 0; Index < SIGNATURE_SIZE; Index++)
BufferFooter -> Signature[Index] = FOOTER_SIGNATURE;
}
return (NewBuffer);
}
HGLOBAL __cdecl
Debug_Realloc(
IN PCHAR FileName,
IN ULONG LineNumber,
IN PALLOCHEADER MemoryBlock,
IN DWORD AllocSize
)
{
MEM_ALLOC_STATUS AllocStatus;
PALLOCHEADER OldBuffer;
PALLOCHEADER NewBuffer;
ASSERT(NULL != MemoryBlock);
OldBuffer = MemoryBlock-1;
Debug_ValidateMemoryAlloc(MemoryBlock,
&AllocStatus
);
NewBuffer = (PALLOCHEADER) Debug_Alloc(FileName,
LineNumber,
AllocSize
);
if (NULL != NewBuffer) {
CopyMemory(NewBuffer, MemoryBlock, OldBuffer -> BufferSize);
Debug_Free(MemoryBlock);
}
return (NewBuffer);
}
HGLOBAL __cdecl
Debug_Free(
IN PALLOCHEADER Buffer
)
{
PALLOCHEADER Header;
MEM_ALLOC_STATUS AllocStatus;
Header = Buffer-1;
Debug_ValidateMemoryAlloc(Buffer, &AllocStatus);
/*
// If the block has already been freed, we will simply return NULL.
*/
if (MEM_ALLOC_ALREADY_FREED == AllocStatus)
return (NULL);
/*
// If we at least have an valid header, we can remove the header entry
// from our list of allocated blocks
*/
if (MEM_ALLOC_INVALID_HEADER != AllocStatus) {
Debug_RemoveListEntry(&(Header -> ListEntry));
Header -> IsValid = FALSE;
}
/*
// Free the block of memory
*/
return (GlobalFree(Header));
}
BOOL __cdecl
Debug_ValidateMemoryAlloc(
IN PALLOCHEADER Header,
OUT PMEM_ALLOC_STATUS AllocStatus
)
{
INT Index;
BOOL IsBadSignature;
PALLOCFOOTER Footer;
MEM_ALLOC_STATUS Status;
/*
// Begin by validating the header signature. If this is messed up there's
// nothing else that can be done. Check each SIGNATURE entry
// starting from the end to verify it is correct. If any of them are
// not equal to HEADER_SIGNATURE then something went wrong. However,
// if the first element in the array. Index 0 is valid, then we can
// reasonably assume that the rest of the header is correct and we can
// extract the appropriate info and display a more meaningful error
// message. If that signature is not valid, however, there's no way
// to insure that any of the other values are valid and therefore we
// can't extract the valid info from the header.
*/
Status = MEM_ALLOC_NO_ERROR;
Header--;
IsBadSignature = FALSE;
for (Index = SIGNATURE_SIZE-1; Index >= 0; Index--) {
if (Header -> Signature[Index] != HEADER_SIGNATURE) {
IsBadSignature = TRUE;
break;
}
}
if (IsBadSignature) {
if (HEADER_SIGNATURE == Header -> Signature[0]) {
static CHAR msg[1024];
sprintf(msg,
"Header overflow in block: %p\nAllocated by %s on line %u\n",
Header,
Header -> FileName,
Header -> LineNumber
);
MEMORY_TRAP(msg);
Status = MEM_ALLOC_HEADER_OVERFLOW;
}
else {
static CHAR msg[1024];
sprintf(msg,
"Corrupted allocation header in block: %p\nCannot extract allocation info",
Header
);
MEMORY_TRAP(msg);
Status = MEM_ALLOC_INVALID_HEADER;
}
}
/*
// We passed the signature phase, let's validate the rest of the memory
// allocation beginning with the header where we'll check the IsValid
// flag to see if this chunk of memory has previously been freed.
*/
else if (!Header -> IsValid) {
static CHAR msg[1024];
sprintf(msg,
"Allocated block already been freed: %p\nAllocated by %s on line %u\n",
Header,
Header -> FileName,
Header -> LineNumber
);
MEMORY_TRAP(msg);
Status = MEM_ALLOC_ALREADY_FREED;
}
else {
/*
// Next step is to verify that the footer is still correct and we did not
// overflow our buffer on the other end.
*/
Footer = (PALLOCFOOTER) (((PCHAR) (Header+1)) + Header -> BufferSize);
IsBadSignature = FALSE;
for (Index = 0; Index < SIGNATURE_SIZE; Index++) {
if (FOOTER_SIGNATURE != Footer -> Signature[Index]) {
IsBadSignature = TRUE;
break;
}
}
if (IsBadSignature) {
static CHAR msg[1024];
sprintf(msg,
"Footer overflow in block: %p\nAllocated by %s on line %u\n",
Header,
Header -> FileName,
Header -> LineNumber
);
MEMORY_TRAP(msg);
Status = MEM_ALLOC_FOOTER_OVERFLOW;
return (FALSE);
}
}
if (NULL != AllocStatus)
*AllocStatus = Status;
return (MEM_ALLOC_NO_ERROR == Status);
}
VOID __cdecl
Debug_CheckForMemoryLeaks(
)
{
static CHAR msg[1024];
PALLOCHEADER Header;
while (!Debug_IsEmptyList(&Debug_AllocList)) {
Header = (PALLOCHEADER) Debug_RemoveHeadOfList(&Debug_AllocList);
sprintf(msg,
"Memory leak block: %p\nAllocated by %s on line %u\n",
Header,
Header -> FileName,
Header -> LineNumber
);
MEMORY_TRAP(msg);
}
return;
}
/*****************************************************************************
/* Local debug function definitions
/*****************************************************************************/
BOOL
Debug_IsEmptyList(
IN PLIST_ENTRY ListHead
)
{
return (ListHead -> Flink == ListHead);
}
VOID
Debug_InsertIntoListAtTail(
IN OUT PLIST_ENTRY ListHead,
IN OUT PLIST_ENTRY NewEntry
)
{
PLIST_ENTRY OldTail;
OldTail = ListHead -> Blink;
NewEntry -> Flink = ListHead;
NewEntry -> Blink = OldTail;
OldTail -> Flink = NewEntry;
ListHead -> Blink = NewEntry;
Debug_ListCount++;
return;
}
VOID
Debug_RemoveListEntry(
IN PLIST_ENTRY OldEntry
)
{
PLIST_ENTRY Flink;
PLIST_ENTRY Blink;
Flink = OldEntry -> Flink;
Blink = OldEntry -> Blink;
Blink -> Flink = OldEntry -> Flink;
Flink -> Blink = OldEntry -> Blink;
Debug_ListCount--;
return;
}
PLIST_ENTRY
Debug_RemoveHeadOfList(
IN PLIST_ENTRY ListHead
)
{
PLIST_ENTRY OldHead;
OldHead = ListHead -> Flink;
ListHead -> Flink = OldHead -> Flink;
OldHead -> Flink -> Blink = ListHead;
Debug_ListCount--;
return (OldHead);
}