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.
 
 
 
 
 
 

437 lines
9.3 KiB

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