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.

829 lines
23 KiB

  1. /***************************************************************************\
  2. *
  3. * File: SimpleHelp.cpp
  4. *
  5. * Description:
  6. * SimpleHeap.cpp implements the heap operations used throughout DirectUser.
  7. *
  8. *
  9. * History:
  10. * 11/26/1999: JStall: Created
  11. *
  12. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  13. *
  14. \***************************************************************************/
  15. #include "stdafx.h"
  16. #include "Base.h"
  17. #include "SimpleHeap.h"
  18. #include "List.h"
  19. #include "Locks.h"
  20. DWORD g_tlsHeap = (DWORD) -1;
  21. HANDLE g_hHeap = NULL;
  22. DUserHeap * g_pheapProcess;
  23. /***************************************************************************\
  24. *****************************************************************************
  25. *
  26. * class DUserHeap
  27. *
  28. *****************************************************************************
  29. \***************************************************************************/
  30. //------------------------------------------------------------------------------
  31. DUserHeap::DUserHeap()
  32. {
  33. m_cRef = 1;
  34. }
  35. //------------------------------------------------------------------------------
  36. void
  37. DUserHeap::Lock()
  38. {
  39. SafeIncrement(&m_cRef);
  40. }
  41. //------------------------------------------------------------------------------
  42. BOOL
  43. DUserHeap::Unlock()
  44. {
  45. AssertMsg(m_cRef > 0, "Must have an outstanding referenced");
  46. if (SafeDecrement(&m_cRef) == 0) {
  47. placement_delete(this, DUserHeap);
  48. HeapFree(g_hHeap, 0, this);
  49. return FALSE; // Heap is no longer valid
  50. }
  51. return TRUE; // Heap is still valid
  52. }
  53. #ifdef _DEBUG // Needs DEBUG CRT's
  54. /***************************************************************************\
  55. *****************************************************************************
  56. *
  57. * class CrtDbgHeap
  58. *
  59. *****************************************************************************
  60. \***************************************************************************/
  61. //------------------------------------------------------------------------------
  62. class CrtDbgHeap : public DUserHeap
  63. {
  64. // Construction
  65. public:
  66. virtual ~CrtDbgHeap();
  67. // Operations
  68. public:
  69. virtual void * Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS);
  70. virtual void * Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS);
  71. virtual void MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS);
  72. virtual void Free(void * pvMem);
  73. virtual void MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize);
  74. };
  75. //------------------------------------------------------------------------------
  76. CrtDbgHeap::~CrtDbgHeap()
  77. {
  78. }
  79. //------------------------------------------------------------------------------
  80. void *
  81. CrtDbgHeap::Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS)
  82. {
  83. void * pvMem = _malloc_dbg(cbSize, _NORMAL_BLOCK, pszFileName, idxLineNum);
  84. if ((pvMem != NULL) && fZero) {
  85. ZeroMemory(pvMem, cbSize);
  86. }
  87. return pvMem;
  88. }
  89. //------------------------------------------------------------------------------
  90. void *
  91. CrtDbgHeap::Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS)
  92. {
  93. void * pvNewMem = _realloc_dbg(pvMem, cbNewSize, _NORMAL_BLOCK, pszFileName, idxLineNum);
  94. return pvNewMem;
  95. }
  96. //------------------------------------------------------------------------------
  97. void
  98. CrtDbgHeap::MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS)
  99. {
  100. int idx = 0;
  101. while (idx < cItems) {
  102. prgAlloc[idx] = _malloc_dbg(cbSize, _NORMAL_BLOCK, pszFileName, idxLineNum);
  103. if (prgAlloc[idx] == NULL) {
  104. break;
  105. }
  106. idx++;
  107. }
  108. *pnActual = idx;
  109. }
  110. //------------------------------------------------------------------------------
  111. void
  112. CrtDbgHeap::Free(void * pvMem)
  113. {
  114. _free_dbg(pvMem, _NORMAL_BLOCK);
  115. }
  116. //------------------------------------------------------------------------------
  117. void
  118. CrtDbgHeap::MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize)
  119. {
  120. UNREFERENCED_PARAMETER(cbSize);
  121. for (int idx = 0; idx < cItems; idx++) {
  122. _free_dbg(prgAlloc[idx], _NORMAL_BLOCK);
  123. }
  124. }
  125. #endif // _DEBUG
  126. /***************************************************************************\
  127. *****************************************************************************
  128. *
  129. * class NtHeap
  130. *
  131. *****************************************************************************
  132. \***************************************************************************/
  133. //------------------------------------------------------------------------------
  134. class NtHeap : public DUserHeap
  135. {
  136. // Construction
  137. public:
  138. inline NtHeap();
  139. virtual ~NtHeap();
  140. HRESULT Create(BOOL fSerialize);
  141. inline void Destroy();
  142. inline void Attach(HANDLE hHeap, BOOL fPassOwnership);
  143. inline HANDLE Detach();
  144. // Operations
  145. public:
  146. virtual void * Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS);
  147. virtual void * Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS);
  148. virtual void MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS);
  149. virtual void Free(void * pvMem);
  150. virtual void MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize);
  151. // Implementation
  152. protected:
  153. inline DWORD GetFlags(DWORD dwExtra = 0) const;
  154. // Data
  155. protected:
  156. HANDLE m_hHeap;
  157. BOOL m_fOwnHeap:1;
  158. BOOL m_fSerialize:1;
  159. };
  160. //------------------------------------------------------------------------------
  161. inline
  162. NtHeap::NtHeap()
  163. {
  164. m_hHeap = NULL;
  165. m_fOwnHeap = FALSE;
  166. m_fSerialize = FALSE;
  167. }
  168. //------------------------------------------------------------------------------
  169. NtHeap::~NtHeap()
  170. {
  171. Destroy();
  172. }
  173. //------------------------------------------------------------------------------
  174. HRESULT
  175. NtHeap::Create(BOOL fSerialize)
  176. {
  177. AssertMsg(m_hHeap == NULL, "Can not re-create heap");
  178. m_hHeap = HeapCreate(fSerialize ? 0 : HEAP_NO_SERIALIZE, 256 * 1024, 0);
  179. if (m_hHeap != NULL) {
  180. m_fOwnHeap = TRUE;
  181. m_fSerialize = fSerialize;
  182. }
  183. return m_hHeap != NULL ? S_OK : E_OUTOFMEMORY;
  184. }
  185. //------------------------------------------------------------------------------
  186. inline void
  187. NtHeap::Destroy()
  188. {
  189. if (m_fOwnHeap && (m_hHeap != NULL)) {
  190. HeapDestroy(m_hHeap);
  191. m_hHeap = NULL;
  192. m_fOwnHeap = FALSE;
  193. m_fSerialize = FALSE;
  194. }
  195. }
  196. //------------------------------------------------------------------------------
  197. inline void
  198. NtHeap::Attach(HANDLE hHeap, BOOL fPassOwnership)
  199. {
  200. AssertMsg(hHeap != NULL, "Must specify valid heap");
  201. AssertMsg(m_hHeap == NULL, "Can re-attach heap");
  202. m_hHeap = hHeap;
  203. m_fOwnHeap = fPassOwnership;
  204. m_fSerialize = TRUE;
  205. }
  206. //------------------------------------------------------------------------------
  207. inline HANDLE
  208. NtHeap::Detach()
  209. {
  210. HANDLE hHeap = m_hHeap;
  211. m_hHeap = NULL;
  212. m_fOwnHeap = FALSE;
  213. m_fSerialize = FALSE;
  214. return hHeap;
  215. }
  216. //------------------------------------------------------------------------------
  217. inline DWORD
  218. NtHeap::GetFlags(DWORD dwExtra) const
  219. {
  220. return dwExtra | (m_fSerialize ? 0 : HEAP_NO_SERIALIZE);
  221. }
  222. //------------------------------------------------------------------------------
  223. void *
  224. NtHeap::Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS)
  225. {
  226. DBG_HEAP_USE;
  227. return HeapAlloc(m_hHeap, GetFlags(fZero ? HEAP_ZERO_MEMORY : 0), cbSize);
  228. }
  229. //------------------------------------------------------------------------------
  230. void *
  231. NtHeap::Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS)
  232. {
  233. DBG_HEAP_USE;
  234. DWORD dwFlags = GetFlags(HEAP_ZERO_MEMORY);
  235. if (pvMem == NULL) {
  236. return HeapAlloc(m_hHeap, dwFlags, cbNewSize);
  237. } else {
  238. return HeapReAlloc(m_hHeap, dwFlags, pvMem, cbNewSize);
  239. }
  240. }
  241. //------------------------------------------------------------------------------
  242. void
  243. NtHeap::MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS)
  244. {
  245. DBG_HEAP_USE;
  246. DWORD dwFlags = GetFlags();
  247. int idx = 0;
  248. while (idx < cItems) {
  249. prgAlloc[idx] = HeapAlloc(m_hHeap, dwFlags, cbSize);
  250. if (prgAlloc[idx] == NULL) {
  251. break;
  252. }
  253. idx++;
  254. }
  255. *pnActual = idx;
  256. }
  257. //------------------------------------------------------------------------------
  258. void
  259. NtHeap::Free(void * pvMem)
  260. {
  261. if (pvMem != NULL) {
  262. HeapFree(m_hHeap, 0, pvMem);
  263. }
  264. }
  265. //------------------------------------------------------------------------------
  266. void
  267. NtHeap::MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize)
  268. {
  269. UNREFERENCED_PARAMETER(cbSize);
  270. DWORD dwFlags = GetFlags(0);
  271. for (int idx = 0; idx < cItems; idx++) {
  272. if (prgAlloc[idx] != NULL) {
  273. HeapFree(m_hHeap, dwFlags, prgAlloc[idx]);
  274. }
  275. }
  276. }
  277. /***************************************************************************\
  278. *****************************************************************************
  279. *
  280. * class RockAllHeap
  281. *
  282. *****************************************************************************
  283. \***************************************************************************/
  284. #if USE_ROCKALL
  285. #include <Rockall.hpp>
  286. #pragma comment(lib, "RAHeap.lib")
  287. #pragma comment(lib, "RALibrary.lib")
  288. #pragma comment(lib, "Rockall.lib")
  289. //------------------------------------------------------------------------------
  290. class RockAllHeap : public DUserHeap
  291. {
  292. // Construction
  293. public:
  294. RockAllHeap(BOOL fSerialize);
  295. HRESULT Create();
  296. // Operations
  297. public:
  298. virtual void * Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS);
  299. virtual void * Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS);
  300. virtual void MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS);
  301. virtual void Free(void * pvMem);
  302. virtual void MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize);
  303. // Implementation
  304. protected:
  305. class CustomHeap : public ROCKALL
  306. {
  307. // Construction
  308. public:
  309. CustomHeap(bool ThreadSafe=true, int MaxFreeSpace=4194304, bool Recycle=true, bool SingleImage=false);
  310. };
  311. // Data
  312. protected:
  313. CustomHeap m_heap;
  314. };
  315. //------------------------------------------------------------------------------
  316. RockAllHeap::RockAllHeap(BOOL fSerialize) : m_heap(!!fSerialize)
  317. {
  318. }
  319. //------------------------------------------------------------------------------
  320. HRESULT
  321. RockAllHeap::Create()
  322. {
  323. return m_heap.Corrupt() ? E_OUTOFMEMORY : S_OK;
  324. }
  325. //------------------------------------------------------------------------------
  326. void *
  327. RockAllHeap::Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS)
  328. {
  329. DBG_HEAP_USE;
  330. return m_heap.New(cbSize, NULL, fZero);
  331. }
  332. //------------------------------------------------------------------------------
  333. void *
  334. RockAllHeap::Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS)
  335. {
  336. DBG_HEAP_USE;
  337. return m_heap.Resize(pvMem, cbNewSize);
  338. }
  339. //------------------------------------------------------------------------------
  340. void
  341. RockAllHeap::MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS)
  342. {
  343. DBG_HEAP_USE;
  344. m_heap.MultipleNew(pnActual, prgAlloc, cItems, cbSize, NULL, false);
  345. }
  346. //------------------------------------------------------------------------------
  347. void
  348. RockAllHeap::Free(void * pvMem)
  349. {
  350. m_heap.Delete(pvMem);
  351. }
  352. //------------------------------------------------------------------------------
  353. void
  354. RockAllHeap::MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize)
  355. {
  356. m_heap.MultipleDelete(cItems, prgAlloc, cbSize);
  357. }
  358. const int FindCacheSize = 4096;
  359. const int FindCacheThreshold = 0;
  360. const int FindSize = 2048;
  361. const int Stride1 = 8;
  362. const int Stride2 = 1024;
  363. /********************************************************************/
  364. /* */
  365. /* The description of the heap. */
  366. /* */
  367. /* A heap is a collection of fixed sized allocation caches. */
  368. /* An allocation cache consists of an allocation size, the */
  369. /* number of pre-built allocations to cache, a chunk size and */
  370. /* a parent page size which is sub-divided to create elements */
  371. /* for this cache. A heap consists of two arrays of caches. */
  372. /* Each of these arrays has a stride (i.e. 'Stride1' and */
  373. /* 'Stride2') which is typically the smallest common factor of */
  374. /* all the allocation sizes in the array. */
  375. /* */
  376. /********************************************************************/
  377. //
  378. // NOTE: DUser needs to ensure that all memory is allocated on 8 byte
  379. // boundaries. This is used be several external components, including
  380. // S-Lists. To ensure this, the smallest "Bucket Size" must be >= 8 bytes.
  381. //
  382. static ROCKALL::CACHE_DETAILS Caches1[] =
  383. {
  384. //
  385. // Bucket Size Of Bucket Parent
  386. // Size Cache Chunks Page Size
  387. //
  388. { 16, 128, 4096, 4096 },
  389. { 24, 64, 4096, 4096 },
  390. { 32, 64, 4096, 4096 },
  391. { 40, 256, 4096, 4096 },
  392. { 64, 256, 4096, 4096 },
  393. { 80, 256, 4096, 4096 },
  394. { 128, 32, 4096, 4096 },
  395. { 256, 16, 4096, 4096 },
  396. { 512, 4, 4096, 4096 },
  397. { 0,0,0,0 }
  398. };
  399. static ROCKALL::CACHE_DETAILS Caches2[] =
  400. {
  401. //
  402. // Bucket Size Of Bucket Parent
  403. // Size Cache Chunks Page Size
  404. //
  405. { 1024, 16, 4096, 4096 },
  406. { 2048, 16, 4096, 4096 },
  407. { 3072, 4, 65536, 65536 },
  408. { 4096, 8, 65536, 65536 },
  409. { 5120, 4, 65536, 65536 },
  410. { 6144, 4, 65536, 65536 },
  411. { 7168, 4, 65536, 65536 },
  412. { 8192, 8, 65536, 65536 },
  413. { 9216, 0, 65536, 65536 },
  414. { 10240, 0, 65536, 65536 },
  415. { 12288, 0, 65536, 65536 },
  416. { 16384, 2, 65536, 65536 },
  417. { 21504, 0, 65536, 65536 },
  418. { 32768, 0, 65536, 65536 },
  419. { 65536, 0, 65536, 65536 },
  420. { 65536, 0, 65536, 65536 },
  421. { 0,0,0,0 }
  422. };
  423. /********************************************************************/
  424. /* */
  425. /* The description bit vectors. */
  426. /* */
  427. /* All heaps keep track of allocations using bit vectors. An */
  428. /* allocation requires 2 bits to keep track of its state. The */
  429. /* following array supplies the size of the available bit */
  430. /* vectors measured in 32 bit words. */
  431. /* */
  432. /********************************************************************/
  433. static int NewPageSizes[] = { 1,4,16,64,128,0 };
  434. //------------------------------------------------------------------------------
  435. RockAllHeap::CustomHeap::CustomHeap(bool ThreadSafe, int MaxFreeSpace, bool Recycle, bool SingleImage) :
  436. ROCKALL(Caches1, Caches2, FindCacheSize, FindCacheThreshold, FindSize,
  437. MaxFreeSpace, NewPageSizes, Recycle, SingleImage,
  438. Stride1, Stride2, ThreadSafe)
  439. {
  440. }
  441. #endif // USE_ROCKALL
  442. //------------------------------------------------------------------------------
  443. HRESULT
  444. CreateProcessHeap()
  445. {
  446. AssertMsg(g_pheapProcess == NULL, "Only should init process heap once");
  447. g_tlsHeap = TlsAlloc();
  448. if (g_tlsHeap == (DWORD) -1) {
  449. return E_OUTOFMEMORY;
  450. }
  451. g_hHeap = GetProcessHeap();
  452. DUserHeap * pNewHeap;
  453. #ifdef _DEBUG
  454. pNewHeap = (DUserHeap *) HeapAlloc(g_hHeap, 0, sizeof(CrtDbgHeap));
  455. #else
  456. pNewHeap = (DUserHeap *) HeapAlloc(g_hHeap, 0, sizeof(NtHeap));
  457. #endif
  458. if (pNewHeap == NULL) {
  459. return E_OUTOFMEMORY;
  460. }
  461. #ifdef _DEBUG
  462. placement_new(pNewHeap, CrtDbgHeap);
  463. #else
  464. placement_new(pNewHeap, NtHeap);
  465. ((NtHeap *) pNewHeap)->Attach(g_hHeap, FALSE /* Don't pass ownership */);
  466. #endif
  467. g_pheapProcess = pNewHeap;
  468. return S_OK;
  469. }
  470. //------------------------------------------------------------------------------
  471. void
  472. DestroyProcessHeap()
  473. {
  474. if (g_pheapProcess != NULL) {
  475. g_pheapProcess->Unlock();
  476. g_pheapProcess = NULL;
  477. }
  478. if (g_tlsHeap == (DWORD) -1) {
  479. TlsFree(g_tlsHeap);
  480. g_tlsHeap = (DWORD) -1;
  481. }
  482. g_hHeap = NULL;
  483. }
  484. /***************************************************************************\
  485. *
  486. * CreateContextHeap
  487. *
  488. * CreateContextHeap() initializes the thread-specific heap to either an
  489. * existing heap or a new heap. All threads in the same Context should be
  490. * initialized with the same heap so that they can safely shared data between
  491. * threads. When the Context is finally destroyed, call DestroyContextHeap()
  492. * to cleanup the heap.
  493. *
  494. \***************************************************************************/
  495. HRESULT
  496. CreateContextHeap(
  497. IN DUserHeap * pLinkHeap, // Existing heap to share
  498. IN BOOL fThreadSafe, // Heap mode
  499. IN DUserHeap::EHeap id, // Heap type
  500. OUT DUserHeap ** ppNewHeap) // New heap (OPTIONAL)
  501. {
  502. HRESULT hr;
  503. if (ppNewHeap != NULL) {
  504. *ppNewHeap = NULL;
  505. }
  506. //
  507. // Check if a heap already exists.
  508. //
  509. // NOTE: This will occur on the starting thread because the initial heap
  510. // must be initialized so that we can create new objects.
  511. //
  512. DUserHeap * pNewHeap = reinterpret_cast<DUserHeap *> (TlsGetValue(g_tlsHeap));
  513. if (pNewHeap == NULL) {
  514. if (pLinkHeap == NULL) {
  515. //
  516. // Need to create a new heap.
  517. //
  518. switch (id)
  519. {
  520. case DUserHeap::idProcessHeap:
  521. case DUserHeap::idNtHeap:
  522. pNewHeap = (DUserHeap *) HeapAlloc(g_hHeap, 0, sizeof(NtHeap));
  523. break;
  524. #ifdef _DEBUG
  525. case DUserHeap::idCrtDbgHeap:
  526. pNewHeap = (DUserHeap *) HeapAlloc(g_hHeap, 0, sizeof(CrtDbgHeap));
  527. break;
  528. #endif
  529. #if USE_ROCKALL
  530. case DUserHeap::idRockAllHeap:
  531. pNewHeap = (DUserHeap *) HeapAlloc(g_hHeap, 0, sizeof(RockAllHeap));
  532. break;
  533. #endif
  534. default:
  535. AssertMsg(0, "Unknown heap type");
  536. }
  537. if (pNewHeap == NULL) {
  538. return E_OUTOFMEMORY;
  539. }
  540. hr = E_FAIL;
  541. switch (id)
  542. {
  543. case DUserHeap::idProcessHeap:
  544. placement_new(pNewHeap, NtHeap);
  545. ((NtHeap *) pNewHeap)->Attach(g_hHeap, FALSE /* Don't pass ownership */);
  546. hr = S_OK;
  547. break;
  548. case DUserHeap::idNtHeap:
  549. placement_new(pNewHeap, NtHeap);
  550. hr = ((NtHeap *) pNewHeap)->Create(fThreadSafe);
  551. break;
  552. #ifdef _DEBUG
  553. case DUserHeap::idCrtDbgHeap:
  554. placement_new(pNewHeap, CrtDbgHeap);
  555. hr = S_OK;
  556. break;
  557. #endif
  558. #if USE_ROCKALL
  559. case DUserHeap::idRockAllHeap:
  560. placement_new1(pNewHeap, RockAllHeap, fThreadSafe);
  561. hr = ((RockAllHeap *) pNewHeap)->Create();
  562. break;
  563. #endif
  564. default:
  565. AssertMsg(0, "Unknown heap type");
  566. }
  567. if (FAILED(hr)) {
  568. pNewHeap->Unlock();
  569. return hr;
  570. }
  571. } else {
  572. pLinkHeap->Lock();
  573. pNewHeap = pLinkHeap;
  574. }
  575. Verify(TlsSetValue(g_tlsHeap, pNewHeap));
  576. }
  577. if (ppNewHeap != NULL) {
  578. *ppNewHeap = pNewHeap;
  579. }
  580. return S_OK;
  581. }
  582. /***************************************************************************\
  583. *
  584. * DestroyContextHeap
  585. *
  586. * DestroyContextHeap() frees resources used by a Context's shared heap.
  587. *
  588. \***************************************************************************/
  589. void
  590. DestroyContextHeap(
  591. IN DUserHeap * pHeapDestroy) // Heap to destroy
  592. {
  593. if (pHeapDestroy != NULL) {
  594. pHeapDestroy->Unlock();
  595. }
  596. DUserHeap * pHeap = reinterpret_cast<DUserHeap *> (TlsGetValue(g_tlsHeap));
  597. if (pHeapDestroy == pHeap) {
  598. Verify(TlsSetValue(g_tlsHeap, NULL));
  599. }
  600. }
  601. /***************************************************************************\
  602. *
  603. * ForceSetContextHeap
  604. *
  605. * ForceSetContextHeap() is called during shutdown when it is necessary to
  606. * "force" the current thread to use a different thread's heap so that the
  607. * objects can be properly destroyed.
  608. *
  609. * NOTE: This function must be VERY carefully called since it directly
  610. * changes the heap for a thread. It should only be called from the
  611. * ResourceManager when destroying threads.
  612. *
  613. \***************************************************************************/
  614. void
  615. ForceSetContextHeap(
  616. IN DUserHeap * pHeapThread) // Heap to use on this Thread
  617. {
  618. Verify(TlsSetValue(g_tlsHeap, pHeapThread));
  619. }
  620. #if DBG
  621. //------------------------------------------------------------------------------
  622. void
  623. DumpData(
  624. IN void * pMem,
  625. IN int nLength)
  626. {
  627. int row = 4;
  628. char * pszData = (char *) pMem;
  629. int cbData = min(16, nLength);
  630. int cbTotal = 0;
  631. //
  632. // For each row, we will dump up to 16 characters in both hexidecimal
  633. // and if an actual character, their displayed character.
  634. //
  635. while ((row-- > 0) && (cbTotal < nLength)) {
  636. int cb = cbData;
  637. char * pszDump = pszData;
  638. Trace("0x%p: ", pszData);
  639. int cbTemp = cbTotal;
  640. while (cb-- > 0) {
  641. cbTemp++;
  642. if (cbTemp > nLength) {
  643. Trace(" ");
  644. } else {
  645. Trace("%02x ", (unsigned char) (*pszDump++));
  646. }
  647. }
  648. Trace(" ");
  649. cb = cbData;
  650. while (cb-- > 0) {
  651. char ch = (unsigned char) (*pszData++);
  652. Trace("%c", IsCharAlphaNumeric(ch) ? ch : '.');
  653. cbTotal++;
  654. if (cbTotal > nLength) {
  655. break;
  656. }
  657. }
  658. Trace("\n");
  659. }
  660. Trace("\n");
  661. }
  662. #endif // DBG