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.

882 lines
23 KiB

  1. /*
  2. * Copyright (c) 1985 - 1999, Microsoft Corporation
  3. */
  4. #include "precomp.h"
  5. #if DBG
  6. WIN32HEAP gWin32Heaps[MAX_HEAPS];
  7. /*
  8. * These globals are used to fail gFail allocs and the succeed the next gSucceed
  9. * Set with Win32HeapStat
  10. */
  11. DWORD gFail, gSucceed;
  12. DWORD gToFail, gToSucceed;
  13. /*
  14. * Support to keep records of pool free
  15. */
  16. HEAPRECORD garrFreeHeapRecord[64];
  17. CONST DWORD gdwFreeHeapRecords = ARRAY_SIZE(garrFreeHeapRecord);
  18. DWORD gdwFreeHeapRecordCrtIndex;
  19. DWORD gdwFreeHeapRecordTotalFrees;
  20. #ifdef _USERK_
  21. FAST_MUTEX* gpHeapFastMutex;
  22. #define EnterHeapCrit() \
  23. KeEnterCriticalRegion(); \
  24. ExAcquireFastMutexUnsafe(pheap->pFastMutex);
  25. #define LeaveHeapCrit() \
  26. ExReleaseFastMutexUnsafe(pheap->pFastMutex); \
  27. KeLeaveCriticalRegion();
  28. #define EnterGlobalHeapCrit() \
  29. KeEnterCriticalRegion(); \
  30. ExAcquireFastMutexUnsafe(gpHeapFastMutex);
  31. #define LeaveGlobalHeapCrit() \
  32. ExReleaseFastMutexUnsafe(gpHeapFastMutex); \
  33. KeLeaveCriticalRegion();
  34. #else
  35. RTL_CRITICAL_SECTION gheapCritSec;
  36. #define EnterHeapCrit() RtlEnterCriticalSection(&pheap->critSec)
  37. #define LeaveHeapCrit() RtlLeaveCriticalSection(&pheap->critSec)
  38. #define EnterGlobalHeapCrit() RtlEnterCriticalSection(&gheapCritSec)
  39. #define LeaveGlobalHeapCrit() RtlLeaveCriticalSection(&gheapCritSec)
  40. #endif
  41. /***************************************************************************\
  42. * InitWin32HeapStubs
  43. *
  44. * Initialize heap stub management
  45. *
  46. * History:
  47. * 11/10/98 CLupu Created
  48. \***************************************************************************/
  49. BOOL InitWin32HeapStubs(
  50. VOID)
  51. {
  52. #ifdef _USERK_
  53. gpHeapFastMutex = ExAllocatePoolWithTag(NonPagedPool,
  54. sizeof(FAST_MUTEX),
  55. 'yssU');
  56. if (gpHeapFastMutex == NULL) {
  57. RIPMSG0(RIP_WARNING, "Fail to create fast mutex for heap allocations");
  58. return FALSE;
  59. }
  60. ExInitializeFastMutex(gpHeapFastMutex);
  61. #else
  62. if (!NT_SUCCESS(RtlInitializeCriticalSection(&gheapCritSec))) {
  63. RIPMSG0(RIP_WARNING, "Fail to initialize critical section for heap allocations");
  64. return FALSE;
  65. }
  66. #endif
  67. return TRUE;
  68. }
  69. /***************************************************************************\
  70. * CleanupWin32HeapStubs
  71. *
  72. * Cleanup heap stub management
  73. *
  74. * History:
  75. * 11/10/98 CLupu Created
  76. \***************************************************************************/
  77. VOID CleanupWin32HeapStubs(
  78. VOID)
  79. {
  80. #ifdef _USERK_
  81. if (gpHeapFastMutex != NULL) {
  82. ExFreePool(gpHeapFastMutex);
  83. gpHeapFastMutex = NULL;
  84. }
  85. #else
  86. RtlDeleteCriticalSection(&gheapCritSec);
  87. #endif
  88. }
  89. /***************************************************************************\
  90. * Win32HeapGetHandle
  91. *
  92. * stub routine for Heap management
  93. *
  94. * History:
  95. * 11/10/98 CLupu Created
  96. \***************************************************************************/
  97. PVOID Win32HeapGetHandle(
  98. PWIN32HEAP pheap)
  99. {
  100. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  101. return pheap->heap;
  102. }
  103. /***************************************************************************\
  104. * Win32HeapCreateTag
  105. *
  106. * stub routine for Heap management
  107. *
  108. * History:
  109. * 11/10/98 CLupu Created
  110. \***************************************************************************/
  111. ULONG Win32HeapCreateTag(
  112. PWIN32HEAP pheap,
  113. ULONG Flags,
  114. PWSTR TagPrefix,
  115. PWSTR TagNames)
  116. {
  117. #ifndef _USERK_
  118. UserAssert(pheap->dwFlags & WIN32_HEAP_INUSE);
  119. pheap->dwFlags |= WIN32_HEAP_USE_HM_TAGS;
  120. return RtlCreateTagHeap(pheap->heap, Flags, TagPrefix, TagNames);
  121. #endif // _USERK_
  122. return 0;
  123. UNREFERENCED_PARAMETER(Flags);
  124. UNREFERENCED_PARAMETER(TagPrefix);
  125. UNREFERENCED_PARAMETER(TagNames);
  126. }
  127. /***************************************************************************\
  128. * Win32HeapCreate
  129. *
  130. * stub routine for Heap management
  131. *
  132. * History:
  133. * 11/10/98 CLupu Created
  134. \***************************************************************************/
  135. PWIN32HEAP Win32HeapCreate(
  136. char* pszHead,
  137. char* pszTail,
  138. ULONG Flags,
  139. PVOID HeapBase,
  140. SIZE_T ReserveSize,
  141. SIZE_T CommitSize,
  142. PVOID Lock,
  143. PRTL_HEAP_PARAMETERS Parameters)
  144. {
  145. int ind;
  146. PWIN32HEAP pheap = NULL;
  147. UserAssert(strlen(pszHead) == HEAP_CHECK_SIZE - sizeof(char));
  148. UserAssert(strlen(pszTail) == HEAP_CHECK_SIZE - sizeof(char));
  149. EnterGlobalHeapCrit();
  150. /*
  151. * Walk the global array of heaps to get an empty spot
  152. */
  153. for (ind = 0; ind < MAX_HEAPS; ind++) {
  154. if (gWin32Heaps[ind].dwFlags & WIN32_HEAP_INUSE)
  155. continue;
  156. /*
  157. * Found an empty spot
  158. */
  159. break;
  160. }
  161. if (ind >= MAX_HEAPS) {
  162. RIPMSG1(RIP_ERROR, "Too many heaps created %d", ind);
  163. goto Exit;
  164. }
  165. pheap = &gWin32Heaps[ind];
  166. #ifdef _USERK_
  167. /*
  168. * Initialize the fast mutex that will protect the memory
  169. * allocations for this heap
  170. */
  171. pheap->pFastMutex = ExAllocatePoolWithTag(NonPagedPool,
  172. sizeof(FAST_MUTEX),
  173. 'yssU');
  174. if (pheap->pFastMutex == NULL) {
  175. RIPMSG0(RIP_WARNING, "Fail to create fast mutex for heap allocations");
  176. pheap = NULL;
  177. goto Exit;
  178. }
  179. ExInitializeFastMutex(pheap->pFastMutex);
  180. #else
  181. /*
  182. * Initialize the critical section that will protect the memory
  183. * allocations for this heap
  184. */
  185. if (!NT_SUCCESS(RtlInitializeCriticalSection(&pheap->critSec))) {
  186. RIPMSG0(RIP_WARNING, "Fail to initialize critical section for heap allocations");
  187. pheap = NULL;
  188. goto Exit;
  189. }
  190. #endif
  191. /*
  192. * Create the heap
  193. */
  194. pheap->heap = RtlCreateHeap(Flags,
  195. HeapBase,
  196. ReserveSize,
  197. CommitSize,
  198. Lock,
  199. Parameters);
  200. if (pheap->heap == NULL) {
  201. RIPMSG0(RIP_WARNING, "Fail to create heap");
  202. #ifdef _USERK_
  203. ExFreePool(pheap->pFastMutex);
  204. pheap->pFastMutex = NULL;
  205. #else
  206. RtlDeleteCriticalSection(&pheap->critSec);
  207. #endif
  208. pheap = NULL;
  209. goto Exit;
  210. }
  211. pheap->dwFlags = (WIN32_HEAP_INUSE | WIN32_HEAP_USE_GUARDS);
  212. pheap->heapReserveSize = ReserveSize;
  213. RtlCopyMemory(pheap->szHead, pszHead, HEAP_CHECK_SIZE);
  214. RtlCopyMemory(pheap->szTail, pszTail, HEAP_CHECK_SIZE);
  215. Exit:
  216. LeaveGlobalHeapCrit();
  217. return pheap;
  218. }
  219. /***************************************************************************\
  220. * Win32HeapDestroy
  221. *
  222. * stub routine for Heap management
  223. *
  224. * History:
  225. * 11/10/98 CLupu Created
  226. \***************************************************************************/
  227. BOOL Win32HeapDestroy(
  228. PWIN32HEAP pheap)
  229. {
  230. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  231. EnterGlobalHeapCrit();
  232. /*
  233. * Mark the spot available
  234. */
  235. pheap->dwFlags = 0;
  236. RtlDestroyHeap(pheap->heap);
  237. #ifdef _USERK_
  238. ExFreePool(pheap->pFastMutex);
  239. pheap->pFastMutex = NULL;
  240. #else
  241. RtlDeleteCriticalSection(&pheap->critSec);
  242. #endif
  243. RtlZeroMemory(pheap, sizeof(WIN32HEAP));
  244. LeaveGlobalHeapCrit();
  245. return TRUE;
  246. }
  247. /***************************************************************************\
  248. * Win32HeapSize
  249. *
  250. * stub routine for Heap management
  251. *
  252. * History:
  253. * 11/10/98 CLupu Created
  254. \***************************************************************************/
  255. SIZE_T Win32HeapSize(
  256. PWIN32HEAP pheap,
  257. PVOID p)
  258. {
  259. PDbgHeapHead ph;
  260. if (!Win32HeapCheckAlloc(pheap, p)) {
  261. return 0;
  262. }
  263. ph = (PDbgHeapHead)p - 1;
  264. return ph->size;
  265. }
  266. /***************************************************************************\
  267. * Win32HeapAlloc
  268. *
  269. * stub routine for Heap management
  270. *
  271. * History:
  272. * 11/10/98 CLupu Created
  273. \***************************************************************************/
  274. PVOID Win32HeapAlloc(
  275. PWIN32HEAP pheap,
  276. SIZE_T uSize,
  277. DWORD tag,
  278. ULONG Flags)
  279. {
  280. PVOID p = NULL;
  281. PDbgHeapHead ph;
  282. SIZE_T uRealSize = uSize;
  283. #ifdef HEAP_ALLOC_TRACE
  284. ULONG hash;
  285. #endif
  286. EnterHeapCrit();
  287. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  288. /*
  289. * Fail if this heap has WIN32_HEAP_FAIL_ALLOC set.
  290. */
  291. if (pheap->dwFlags & WIN32_HEAP_FAIL_ALLOC) {
  292. RIPMSG3(RIP_WARNING, "Heap allocation failed because of global restriction. heap %#p, size 0x%x tag %d",
  293. pheap, uSize, tag);
  294. goto Exit;
  295. }
  296. /*
  297. * Fail if gToFail is set.
  298. */
  299. if (gToFail) {
  300. if (--gToFail == 0) {
  301. gToSucceed = gSucceed;
  302. }
  303. RIPMSG3(RIP_WARNING, "Heap allocation failed on temporary restriction. heap %#p, size 0x%x tag %d",
  304. pheap, uSize, tag);
  305. goto Exit;
  306. }
  307. if (gToSucceed) {
  308. if (--gToSucceed) {
  309. gToFail = gFail;
  310. }
  311. }
  312. /*
  313. * Calculate the size that we actually are going to allocate.
  314. */
  315. uSize += sizeof(DbgHeapHead);
  316. if (pheap->dwFlags & WIN32_HEAP_USE_GUARDS) {
  317. uSize += sizeof(pheap->szHead) + sizeof(pheap->szTail);
  318. }
  319. p = RtlAllocateHeap(pheap->heap,
  320. Flags,
  321. uSize);
  322. if (p == NULL) {
  323. RIPMSG3(RIP_WARNING, "Heap allocation failed. heap %#p, size 0x%x tag %d",
  324. pheap, uSize, tag);
  325. goto Exit;
  326. }
  327. /*
  328. * Copy the secure strings in the head and tail of the allocation.
  329. */
  330. if (pheap->dwFlags & WIN32_HEAP_USE_GUARDS) {
  331. RtlCopyMemory((PBYTE)p,
  332. pheap->szHead,
  333. sizeof(pheap->szHead));
  334. RtlCopyMemory((PBYTE)p + uSize - sizeof(pheap->szTail),
  335. pheap->szTail,
  336. sizeof(pheap->szTail));
  337. ph = (PDbgHeapHead)((PBYTE)p + sizeof(pheap->szHead));
  338. } else {
  339. ph = (PDbgHeapHead)p;
  340. }
  341. /*
  342. * Zero out the header
  343. */
  344. RtlZeroMemory(ph, sizeof(DbgHeapHead));
  345. ph->mark = HEAP_ALLOC_MARK;
  346. ph->pheap = pheap;
  347. ph->size = uRealSize;
  348. ph->tag = tag;
  349. #ifdef _USERK_
  350. ph->pid = HandleToUlong(PsGetCurrentProcessId());
  351. #else // !_USERK_
  352. ph->pid = GetCurrentProcessId();
  353. #endif // _USERK_
  354. #ifdef HEAP_ALLOC_TRACE
  355. RtlZeroMemory(ph->trace, HEAP_ALLOC_TRACE_SIZE * sizeof(PVOID));
  356. RtlCaptureStackBackTrace(
  357. 1,
  358. HEAP_ALLOC_TRACE_SIZE,
  359. ph->trace,
  360. &hash);
  361. #endif // HEAP_ALLOC_TRACE
  362. /*
  363. * Now link it into the list for this tag (if any).
  364. */
  365. ph->pPrev = NULL;
  366. ph->pNext = pheap->pFirstAlloc;
  367. (pheap->crtAllocations)++;
  368. pheap->crtMemory += uRealSize;
  369. if (pheap->maxAllocations < pheap->crtAllocations) {
  370. pheap->maxAllocations = pheap->crtAllocations;
  371. }
  372. if (pheap->maxMemory < pheap->crtMemory) {
  373. pheap->maxMemory = pheap->crtMemory;
  374. }
  375. if (pheap->pFirstAlloc != NULL) {
  376. pheap->pFirstAlloc->pPrev = ph;
  377. }
  378. pheap->pFirstAlloc = ph;
  379. p = (PVOID)(ph + 1);
  380. Exit:
  381. LeaveHeapCrit();
  382. return p;
  383. }
  384. /***************************************************************************\
  385. * RecordFreeHeap
  386. *
  387. * Records free heap
  388. *
  389. * 3-24-99 CLupu Created.
  390. \***************************************************************************/
  391. VOID RecordFreeHeap(
  392. PWIN32HEAP pheap,
  393. PVOID p,
  394. SIZE_T size)
  395. {
  396. garrFreeHeapRecord[gdwFreeHeapRecordCrtIndex].p = p;
  397. garrFreeHeapRecord[gdwFreeHeapRecordCrtIndex].size = size;
  398. garrFreeHeapRecord[gdwFreeHeapRecordCrtIndex].pheap = pheap;
  399. gdwFreeHeapRecordTotalFrees++;
  400. RtlZeroMemory(garrFreeHeapRecord[gdwFreeHeapRecordCrtIndex].trace,
  401. RECORD_HEAP_STACK_TRACE_SIZE * sizeof(PVOID));
  402. RtlWalkFrameChain(garrFreeHeapRecord[gdwFreeHeapRecordCrtIndex].trace,
  403. RECORD_HEAP_STACK_TRACE_SIZE,
  404. 0);
  405. gdwFreeHeapRecordCrtIndex++;
  406. if (gdwFreeHeapRecordCrtIndex >= gdwFreeHeapRecords) {
  407. gdwFreeHeapRecordCrtIndex = 0;
  408. }
  409. }
  410. /***************************************************************************\
  411. * Win32HeapReAlloc
  412. *
  413. * stub routine for Heap management
  414. *
  415. * History:
  416. * 11/10/98 CLupu Created
  417. \***************************************************************************/
  418. PVOID Win32HeapReAlloc(
  419. PWIN32HEAP pheap,
  420. PVOID p,
  421. SIZE_T uSize,
  422. ULONG Flags)
  423. {
  424. PVOID pdest;
  425. PDbgHeapHead ph;
  426. if (!Win32HeapCheckAlloc(pheap, p)) {
  427. return NULL;
  428. }
  429. ph = (PDbgHeapHead)p - 1;
  430. pdest = Win32HeapAlloc(pheap, uSize, ph->tag, Flags);
  431. if (pdest != NULL) {
  432. /*
  433. * If the block is shrinking, don't copy too many bytes.
  434. */
  435. if (ph->size < uSize) {
  436. uSize = ph->size;
  437. }
  438. RtlCopyMemory(pdest, p, uSize);
  439. Win32HeapFree(pheap, p);
  440. }
  441. return pdest;
  442. }
  443. /***************************************************************************\
  444. * Win32HeapFree
  445. *
  446. * stub routine for Heap management
  447. *
  448. * History:
  449. * 11/10/98 CLupu Created
  450. \***************************************************************************/
  451. BOOL Win32HeapFree(
  452. PWIN32HEAP pheap,
  453. PVOID p)
  454. {
  455. PDbgHeapHead ph;
  456. SIZE_T uSize;
  457. BOOL bRet;
  458. EnterHeapCrit();
  459. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  460. ph = (PDbgHeapHead)p - 1;
  461. /*
  462. * Validate always on free
  463. */
  464. Win32HeapCheckAlloc(pheap, p);
  465. UserAssert((pheap->crtAllocations > 1 && pheap->crtMemory > ph->size) ||
  466. (pheap->crtAllocations == 1 && pheap->crtMemory == ph->size));
  467. (pheap->crtAllocations)--;
  468. pheap->crtMemory -= ph->size;
  469. /*
  470. * now, remove it from the linked list
  471. */
  472. if (ph->pPrev == NULL) {
  473. if (ph->pNext == NULL) {
  474. pheap->pFirstAlloc = NULL;
  475. } else {
  476. ph->pNext->pPrev = NULL;
  477. pheap->pFirstAlloc = ph->pNext;
  478. }
  479. } else {
  480. ph->pPrev->pNext = ph->pNext;
  481. if (ph->pNext != NULL) {
  482. ph->pNext->pPrev = ph->pPrev;
  483. }
  484. }
  485. uSize = ph->size + sizeof(DbgHeapHead);
  486. if (pheap->dwFlags & WIN32_HEAP_USE_GUARDS) {
  487. p = (PVOID)((BYTE*)ph - sizeof(pheap->szHead));
  488. uSize += sizeof(pheap->szHead) + sizeof(pheap->szTail);
  489. } else {
  490. p = (PVOID)ph;
  491. }
  492. RecordFreeHeap(pheap, p, ph->size);
  493. /*
  494. * Fill the allocation with a pattern that we can recognize
  495. * after the free takes place.
  496. */
  497. RtlFillMemoryUlong(p, uSize, (0xCACA0000 | ph->tag));
  498. /*
  499. * Free the allocation
  500. */
  501. bRet = RtlFreeHeap(pheap->heap, 0, p);
  502. LeaveHeapCrit();
  503. return bRet;
  504. }
  505. /***************************************************************************\
  506. * Win32HeapCheckAlloc
  507. *
  508. * validates heap allocations in a heap
  509. *
  510. * History:
  511. * 11/10/98 CLupu Created
  512. \***************************************************************************/
  513. BOOL Win32HeapCheckAllocHeader(
  514. PWIN32HEAP pheap,
  515. PDbgHeapHead ph)
  516. {
  517. PBYTE pb;
  518. if (ph == NULL) {
  519. RIPMSG0(RIP_ERROR, "NULL pointer passed to Win32HeapCheckAllocHeader");
  520. return FALSE;
  521. }
  522. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  523. /*
  524. * Make sure it's one of our heap allocations
  525. */
  526. if (ph->mark != HEAP_ALLOC_MARK) {
  527. RIPMSG2(RIP_ERROR, "%#p invalid heap allocation for pheap %#p",
  528. ph, pheap);
  529. return FALSE;
  530. }
  531. /*
  532. * Make sure it belongs to this heap
  533. */
  534. if (ph->pheap != pheap) {
  535. RIPMSG3(RIP_ERROR, "%#p heap allocation for heap %#p belongs to a different heap %#p",
  536. ph,
  537. pheap,
  538. ph->pheap);
  539. return FALSE;
  540. }
  541. if (pheap->dwFlags & WIN32_HEAP_USE_GUARDS) {
  542. pb = (BYTE*)ph - sizeof(pheap->szHead);
  543. if (!RtlEqualMemory(pb, pheap->szHead, sizeof(pheap->szHead))) {
  544. RIPMSG2(RIP_ERROR, "head corrupted for heap %#p allocation %#p", pheap, ph);
  545. return FALSE;
  546. }
  547. pb = (BYTE*)ph + ph->size + sizeof(*ph);
  548. if (!RtlEqualMemory(pb, pheap->szTail, sizeof(pheap->szTail))) {
  549. RIPMSG2(RIP_ERROR, "tail corrupted for heap %#p allocation %#p",
  550. pheap,
  551. ph);
  552. return FALSE;
  553. }
  554. }
  555. return TRUE;
  556. }
  557. /***************************************************************************\
  558. * Win32HeapCheckAlloc
  559. *
  560. * validates heap allocations in a heap
  561. *
  562. * History:
  563. * 11/10/98 CLupu Created
  564. \***************************************************************************/
  565. BOOL Win32HeapCheckAlloc(
  566. PWIN32HEAP pheap,
  567. PVOID p)
  568. {
  569. PDbgHeapHead ph;
  570. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  571. if (p == NULL) {
  572. RIPMSG0(RIP_ERROR, "NULL pointer passed to Win32HeapCheckAlloc");
  573. return FALSE;
  574. }
  575. ph = (PDbgHeapHead)p - 1;
  576. return Win32HeapCheckAllocHeader(pheap, ph);
  577. }
  578. /***************************************************************************\
  579. * Win32HeapValidate
  580. *
  581. * validates all the heap allocations in a heap
  582. *
  583. * History:
  584. * 11/10/98 CLupu Created
  585. \***************************************************************************/
  586. BOOL Win32HeapValidate(
  587. PWIN32HEAP pheap)
  588. {
  589. PDbgHeapHead ph;
  590. UserAssert(pheap != NULL && (pheap->dwFlags & WIN32_HEAP_INUSE));
  591. EnterHeapCrit();
  592. ph = pheap->pFirstAlloc;
  593. while (ph != NULL) {
  594. Win32HeapCheckAllocHeader(pheap, ph);
  595. ph = ph->pNext;
  596. }
  597. LeaveHeapCrit();
  598. #ifndef _USERK_
  599. return RtlValidateHeap(pheap->heap, 0, NULL);
  600. #else
  601. return TRUE;
  602. #endif
  603. }
  604. /***************************************************************************\
  605. * Win32HeapDump
  606. *
  607. * dump heap allocations in a heap
  608. *
  609. * History:
  610. * 11/10/98 CLupu Created
  611. \***************************************************************************/
  612. VOID Win32HeapDump(
  613. PWIN32HEAP pheap)
  614. {
  615. PDbgHeapHead pAlloc = pheap->pFirstAlloc;
  616. if (pAlloc == NULL) {
  617. return;
  618. }
  619. UserAssert(pAlloc->pPrev == NULL);
  620. RIPMSG1(RIP_WARNING, "-- Dumping heap allocations for heap %#p... --",
  621. pheap);
  622. while (pAlloc != NULL) {
  623. DbgPrint("tag %04d size %08d\n", pAlloc->tag, pAlloc->size);
  624. pAlloc = pAlloc->pNext;
  625. }
  626. RIPMSG0(RIP_WARNING, "--- End Dump ---");
  627. }
  628. /***************************************************************************\
  629. * Win32HeapFailAllocations
  630. *
  631. * fails the heap allocations
  632. *
  633. * History:
  634. * 11/10/98 CLupu Created
  635. \***************************************************************************/
  636. VOID Win32HeapFailAllocations(
  637. BOOL bFail)
  638. {
  639. PWIN32HEAP pheap;
  640. int ind;
  641. EnterGlobalHeapCrit();
  642. for (ind = 0; ind < MAX_HEAPS; ind++) {
  643. pheap = &gWin32Heaps[ind];
  644. if (!(pheap->dwFlags & WIN32_HEAP_INUSE))
  645. continue;
  646. EnterHeapCrit();
  647. if (bFail) {
  648. pheap->dwFlags |= WIN32_HEAP_FAIL_ALLOC;
  649. RIPMSG1(RIP_WARNING, "Heap allocations for heap %#p will fail !", pheap);
  650. } else {
  651. pheap->dwFlags &= ~WIN32_HEAP_FAIL_ALLOC;
  652. }
  653. LeaveHeapCrit();
  654. }
  655. LeaveGlobalHeapCrit();
  656. }
  657. /***************************************************************************\
  658. * Win32HeapStat
  659. *
  660. * Retrieves the heap statistics.
  661. * dwLen is the size of phs in bytes. If there are more tags in this module
  662. * than what the caller requested, a higher buffer is asked for by returning
  663. * the total number of tags in use.
  664. * winsrv uses the MAKE_TAG macro to construct their tags, so it needs to pass
  665. * TRUE for bNeedTagShift
  666. *
  667. * If there is only one structure passed in, the phs->dwSize will hold gXFail
  668. * and phs->dwCount will hold gYFail to be used to fail gXFail allocs and then
  669. * succeed the next gYFail allocations.
  670. *
  671. * History:
  672. * 02/25/99 MCostea Created
  673. \***************************************************************************/
  674. DWORD Win32HeapStat(
  675. PDBGHEAPSTAT phs,
  676. DWORD dwLen,
  677. BOOL bNeedTagShift)
  678. {
  679. PWIN32HEAP pheap;
  680. PDbgHeapHead pAlloc;
  681. UINT ind, maxTagExpected, maxTag, currentTag;
  682. /*
  683. * We need at least one structure to do anything
  684. */
  685. if (dwLen < sizeof(DBGHEAPSTAT)) {
  686. return 0;
  687. }
  688. if (dwLen == sizeof(DBGHEAPSTAT)) {
  689. /*
  690. * This call is actually intended to set the gXFail and gYFail parameters
  691. */
  692. gFail = phs->dwSize;
  693. gSucceed = phs->dwCount;
  694. gToFail = gFail;
  695. return 1;
  696. }
  697. RtlZeroMemory(phs, dwLen);
  698. maxTagExpected = dwLen/sizeof(DBGHEAPSTAT) - 1;
  699. maxTag = 0;
  700. EnterGlobalHeapCrit();
  701. for (ind = 0; ind < MAX_HEAPS; ind++) {
  702. pheap = &gWin32Heaps[ind];
  703. if (!(pheap->dwFlags & WIN32_HEAP_INUSE))
  704. continue;
  705. EnterHeapCrit();
  706. pAlloc = pheap->pFirstAlloc;
  707. while (pAlloc != NULL) {
  708. currentTag = pAlloc->tag;
  709. if (bNeedTagShift) {
  710. currentTag >>= HEAP_TAG_SHIFT;
  711. }
  712. if (maxTag < currentTag) {
  713. maxTag = currentTag;
  714. }
  715. if (currentTag <= maxTagExpected) {
  716. phs[currentTag].dwSize += (DWORD)(pAlloc->size);
  717. phs[currentTag].dwCount++;
  718. }
  719. pAlloc = pAlloc->pNext;
  720. }
  721. LeaveHeapCrit();
  722. }
  723. LeaveGlobalHeapCrit();
  724. /*
  725. * Now fill the dwTag for tags that have allocations
  726. */
  727. for (ind = 0; ind < maxTagExpected; ind++) {
  728. if (phs[ind].dwCount) {
  729. phs[ind].dwTag = ind;
  730. }
  731. }
  732. return maxTag;
  733. }
  734. #endif // DBG