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

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. mem.c
  5. Abstract:
  6. This file implements memory allocation functions for fax.
  7. Author:
  8. Wesley Witt (wesw) 23-Jan-1995
  9. Environment:
  10. User Mode
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <tchar.h>
  16. #include "faxutil.h"
  17. HANDLE hHeap;
  18. DWORD HeapFlags;
  19. PMEMALLOC pMemAllocUser;
  20. PMEMREALLOC pMemReAllocUser;
  21. PMEMFREE pMemFreeUser;
  22. #ifdef FAX_HEAP_DEBUG
  23. LIST_ENTRY HeapHeader;
  24. ULONG TotalMemory;
  25. ULONG MaxTotalMemory;
  26. ULONG MaxTotalAllocs;
  27. VOID PrintAllocations(VOID);
  28. ULONG TotalAllocs;
  29. CRITICAL_SECTION CsHeap;
  30. #endif
  31. BOOL
  32. HeapExistingInitialize(
  33. HANDLE hExistHeap
  34. )
  35. {
  36. #ifdef FAX_HEAP_DEBUG
  37. InitializeListHead( &HeapHeader );
  38. MaxTotalMemory = 0;
  39. MaxTotalAllocs = 0;
  40. InitializeCriticalSection( &CsHeap );
  41. #endif
  42. if (!hExistHeap) {
  43. return FALSE;
  44. }
  45. else {
  46. hHeap = hExistHeap;
  47. return TRUE;
  48. }
  49. }
  50. HANDLE
  51. HeapInitialize(
  52. HANDLE hHeapUser,
  53. PMEMALLOC pMemAlloc,
  54. PMEMFREE pMemFree,
  55. DWORD Flags
  56. )
  57. {
  58. #ifdef FAX_HEAP_DEBUG
  59. InitializeListHead( &HeapHeader );
  60. MaxTotalMemory = 0;
  61. MaxTotalAllocs = 0;
  62. InitializeCriticalSection( &CsHeap );
  63. #endif
  64. HeapFlags = Flags | HEAPINIT_NO_STRINGS;
  65. if (pMemAlloc && pMemFree) {
  66. pMemAllocUser = pMemAlloc;
  67. pMemFreeUser = pMemFree;
  68. hHeap = NULL;
  69. } else {
  70. if (hHeapUser) {
  71. hHeap = hHeapUser;
  72. } else {
  73. hHeap = HeapCreate( 0, HEAP_SIZE, 0 );
  74. }
  75. if (!hHeap) {
  76. return NULL;
  77. }
  78. }
  79. return hHeap;
  80. }
  81. BOOL
  82. HeapCleanup(
  83. VOID
  84. )
  85. {
  86. #ifdef FAX_HEAP_DEBUG
  87. PrintAllocations();
  88. #endif
  89. if (hHeap) {
  90. HeapDestroy( hHeap );
  91. }
  92. return TRUE;
  93. }
  94. #ifdef FAX_HEAP_DEBUG
  95. VOID
  96. pCheckHeap(
  97. PVOID MemPtr,
  98. ULONG Line,
  99. LPSTR File
  100. )
  101. {
  102. HeapValidate( hHeap, 0, MemPtr );
  103. }
  104. #endif
  105. PVOID
  106. pMemAlloc(
  107. ULONG AllocSize
  108. #ifdef FAX_HEAP_DEBUG
  109. , ULONG Line,
  110. LPSTR File
  111. #endif
  112. )
  113. {
  114. PVOID MemPtr;
  115. #ifdef FAX_HEAP_DEBUG
  116. PHEAP_BLOCK hb;
  117. #ifdef UNICODE
  118. TCHAR fname[MAX_PATH];
  119. #endif
  120. LPTSTR p = NULL;
  121. if (pMemAllocUser) {
  122. hb = (PHEAP_BLOCK) pMemAllocUser( AllocSize + sizeof(HEAP_BLOCK) );
  123. } else {
  124. if (hHeap == NULL) {
  125. HeapInitialize( NULL, NULL, NULL, 0 );
  126. if (hHeap == NULL) {
  127. return NULL;
  128. }
  129. }
  130. hb = (PHEAP_BLOCK) HeapAlloc( hHeap, HEAP_ZERO_MEMORY, AllocSize + sizeof(HEAP_BLOCK) );
  131. }
  132. if (hb) {
  133. TotalAllocs += 1;
  134. TotalMemory += AllocSize;
  135. if (TotalMemory > MaxTotalMemory) {
  136. MaxTotalMemory = TotalMemory;
  137. }
  138. if (TotalAllocs > MaxTotalAllocs) {
  139. MaxTotalAllocs = TotalAllocs;
  140. }
  141. EnterCriticalSection( &CsHeap );
  142. InsertTailList( &HeapHeader, &hb->ListEntry );
  143. hb->Signature = HEAP_SIG;
  144. hb->Size = AllocSize;
  145. hb->Line = Line;
  146. #ifdef UNICODE
  147. MultiByteToWideChar(
  148. CP_ACP,
  149. MB_PRECOMPOSED,
  150. File,
  151. -1,
  152. fname,
  153. sizeof(fname)/sizeof(WCHAR)
  154. );
  155. p = wcsrchr( fname, L'\\' );
  156. if (p) {
  157. wcscpy( hb->File, p+1 );
  158. }
  159. #else
  160. p = strrchr( File, '\\' );
  161. if (p) {
  162. strcpy( hb->File, p+1 );
  163. }
  164. #endif
  165. MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  166. LeaveCriticalSection( &CsHeap );
  167. } else {
  168. MemPtr = NULL;
  169. }
  170. #else
  171. if (pMemAllocUser) {
  172. MemPtr = (PVOID) pMemAllocUser( AllocSize );
  173. } else {
  174. if (hHeap == NULL) {
  175. HeapInitialize( NULL, NULL, NULL, 0 );
  176. if (hHeap == NULL) {
  177. return NULL;
  178. }
  179. }
  180. MemPtr = (PVOID) HeapAlloc( hHeap, HEAP_ZERO_MEMORY, AllocSize );
  181. }
  182. #endif
  183. if (!MemPtr) {
  184. DebugPrint(( TEXT("MemAlloc() failed, size=%d"), AllocSize ));
  185. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  186. }
  187. return MemPtr;
  188. }
  189. PVOID
  190. pMemReAlloc(
  191. PVOID Src,
  192. ULONG AllocSize
  193. #ifdef FAX_HEAP_DEBUG
  194. , ULONG Line,
  195. LPSTR File
  196. #endif
  197. )
  198. {
  199. PVOID MemPtr;
  200. #ifdef FAX_HEAP_DEBUG
  201. PHEAP_BLOCK hb;
  202. #ifdef UNICODE
  203. TCHAR fname[MAX_PATH];
  204. #endif
  205. LPTSTR p = NULL;
  206. EnterCriticalSection( &CsHeap );
  207. hb = (PHEAP_BLOCK) ((LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK));
  208. RemoveEntryList( &hb->ListEntry );
  209. TotalMemory -= hb->Size;
  210. LeaveCriticalSection( &CsHeap );
  211. if (pMemReAllocUser) {
  212. hb = (PHEAP_BLOCK) pMemReAllocUser( (LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
  213. AllocSize + sizeof(HEAP_BLOCK) );
  214. } else {
  215. if (hHeap == NULL) {
  216. HeapInitialize( NULL, NULL, NULL, 0 );
  217. if (hHeap == NULL) {
  218. return NULL;
  219. }
  220. }
  221. //
  222. // we have to back up a bit since the actual pointer passed in points to the data after the heap block.
  223. //
  224. hb = (PHEAP_BLOCK) HeapReAlloc( hHeap,
  225. HEAP_ZERO_MEMORY,
  226. (LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
  227. AllocSize + sizeof(HEAP_BLOCK)
  228. );
  229. }
  230. if (hb) {
  231. TotalMemory += AllocSize;
  232. if (TotalMemory > MaxTotalMemory) {
  233. MaxTotalMemory = TotalMemory;
  234. }
  235. EnterCriticalSection( &CsHeap );
  236. InsertTailList( &HeapHeader, &hb->ListEntry );
  237. hb->Signature = HEAP_SIG;
  238. hb->Size = AllocSize;
  239. hb->Line = Line;
  240. #ifdef UNICODE
  241. MultiByteToWideChar(
  242. CP_ACP,
  243. MB_PRECOMPOSED,
  244. File,
  245. -1,
  246. fname,
  247. sizeof(fname)/sizeof(WCHAR)
  248. );
  249. p = wcsrchr( fname, L'\\' );
  250. if (p) {
  251. wcscpy( hb->File, p+1 );
  252. }
  253. #else
  254. p = strrchr( File, '\\' );
  255. if (p) {
  256. strcpy( hb->File, p+1 );
  257. }
  258. #endif
  259. MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  260. LeaveCriticalSection( &CsHeap );
  261. } else {
  262. MemPtr = NULL;
  263. }
  264. #else
  265. if (pMemReAllocUser) {
  266. MemPtr = (PVOID) pMemReAllocUser( Src, AllocSize );
  267. } else {
  268. if (hHeap == NULL) {
  269. HeapInitialize( NULL, NULL, NULL, 0 );
  270. if (hHeap == NULL) {
  271. return NULL;
  272. }
  273. }
  274. MemPtr = (PVOID) HeapReAlloc( hHeap, HEAP_ZERO_MEMORY, Src, AllocSize );
  275. }
  276. #endif
  277. if (!MemPtr) {
  278. DebugPrint(( TEXT("MemReAlloc() failed, src=%x, size=%d"), (ULONG_PTR)Src, AllocSize ));
  279. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  280. }
  281. return MemPtr;
  282. }
  283. VOID
  284. pMemFreeForHeap(
  285. HANDLE hHeap,
  286. PVOID MemPtr
  287. #ifdef FAX_HEAP_DEBUG
  288. , ULONG Line,
  289. LPSTR File
  290. #endif
  291. )
  292. {
  293. #ifdef FAX_HEAP_DEBUG
  294. PHEAP_BLOCK hb;
  295. if (!MemPtr) {
  296. return;
  297. }
  298. hb = (PHEAP_BLOCK) ((PUCHAR)MemPtr - sizeof(HEAP_BLOCK));
  299. if (hb->Signature == HEAP_SIG) {
  300. EnterCriticalSection( &CsHeap );
  301. RemoveEntryList( &hb->ListEntry );
  302. TotalMemory -= hb->Size;
  303. TotalAllocs -= 1;
  304. LeaveCriticalSection( &CsHeap );
  305. } else {
  306. if (HeapFlags & HEAPINIT_NO_VALIDATION) {
  307. hb = (PHEAP_BLOCK) MemPtr;
  308. } else {
  309. dprintf( TEXT("MemFree(): Corrupt heap block") );
  310. PrintAllocations();
  311. __try {
  312. DebugBreak();
  313. } __except (UnhandledExceptionFilter(GetExceptionInformation())) {
  314. // Nothing to do in here.
  315. }
  316. }
  317. }
  318. if (pMemFreeUser) {
  319. pMemFreeUser( (PVOID) hb );
  320. } else {
  321. HeapFree( hHeap, 0, (PVOID) hb );
  322. }
  323. #else
  324. if (!MemPtr) {
  325. return;
  326. }
  327. if (pMemFreeUser) {
  328. pMemFreeUser( (PVOID) MemPtr );
  329. } else {
  330. HeapFree( hHeap, 0, (PVOID) MemPtr );
  331. }
  332. #endif
  333. }
  334. VOID
  335. pMemFree(
  336. PVOID MemPtr
  337. #ifdef FAX_HEAP_DEBUG
  338. , ULONG Line,
  339. LPSTR File
  340. #endif
  341. )
  342. {
  343. #ifdef FAX_HEAP_DEBUG
  344. pMemFreeForHeap( hHeap, MemPtr, Line, File );
  345. #else
  346. pMemFreeForHeap( hHeap, MemPtr );
  347. #endif
  348. }
  349. #ifdef FAX_HEAP_DEBUG
  350. VOID
  351. PrintAllocations(
  352. VOID
  353. )
  354. {
  355. PLIST_ENTRY Next;
  356. PHEAP_BLOCK hb;
  357. LPTSTR s;
  358. dprintf( TEXT("-------------------------------------------------------------------------------------------------------") );
  359. dprintf( TEXT("Memory Allocations for Heap 0x%08x, Allocs=%d, MaxAllocs=%d, TotalMem=%d, MaxTotalMem=%d"),\
  360. hHeap, TotalAllocs, MaxTotalAllocs, TotalMemory, MaxTotalMemory );
  361. dprintf( TEXT("-------------------------------------------------------------------------------------------------------") );
  362. EnterCriticalSection( &CsHeap );
  363. Next = HeapHeader.Flink;
  364. if (Next == NULL || TotalAllocs == 0) {
  365. return;
  366. }
  367. while ((ULONG_PTR)Next != (ULONG_PTR)&HeapHeader) {
  368. hb = CONTAINING_RECORD( Next, HEAP_BLOCK, ListEntry );
  369. Next = hb->ListEntry.Flink;
  370. s = (LPTSTR) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  371. dprintf( TEXT("%8d %16s @ %5d 0x%08x"), hb->Size, hb->File, hb->Line, s );
  372. if (!(HeapFlags & HEAPINIT_NO_STRINGS)) {
  373. dprintf( TEXT(" \"%s\""), s );
  374. }
  375. }
  376. LeaveCriticalSection( &CsHeap );
  377. return;
  378. }
  379. #endif