Leaked source code of windows server 2003
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.

613 lines
13 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. static HANDLE gs_hHeap = NULL; // this should be done in an intialization function that every module should call once we move to svchost
  18. PMEMALLOC pMemAllocUser;
  19. PMEMREALLOC pMemReAllocUser;
  20. PMEMFREE pMemFreeUser;
  21. #ifdef FAX_HEAP_DEBUG
  22. LIST_ENTRY HeapHeader;
  23. SIZE_T TotalMemory;
  24. SIZE_T MaxTotalMemory;
  25. ULONG MaxTotalAllocs;
  26. VOID PrintAllocations(VOID);
  27. ULONG TotalAllocs;
  28. static CRITICAL_SECTION gs_CsHeap;
  29. static BOOL gs_fCsHeapInit;
  30. #endif
  31. #if _CHICAGO_ == 200
  32. // The code is supposed to run on win9x and win2k
  33. #define WIN9X
  34. #endif
  35. long
  36. StatusNoMemoryExceptionFilter (DWORD dwExceptionCode)
  37. {
  38. return (STATUS_NO_MEMORY == dwExceptionCode) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
  39. }
  40. HRESULT
  41. SafeInitializeCriticalSection (LPCRITICAL_SECTION lpCriticalSection)
  42. {
  43. DWORD dwExCode = 0;
  44. __try
  45. {
  46. InitializeCriticalSection(lpCriticalSection);
  47. }
  48. __except (StatusNoMemoryExceptionFilter(dwExCode = GetExceptionCode()))
  49. {
  50. SetLastError(dwExCode);
  51. return HRESULT_FROM_NT(dwExCode);
  52. }
  53. return S_OK;
  54. }
  55. BOOL
  56. HeapExistingInitialize(
  57. HANDLE hExistHeap
  58. )
  59. {
  60. Assert (NULL == gs_hHeap);
  61. pMemAllocUser = NULL;
  62. pMemReAllocUser = NULL;
  63. pMemFreeUser = NULL;
  64. #ifdef FAX_HEAP_DEBUG
  65. gs_fCsHeapInit = FALSE;
  66. InitializeListHead( &HeapHeader );
  67. MaxTotalMemory = 0;
  68. MaxTotalAllocs = 0;
  69. __try
  70. {
  71. InitializeCriticalSection (&gs_CsHeap);
  72. gs_fCsHeapInit = TRUE;
  73. }
  74. __except (StatusNoMemoryExceptionFilter(GetExceptionCode()))
  75. {
  76. return FALSE;
  77. }
  78. #endif
  79. if (!hExistHeap)
  80. {
  81. return FALSE;
  82. }
  83. else
  84. {
  85. gs_hHeap = hExistHeap;
  86. return TRUE;
  87. }
  88. }
  89. HANDLE
  90. HeapInitialize(
  91. HANDLE hHeapUser,
  92. PMEMALLOC pMemAlloc,
  93. PMEMFREE pMemFree,
  94. PMEMREALLOC pMemReAlloc
  95. )
  96. {
  97. Assert (NULL == gs_hHeap);
  98. pMemAllocUser = NULL;
  99. pMemReAllocUser = NULL;
  100. pMemFreeUser = NULL;
  101. #ifdef FAX_HEAP_DEBUG
  102. gs_fCsHeapInit = FALSE;
  103. InitializeListHead( &HeapHeader );
  104. MaxTotalMemory = 0;
  105. MaxTotalAllocs = 0;
  106. __try
  107. {
  108. InitializeCriticalSection (&gs_CsHeap);
  109. gs_fCsHeapInit = TRUE;
  110. }
  111. __except (StatusNoMemoryExceptionFilter(GetExceptionCode()))
  112. {
  113. return NULL;
  114. }
  115. fax_dprintf(TEXT("in HeapInitialize()"));
  116. #endif
  117. if (pMemAlloc && pMemFree && pMemReAlloc)
  118. {
  119. pMemAllocUser = pMemAlloc;
  120. pMemFreeUser = pMemFree;
  121. pMemReAllocUser = pMemReAlloc;
  122. gs_hHeap = NULL;
  123. }
  124. else
  125. {
  126. if (hHeapUser)
  127. {
  128. gs_hHeap = hHeapUser;
  129. }
  130. else
  131. {
  132. gs_hHeap = HeapCreate( 0, HEAP_SIZE, 0 );
  133. }
  134. if (!gs_hHeap)
  135. {
  136. return NULL;
  137. }
  138. }
  139. return gs_hHeap;
  140. }
  141. BOOL
  142. HeapCleanup(
  143. VOID
  144. )
  145. {
  146. #ifdef FAX_HEAP_DEBUG
  147. PrintAllocations();
  148. #endif
  149. if (gs_hHeap)
  150. {
  151. if (gs_hHeap != GetProcessHeap())
  152. {
  153. HeapDestroy( gs_hHeap );
  154. }
  155. gs_hHeap = NULL;
  156. }
  157. #ifdef FAX_HEAP_DEBUG
  158. if (TRUE == gs_fCsHeapInit)
  159. {
  160. DeleteCriticalSection(&gs_CsHeap);
  161. gs_fCsHeapInit = FALSE;
  162. }
  163. #endif
  164. return TRUE;
  165. }
  166. #ifdef FAX_HEAP_DEBUG
  167. BOOL
  168. pCheckHeap(
  169. PVOID MemPtr,
  170. ULONG Line,
  171. LPSTR File
  172. )
  173. {
  174. #ifndef WIN9X
  175. return HeapValidate( gs_hHeap, 0, MemPtr );
  176. #else
  177. return TRUE;
  178. #endif
  179. }
  180. #endif
  181. PVOID
  182. pMemAlloc(
  183. SIZE_T AllocSize
  184. #ifdef FAX_HEAP_DEBUG
  185. , ULONG Line,
  186. LPSTR File
  187. #endif
  188. )
  189. {
  190. PVOID MemPtr;
  191. #ifdef FAX_HEAP_DEBUG
  192. PHEAP_BLOCK hb;
  193. #ifdef UNICODE
  194. TCHAR fname[MAX_PATH];
  195. #endif
  196. LPTSTR p = NULL;
  197. if (pMemAllocUser)
  198. {
  199. hb = (PHEAP_BLOCK) pMemAllocUser( AllocSize + sizeof(HEAP_BLOCK) );
  200. }
  201. else
  202. {
  203. if (gs_hHeap == NULL)
  204. {
  205. if (!HeapExistingInitialize(GetProcessHeap()))
  206. {
  207. return NULL;
  208. }
  209. }
  210. // In win9X this call will return TRUE
  211. if (!CheckHeap(NULL))
  212. {
  213. fax_dprintf((TEXT("HeapValidate() failed")));
  214. DebugBreak();
  215. }
  216. hb = (PHEAP_BLOCK) HeapAlloc( gs_hHeap, HEAP_ZERO_MEMORY, AllocSize + sizeof(HEAP_BLOCK) );
  217. }
  218. if (hb)
  219. {
  220. TotalAllocs += 1;
  221. TotalMemory += AllocSize;
  222. if (TotalMemory > MaxTotalMemory)
  223. {
  224. MaxTotalMemory = TotalMemory;
  225. }
  226. if (TotalAllocs > MaxTotalAllocs)
  227. {
  228. MaxTotalAllocs = TotalAllocs;
  229. }
  230. EnterCriticalSection( &gs_CsHeap );
  231. InsertTailList( &HeapHeader, &hb->ListEntry );
  232. hb->Signature = HEAP_SIG;
  233. hb->Size = AllocSize;
  234. hb->Line = Line;
  235. #ifdef UNICODE
  236. MultiByteToWideChar(
  237. CP_ACP,
  238. MB_PRECOMPOSED,
  239. File,
  240. -1,
  241. fname,
  242. sizeof(fname)/sizeof(WCHAR)
  243. );
  244. p = wcsrchr( fname, L'\\' );
  245. if (p)
  246. {
  247. wcscpy( hb->File, p+1 );
  248. }
  249. #else
  250. p = _tcsrchr( File, TEXT('\\') );
  251. if (p)
  252. {
  253. _tcscpy( hb->File, _tcsinc(p) );
  254. }
  255. #endif
  256. MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  257. LeaveCriticalSection( &gs_CsHeap );
  258. }
  259. else
  260. {
  261. MemPtr = NULL;
  262. }
  263. #else
  264. if (pMemAllocUser)
  265. {
  266. MemPtr = (PVOID) pMemAllocUser( AllocSize );
  267. }
  268. else
  269. {
  270. if (gs_hHeap == NULL)
  271. {
  272. if (!HeapExistingInitialize(GetProcessHeap()))
  273. {
  274. return NULL;
  275. }
  276. }
  277. MemPtr = (PVOID) HeapAlloc( gs_hHeap, HEAP_ZERO_MEMORY, AllocSize );
  278. }
  279. #endif
  280. if (!MemPtr)
  281. {
  282. DebugPrint(( TEXT("MemAlloc() failed, size=%d"), AllocSize ));
  283. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  284. }
  285. return MemPtr;
  286. }
  287. PVOID
  288. pMemReAlloc(
  289. PVOID Src,
  290. ULONG AllocSize
  291. #ifdef FAX_HEAP_DEBUG
  292. , ULONG Line,
  293. LPSTR File
  294. #endif
  295. )
  296. {
  297. PVOID MemPtr;
  298. #ifdef FAX_HEAP_DEBUG
  299. PHEAP_BLOCK hb;
  300. #ifdef UNICODE
  301. TCHAR fname[MAX_PATH];
  302. #endif
  303. LPTSTR p = NULL;
  304. EnterCriticalSection( &gs_CsHeap );
  305. hb = (PHEAP_BLOCK) ((LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK));
  306. RemoveEntryList( &hb->ListEntry );
  307. TotalMemory -= hb->Size;
  308. LeaveCriticalSection( &gs_CsHeap );
  309. if (pMemReAllocUser)
  310. {
  311. hb = (PHEAP_BLOCK) pMemReAllocUser( (LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
  312. AllocSize + sizeof(HEAP_BLOCK) );
  313. }
  314. else
  315. {
  316. if (gs_hHeap == NULL)
  317. {
  318. if (!HeapExistingInitialize(GetProcessHeap()))
  319. {
  320. return NULL;
  321. }
  322. }
  323. //
  324. // we have to back up a bit since the actual pointer passed in points to the data after the heap block.
  325. //
  326. hb = (PHEAP_BLOCK) HeapReAlloc( gs_hHeap,
  327. HEAP_ZERO_MEMORY,
  328. (LPBYTE)Src-(ULONG_PTR)sizeof(HEAP_BLOCK),
  329. AllocSize + sizeof(HEAP_BLOCK)
  330. );
  331. }
  332. if (hb)
  333. {
  334. TotalMemory += AllocSize;
  335. if (TotalMemory > MaxTotalMemory)
  336. {
  337. MaxTotalMemory = TotalMemory;
  338. }
  339. EnterCriticalSection( &gs_CsHeap );
  340. InsertTailList( &HeapHeader, &hb->ListEntry );
  341. hb->Signature = HEAP_SIG;
  342. hb->Size = AllocSize;
  343. hb->Line = Line;
  344. #ifdef UNICODE
  345. MultiByteToWideChar(
  346. CP_ACP,
  347. MB_PRECOMPOSED,
  348. File,
  349. -1,
  350. fname,
  351. sizeof(fname)/sizeof(WCHAR)
  352. );
  353. p = wcsrchr( fname, L'\\' );
  354. if (p)
  355. {
  356. wcscpy( hb->File, p+1 );
  357. }
  358. #else
  359. p = _tcsrchr( File, TEXT('\\') );
  360. if (p)
  361. {
  362. _tcscpy( hb->File, _tcsinc(p) );
  363. }
  364. #endif
  365. MemPtr = (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  366. LeaveCriticalSection( &gs_CsHeap );
  367. }
  368. else
  369. {
  370. MemPtr = NULL;
  371. }
  372. #else
  373. if (pMemReAllocUser)
  374. {
  375. MemPtr = (PVOID) pMemReAllocUser( Src, AllocSize );
  376. }
  377. else
  378. {
  379. if (gs_hHeap == NULL)
  380. {
  381. if (!HeapExistingInitialize(GetProcessHeap()))
  382. {
  383. return NULL;
  384. }
  385. }
  386. MemPtr = (PVOID) HeapReAlloc( gs_hHeap, HEAP_ZERO_MEMORY, Src, AllocSize );
  387. }
  388. #endif
  389. if (!MemPtr)
  390. {
  391. DebugPrint(( TEXT("MemReAlloc() failed, src=%x, size=%d"), (ULONG_PTR)Src, AllocSize ));
  392. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  393. }
  394. return MemPtr;
  395. }
  396. VOID
  397. pMemFreeForHeap(
  398. HANDLE gs_hHeap,
  399. PVOID MemPtr
  400. #ifdef FAX_HEAP_DEBUG
  401. , ULONG Line,
  402. LPSTR File
  403. #endif
  404. )
  405. {
  406. #ifdef FAX_HEAP_DEBUG
  407. PHEAP_BLOCK hb;
  408. if (!MemPtr)
  409. {
  410. return;
  411. }
  412. hb = (PHEAP_BLOCK) ((PUCHAR)MemPtr - sizeof(HEAP_BLOCK));
  413. if (hb->Signature == HEAP_SIG)
  414. {
  415. EnterCriticalSection( &gs_CsHeap );
  416. RemoveEntryList( &hb->ListEntry );
  417. TotalMemory -= hb->Size;
  418. TotalAllocs -= 1;
  419. LeaveCriticalSection( &gs_CsHeap );
  420. }
  421. else
  422. {
  423. fax_dprintf( TEXT("MemFree(): Corrupt heap block") );
  424. PrintAllocations();
  425. __try
  426. {
  427. DebugBreak();
  428. }
  429. __except (UnhandledExceptionFilter(GetExceptionInformation()))
  430. {
  431. // Nothing to do in here.
  432. }
  433. }
  434. if (pMemFreeUser)
  435. {
  436. pMemFreeUser( (PVOID) hb );
  437. } else
  438. {
  439. HeapFree( gs_hHeap, 0, (PVOID) hb );
  440. }
  441. #else
  442. if (!MemPtr)
  443. {
  444. return;
  445. }
  446. if (pMemFreeUser)
  447. {
  448. pMemFreeUser( (PVOID) MemPtr );
  449. }
  450. else
  451. {
  452. HeapFree( gs_hHeap, 0, (PVOID) MemPtr );
  453. }
  454. #endif
  455. }
  456. VOID
  457. pMemFree(
  458. PVOID MemPtr
  459. #ifdef FAX_HEAP_DEBUG
  460. , ULONG Line,
  461. LPSTR File
  462. #endif
  463. )
  464. {
  465. #ifdef FAX_HEAP_DEBUG
  466. pMemFreeForHeap( gs_hHeap, MemPtr, Line, File );
  467. #else
  468. pMemFreeForHeap( gs_hHeap, MemPtr );
  469. #endif
  470. }
  471. #ifdef FAX_HEAP_DEBUG
  472. VOID
  473. PrintAllocations()
  474. /*++
  475. Routine name : PrintAllocations
  476. Routine description:
  477. Prints the current list of allocations for a given heap
  478. Author:
  479. Eran Yariv (EranY), Nov, 2000
  480. Arguments:
  481. Return Value:
  482. None.
  483. --*/
  484. {
  485. PLIST_ENTRY Next;
  486. PHEAP_BLOCK hb;
  487. LPTSTR s;
  488. DEBUG_FUNCTION_NAME(TEXT("PrintAllocations"));
  489. if (FALSE == gs_fCsHeapInit)
  490. {
  491. //
  492. // The module was not initialized
  493. //
  494. return;
  495. }
  496. DebugPrintEx(
  497. DEBUG_MSG,
  498. TEXT("-------------------------------------------------------------------------------------------------------") );
  499. DebugPrintEx(
  500. DEBUG_MSG,
  501. TEXT("Memory Allocations for Heap 0x%08x, Allocs=%d, MaxAllocs=%d, TotalMem=%d, MaxTotalMem=%d"),
  502. gs_hHeap,
  503. TotalAllocs,
  504. MaxTotalAllocs,
  505. TotalMemory,
  506. MaxTotalMemory );
  507. DebugPrintEx(
  508. DEBUG_MSG,
  509. TEXT("-------------------------------------------------------------------------------------------------------") );
  510. EnterCriticalSection( &gs_CsHeap );
  511. Next = HeapHeader.Flink;
  512. if (Next == NULL)
  513. {
  514. DebugPrintEx(
  515. DEBUG_ERR,
  516. TEXT("Memory allocation list is corrupted !!!"));
  517. LeaveCriticalSection( &gs_CsHeap );
  518. return;
  519. }
  520. if ((ULONG_PTR)Next == (ULONG_PTR)&HeapHeader)
  521. {
  522. DebugPrintEx(
  523. DEBUG_MSG,
  524. TEXT("All allocated memory blocks are now free. Good work."));
  525. LeaveCriticalSection( &gs_CsHeap );
  526. return;
  527. }
  528. while ((ULONG_PTR)Next != (ULONG_PTR)&HeapHeader)
  529. {
  530. hb = CONTAINING_RECORD( Next, HEAP_BLOCK, ListEntry );
  531. Next = hb->ListEntry.Flink;
  532. s = (LPTSTR) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  533. DebugPrintEx(
  534. DEBUG_MSG,
  535. TEXT("%8d %16s @ %5d 0x%08x"),
  536. hb->Size,
  537. hb->File,
  538. hb->Line,
  539. s );
  540. }
  541. LeaveCriticalSection( &gs_CsHeap );
  542. } // PrintAllocations
  543. #endif