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.

1441 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. heapdbg.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Heap debugging routines.
  8. Author:
  9. Jim Gilroy (jamesg) January 31, 1995
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "heapdbg.h"
  14. //
  15. // locking
  16. //
  17. #define LOCK_HEAP(p) EnterCriticalSection( &p->ListCs )
  18. #define UNLOCK_HEAP(p) LeaveCriticalSection( &p->ListCs )
  19. //
  20. // Heap
  21. //
  22. // Debug heap routines allow heap to be specified by caller of
  23. // each routine, or by having heap global.
  24. // If global, the heap handle may be supplied to initialization
  25. // routine OR created internally.
  26. //
  27. #define HEAP_DBG_DEFAULT_CREATE_FLAGS \
  28. ( HEAP_GROWABLE | \
  29. HEAP_GENERATE_EXCEPTIONS | \
  30. HEAP_TAIL_CHECKING_ENABLED | \
  31. HEAP_FREE_CHECKING_ENABLED | \
  32. HEAP_CREATE_ALIGN_16 | \
  33. HEAP_CLASS_1 )
  34. //
  35. // Dnslib using this heap
  36. //
  37. PHEAP_BLOB g_pDnslibHeapBlob;
  38. HEAP_BLOB g_DnslibHeapBlob;
  39. //
  40. // Heap Header / Trailer Flags
  41. //
  42. #define HEAP_CODE 0xdddddddd
  43. #define HEAP_CODE_ACTIVE 0xaaaaaaaa
  44. #define HEAP_CODE_FREE 0xeeeeeeee
  45. //
  46. // Heap Trailer from Header
  47. //
  48. #define HEAP_TRAILER(_head_) \
  49. ( (PHEAP_TRAILER) ( \
  50. (PCHAR)(_head_) \
  51. + (_head_)->AllocSize \
  52. - sizeof(HEAP_TRAILER) ) )
  53. //
  54. // Private protos
  55. //
  56. VOID
  57. DbgHeapValidateHeader(
  58. IN PHEAP_HEADER h
  59. );
  60. //
  61. // Private utilities
  62. //
  63. INT
  64. DbgHeapFindAllocSize(
  65. IN INT iRequestSize
  66. )
  67. /*++
  68. Routine Description:
  69. Determines actual size of debug alloc.
  70. Adds in sizes of DWORD aligned header and trailer.
  71. Arguments:
  72. iRequestSize - requested allocation size
  73. Return Value:
  74. None
  75. --*/
  76. {
  77. register INT imodSize;
  78. //
  79. // find DWORD multiple size of original alloc,
  80. // this is required so debug trailer will be DWORD aligned
  81. //
  82. imodSize = iRequestSize % sizeof(DWORD);
  83. if ( imodSize )
  84. {
  85. imodSize = sizeof(DWORD) - imodSize;
  86. }
  87. imodSize += iRequestSize + sizeof(HEAP_HEADER) + sizeof(HEAP_TRAILER);
  88. ASSERT( ! (imodSize % sizeof(DWORD)) );
  89. return( imodSize );
  90. }
  91. PVOID
  92. DbgHeapSetHeaderAlloc(
  93. IN OUT PHEAP_BLOB pHeap,
  94. IN OUT PHEAP_HEADER h,
  95. IN INT iSize,
  96. IN LPSTR pszFile,
  97. IN DWORD dwLine
  98. )
  99. /*++
  100. Routine Description:
  101. Sets/Resets heap globals and heap header info.
  102. Arguments:
  103. h - ptr to new memory block
  104. iSize - size allocated
  105. Return Value:
  106. None
  107. --*/
  108. {
  109. PHEAP_TRAILER t;
  110. INT allocSize;
  111. ASSERT( iSize > 0 );
  112. //
  113. // determine actual alloc
  114. //
  115. allocSize = DbgHeapFindAllocSize( iSize );
  116. //
  117. // update heap info globals
  118. //
  119. pHeap->AllocMem += allocSize;
  120. pHeap->CurrentMem += allocSize;
  121. pHeap->AllocCount++;
  122. pHeap->CurrentCount++;
  123. //
  124. // fill in header
  125. //
  126. h->HeapCodeBegin = HEAP_CODE;
  127. h->AllocCount = pHeap->AllocCount;
  128. h->AllocSize = allocSize;
  129. h->RequestSize = iSize;
  130. h->LineNo = dwLine;
  131. h->FileName = pszFile;
  132. #if 0
  133. allocSize = strlen(pszFile) - HEAP_HEADER_FILE_SIZE;
  134. if ( allocSize > 0 )
  135. {
  136. pszFile = &pszFile[ allocSize ];
  137. }
  138. strncpy(
  139. h->FileName,
  140. pszFile,
  141. HEAP_HEADER_FILE_SIZE );
  142. #endif
  143. h->AllocTime = GetCurrentTime();
  144. h->CurrentMem = pHeap->CurrentMem;
  145. h->CurrentCount = pHeap->CurrentCount;
  146. h->HeapCodeEnd = HEAP_CODE_ACTIVE;
  147. //
  148. // fill in trailer
  149. //
  150. t = HEAP_TRAILER( h );
  151. t->HeapCodeBegin = h->HeapCodeBegin;
  152. t->AllocCount = h->AllocCount;
  153. t->AllocSize = h->AllocSize;
  154. t->HeapCodeEnd = h->HeapCodeEnd;
  155. //
  156. // attach to alloc list
  157. //
  158. LOCK_HEAP(pHeap);
  159. InsertTailList( &pHeap->ListHead, &h->ListEntry );
  160. UNLOCK_HEAP(pHeap);
  161. //
  162. // return ptr to user memory
  163. // - first byte past header
  164. //
  165. return( h+1 );
  166. }
  167. PHEAP_HEADER
  168. DbgHeapSetHeaderFree(
  169. IN OUT PHEAP_BLOB pHeap,
  170. IN OUT PVOID pMem
  171. )
  172. /*++
  173. Routine Description:
  174. Resets heap globals and heap header info for free.
  175. Arguments:
  176. pMem - ptr to user memory to free
  177. Return Value:
  178. Ptr to block to be freed.
  179. --*/
  180. {
  181. register PHEAP_HEADER h;
  182. //
  183. // validate memory block -- get ptr to header
  184. //
  185. h = Dns_DbgHeapValidateMemory( pMem, TRUE );
  186. //
  187. // get blob if not passed in
  188. //
  189. if ( !pHeap )
  190. {
  191. pHeap = h->pHeap;
  192. }
  193. //
  194. // remove from current allocs list
  195. //
  196. LOCK_HEAP(pHeap);
  197. RemoveEntryList( &h->ListEntry );
  198. UNLOCK_HEAP(pHeap);
  199. //
  200. // update heap info globals
  201. //
  202. pHeap->CurrentMem -= h->AllocSize;
  203. pHeap->FreeMem += h->AllocSize;
  204. pHeap->FreeCount++;
  205. pHeap->CurrentCount--;
  206. //
  207. // reset header
  208. //
  209. h->HeapCodeEnd = HEAP_CODE_FREE;
  210. HEAP_TRAILER(h)->HeapCodeBegin = HEAP_CODE_FREE;
  211. //
  212. // return ptr to block to be freed
  213. //
  214. return( h );
  215. }
  216. //
  217. // Heap Init\Cleanup
  218. //
  219. VOID
  220. Dns_HeapInitialize(
  221. OUT PHEAP_BLOB pHeap,
  222. IN HANDLE hHeap,
  223. IN DWORD dwCreateFlags,
  224. IN BOOL fUseHeaders,
  225. IN BOOL fResetDnslib,
  226. IN BOOL fFullHeapChecks,
  227. IN DWORD dwException,
  228. IN DWORD dwDefaultFlags,
  229. IN PSTR pszDefaultFileName,
  230. IN DWORD dwDefaultFileLine
  231. )
  232. /*++
  233. Routine Description:
  234. Initialize heap debugging.
  235. MUST call this routine before using DbgHeapMessage routines.
  236. Arguments:
  237. pHeap -- heap blob to setup
  238. hHeap -- heap to use
  239. dwCreateFlags -- flags to RtlCreateHeap() if creating
  240. fUseHeaders -- use headers and trailers for full debug
  241. fResetDnslib -- reset dnslib heap to use these routines
  242. fFullHeapChecks -- flag, TRUE for full heap checks
  243. dwException -- exception to raise if out of heap
  244. dwDefaultFlags -- heap flags for simple alloc\free
  245. pszDefaultFileName -- file name for simple alloc\free
  246. dwDefaultFileLine -- file line# for simple alloc\free
  247. Return Value:
  248. None.
  249. --*/
  250. {
  251. DNSDBG( TRACE, (
  252. "Dns_DbgHeapInit( %p )\n",
  253. pHeap ));
  254. //
  255. // zero heap blob
  256. //
  257. RtlZeroMemory(
  258. pHeap,
  259. sizeof(*pHeap) );
  260. // alloc list
  261. // - alloc list head
  262. // - critical section to protect list operations
  263. InitializeListHead( &pHeap->ListHead );
  264. if ( fUseHeaders )
  265. {
  266. InitializeCriticalSection( &pHeap->ListCs );
  267. }
  268. //
  269. // heap
  270. // can either
  271. // - always get heap in each call
  272. // - use heap caller supplies here
  273. // - create a heap here
  274. //
  275. // to use simple dnslib compatible calls we must have
  276. // a known heap, so must get one created here
  277. // DCR: not sure this is TRUE, process heap may work
  278. // g_hDnsHeap left NULL
  279. //
  280. if ( hHeap )
  281. {
  282. pHeap->hHeap = hHeap;
  283. }
  284. else
  285. {
  286. pHeap->hHeap = RtlCreateHeap(
  287. dwCreateFlags
  288. ? dwCreateFlags
  289. : HEAP_DBG_DEFAULT_CREATE_FLAGS,
  290. NULL, // no base specified
  291. 0, // default reserve size
  292. 0, // default commit size
  293. NULL, // no lock
  294. NULL // no parameters
  295. );
  296. pHeap->fCreated = TRUE;
  297. }
  298. pHeap->Tag = HEAP_CODE_ACTIVE;
  299. // set globals
  300. // - full heap checks before all heap operations?
  301. // - raise exception on alloc failure?
  302. pHeap->fHeaders = fUseHeaders;
  303. pHeap->fCheckAll = fFullHeapChecks;
  304. pHeap->FailureException = dwException;
  305. // set globals for simple allocator
  306. pHeap->DefaultFlags = dwDefaultFlags;
  307. pHeap->pszDefaultFile = pszDefaultFileName;
  308. pHeap->DefaultLine = dwDefaultFileLine;
  309. // reset dnslib heap routines to use debug heap
  310. if ( fResetDnslib )
  311. {
  312. if ( fUseHeaders )
  313. {
  314. Dns_LibHeapReset(
  315. Dns_DbgHeapAlloc,
  316. Dns_DbgHeapRealloc,
  317. Dns_DbgHeapFree );
  318. }
  319. else
  320. {
  321. Dns_LibHeapReset(
  322. Dns_HeapAlloc,
  323. Dns_HeapRealloc,
  324. Dns_HeapFree );
  325. }
  326. g_pDnslibHeapBlob = pHeap;
  327. }
  328. }
  329. VOID
  330. Dns_HeapCleanup(
  331. IN OUT PHEAP_BLOB pHeap
  332. )
  333. /*++
  334. Routine Description:
  335. Cleanup.
  336. Arguments:
  337. None.
  338. Return Value:
  339. None.
  340. --*/
  341. {
  342. DNSDBG( TRACE, ( "Dns_HeapCleanup( %p )\n", pHeap ));
  343. // if not initialized -- do nothing
  344. if ( !pHeap )
  345. {
  346. return;
  347. }
  348. if ( pHeap->Tag != HEAP_CODE_ACTIVE )
  349. {
  350. DNS_ASSERT( pHeap->Tag == HEAP_CODE_ACTIVE );
  351. return;
  352. }
  353. DNS_ASSERT( pHeap->hHeap );
  354. // if created heap, destroy it
  355. if ( pHeap->fCreated )
  356. {
  357. RtlDestroyHeap( pHeap->hHeap );
  358. }
  359. // cleanup critical section
  360. if ( pHeap->fHeaders )
  361. {
  362. RtlDeleteCriticalSection( &pHeap->ListCs );
  363. }
  364. // tag as invalid
  365. pHeap->Tag = HEAP_CODE_FREE;
  366. }
  367. //
  368. // Heap Validation
  369. //
  370. VOID
  371. DbgHeapValidateHeader(
  372. IN PHEAP_HEADER h
  373. )
  374. /*++
  375. Routine Description:
  376. Validates heap header.
  377. Arguments:
  378. h - ptr to header of block
  379. Return Value:
  380. None.
  381. --*/
  382. {
  383. register PHEAP_TRAILER t;
  384. //
  385. // extract trailer
  386. //
  387. t = HEAP_TRAILER( h );
  388. //
  389. // verify header
  390. //
  391. if ( h->HeapCodeBegin != HEAP_CODE
  392. ||
  393. h->HeapCodeEnd != HEAP_CODE_ACTIVE )
  394. {
  395. DNSDBG( HEAPDBG, (
  396. "Invalid memory block at %p -- invalid header.\n",
  397. h ));
  398. if ( h->HeapCodeEnd == HEAP_CODE_FREE )
  399. {
  400. DNSDBG( HEAPDBG, (
  401. "ERROR: Previous freed memory.\n" ));
  402. }
  403. goto Invalid;
  404. }
  405. //
  406. // match header, trailer alloc number
  407. //
  408. if ( h->HeapCodeBegin != t->HeapCodeBegin
  409. ||
  410. h->AllocCount != t->AllocCount
  411. ||
  412. h->AllocSize != t->AllocSize
  413. ||
  414. h->HeapCodeEnd != t->HeapCodeEnd )
  415. {
  416. DNSDBG( HEAPDBG, (
  417. "Invalid memory block at %p -- header / trailer mismatch.\n",
  418. h ));
  419. goto Invalid;
  420. }
  421. return;
  422. Invalid:
  423. DNSDBG( ANY, (
  424. "Validation failure, in heap blob %p\n",
  425. h->pHeap ));
  426. Dns_DbgHeapHeaderPrint( h, t );
  427. ASSERT( FALSE );
  428. Dns_DbgHeapGlobalInfoPrint( h->pHeap );
  429. Dns_DbgHeapDumpAllocList( h->pHeap );
  430. ASSERT( FALSE );
  431. return;
  432. }
  433. PHEAP_HEADER
  434. Dns_DbgHeapValidateMemory(
  435. IN PVOID pMem,
  436. IN BOOL fAtHeader
  437. )
  438. /*++
  439. Routine Description:
  440. Validates users heap pointer, and returns actual.
  441. Note: This memory MUST have been allocated by THESE MEMORY routines.
  442. Arguments:
  443. pMem - ptr to memory to validate
  444. fAtHeader - TRUE if pMem is known to be immediately after a head header,
  445. otherwise this function will search backwards through memory starting
  446. at pMem looking for a valid heap header
  447. Return Value:
  448. Pointer to actual heap pointer.
  449. --*/
  450. {
  451. register PHEAP_HEADER pheader;
  452. //
  453. // Get pointer to heap header.
  454. //
  455. pheader = (PHEAP_HEADER) pMem - 1;
  456. if ( !fAtHeader )
  457. {
  458. int iterations = 32 * 1024;
  459. //
  460. // Back up from pMem a DWORD at a time looking for HEAP_CODE.
  461. // If we don't find one, eventually we will generate an exception,
  462. // which will be interesting. This could be handled, but for now
  463. // this loop will just walk to past the start of valid memory.
  464. //
  465. while ( 1 )
  466. {
  467. //
  468. // Break if we've found the heap header.
  469. //
  470. if ( pheader->HeapCodeBegin == HEAP_CODE &&
  471. ( pheader->HeapCodeEnd == HEAP_CODE_ACTIVE ||
  472. pheader->HeapCodeEnd == HEAP_CODE_FREE ) )
  473. {
  474. break;
  475. }
  476. //
  477. // Sanity check: too many iterations?
  478. //
  479. if ( ( --iterations ) == 0 )
  480. {
  481. ASSERT( iterations > 0 );
  482. return NULL;
  483. }
  484. //
  485. // Back up another DWORD.
  486. //
  487. pheader = ( PHEAP_HEADER ) ( ( PBYTE ) pheader - 4 );
  488. }
  489. }
  490. //
  491. // Verify header and trailer.
  492. //
  493. DbgHeapValidateHeader( pheader );
  494. return pheader;
  495. }
  496. VOID
  497. Dns_DbgHeapValidateAllocList(
  498. IN OUT PHEAP_BLOB pHeap
  499. )
  500. /*++
  501. Routine Description:
  502. Dumps header information for all nodes in alloc list.
  503. Arguments:
  504. None
  505. Return Value:
  506. None
  507. --*/
  508. {
  509. PLIST_ENTRY pentry;
  510. DNSDBG( TRACE, (
  511. "Dns_DbgHeapValidateAllocList( %p )\n",
  512. pHeap ));
  513. if ( !pHeap->fHeaders )
  514. {
  515. DNS_ASSERT( pHeap->fHeaders );
  516. return;
  517. }
  518. //
  519. // loop through all outstanding alloc's, validating each one
  520. //
  521. LOCK_HEAP(pHeap);
  522. pentry = pHeap->ListHead.Flink;
  523. while( pentry != &pHeap->ListHead )
  524. {
  525. DbgHeapValidateHeader( HEAP_HEADER_FROM_LIST_ENTRY(pentry) );
  526. pentry = pentry->Flink;
  527. }
  528. UNLOCK_HEAP(pHeap);
  529. }
  530. //
  531. // Heap Printing
  532. //
  533. VOID
  534. Dns_DbgHeapGlobalInfoPrint(
  535. IN PHEAP_BLOB pHeap
  536. )
  537. /*++
  538. Routine Description:
  539. Prints global heap info.
  540. Arguments:
  541. None
  542. Return Value:
  543. None
  544. --*/
  545. {
  546. DNS_PRINT((
  547. "Debug Heap Information:\n"
  548. "\tHeap Blob = %p\n"
  549. "\tHandle = %p\n"
  550. "\tDebug headers = %d\n"
  551. "\tDnslib redirect = %d\n"
  552. "\tFull checks = %d\n"
  553. "\tFlags = %08x\n"
  554. "\tStats ---------------\n"
  555. "\tMemory Allocated = %d\n"
  556. "\tMemory Freed = %d\n"
  557. "\tMemory Current = %d\n"
  558. "\tAlloc Count = %d\n"
  559. "\tFree Count = %d\n"
  560. "\tCurrent Count = %d\n",
  561. pHeap,
  562. pHeap->hHeap,
  563. pHeap->fHeaders,
  564. pHeap->fDnsLib,
  565. pHeap->fCheckAll,
  566. pHeap->DefaultFlags,
  567. pHeap->AllocMem,
  568. pHeap->FreeMem,
  569. pHeap->CurrentMem,
  570. pHeap->AllocCount,
  571. pHeap->FreeCount,
  572. pHeap->CurrentCount
  573. ));
  574. }
  575. VOID
  576. Dns_DbgHeapHeaderPrint(
  577. IN PHEAP_HEADER h,
  578. IN PHEAP_TRAILER t
  579. )
  580. /*++
  581. Routine Description:
  582. Prints heap header and trailer.
  583. Arguments:
  584. None
  585. Return Value:
  586. None
  587. --*/
  588. {
  589. if ( h )
  590. {
  591. DNSDBG( HEAPDBG, (
  592. "Heap Header at %p:\n"
  593. "\tHeapCodeBegin = %08lx\n"
  594. "\tAllocCount = %d\n"
  595. "\tAllocSize = %d\n"
  596. "\tRequestSize = %d\n"
  597. "\tHeapBlob = %p\n"
  598. //"\tFileName = %.*s\n"
  599. "\tFileName = %s\n"
  600. "\tLineNo = %d\n"
  601. "\tAllocTime = %d\n"
  602. "\tCurrentMem = %d\n"
  603. "\tCurrentCount = %d\n"
  604. "\tHeapCodeEnd = %08lx\n",
  605. h,
  606. h->HeapCodeBegin,
  607. h->AllocCount,
  608. h->AllocSize,
  609. h->RequestSize,
  610. h->pHeap,
  611. //HEAP_HEADER_FILE_SIZE,
  612. h->FileName,
  613. h->LineNo,
  614. h->AllocTime / 1000,
  615. h->CurrentMem,
  616. h->CurrentCount,
  617. h->HeapCodeEnd
  618. ));
  619. }
  620. if ( t )
  621. {
  622. DNSDBG( HEAPDBG, (
  623. "Heap Trailer at %p:\n"
  624. "\tHeapCodeBegin = %08lx\n"
  625. "\tAllocCount = %d\n"
  626. "\tAllocSize = %d\n"
  627. "\tHeapCodeEnd = %08lx\n",
  628. t,
  629. t->HeapCodeBegin,
  630. t->AllocCount,
  631. t->AllocSize,
  632. t->HeapCodeEnd
  633. ));
  634. }
  635. }
  636. VOID
  637. Dns_DbgHeapDumpAllocList(
  638. IN PHEAP_BLOB pHeap
  639. )
  640. /*++
  641. Routine Description:
  642. Dumps header information for all nodes in alloc list.
  643. Arguments:
  644. None
  645. Return Value:
  646. None
  647. --*/
  648. {
  649. PLIST_ENTRY pentry;
  650. PHEAP_HEADER phead;
  651. if ( !pHeap->fHeaders )
  652. {
  653. DNSDBG( HEAPDBG, ( "Non-debug heap -- no alloc list!\n" ));
  654. return;
  655. }
  656. //
  657. // loop through all outstanding alloc's, dumping output
  658. //
  659. LOCK_HEAP(pHeap);
  660. DNSDBG( HEAPDBG, ( "Dumping Alloc List:\n" ));
  661. pentry = pHeap->ListHead.Flink;
  662. while( pentry != &pHeap->ListHead )
  663. {
  664. phead = HEAP_HEADER_FROM_LIST_ENTRY( pentry );
  665. Dns_DbgHeapHeaderPrint(
  666. phead,
  667. HEAP_TRAILER( phead )
  668. );
  669. pentry = pentry->Flink;
  670. }
  671. DNSDBG( HEAPDBG, ( "End Dump of Alloc List.\n" ));
  672. UNLOCK_HEAP(pHeap);
  673. }
  674. //
  675. // Full debug heap routines
  676. //
  677. PVOID
  678. Dns_DbgHeapAllocEx(
  679. IN OUT PHEAP_BLOB pHeap,
  680. IN DWORD dwFlags,
  681. IN INT iSize,
  682. IN LPSTR pszFile,
  683. IN DWORD dwLine
  684. )
  685. /*++
  686. Routine Description:
  687. Allocates memory.
  688. Arguments:
  689. iSize - number of bytes to allocate
  690. Return Value:
  691. Pointer to memory allocated.
  692. NULL if allocation fails.
  693. --*/
  694. {
  695. register PHEAP_HEADER h;
  696. INT allocSize;
  697. DNSDBG( HEAP2, (
  698. "Dns_DbgHeapAlloc( %p, %d )\n",
  699. pHeap, iSize ));
  700. //
  701. // full heap check?
  702. //
  703. IF_DNSDBG( HEAP_CHECK )
  704. {
  705. Dns_DbgHeapValidateAllocList( pHeap );
  706. }
  707. if ( iSize <= 0 )
  708. {
  709. DNSDBG( ANY, ( "Invalid alloc size = %d\n", iSize ));
  710. DNS_ASSERT( FALSE );
  711. return( NULL );
  712. }
  713. //
  714. // allocate memory
  715. //
  716. // first add heap header to size
  717. //
  718. allocSize = DbgHeapFindAllocSize( iSize );
  719. h = (PHEAP_HEADER) RtlAllocateHeap(
  720. pHeap->hHeap,
  721. dwFlags
  722. ? dwFlags
  723. : pHeap->DefaultFlags,
  724. allocSize );
  725. if ( ! h )
  726. {
  727. Dns_DbgHeapGlobalInfoPrint( pHeap );
  728. return NULL;
  729. }
  730. //
  731. // setup header / globals for new alloc
  732. //
  733. // return ptr to first byte after header
  734. //
  735. return DbgHeapSetHeaderAlloc(
  736. pHeap,
  737. h,
  738. iSize,
  739. pszFile,
  740. dwLine
  741. );
  742. }
  743. PVOID
  744. Dns_DbgHeapReallocEx(
  745. IN OUT PHEAP_BLOB pHeap,
  746. IN DWORD dwFlags,
  747. IN OUT PVOID pMem,
  748. IN INT iSize,
  749. IN LPSTR pszFile,
  750. IN DWORD dwLine
  751. )
  752. /*++
  753. Routine Description:
  754. Reallocates memory
  755. Arguments:
  756. pMem - ptr to existing memory to reallocated
  757. iSize - number of bytes to reallocate
  758. Return Value:
  759. Pointer to memory allocated.
  760. NULL if allocation fails.
  761. --*/
  762. {
  763. register PHEAP_HEADER h;
  764. INT previousSize;
  765. INT allocSize;
  766. //
  767. // full heap check?
  768. //
  769. IF_DNSDBG( HEAP_CHECK )
  770. {
  771. Dns_DbgHeapValidateAllocList( pHeap );
  772. }
  773. if ( iSize <= 0 )
  774. {
  775. DNSDBG( HEAPDBG, ( "Invalid realloc size = %d\n", iSize ));
  776. return( NULL );
  777. }
  778. //
  779. // validate memory
  780. //
  781. // extract pointer to actual alloc'd block
  782. // mark as free, and reset globals appropriately
  783. //
  784. h = DbgHeapSetHeaderFree( pHeap, pMem );
  785. //
  786. // reallocate memory
  787. //
  788. // first add heap header to size
  789. //
  790. allocSize = DbgHeapFindAllocSize( iSize );
  791. h = (PHEAP_HEADER) RtlReAllocateHeap(
  792. pHeap->hHeap,
  793. dwFlags
  794. ? dwFlags
  795. : pHeap->DefaultFlags,
  796. h,
  797. allocSize );
  798. if ( ! h )
  799. {
  800. Dns_DbgHeapGlobalInfoPrint( pHeap );
  801. return( NULL );
  802. }
  803. //
  804. // setup header / globals for realloc
  805. //
  806. // return ptr to first byte after header
  807. //
  808. return DbgHeapSetHeaderAlloc(
  809. pHeap,
  810. h,
  811. iSize,
  812. pszFile,
  813. dwLine
  814. );
  815. }
  816. VOID
  817. Dns_DbgHeapFreeEx(
  818. IN OUT PHEAP_BLOB pHeap,
  819. IN DWORD dwFlags,
  820. IN OUT PVOID pMem
  821. )
  822. /*++
  823. Routine Description:
  824. Frees memory
  825. Note: This memory MUST have been allocated by DbgHeap routines.
  826. Arguments:
  827. pMem - ptr to memory to be freed
  828. Return Value:
  829. None.
  830. --*/
  831. {
  832. register PHEAP_HEADER h;
  833. DNSDBG( HEAP2, (
  834. "Dns_DbgHeapFreeEx( %p, %p )\n",
  835. pHeap, pMem ));
  836. //
  837. // validate header
  838. //
  839. // reset heap header / globals for free
  840. //
  841. h = DbgHeapSetHeaderFree( pHeap, pMem );
  842. //
  843. // get blob
  844. //
  845. if ( !pHeap )
  846. {
  847. pHeap = h->pHeap;
  848. }
  849. //
  850. // full heap check?
  851. //
  852. IF_DNSDBG( HEAP_CHECK )
  853. {
  854. Dns_DbgHeapValidateAllocList( pHeap );
  855. }
  856. RtlFreeHeap(
  857. pHeap->hHeap,
  858. dwFlags
  859. ? dwFlags
  860. : pHeap->DefaultFlags,
  861. h );
  862. }
  863. //
  864. // Dnslib memory compatible versions
  865. //
  866. // Heap routines with simple function signature that matches
  867. // the dnslib routines and allows DnsLib memory routines to
  868. // be redirected to these routines through Dns_LibHeapReset().
  869. //
  870. // Note: to use these functions, must have specified at particular
  871. // heap to use.
  872. //
  873. PVOID
  874. Dns_DbgHeapAlloc(
  875. IN INT iSize
  876. )
  877. {
  878. return Dns_DbgHeapAllocEx(
  879. g_pDnslibHeapBlob,
  880. 0,
  881. iSize,
  882. NULL,
  883. 0 );
  884. }
  885. PVOID
  886. Dns_DbgHeapRealloc(
  887. IN OUT PVOID pMem,
  888. IN INT iSize
  889. )
  890. {
  891. return Dns_DbgHeapReallocEx(
  892. g_pDnslibHeapBlob,
  893. 0,
  894. pMem,
  895. iSize,
  896. NULL,
  897. 0
  898. );
  899. }
  900. VOID
  901. Dns_DbgHeapFree(
  902. IN OUT PVOID pMem
  903. )
  904. {
  905. Dns_DbgHeapFreeEx(
  906. g_pDnslibHeapBlob,
  907. 0,
  908. pMem );
  909. }
  910. //
  911. // Non debug header versions
  912. //
  913. // These allow you to use a private heap with some of the features
  914. // of the debug heap
  915. // - same initialization
  916. // - specifying individual heap
  917. // - redirection of dnslib (without building your own routines)
  918. // - alloc and free counts
  919. // but without the overhead of the headers.
  920. //
  921. PVOID
  922. Dns_HeapAllocEx(
  923. IN OUT PHEAP_BLOB pHeap,
  924. IN DWORD dwFlags,
  925. IN INT iSize
  926. )
  927. /*++
  928. Routine Description:
  929. Allocates memory.
  930. Arguments:
  931. pHeap - heap to use
  932. dwFlags - flags
  933. iSize - number of bytes to allocate
  934. Return Value:
  935. Pointer to memory allocated.
  936. NULL if allocation fails.
  937. --*/
  938. {
  939. PVOID p;
  940. DNSDBG( HEAP2, (
  941. "Dns_HeapAlloc( %p, %d )\n",
  942. pHeap, iSize ));
  943. //
  944. // allocate memory
  945. //
  946. p = (PHEAP_HEADER) RtlAllocateHeap(
  947. pHeap->hHeap,
  948. dwFlags
  949. ? dwFlags
  950. : pHeap->DefaultFlags,
  951. iSize );
  952. if ( p )
  953. {
  954. pHeap->AllocCount++;
  955. pHeap->CurrentCount++;
  956. }
  957. return p;
  958. }
  959. PVOID
  960. Dns_HeapReallocEx(
  961. IN OUT PHEAP_BLOB pHeap,
  962. IN DWORD dwFlags,
  963. IN OUT PVOID pMem,
  964. IN INT iSize
  965. )
  966. /*++
  967. Routine Description:
  968. Reallocates memory
  969. Arguments:
  970. pMem - ptr to existing memory to reallocated
  971. iSize - number of bytes to reallocate
  972. Return Value:
  973. Pointer to memory allocated.
  974. NULL if allocation fails.
  975. --*/
  976. {
  977. PVOID p;
  978. INT previousSize;
  979. INT allocSize;
  980. //
  981. // reallocate memory
  982. //
  983. // first add heap header to size
  984. //
  985. p = RtlReAllocateHeap(
  986. pHeap->hHeap,
  987. dwFlags
  988. ? dwFlags
  989. : pHeap->DefaultFlags,
  990. pMem,
  991. iSize );
  992. if ( p )
  993. {
  994. pHeap->AllocCount++;
  995. pHeap->FreeCount++;
  996. }
  997. return p;
  998. }
  999. VOID
  1000. Dns_HeapFreeEx(
  1001. IN OUT PHEAP_BLOB pHeap,
  1002. IN DWORD dwFlags,
  1003. IN OUT PVOID pMem
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. Frees memory
  1008. Note: This memory MUST have been allocated by DbgHeap routines.
  1009. Arguments:
  1010. pMem - ptr to memory to be freed
  1011. Return Value:
  1012. None.
  1013. --*/
  1014. {
  1015. DNSDBG( HEAP2, (
  1016. "Dns_HeapFreeEx( %p, %p )\n",
  1017. pHeap, pMem ));
  1018. RtlFreeHeap(
  1019. pHeap->hHeap,
  1020. dwFlags
  1021. ? dwFlags
  1022. : pHeap->DefaultFlags,
  1023. pMem );
  1024. pHeap->FreeCount++;
  1025. pHeap->CurrentCount--;
  1026. }
  1027. //
  1028. // Dnslib memory compatible versions
  1029. //
  1030. // Heap routines with simple function signature that matches
  1031. // the dnslib routines and allows DnsLib memory routines to
  1032. // be redirected to these routines through Dns_LibHeapReset().
  1033. //
  1034. // Note: to use these functions, must have specified at particular
  1035. // heap to use.
  1036. //
  1037. PVOID
  1038. Dns_HeapAlloc(
  1039. IN INT iSize
  1040. )
  1041. {
  1042. return Dns_HeapAllocEx(
  1043. g_pDnslibHeapBlob,
  1044. 0,
  1045. iSize );
  1046. }
  1047. PVOID
  1048. Dns_HeapRealloc(
  1049. IN OUT PVOID pMem,
  1050. IN INT iSize
  1051. )
  1052. {
  1053. return Dns_HeapReallocEx(
  1054. g_pDnslibHeapBlob,
  1055. 0,
  1056. pMem,
  1057. iSize );
  1058. }
  1059. VOID
  1060. Dns_HeapFree(
  1061. IN OUT PVOID pMem
  1062. )
  1063. {
  1064. Dns_HeapFreeEx(
  1065. g_pDnslibHeapBlob,
  1066. 0,
  1067. pMem );
  1068. }
  1069. //
  1070. // End heapdbg.c
  1071. //