438 lines
9.3 KiB
C
438 lines
9.3 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mem.c
|
|
|
|
Abstract:
|
|
|
|
This file implements memory allocation functions for fax.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 23-Jan-1995
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <tchar.h>
|
|
|
|
#include "faxutil.h"
|
|
|
|
|
|
|
|
HANDLE hHeap;
|
|
DWORD HeapFlags;
|
|
PMEMALLOC pMemAllocUser;
|
|
PMEMREALLOC pMemReAllocUser;
|
|
PMEMFREE pMemFreeUser;
|
|
|
|
|
|
#ifdef FAX_HEAP_DEBUG
|
|
LIST_ENTRY HeapHeader;
|
|
ULONG TotalMemory;
|
|
ULONG MaxTotalMemory;
|
|
ULONG MaxTotalAllocs;
|
|
VOID PrintAllocations(VOID);
|
|
ULONG TotalAllocs;
|
|
CRITICAL_SECTION CsHeap;
|
|
#endif
|
|
|
|
|
|
|
|
BOOL
|
|
HeapExistingInitialize(
|
|
HANDLE hExistHeap
|
|
)
|
|
{
|
|
|
|
#ifdef FAX_HEAP_DEBUG
|
|
InitializeListHead( &HeapHeader );
|
|
MaxTotalMemory = 0;
|
|
MaxTotalAllocs = 0;
|
|
InitializeCriticalSection( &CsHeap );
|
|
#endif
|
|
|
|
if (!hExistHeap) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
hHeap = hExistHeap;
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
HANDLE
|
|
HeapInitialize(
|
|
HANDLE hHeapUser,
|
|
PMEMALLOC pMemAlloc,
|
|
PMEMFREE pMemFree,
|
|
DWORD Flags
|
|
)
|
|
{
|
|
|
|
#ifdef FAX_HEAP_DEBUG
|
|
InitializeListHead( &HeapHeader );
|
|
MaxTotalMemory = 0;
|
|
MaxTotalAllocs = 0;
|
|
InitializeCriticalSection( &CsHeap );
|
|
#endif
|
|
|
|
HeapFlags = Flags | HEAPINIT_NO_STRINGS;
|
|
|
|
if (pMemAlloc && pMemFree) {
|
|
pMemAllocUser = pMemAlloc;
|
|
pMemFreeUser = pMemFree;
|
|
hHeap = NULL;
|
|
} else {
|
|
if (hHeapUser) {
|
|
hHeap = hHeapUser;
|
|
} else {
|
|
hHeap = HeapCreate( 0, HEAP_SIZE, 0 );
|
|
}
|
|
if (!hHeap) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return hHeap;
|
|
}
|
|
|
|
BOOL
|
|
HeapCleanup(
|
|
VOID
|
|
)
|
|
{
|
|
#ifdef FAX_HEAP_DEBUG
|
|
PrintAllocations();
|
|
#endif
|
|
if (hHeap) {
|
|
HeapDestroy( hHeap );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef FAX_HEAP_DEBUG
|
|
VOID
|
|
pCheckHeap(
|
|
PVOID MemPtr,
|
|
ULONG Line,
|
|
LPSTR File
|
|
)
|
|
{
|
|
HeapValidate( hHeap, 0, MemPtr );
|
|
}
|
|
#endif
|
|
|
|
PVOID
|
|
pMemAlloc(
|
|
ULONG AllocSize
|
|
#ifdef FAX_HEAP_DEBUG
|
|
, ULONG Line,
|
|
LPSTR File
|
|
#endif
|
|
)
|
|
{
|
|
PVOID MemPtr;
|
|
#ifdef FAX_HEAP_DEBUG
|
|
PHEAP_BLOCK hb;
|
|
#ifdef UNICODE
|
|
TCHAR fname[MAX_PATH];
|
|
#endif
|
|
LPTSTR p = NULL;
|
|
if (pMemAllocUser) {
|
|
hb = (PHEAP_BLOCK) pMemAllocUser( AllocSize + sizeof(HEAP_BLOCK) );
|
|
} else {
|
|
if (hHeap == NULL) {
|
|
HeapInitialize( NULL, NULL, NULL, 0 );
|
|
if (hHeap == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
hb = (PHEAP_BLOCK) HeapAlloc( hHeap, HEAP_ZERO_MEMORY, AllocSize + sizeof(HEAP_BLOCK) );
|
|
}
|
|
if (hb) {
|
|
TotalAllocs += 1;
|
|
TotalMemory += AllocSize;
|
|
if (TotalMemory > MaxTotalMemory) {
|
|
MaxTotalMemory = TotalMemory;
|
|
}
|
|
if (TotalAllocs > MaxTotalAllocs) {
|
|
MaxTotalAllocs = TotalAllocs;
|
|
}
|
|
EnterCriticalSection( &CsHeap );
|
|
InsertTailList( &HeapHeader, &hb->ListEntry );
|
|
hb->Signature = HEAP_SIG;
|
|
hb->Size = AllocSize;
|
|
hb->Line = Line;
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
File,
|
|
-1,
|
|
fname,
|
|
sizeof(fname)/sizeof(WCHAR)
|
|
);
|
|
p = wcsrchr( fname, L'\\' );
|
|
if (p) {
|
|
wcscpy( hb->File, p+1 );
|
|
}
|
|
#else
|
|
p = strrchr( File, '\\' );
|
|
if (p) {
|
|
strcpy( hb->File, p+1 );
|
|
}
|
|
#endif
|
|
MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
|
|
LeaveCriticalSection( &CsHeap );
|
|
} else {
|
|
MemPtr = NULL;
|
|
}
|
|
#else
|
|
if (pMemAllocUser) {
|
|
MemPtr = (PVOID) pMemAllocUser( AllocSize );
|
|
} else {
|
|
if (hHeap == NULL) {
|
|
HeapInitialize( NULL, NULL, NULL, 0 );
|
|
if (hHeap == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
MemPtr = (PVOID) HeapAlloc( hHeap, HEAP_ZERO_MEMORY, AllocSize );
|
|
}
|
|
#endif
|
|
|
|
if (!MemPtr) {
|
|
DebugPrint(( TEXT("MemAlloc() failed, size=%d"), AllocSize ));
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
return MemPtr;
|
|
}
|
|
|
|
PVOID
|
|
pMemReAlloc(
|
|
PVOID Src,
|
|
ULONG AllocSize
|
|
#ifdef FAX_HEAP_DEBUG
|
|
, ULONG Line,
|
|
LPSTR File
|
|
#endif
|
|
)
|
|
{
|
|
PVOID MemPtr;
|
|
#ifdef FAX_HEAP_DEBUG
|
|
PHEAP_BLOCK hb;
|
|
#ifdef UNICODE
|
|
TCHAR fname[MAX_PATH];
|
|
#endif
|
|
LPTSTR p = NULL;
|
|
|
|
EnterCriticalSection( &CsHeap );
|
|
hb = (PHEAP_BLOCK) ((LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK));
|
|
RemoveEntryList( &hb->ListEntry );
|
|
TotalMemory -= hb->Size;
|
|
LeaveCriticalSection( &CsHeap );
|
|
|
|
|
|
if (pMemReAllocUser) {
|
|
hb = (PHEAP_BLOCK) pMemReAllocUser( (LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
|
|
AllocSize + sizeof(HEAP_BLOCK) );
|
|
} else {
|
|
if (hHeap == NULL) {
|
|
HeapInitialize( NULL, NULL, NULL, 0 );
|
|
if (hHeap == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// we have to back up a bit since the actual pointer passed in points to the data after the heap block.
|
|
//
|
|
hb = (PHEAP_BLOCK) HeapReAlloc( hHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
(LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
|
|
AllocSize + sizeof(HEAP_BLOCK)
|
|
);
|
|
}
|
|
if (hb) {
|
|
TotalMemory += AllocSize;
|
|
if (TotalMemory > MaxTotalMemory) {
|
|
MaxTotalMemory = TotalMemory;
|
|
}
|
|
|
|
EnterCriticalSection( &CsHeap );
|
|
InsertTailList( &HeapHeader, &hb->ListEntry );
|
|
hb->Signature = HEAP_SIG;
|
|
hb->Size = AllocSize;
|
|
hb->Line = Line;
|
|
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
File,
|
|
-1,
|
|
fname,
|
|
sizeof(fname)/sizeof(WCHAR)
|
|
);
|
|
p = wcsrchr( fname, L'\\' );
|
|
if (p) {
|
|
wcscpy( hb->File, p+1 );
|
|
}
|
|
#else
|
|
p = strrchr( File, '\\' );
|
|
if (p) {
|
|
strcpy( hb->File, p+1 );
|
|
}
|
|
#endif
|
|
MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
|
|
LeaveCriticalSection( &CsHeap );
|
|
} else {
|
|
MemPtr = NULL;
|
|
}
|
|
#else
|
|
if (pMemReAllocUser) {
|
|
MemPtr = (PVOID) pMemReAllocUser( Src, AllocSize );
|
|
} else {
|
|
if (hHeap == NULL) {
|
|
HeapInitialize( NULL, NULL, NULL, 0 );
|
|
if (hHeap == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
MemPtr = (PVOID) HeapReAlloc( hHeap, HEAP_ZERO_MEMORY, Src, AllocSize );
|
|
}
|
|
#endif
|
|
|
|
if (!MemPtr) {
|
|
DebugPrint(( TEXT("MemReAlloc() failed, src=%x, size=%d"), (ULONG_PTR)Src, AllocSize ));
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
return MemPtr;
|
|
}
|
|
|
|
VOID
|
|
pMemFreeForHeap(
|
|
HANDLE hHeap,
|
|
PVOID MemPtr
|
|
#ifdef FAX_HEAP_DEBUG
|
|
, ULONG Line,
|
|
LPSTR File
|
|
#endif
|
|
)
|
|
{
|
|
#ifdef FAX_HEAP_DEBUG
|
|
PHEAP_BLOCK hb;
|
|
if (!MemPtr) {
|
|
return;
|
|
}
|
|
|
|
hb = (PHEAP_BLOCK) ((PUCHAR)MemPtr - sizeof(HEAP_BLOCK));
|
|
|
|
if (hb->Signature == HEAP_SIG) {
|
|
EnterCriticalSection( &CsHeap );
|
|
RemoveEntryList( &hb->ListEntry );
|
|
TotalMemory -= hb->Size;
|
|
TotalAllocs -= 1;
|
|
LeaveCriticalSection( &CsHeap );
|
|
} else {
|
|
if (HeapFlags & HEAPINIT_NO_VALIDATION) {
|
|
hb = (PHEAP_BLOCK) MemPtr;
|
|
} else {
|
|
dprintf( TEXT("MemFree(): Corrupt heap block") );
|
|
PrintAllocations();
|
|
__try {
|
|
DebugBreak();
|
|
} __except (UnhandledExceptionFilter(GetExceptionInformation())) {
|
|
// Nothing to do in here.
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pMemFreeUser) {
|
|
pMemFreeUser( (PVOID) hb );
|
|
} else {
|
|
HeapFree( hHeap, 0, (PVOID) hb );
|
|
}
|
|
|
|
#else
|
|
if (!MemPtr) {
|
|
return;
|
|
}
|
|
if (pMemFreeUser) {
|
|
pMemFreeUser( (PVOID) MemPtr );
|
|
} else {
|
|
HeapFree( hHeap, 0, (PVOID) MemPtr );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
pMemFree(
|
|
PVOID MemPtr
|
|
#ifdef FAX_HEAP_DEBUG
|
|
, ULONG Line,
|
|
LPSTR File
|
|
#endif
|
|
)
|
|
{
|
|
#ifdef FAX_HEAP_DEBUG
|
|
pMemFreeForHeap( hHeap, MemPtr, Line, File );
|
|
#else
|
|
pMemFreeForHeap( hHeap, MemPtr );
|
|
#endif
|
|
}
|
|
|
|
#ifdef FAX_HEAP_DEBUG
|
|
VOID
|
|
PrintAllocations(
|
|
VOID
|
|
)
|
|
{
|
|
PLIST_ENTRY Next;
|
|
PHEAP_BLOCK hb;
|
|
LPTSTR s;
|
|
|
|
|
|
dprintf( TEXT("-------------------------------------------------------------------------------------------------------") );
|
|
dprintf( TEXT("Memory Allocations for Heap 0x%08x, Allocs=%d, MaxAllocs=%d, TotalMem=%d, MaxTotalMem=%d"),\
|
|
hHeap, TotalAllocs, MaxTotalAllocs, TotalMemory, MaxTotalMemory );
|
|
dprintf( TEXT("-------------------------------------------------------------------------------------------------------") );
|
|
|
|
EnterCriticalSection( &CsHeap );
|
|
|
|
Next = HeapHeader.Flink;
|
|
if (Next == NULL || TotalAllocs == 0) {
|
|
return;
|
|
}
|
|
|
|
while ((ULONG_PTR)Next != (ULONG_PTR)&HeapHeader) {
|
|
hb = CONTAINING_RECORD( Next, HEAP_BLOCK, ListEntry );
|
|
Next = hb->ListEntry.Flink;
|
|
s = (LPTSTR) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
|
|
dprintf( TEXT("%8d %16s @ %5d 0x%08x"), hb->Size, hb->File, hb->Line, s );
|
|
if (!(HeapFlags & HEAPINIT_NO_STRINGS)) {
|
|
dprintf( TEXT(" \"%s\""), s );
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection( &CsHeap );
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|