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