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.

1040 lines
20 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. memory.c
  5. Abstract:
  6. Implements macros and declares functions for basic allocation functions.
  7. Author:
  8. Marc R. Whitten (marcw) 09-Sep-1999
  9. Revision History:
  10. jimschm 25-Jul-2001 Consolidated coding conventions
  11. --*/
  12. #include "pch.h"
  13. #include "commonp.h"
  14. //
  15. // Constants
  16. //
  17. #ifdef DEBUG
  18. #define TRAIL_SIG 0x708aa210
  19. #define TRACK_SIGNATURE 0x30405060
  20. #endif
  21. //
  22. // Macros
  23. //
  24. #define REUSE_SIZE_PTR(ptr) ((PDWORD) ((PBYTE) ptr - sizeof (DWORD)))
  25. #define REUSE_TAG_PTR(ptr) ((PDWORD) ((PBYTE) ptr + (*REUSE_SIZE_PTR(ptr))))
  26. //
  27. // Types
  28. //
  29. #ifdef DEBUG
  30. typedef struct {
  31. DWORD Signature;
  32. SIZE_T Size;
  33. } TRACKSTRUCT, *PTRACKSTRUCT;
  34. #endif
  35. //
  36. // Globals
  37. //
  38. #ifdef DEBUG
  39. PTRACKSTRUCT g_TrackHead = NULL;
  40. #endif
  41. static DWORD g_MemTlsIndex;
  42. static SIZE_T g_TotalBytesAllocated = 0;
  43. static SIZE_T g_MaxBytesInUse = 0;
  44. static SIZE_T g_HeapAllocs = 0;
  45. static SIZE_T g_HeapReAllocs = 0;
  46. static SIZE_T g_HeapFrees = 0;
  47. static SIZE_T g_HeapAllocFails = 0;
  48. static SIZE_T g_HeapReAllocFails = 0;
  49. static SIZE_T g_HeapFreeFails = 0;
  50. //
  51. // Out of memory string -- loaded at initialization
  52. //
  53. PCSTR g_OutOfMemoryString = NULL;
  54. PCSTR g_OutOfMemoryRetry = NULL;
  55. HWND g_OutOfMemoryParentWnd;
  56. //
  57. // Macro expansion list
  58. //
  59. // None
  60. //
  61. // Private function prototypes
  62. //
  63. VOID
  64. MemOutOfMemory_Terminate (
  65. VOID
  66. );
  67. #ifdef DEBUG
  68. SIZE_T
  69. pDebugHeapValidatePtrUnlocked (
  70. HANDLE HeapHandle,
  71. PCVOID CallerPtr,
  72. PCSTR File,
  73. DWORD Line
  74. );
  75. VOID
  76. pCreateSignatures (
  77. PCSTR File,
  78. DWORD Line,
  79. SIZE_T Size,
  80. PTRACKSTRUCT p
  81. );
  82. VOID
  83. pCheckSignatures (
  84. PTRACKSTRUCT p
  85. );
  86. #endif
  87. //
  88. // Macro expansion definition
  89. //
  90. // None
  91. //
  92. // Code
  93. //
  94. VOID
  95. pHeapCallFailed (
  96. IN PCSTR Msg,
  97. IN PCSTR File,
  98. IN DWORD Line
  99. )
  100. {
  101. CHAR Msg2[2048];
  102. wsprintfA (Msg2, "Error in %s line %u\n\n", File, Line);
  103. if (strlen(Msg) + strlen(Msg2) < 2025) {
  104. strcat (Msg2, Msg);
  105. }
  106. strcat (Msg2, "\n\nBreak execution now?");
  107. if (IDYES == MessageBoxA (GetFocus(), Msg2, "Heap Call Failed", MB_YESNO|MB_APPLMODAL)) {
  108. BreakPoint();
  109. }
  110. }
  111. #ifdef DEBUG
  112. SIZE_T
  113. DbgHeapValidatePtr (
  114. HANDLE HeapHandle,
  115. PCVOID CallerPtr,
  116. PCSTR File,
  117. DWORD Line
  118. )
  119. {
  120. SIZE_T rc;
  121. //EnterCriticalSection (&g_MemAllocCs);
  122. rc = pDebugHeapValidatePtrUnlocked (HeapHandle, CallerPtr, File, Line);
  123. //LeaveCriticalSection (&g_MemAllocCs);
  124. return rc;
  125. }
  126. SIZE_T
  127. pDebugHeapValidatePtrUnlocked (
  128. HANDLE HeapHandle,
  129. PCVOID CallerPtr,
  130. PCSTR File,
  131. DWORD Line
  132. )
  133. {
  134. SIZE_T size;
  135. PCVOID realPtr;
  136. SIZE_T sizeAdjust;
  137. sizeAdjust = sizeof (TRACKSTRUCT);
  138. realPtr = (PCVOID) ((PBYTE) CallerPtr - sizeAdjust);
  139. if (IsBadWritePtr ((PBYTE) realPtr - 8, 8)) {
  140. CHAR badPtrMsg[256];
  141. //lint --e(572)
  142. wsprintfA (
  143. badPtrMsg,
  144. "Attempt to free memory at 0x%08x%08x. This address is not valid.",
  145. (DWORD)((ULONG_PTR)CallerPtr >> 32),
  146. (DWORD)(ULONG_PTR)CallerPtr
  147. );
  148. pHeapCallFailed (badPtrMsg, File, Line);
  149. return (SIZE_T)INVALID_PTR;
  150. }
  151. size = HeapSize (HeapHandle, 0, realPtr);
  152. if (size == (SIZE_T)-1) {
  153. CHAR badPtrMsg[256];
  154. //lint --e(572)
  155. wsprintfA (
  156. badPtrMsg,
  157. "Attempt to free memory at 0x%08x%08x. "
  158. "This address is not the start of a memory block.",
  159. (DWORD)((ULONGLONG)CallerPtr >> 32),
  160. (DWORD)(ULONG_PTR)CallerPtr
  161. );
  162. pHeapCallFailed (badPtrMsg, File, Line);
  163. return (SIZE_T)INVALID_PTR;
  164. }
  165. return size;
  166. }
  167. PVOID
  168. DbgHeapAlloc (
  169. PCSTR File,
  170. DWORD Line,
  171. HANDLE HeapHandle,
  172. DWORD Flags,
  173. SIZE_T BytesToAlloc
  174. )
  175. {
  176. PVOID realPtr;
  177. PVOID returnPtr = NULL;
  178. DWORD sizeAdjust;
  179. DWORD trackStructSize;
  180. DWORD orgError;
  181. //EnterCriticalSection (&g_MemAllocCs);
  182. __try {
  183. //
  184. // Save the last error
  185. //
  186. orgError = GetLastError();
  187. //
  188. // Compute the size we need to allocate, plus the offset to
  189. // the start of the return memory
  190. //
  191. sizeAdjust = sizeof (TRACKSTRUCT) + sizeof (DWORD); // DWORD is for a signature
  192. trackStructSize = sizeof (TRACKSTRUCT);
  193. //
  194. // Validate the entire heap. This is a slow operation!
  195. //
  196. if (!HeapValidate (HeapHandle, 0, NULL)) {
  197. pHeapCallFailed ("Heap is corrupt!", File, Line);
  198. // we want to go on, most likely we will AV shortly
  199. }
  200. //
  201. // Allocate memory
  202. //
  203. realPtr = HeapAlloc (HeapHandle, Flags, BytesToAlloc + sizeAdjust);
  204. if (realPtr) {
  205. g_HeapAllocs++;
  206. g_TotalBytesAllocated += HeapSize (HeapHandle, 0, realPtr);
  207. g_MaxBytesInUse = max (g_MaxBytesInUse, g_TotalBytesAllocated);
  208. pCreateSignatures (File, Line, BytesToAlloc, (PTRACKSTRUCT) realPtr);
  209. returnPtr = (PVOID) ((PBYTE) realPtr + trackStructSize);
  210. if (!(Flags & HEAP_ZERO_MEMORY)) {
  211. FillMemory (returnPtr, BytesToAlloc, 0xAA);
  212. }
  213. SetLastError (orgError);
  214. } else {
  215. g_HeapAllocFails++;
  216. }
  217. }
  218. __finally {
  219. //LeaveCriticalSection (&g_MemAllocCs);
  220. MYASSERT (TRUE); // debugger workaround
  221. }
  222. return returnPtr;
  223. }
  224. PVOID
  225. DbgHeapAllocNeverFail (
  226. PCSTR File,
  227. DWORD Line,
  228. HANDLE HeapHandle,
  229. DWORD Flags,
  230. SIZE_T BytesToAlloc
  231. )
  232. {
  233. PVOID result;
  234. INT_PTR rc;
  235. do {
  236. result = DbgHeapAlloc (File, Line, HeapHandle, Flags, BytesToAlloc);
  237. rc = MessageBoxA (
  238. g_OutOfMemoryParentWnd,
  239. g_OutOfMemoryRetry,
  240. NULL,
  241. MB_RETRYCANCEL|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  242. );
  243. if (rc == IDCANCEL) {
  244. MemOutOfMemory_Terminate();
  245. }
  246. } while (!result);
  247. return result;
  248. }
  249. PVOID
  250. DbgHeapReAlloc (
  251. PCSTR File,
  252. DWORD Line,
  253. HANDLE HeapHandle,
  254. DWORD Flags,
  255. PCVOID CallerPtr,
  256. SIZE_T BytesToAlloc
  257. )
  258. {
  259. ULONG_PTR lastSize;
  260. PVOID newRealPtr;
  261. PCVOID realPtr;
  262. PVOID returnPtr = NULL;
  263. DWORD sizeAdjust;
  264. DWORD orgError;
  265. DWORD trackStructSize;
  266. SIZE_T orgSize;
  267. PTRACKSTRUCT pts = NULL;
  268. //EnterCriticalSection (&g_MemAllocCs);
  269. __try {
  270. orgError = GetLastError();
  271. sizeAdjust = sizeof (TRACKSTRUCT) + sizeof (DWORD);
  272. trackStructSize = sizeof (TRACKSTRUCT);
  273. realPtr = (PCVOID) ((PBYTE) CallerPtr - trackStructSize);
  274. pts = (PTRACKSTRUCT) realPtr;
  275. orgSize = pts->Size;
  276. if (!HeapValidate (HeapHandle, 0, NULL)) {
  277. pHeapCallFailed ("Heap is corrupt!", File, Line);
  278. // we want to go on, most likely we will AV shortly
  279. }
  280. lastSize = pDebugHeapValidatePtrUnlocked (HeapHandle, CallerPtr, File, Line);
  281. if (lastSize == (ULONG_PTR)INVALID_PTR) {
  282. // we want to go on, most likely we will AV shortly
  283. }
  284. pCheckSignatures (pts);
  285. newRealPtr = HeapReAlloc (HeapHandle, Flags, (PVOID) realPtr, BytesToAlloc + sizeAdjust);
  286. if (newRealPtr) {
  287. g_HeapReAllocs++;
  288. g_TotalBytesAllocated -= lastSize;
  289. g_TotalBytesAllocated += HeapSize (HeapHandle, 0, newRealPtr);
  290. g_MaxBytesInUse = max (g_MaxBytesInUse, g_TotalBytesAllocated);
  291. pCreateSignatures (File, Line, BytesToAlloc, (PTRACKSTRUCT) newRealPtr);
  292. DbgUnregisterAllocation (RAW_MEMORY, realPtr);
  293. returnPtr = (PVOID) ((PBYTE) newRealPtr + trackStructSize);
  294. if (BytesToAlloc > orgSize && !(Flags & HEAP_ZERO_MEMORY)) {
  295. FillMemory ((PBYTE) returnPtr + orgSize, BytesToAlloc - orgSize, 0xAA);
  296. }
  297. SetLastError (orgError);
  298. } else {
  299. g_HeapReAllocFails++;
  300. }
  301. }
  302. __finally {
  303. //LeaveCriticalSection (&g_MemAllocCs);
  304. }
  305. return returnPtr;
  306. }
  307. PVOID
  308. DbgHeapReAllocNeverFail (
  309. PCSTR File,
  310. DWORD Line,
  311. HANDLE HeapHandle,
  312. DWORD Flags,
  313. PCVOID OldMem,
  314. SIZE_T BytesToAlloc
  315. )
  316. {
  317. PVOID result;
  318. INT_PTR rc;
  319. do {
  320. result = DbgHeapReAlloc (File, Line, HeapHandle, Flags, OldMem, BytesToAlloc);
  321. rc = MessageBoxA (
  322. g_OutOfMemoryParentWnd,
  323. g_OutOfMemoryRetry,
  324. NULL,
  325. MB_RETRYCANCEL|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  326. );
  327. if (rc == IDCANCEL) {
  328. MemOutOfMemory_Terminate();
  329. }
  330. } while (!result);
  331. return result;
  332. }
  333. BOOL
  334. DbgHeapFree (
  335. PCSTR File,
  336. DWORD Line,
  337. HANDLE HeapHandle,
  338. DWORD Flags,
  339. PCVOID CallerPtr
  340. )
  341. {
  342. ULONG_PTR size;
  343. PCVOID realPtr;
  344. DWORD sizeAdjust;
  345. DWORD orgError;
  346. BOOL result = FALSE;
  347. PTRACKSTRUCT pts = NULL;
  348. //EnterCriticalSection (&g_MemAllocCs);
  349. __try {
  350. orgError = GetLastError();
  351. sizeAdjust = sizeof (TRACKSTRUCT);
  352. realPtr = (PCVOID) ((PBYTE) CallerPtr - sizeAdjust);
  353. pts = (PTRACKSTRUCT) realPtr;
  354. if (!HeapValidate (HeapHandle, 0, NULL)) {
  355. pHeapCallFailed ("Heap is corrupt!", File, Line);
  356. g_HeapFreeFails++;
  357. __leave;
  358. }
  359. size = pDebugHeapValidatePtrUnlocked (HeapHandle, CallerPtr, File, Line);
  360. if (size == (ULONG_PTR)INVALID_PTR) {
  361. g_HeapFreeFails++;
  362. __leave;
  363. }
  364. pCheckSignatures ((PTRACKSTRUCT) realPtr);
  365. if (!HeapFree (HeapHandle, Flags, (PVOID) realPtr)) {
  366. CHAR badPtrMsg[256];
  367. wsprintfA (
  368. badPtrMsg,
  369. "Attempt to free memory at 0x%08x with flags 0x%08x. "
  370. "HeapFree() failed.",
  371. CallerPtr,
  372. Flags
  373. );
  374. pHeapCallFailed (badPtrMsg, File, Line);
  375. g_HeapFreeFails++;
  376. __leave;
  377. }
  378. g_HeapFrees++;
  379. if (g_TotalBytesAllocated < size) {
  380. DEBUGMSG ((DBG_WARNING, "Total bytes allocated is less than amount being freed. "
  381. "This suggests memory corruption."));
  382. g_TotalBytesAllocated = 0;
  383. } else {
  384. g_TotalBytesAllocated -= size;
  385. }
  386. DbgUnregisterAllocation (RAW_MEMORY, realPtr);
  387. SetLastError (orgError);
  388. result = TRUE;
  389. }
  390. __finally {
  391. //LeaveCriticalSection (&g_MemAllocCs);
  392. }
  393. return result;
  394. }
  395. VOID
  396. DbgDumpHeapStats (
  397. VOID
  398. )
  399. {
  400. CHAR OutputMsg[4096];
  401. wsprintfA (
  402. OutputMsg,
  403. "Bytes currently allocated: %u\n"
  404. "Peak bytes allocated: %u\n"
  405. "Allocation count: %u\n"
  406. "Reallocation count: %u\n"
  407. "Free count: %u\n",
  408. g_TotalBytesAllocated,
  409. g_MaxBytesInUse,
  410. g_HeapAllocs,
  411. g_HeapReAllocs,
  412. g_HeapFrees
  413. );
  414. if (g_HeapAllocFails) {
  415. wsprintfA (
  416. strchr (OutputMsg, 0),
  417. "***Allocation failures: %u\n",
  418. g_HeapAllocFails
  419. );
  420. }
  421. if (g_HeapReAllocFails) {
  422. wsprintfA (
  423. strchr (OutputMsg, 0),
  424. "***Reallocation failures: %u\n",
  425. g_HeapReAllocFails
  426. );
  427. }
  428. if (g_HeapFreeFails) {
  429. wsprintfA (
  430. strchr (OutputMsg, 0),
  431. "***Free failures: %u\n",
  432. g_HeapFreeFails
  433. );
  434. }
  435. DEBUGMSG ((DBG_STATS, "%s", OutputMsg));
  436. }
  437. VOID
  438. DbgHeapCheck (
  439. PCSTR File,
  440. DWORD Line,
  441. HANDLE HeapHandle
  442. )
  443. {
  444. //EnterCriticalSection (&g_MemAllocCs);
  445. if (!HeapValidate (HeapHandle, 0, NULL)) {
  446. pHeapCallFailed ("HeapCheck failed: Heap is corrupt!", File, Line);
  447. }
  448. //LeaveCriticalSection (&g_MemAllocCs);
  449. }
  450. PVOID
  451. DbgFastAlloc (
  452. IN PCSTR SourceFile,
  453. IN DWORD Line,
  454. IN SIZE_T Size
  455. )
  456. {
  457. //
  458. // BUGBUG - implement
  459. //
  460. return DbgHeapAlloc (SourceFile, Line, g_hHeap, 0, Size);
  461. }
  462. PVOID
  463. DbgFastReAlloc (
  464. IN PCSTR SourceFile,
  465. IN DWORD Line,
  466. IN PCVOID OldBlock,
  467. IN SIZE_T Size
  468. )
  469. {
  470. //
  471. // BUGBUG - implement
  472. //
  473. return DbgHeapReAlloc (SourceFile, Line, g_hHeap, 0, OldBlock, Size);
  474. }
  475. BOOL
  476. DbgFastFree (
  477. IN PCSTR SourceFile,
  478. IN DWORD Line,
  479. IN PCVOID Block
  480. )
  481. {
  482. //
  483. // BUGBUG - implement
  484. //
  485. return DbgHeapFree (SourceFile, Line, g_hHeap, 0, Block);
  486. }
  487. PVOID
  488. DbgFastAllocNeverFail (
  489. IN PCSTR SourceFile,
  490. IN DWORD Line,
  491. IN SIZE_T Size
  492. )
  493. {
  494. //
  495. // BUGBUG - implement
  496. //
  497. return DbgHeapAlloc (SourceFile, Line, g_hHeap, 0, Size);
  498. }
  499. PVOID
  500. DbgFastReAllocNeverFail (
  501. IN PCSTR SourceFile,
  502. IN DWORD Line,
  503. IN PCVOID OldBlock,
  504. IN SIZE_T Size
  505. )
  506. {
  507. //
  508. // BUGBUG - implement
  509. //
  510. return DbgHeapReAlloc (SourceFile, Line, g_hHeap, 0, OldBlock, Size);
  511. }
  512. #else
  513. PVOID
  514. MemFastAlloc (
  515. IN SIZE_T Size
  516. )
  517. {
  518. //
  519. // BUGBUG - implement
  520. //
  521. return HeapAlloc (g_hHeap, 0, Size);
  522. }
  523. PVOID
  524. MemFastReAlloc (
  525. IN PCVOID OldBlock,
  526. IN SIZE_T Size
  527. )
  528. {
  529. //
  530. // BUGBUG - implement
  531. //
  532. return HeapReAlloc (g_hHeap, 0, (PVOID) OldBlock, Size);
  533. }
  534. BOOL
  535. MemFastFree (
  536. IN PCVOID Block
  537. )
  538. {
  539. //
  540. // BUGBUG - implement
  541. //
  542. return HeapFree (g_hHeap, 0, (PVOID) Block);
  543. }
  544. PVOID
  545. MemFastAllocNeverFail (
  546. IN SIZE_T Size
  547. )
  548. {
  549. //
  550. // BUGBUG - implement
  551. //
  552. return MemAllocNeverFail (g_hHeap, 0, Size);
  553. }
  554. PVOID
  555. MemFastReAllocNeverFail (
  556. IN PVOID OldBlock,
  557. IN SIZE_T Size
  558. )
  559. {
  560. //
  561. // BUGBUG - implement
  562. //
  563. return MemReAllocNeverFail (g_hHeap, 0, OldBlock, Size);
  564. }
  565. #endif
  566. PVOID
  567. MemReuseAlloc (
  568. IN HANDLE Heap,
  569. IN PVOID OldPtr, OPTIONAL
  570. IN DWORD SizeNeeded
  571. )
  572. {
  573. DWORD CurrentSize;
  574. PVOID Ptr = NULL;
  575. UINT AllocAdjustment = sizeof(DWORD);
  576. //
  577. // HeapSize is not very good, so while it may look good, don't
  578. // use it.
  579. //
  580. #ifdef DEBUG
  581. AllocAdjustment += sizeof (DWORD);
  582. #endif
  583. if (!OldPtr) {
  584. Ptr = MemAlloc (Heap, 0, SizeNeeded + AllocAdjustment);
  585. } else {
  586. CurrentSize = *REUSE_SIZE_PTR(OldPtr);
  587. #ifdef DEBUG
  588. if (*REUSE_TAG_PTR(OldPtr) != 0x10a28a70) {
  589. DEBUGMSG ((DBG_WHOOPS, "MemReuse detected corruption!"));
  590. Ptr = MemAlloc (Heap, 0, SizeNeeded + AllocAdjustment);
  591. } else
  592. #endif
  593. if (SizeNeeded > CurrentSize) {
  594. SizeNeeded += 1024 - (SizeNeeded & 1023);
  595. Ptr = MemReAlloc (Heap, 0, REUSE_SIZE_PTR(OldPtr), SizeNeeded + AllocAdjustment);
  596. OldPtr = NULL;
  597. }
  598. }
  599. if (Ptr) {
  600. *((PDWORD) Ptr) = SizeNeeded;
  601. Ptr = (PVOID) ((PBYTE) Ptr + sizeof (DWORD));
  602. #ifdef DEBUG
  603. *REUSE_TAG_PTR(Ptr) = 0x10a28a70;
  604. #endif
  605. }
  606. return Ptr ? Ptr : OldPtr;
  607. }
  608. VOID
  609. MemReuseFree (
  610. HANDLE Heap,
  611. PVOID Ptr
  612. )
  613. {
  614. if (Ptr) {
  615. MemFree (Heap, 0, REUSE_SIZE_PTR(Ptr));
  616. }
  617. }
  618. VOID
  619. MemSetOutOfMemoryParent (
  620. HWND hwnd
  621. )
  622. {
  623. g_OutOfMemoryParentWnd = hwnd;
  624. }
  625. VOID
  626. MemOutOfMemory_Terminate (
  627. VOID
  628. )
  629. {
  630. if (!g_OutOfMemoryString || !g_OutOfMemoryString[0]) {
  631. return;
  632. }
  633. MessageBoxA (
  634. g_OutOfMemoryParentWnd,
  635. g_OutOfMemoryString,
  636. NULL,
  637. MB_OK|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  638. );
  639. ExitProcess (0);
  640. //
  641. // Not needed, will never get here
  642. //
  643. // TerminateProcess (GetModuleHandle (NULL), 0);
  644. }
  645. VOID
  646. pValidateBlock (
  647. PVOID Block,
  648. SIZE_T Size
  649. )
  650. /*++
  651. Routine Description:
  652. pValidateBlock makes sure Block is non-NULL. If it is NULL, then the user
  653. is given a popup, unless the request size is bogus.
  654. There are two cases for the popup.
  655. - If g_OutOfMemoryParentWnd was set with SetOutOfMemoryParent,
  656. then the user is asked to close other programs, and is given a retry
  657. option.
  658. - If there is no out of memory parent, then the user is told they
  659. need to get more memory.
  660. In either case, Setup is terminated. In GUI mode, Setup will be
  661. stuck and the machine will be unbootable.
  662. Arguments:
  663. Block - Specifies the block to validate.
  664. Size - Specifies the request size
  665. Return Value:
  666. none
  667. --*/
  668. {
  669. LONG rc;
  670. if (!Block && Size < 0x2000000) {
  671. if (g_OutOfMemoryParentWnd) {
  672. rc = MessageBoxA (
  673. g_OutOfMemoryParentWnd,
  674. g_OutOfMemoryRetry,
  675. NULL,
  676. MB_RETRYCANCEL|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST
  677. );
  678. if (rc == IDCANCEL) {
  679. MemOutOfMemory_Terminate();
  680. }
  681. } else {
  682. MemOutOfMemory_Terminate();
  683. }
  684. } else {
  685. if (!Block) {
  686. // this is serious. We want to break now and give Dr. Watson a
  687. // chance to get our stack.
  688. BreakPoint();
  689. }
  690. }
  691. }
  692. #ifndef DEBUG
  693. PVOID
  694. MemAllocNeverFail (
  695. HANDLE Heap,
  696. DWORD Flags,
  697. SIZE_T Size
  698. )
  699. {
  700. PVOID Block;
  701. do {
  702. Block = HeapAlloc (Heap, Flags, Size);
  703. pValidateBlock (Block, Size);
  704. } while (!Block);
  705. return Block;
  706. }
  707. PVOID
  708. MemReAllocNeverFail (
  709. HANDLE Heap,
  710. DWORD Flags,
  711. PVOID OldBlock,
  712. SIZE_T Size
  713. )
  714. {
  715. PVOID Block;
  716. do {
  717. Block = HeapReAlloc (Heap, Flags, OldBlock, Size);
  718. pValidateBlock (Block, Size);
  719. } while (!Block);
  720. return Block;
  721. }
  722. #endif
  723. #ifdef DEBUG
  724. VOID
  725. pCreateSignatures (
  726. PCSTR File,
  727. DWORD Line,
  728. SIZE_T Size,
  729. PTRACKSTRUCT Pointer
  730. )
  731. {
  732. DWORD signature;
  733. PBYTE end;
  734. DbgRegisterAllocation (RAW_MEMORY, Pointer, File, Line);
  735. Pointer->Signature = TRACK_SIGNATURE;
  736. Pointer->Size = Size;
  737. end = (PBYTE) Pointer + sizeof (TRACKSTRUCT) + Size;
  738. signature = TRAIL_SIG;
  739. CopyMemory (end, &signature, sizeof (DWORD));
  740. }
  741. VOID
  742. pCheckSignatures (
  743. IN PTRACKSTRUCT Pointer
  744. )
  745. {
  746. DWORD signature;
  747. PBYTE end;
  748. if (Pointer->Signature != TRACK_SIGNATURE) {
  749. DEBUGMSG ((DBG_ERROR, "A tracking head signature is invalid. "
  750. "This suggests memory corruption."));
  751. return;
  752. }
  753. end = (PBYTE) Pointer + sizeof (TRACKSTRUCT) + Pointer->Size;
  754. CopyMemory (&signature, end, sizeof (DWORD));
  755. if (signature != TRAIL_SIG) {
  756. DEBUGMSG ((DBG_ERROR, "A tracking trail signature is invalid. "
  757. "This suggests memory corruption."));
  758. return;
  759. }
  760. }
  761. #endif
  762. BOOL
  763. MemInitialize (
  764. VOID
  765. )
  766. {
  767. if (g_MemTlsIndex) {
  768. return TRUE;
  769. }
  770. g_MemTlsIndex = TlsAlloc();
  771. if (g_MemTlsIndex == TLS_OUT_OF_INDEXES) {
  772. return FALSE;
  773. }
  774. if (!g_hHeap) {
  775. g_hHeap = GetProcessHeap();
  776. }
  777. return TRUE;
  778. }
  779. PVOID
  780. MemFastAllocAndZero (
  781. IN SIZE_T Size
  782. )
  783. {
  784. PVOID result;
  785. result = MemFastAlloc (Size);
  786. if (result) {
  787. ZeroMemory (result, Size);
  788. }
  789. return result;
  790. }
  791. PVOID
  792. MemFastReAllocAndZero (
  793. IN PCVOID Ptr,
  794. IN SIZE_T Size
  795. )
  796. {
  797. SIZE_T orgSize;
  798. PVOID result;
  799. orgSize = HeapSize (g_hHeap, 0, Ptr);
  800. result = MemFastReAlloc (Ptr, Size);
  801. if (result && Size > orgSize) {
  802. ZeroMemory ((PBYTE) result + orgSize, Size - orgSize);
  803. }
  804. return result;
  805. }