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.

2824 lines
73 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. debugmem.cxx
  5. Abstract:
  6. Debug memory allocator
  7. Contents:
  8. InternetDebugMemInitialize
  9. InternetDebugMemTerminate
  10. InternetDebugAllocMem
  11. InternetDebugFreeMem
  12. InternetDebugReAllocMem
  13. InternetDebugSizeMem
  14. InternetDebugCheckMemFreed
  15. InternetDebugMemReport
  16. (InternetDebugCheckMemBlock)
  17. (DebugFillMem)
  18. (InternetAlloc)
  19. (InternetFree)
  20. (InternetReAlloc)
  21. (InternetSize)
  22. (InternetHeapAlloc)
  23. (InternetHeapReAlloc)
  24. (InternetHeapFree)
  25. (InternetHeapSize)
  26. (InternetDebugMemTest)
  27. (ReportMemoryUsage)
  28. (ReportMemoryBlocks)
  29. (DumpDeferredFreeList)
  30. (DumpMemoryList)
  31. (FindAndDumpDeferredBlock)
  32. (DumpBlock)
  33. (DumpDebugMemoryHeader)
  34. (DumpDebugMemoryFooter)
  35. (DumpUserData)
  36. (MapLastAccessOperation)
  37. (MapMemoryFlags)
  38. (DbgMemGetDebugSymbol)
  39. Author:
  40. Richard L Firth (rfirth) 02-Feb-1995
  41. Environment:
  42. Win32 user mode
  43. Revision History:
  44. 02-Feb-1995
  45. Created
  46. --*/
  47. #include <wininetp.h>
  48. #include "rprintf.h"
  49. #if defined(USE_DEBUG_MEMORY)
  50. //
  51. // manifests
  52. //
  53. #define DEFAULT_INITIAL_HEAP_SIZE (64 K)
  54. #define DEFAULT_MAXIMUM_HEAP_SIZE (1 M)
  55. #define DEFAULT_HEADER_GUARD_SIZE 32
  56. #define DEFAULT_FOOTER_GUARD_SIZE 32
  57. #define DEFAULT_ALLOC_ALIGNMENT 4
  58. #define HEADER_SIGNATURE 0x414d454d // "MEMA"
  59. #define FOOTER_SIGNATURE 0x434f4c4c // "LLOC"
  60. #define DWORD_ALLOC_FILL 0xc5c5c5c5
  61. #define BYTE_ALLOC_FILL 0xc5
  62. #define BYTE_ALLOC_FILL_EXTRA 0x88
  63. #define GUARD_DWORD_FILL 0x44524147 // "GARD"
  64. #define DWORD_FREE_FILL 0xb7b7b7b7
  65. #define BYTE_FREE_FILL 0xb7
  66. #define DEFAULT_MAX_BLOCKS_DUMPED 1024
  67. #define DEFAULT_MAX_DATA_DUMPED 65536
  68. #define DEFAULT_BACKTRACE_DEPTH 2
  69. //
  70. // only perform stack dump for x86 (or other stack-based processors)
  71. //
  72. #if defined(i386)
  73. #define DUMP_STACK 1
  74. #else
  75. #define DUMP_STACK 0
  76. #endif
  77. //
  78. // just using one stack these days
  79. //
  80. #define ONE_STACK 1
  81. //
  82. // private types
  83. //
  84. typedef enum {
  85. MemAllocate = 0x6f6c6c41, // "Allo"
  86. MemReallocate = 0x6c416552, // "ReAl"
  87. MemLock = 0x6b636f4c, // "Lock"
  88. MemUnlock = 0x6f6c6e55, // "Unlo"
  89. MemFree = 0x65657246, // "Free"
  90. MemSize = 0x657a6953 // "Size"
  91. } MEMORY_ACTION;
  92. typedef enum {
  93. HEAP_COMPACT_NEVER = 0,
  94. HEAP_COMPACT_ON_ALLOC_FAIL,
  95. HEAP_COMPACT_ON_FREE
  96. } HEAP_COMPACT_TYPE;
  97. typedef enum {
  98. HEAP_VALIDATE_NEVER = 0,
  99. HEAP_VALIDATE_ON_ALLOC,
  100. HEAP_VALIDATE_ON_FREE
  101. } HEAP_VALIDATE_TYPE;
  102. //
  103. // DEBUG_MEMORY_HEADER - keeps debug memory on list
  104. //
  105. typedef struct {
  106. LIST_ENTRY List;
  107. DWORD ThreadId;
  108. LPSTR CreatedFile;
  109. DWORD CreatedLine;
  110. LPSTR AccessedFile;
  111. DWORD AccessedLine;
  112. SIZE_T RequestedLength;
  113. SIZE_T BlockLength;
  114. SIZE_T ActualLength;
  115. DWORD Signature;
  116. DWORD Flags;
  117. DWORD TimeDeferred;
  118. LONG ClashTest;
  119. MEMORY_ACTION LastAccessOperation;
  120. #if DUMP_STACK
  121. #if ONE_STACK
  122. LPVOID Stack[8]; // should be variable
  123. #else
  124. LPVOID CreateStack[4];
  125. LPVOID LastAccessStack[4];
  126. #endif // ONE_STACK
  127. #endif // DUMP_STACK
  128. DWORD Guard[2];
  129. //
  130. // sizeof(MEMORY_SIGNATURE) currently 24 DWORDs in Win32
  131. //
  132. } DEBUG_MEMORY_HEADER, *LPDEBUG_MEMORY_HEADER;
  133. //
  134. // DEBUG_MEMORY_FOOTER - used to check for overwrites
  135. //
  136. typedef struct {
  137. DWORD Guard[4];
  138. DWORD Signature;
  139. SIZE_T BlockLength; // should be the same as the header
  140. DWORD Guard2[2];
  141. //
  142. // sizeof(DEBUG_MEMORY_FOOTER) currently 8 DWORDs in Win32
  143. //
  144. } DEBUG_MEMORY_FOOTER, *LPDEBUG_MEMORY_FOOTER;
  145. //
  146. // private data
  147. //
  148. PRIVATE BOOL MemoryPackageInitialized = FALSE;
  149. //
  150. // InternetDebugMemFlags - bitfield of flags controlling debug memory usage.
  151. // The default is no debug alloc (don't create header + footers) and to use
  152. // LocalAlloc() etc.
  153. //
  154. //
  155. // BUGBUG - I'm making an assumption that the compiler thinks the bits have the
  156. // same values as I think they have. If not, it could mess up the
  157. // registry/environment flags
  158. //
  159. PRIVATE struct { // default value
  160. DWORD bNoDebugAlloc : 1; // 0x00000001 TRUE
  161. DWORD bUseLocalAlloc : 1; // 0x00000002 TRUE
  162. DWORD bUseSymbols : 1; // 0x00000004 FALSE
  163. DWORD bAssertOnMemoryErrors : 1; // 0x00000008 FALSE
  164. DWORD bFillMemoryOnAlloc : 1; // 0x00000010 FALSE
  165. DWORD bFillMemoryOnFree : 1; // 0x00000020 FALSE
  166. DWORD bReportMemoryUsage : 1; // 0x00000040 FALSE
  167. DWORD bReportUnfreedBlocks : 1; // 0x00000080 FALSE
  168. DWORD bReportMemoryFooters : 1; // 0x00000100 FALSE
  169. DWORD bReportUserData : 1; // 0x00000200 FALSE
  170. DWORD bStopDumpIfBadBlock : 1; // 0x00000400 FALSE
  171. DWORD bLimitUnfreedBlocks : 1; // 0x00000800 FALSE
  172. DWORD bLimitUserData : 1; // 0x00001000 FALSE
  173. DWORD bDumpAsDwords : 1; // 0x00002000 FALSE
  174. DWORD bHeapNoSerialize : 1; // 0x00004000 FALSE
  175. DWORD bHeapGenerateExceptions : 1; // 0x00008000 FALSE
  176. DWORD bHeapIsGrowable : 1; // 0x00010000 FALSE
  177. DWORD bDeferFree : 1; // 0x00020000 FALSE
  178. DWORD bDumpToFile : 1; // 0x00040000 FALSE
  179. } InternetDebugMemFlags = {
  180. TRUE, // no debug alloc
  181. TRUE, // use LocalAlloc()
  182. FALSE, // don't load debug symbols
  183. FALSE, // don't assert on memory errors
  184. FALSE, // don't fill memory on alloc
  185. FALSE, // don't fill memory on free
  186. FALSE, // don't report memory usage (stats)
  187. FALSE, // don't report unfreed blocks
  188. FALSE, // don't report memory footers (irrelevant)
  189. FALSE, // don't report user data (irrelevant)
  190. FALSE, // don't stop dump if bad block (irrelevant)
  191. FALSE, // don't limit dump of unfreed blocks (irrelevant)
  192. FALSE, // don't limit dump of user data (irrelevant)
  193. FALSE, // don't dump user data as DWORDs (irrelevant)
  194. FALSE, // serialize access to heap (irrelevant)
  195. FALSE, // don't generate heap exceptions (irrelevant)
  196. TRUE, // heap is growable (irrelevant)
  197. FALSE, // don't defer frees
  198. FALSE // don't dump to WinHttp log file
  199. };
  200. //
  201. // defines to make using InternetDebugMemFlags easier
  202. //
  203. #define bNoDebugAlloc InternetDebugMemFlags.bNoDebugAlloc
  204. #define bUseLocalAlloc InternetDebugMemFlags.bUseLocalAlloc
  205. #define bUseSymbols InternetDebugMemFlags.bUseSymbols
  206. #define bAssertOnMemoryErrors InternetDebugMemFlags.bAssertOnMemoryErrors
  207. #define bFillMemoryOnAlloc InternetDebugMemFlags.bFillMemoryOnAlloc
  208. #define bFillMemoryOnFree InternetDebugMemFlags.bFillMemoryOnFree
  209. #define bReportMemoryUsage InternetDebugMemFlags.bReportMemoryUsage
  210. #define bReportUnfreedBlocks InternetDebugMemFlags.bReportUnfreedBlocks
  211. #define bReportMemoryFooters InternetDebugMemFlags.bReportMemoryFooters
  212. #define bReportUserData InternetDebugMemFlags.bReportUserData
  213. #define bStopDumpIfBadBlock InternetDebugMemFlags.bStopDumpIfBadBlock
  214. #define bLimitUnfreedBlocks InternetDebugMemFlags.bLimitUnfreedBlocks
  215. #define bLimitUserData InternetDebugMemFlags.bLimitUserData
  216. #define bDumpAsDwords InternetDebugMemFlags.bDumpAsDwords
  217. #define bHeapNoSerialize InternetDebugMemFlags.bHeapNoSerialize
  218. #define bHeapGenerateExceptions InternetDebugMemFlags.bHeapGenerateExceptions
  219. #define bHeapIsGrowable InternetDebugMemFlags.bHeapIsGrowable
  220. #define bDeferFree InternetDebugMemFlags.bDeferFree
  221. #define bDumpToFile InternetDebugMemFlags.bDumpToFile
  222. PRIVATE DWORD MaxBlocksDumped = DEFAULT_MAX_BLOCKS_DUMPED;
  223. PRIVATE DWORD MaxUserDataDumped = DEFAULT_MAX_DATA_DUMPED;
  224. PRIVATE DWORD StackBacktraceDepth = DEFAULT_BACKTRACE_DEPTH;
  225. //
  226. // heap variables
  227. //
  228. PRIVATE HANDLE hDebugHeap = NULL;
  229. PRIVATE DWORD InitialHeapSize = DEFAULT_INITIAL_HEAP_SIZE;
  230. PRIVATE DWORD MaximumHeapSize = DEFAULT_MAXIMUM_HEAP_SIZE;
  231. PRIVATE HEAP_COMPACT_TYPE HeapCompactControl = HEAP_COMPACT_NEVER;
  232. PRIVATE HEAP_VALIDATE_TYPE HeapValidateControl = HEAP_VALIDATE_NEVER;
  233. //
  234. // debug mem signatures etc.
  235. //
  236. PRIVATE DWORD AllocAlignment = DEFAULT_ALLOC_ALIGNMENT;
  237. PRIVATE DWORD HeaderGuardSize = DEFAULT_HEADER_GUARD_SIZE;
  238. PRIVATE DWORD FooterGuardSize = DEFAULT_FOOTER_GUARD_SIZE;
  239. PRIVATE DWORD AllocMemoryFiller = DWORD_ALLOC_FILL;
  240. PRIVATE DWORD FreeMemoryFiller = DWORD_FREE_FILL;
  241. //
  242. // usage variables - access using some sort of lock (critsec/interlocked)
  243. //
  244. PRIVATE CRITICAL_SECTION MemoryVarsCritSec;
  245. PRIVATE SIZE_T TotalActualMemoryAllocated = 0; // cumulative
  246. PRIVATE SIZE_T TotalBlockMemoryAllocated = 0; // "
  247. PRIVATE SIZE_T TotalRealMemoryAllocated = 0; // "
  248. PRIVATE SIZE_T TotalActualMemoryFreed = 0; // "
  249. PRIVATE SIZE_T TotalBlockMemoryFreed = 0; // "
  250. PRIVATE SIZE_T TotalRealMemoryFreed = 0; // "
  251. PRIVATE SIZE_T ActualMemoryAllocated = 0; // difference
  252. PRIVATE SIZE_T BlockLengthAllocated = 0; // "
  253. PRIVATE SIZE_T RealLengthAllocated = 0; // "
  254. PRIVATE DWORD MemoryAllocations = 0; // cumulative
  255. PRIVATE DWORD GoodMemoryAllocations = 0; // "
  256. PRIVATE DWORD MemoryReAllocations = 0; // "
  257. PRIVATE DWORD GoodMemoryReAllocations = 0; // "
  258. PRIVATE DWORD MemoryFrees = 0; // "
  259. PRIVATE DWORD GoodMemoryFrees = 0; // "
  260. PRIVATE SIZE_T LargestBlockRequested = 0;
  261. PRIVATE SIZE_T LargestBlockAllocated = 0;
  262. PRIVATE LPSTR LargestBlockRequestedFile = NULL;
  263. PRIVATE DWORD LargestBlockRequestedLine = 0;
  264. PRIVATE SIZE_T SmallestBlockRequested = (SIZE_T)-1;
  265. PRIVATE SIZE_T SmallestBlockAllocated = (SIZE_T)-1;
  266. PRIVATE LPSTR SmallestBlockRequestedFile = NULL;
  267. PRIVATE DWORD SmallestBlockRequestedLine = 0;
  268. PRIVATE DWORD DeferFreeTime = 0;
  269. //
  270. // lists
  271. //
  272. PRIVATE SERIALIZED_LIST AllocatedBlockList;
  273. PRIVATE SERIALIZED_LIST DeferredFreeList;
  274. //
  275. // macros
  276. //
  277. #define MEMORY_ASSERT(x) \
  278. if (bAssertOnMemoryErrors) { \
  279. INET_ASSERT(x); \
  280. } else { \
  281. /* NOTHING */ \
  282. }
  283. //
  284. // private prototypes
  285. //
  286. PRIVATE
  287. VOID
  288. DebugFillMem(
  289. IN LPVOID Pointer,
  290. IN SIZE_T Size,
  291. IN DWORD dwFiller
  292. );
  293. PRIVATE
  294. HLOCAL
  295. InternetAlloc(
  296. IN UINT Flags,
  297. IN SIZE_T Size
  298. );
  299. PRIVATE
  300. HLOCAL
  301. InternetFree(
  302. IN HLOCAL hLocal
  303. );
  304. PRIVATE
  305. HLOCAL
  306. InternetReAlloc(
  307. IN HLOCAL hLocal,
  308. IN SIZE_T Size,
  309. IN UINT Flags
  310. );
  311. PRIVATE
  312. SIZE_T
  313. InternetSize(
  314. IN HLOCAL hLocal
  315. );
  316. PRIVATE
  317. HLOCAL
  318. InternetHeapAlloc(
  319. IN UINT Flags,
  320. IN SIZE_T Size
  321. );
  322. PRIVATE
  323. HLOCAL
  324. InternetHeapReAlloc(
  325. IN HLOCAL hLocal,
  326. IN SIZE_T Size,
  327. IN UINT Flags
  328. );
  329. PRIVATE
  330. HLOCAL
  331. InternetHeapFree(
  332. IN HLOCAL hLocal
  333. );
  334. PRIVATE
  335. SIZE_T
  336. InternetHeapSize(
  337. IN HLOCAL hLocal
  338. );
  339. PRIVATE
  340. BOOL
  341. InternetDebugCheckMemBlock(
  342. IN LPDEBUG_MEMORY_HEADER lpHeader
  343. );
  344. PRIVATE
  345. VOID
  346. InternetDebugMemTest(
  347. VOID
  348. );
  349. PRIVATE
  350. VOID
  351. ReportMemoryUsage(
  352. VOID
  353. );
  354. PRIVATE
  355. VOID
  356. ReportMemoryBlocks(
  357. VOID
  358. );
  359. PRIVATE
  360. VOID
  361. DumpDeferredFreeList(
  362. VOID
  363. );
  364. PRIVATE
  365. VOID
  366. DumpMemoryList(
  367. IN LPSERIALIZED_LIST lpList
  368. );
  369. PRIVATE
  370. VOID
  371. FindAndDumpDeferredBlock(
  372. IN HLOCAL hLocal
  373. );
  374. PRIVATE
  375. BOOL
  376. DumpBlock(
  377. IN LPDEBUG_MEMORY_HEADER lpHeader
  378. );
  379. PRIVATE
  380. BOOL
  381. DumpDebugMemoryHeader(
  382. LPDEBUG_MEMORY_HEADER lpHeader
  383. );
  384. PRIVATE
  385. BOOL
  386. DumpDebugMemoryFooter(
  387. LPDEBUG_MEMORY_FOOTER lpFooter
  388. );
  389. PRIVATE
  390. VOID
  391. DumpUserData(
  392. LPDEBUG_MEMORY_HEADER lpHeader
  393. );
  394. PRIVATE
  395. LPSTR
  396. MapLastAccessOperation(
  397. MEMORY_ACTION Action
  398. );
  399. PRIVATE
  400. LPSTR
  401. MapMemoryFlags(
  402. DWORD Flags,
  403. LPSTR Buffer
  404. );
  405. PRIVATE
  406. LPSTR
  407. DbgMemGetDebugSymbol(
  408. DWORD Address,
  409. LPDWORD Offset
  410. );
  411. //
  412. // functions
  413. //
  414. VOID
  415. InternetDebugMemInitialize(
  416. VOID
  417. )
  418. /*++
  419. Routine Description:
  420. Initializes debug memory allocator
  421. Arguments:
  422. None.
  423. Return Value:
  424. None.
  425. --*/
  426. {
  427. BOOL init;
  428. init = (BOOL)InterlockedExchange((LPLONG)&MemoryPackageInitialized, TRUE);
  429. if (init) {
  430. DEBUG_PRINT(MEMALLOC,
  431. ERROR,
  432. ("Memory package already initialized\n"
  433. ));
  434. DEBUG_BREAK(MEMALLOC);
  435. return;
  436. }
  437. InitializeSerializedList(&AllocatedBlockList);
  438. InitializeSerializedList(&DeferredFreeList);
  439. InitializeCriticalSection(&MemoryVarsCritSec);
  440. //
  441. // sleaze: disable any debug output until we finish this. Debug log
  442. // routines want to allocate memory(!). InternetReadRegistryDword()
  443. // (called from InternetGetDebugVariable()) wants to perform DEBUG_ENTER
  444. // etc.
  445. //
  446. DWORD debugControlFlags = InternetDebugControlFlags;
  447. InternetDebugControlFlags = DBG_NO_DEBUG;
  448. //
  449. // if "WinHttpMem" is set then we set up to use debug memory - we use our
  450. // own heap, full debugging & reporting etc. (basically max memory debugging
  451. // as defined by me)
  452. //
  453. DWORD useDefaultDebugMemoryFlags = FALSE;
  454. InternetGetDebugVariable("WinHttpMem",
  455. &useDefaultDebugMemoryFlags
  456. );
  457. if (useDefaultDebugMemoryFlags) {
  458. bNoDebugAlloc = FALSE; // use full debug allocator (header + footers, etc.)
  459. bUseLocalAlloc = FALSE; // use our own heap
  460. bUseSymbols = FALSE; // don't load debug symbols
  461. bAssertOnMemoryErrors = TRUE; // assert to debugger/log if memory errors
  462. bFillMemoryOnAlloc = TRUE; // fill user data w/ signature if not zeroinit
  463. bFillMemoryOnFree = TRUE; // fill freed memory (useful on Win95/non-debug on NT)
  464. bReportMemoryUsage = TRUE; // dump memory usage stats
  465. bReportUnfreedBlocks = TRUE; // dump unfreed blocks (headers)
  466. bReportMemoryFooters = TRUE; // dump unfreed block footers
  467. bReportUserData = TRUE; // dump unfreed block user data
  468. bStopDumpIfBadBlock = TRUE; // stop dumping if error occurs
  469. bLimitUnfreedBlocks = TRUE; // limit block dump in case of loop in list
  470. bLimitUserData = TRUE; // limit user data dump in case of bad length
  471. bDumpAsDwords = TRUE; // dump data in dc format vs. db
  472. bHeapNoSerialize = FALSE; // heap functions are serialized
  473. bHeapGenerateExceptions = FALSE;// heap functions return errors
  474. bHeapIsGrowable = FALSE; // limit heap to maximum size (1 Meg)
  475. if (useDefaultDebugMemoryFlags == 2) {
  476. bDumpToFile = TRUE;
  477. }
  478. } else {
  479. //
  480. // no use-debug-mem override, see if there are any specific flags set
  481. //
  482. InternetGetDebugVariable("WinHttpDebugMemFlags",
  483. (LPDWORD)&InternetDebugMemFlags
  484. );
  485. }
  486. //
  487. // we used to load IMAGEHLP.DLL here and not use its functions until we were
  488. // dumping still in-use memory during DLL shutdown. Problem is that the
  489. // system has probably already freed IMAGEHLP.DLL by the time we come to use
  490. // it, resulting in GPF, so now we only load it at the time we're about to
  491. // use it
  492. //
  493. //if (bUseSymbols) {
  494. // InitSymLib();
  495. //}
  496. if (!bUseLocalAlloc) {
  497. //
  498. // not using LocalAlloc(), using HeapAlloc(). Create heap
  499. //
  500. InitialHeapSize = DEFAULT_INITIAL_HEAP_SIZE;
  501. InternetGetDebugVariable("WinHttpDebugHeapInitialSize",
  502. &InitialHeapSize
  503. );
  504. MaximumHeapSize = DEFAULT_MAXIMUM_HEAP_SIZE;
  505. InternetGetDebugVariable("WinHttpDebugHeapMaximumSize",
  506. &MaximumHeapSize
  507. );
  508. if (bHeapIsGrowable) {
  509. MaximumHeapSize = 0;
  510. }
  511. hDebugHeap = HeapCreate((bHeapGenerateExceptions
  512. ? HEAP_GENERATE_EXCEPTIONS
  513. : 0)
  514. | (bHeapNoSerialize
  515. ? HEAP_NO_SERIALIZE
  516. : 0),
  517. InitialHeapSize,
  518. MaximumHeapSize
  519. );
  520. if (hDebugHeap == NULL) {
  521. DEBUG_PUT(("HeapCreate() failed - %d\n",
  522. GetLastError()
  523. ));
  524. bUseLocalAlloc = TRUE;
  525. } else {
  526. HeapCompactControl = HEAP_COMPACT_NEVER;
  527. InternetGetDebugVariable("WinHttpDebugHeapCompactControl",
  528. (LPDWORD)&HeapCompactControl
  529. );
  530. HeapValidateControl = HEAP_VALIDATE_NEVER;
  531. InternetGetDebugVariable("WinHttpDebugHeapValidateControl",
  532. (LPDWORD)&HeapValidateControl
  533. );
  534. DEBUG_PUT(("WinHttp heap = %#x\n",
  535. hDebugHeap
  536. ));
  537. }
  538. }
  539. //
  540. // restore default debug flags
  541. //
  542. InternetDebugControlFlags = debugControlFlags;
  543. //InternetDebugMemTest();
  544. }
  545. VOID
  546. InternetDebugMemTerminate(
  547. IN BOOL bReport
  548. )
  549. /*++
  550. Routine Description:
  551. Frees resources allocated in InternetDebugMemInitialize, after checking that
  552. all memory is freed
  553. Arguments:
  554. bReport - TRUE if in-use blocks reported at termination
  555. Return Value:
  556. None.
  557. --*/
  558. {
  559. BOOL bOpened = bReport ? InternetDebugMemReport(TRUE, FALSE) : FALSE;
  560. InternetDebugCheckMemFreed(FALSE);
  561. DeleteCriticalSection(&MemoryVarsCritSec);
  562. TerminateSerializedList(&AllocatedBlockList);
  563. TerminateSerializedList(&DeferredFreeList);
  564. if (hDebugHeap != NULL) {
  565. //
  566. // any future allocations(!) must use process heap
  567. //
  568. bUseLocalAlloc = TRUE;
  569. if (!HeapDestroy(hDebugHeap)) {
  570. DWORD error = GetLastError();
  571. DEBUG_PRINT(MEMALLOC,
  572. ERROR,
  573. ("HeapDestroy(%#x) returns %s (%d)\n",
  574. hDebugHeap,
  575. InternetMapError(error),
  576. error
  577. ));
  578. MEMORY_ASSERT(FALSE);
  579. }
  580. }
  581. if (bOpened) {
  582. InternetCloseDebugFile();
  583. }
  584. MemoryPackageInitialized = FALSE;
  585. }
  586. HLOCAL
  587. InternetDebugAllocMem(
  588. IN UINT Flags,
  589. IN UINT Size,
  590. IN LPSTR File,
  591. IN DWORD Line
  592. )
  593. /*++
  594. Routine Description:
  595. Debug memory allocator. If this succeeds, then the real block is put on our
  596. list and has its head & tail (& possibly contents) initialized. The caller
  597. gets an pointer which is an offset to the user area in the block
  598. Arguments:
  599. Flags - controlling flags (normally passed to LocalAlloc)
  600. Size - of block to allocate
  601. File - from where alloc called
  602. Line - in File
  603. Return Value:
  604. HLOCAL
  605. Success - pointer to caller's start of allocated block
  606. Failure - NULL
  607. --*/
  608. {
  609. if (!MemoryPackageInitialized) {
  610. return NULL;
  611. }
  612. //dprintf("InternetDebugAllocMem(%#x, %d) = ", Flags, Size);
  613. InterlockedIncrement((LPLONG)&MemoryAllocations);
  614. //
  615. // keep these tests separate so we don't have to look up the flags #defines
  616. //
  617. INET_ASSERT(!(Flags & LMEM_MOVEABLE));
  618. INET_ASSERT(!(Flags & LMEM_DISCARDABLE));
  619. if (Size == 0) {
  620. DEBUG_PRINT(MEMALLOC,
  621. WARNING,
  622. ("InternetDebugAllocMem(%#x, %d)\n",
  623. Flags,
  624. Size
  625. ));
  626. MEMORY_ASSERT(FALSE);
  627. }
  628. SIZE_T blockLength;
  629. if (bNoDebugAlloc) {
  630. blockLength = Size;
  631. } else {
  632. if (Size > LargestBlockRequested) {
  633. LargestBlockRequested = Size;
  634. LargestBlockRequestedFile = File;
  635. LargestBlockRequestedLine = Line;
  636. } else if (Size < SmallestBlockRequested) {
  637. SmallestBlockRequested = Size;
  638. SmallestBlockRequestedFile = File;
  639. SmallestBlockRequestedLine = Line;
  640. }
  641. blockLength = ROUND_UP_DWORD(Size)
  642. + sizeof(DEBUG_MEMORY_HEADER)
  643. + sizeof(DEBUG_MEMORY_FOOTER);
  644. }
  645. //
  646. // possible problem: if Size + signatures would overflow UINT. Only really
  647. // problematic on 16-bit platforms
  648. //
  649. if (blockLength < Size) {
  650. DEBUG_PRINT(MEMALLOC,
  651. ERROR,
  652. ("can't allocate %lu bytes: would overflow\n",
  653. (DWORD)Size
  654. ));
  655. DEBUG_BREAK(MEMALLOC);
  656. //dprintf("NULL\n");
  657. return NULL;
  658. }
  659. //
  660. // BUGBUG - allocating 0 bytes?
  661. //
  662. HLOCAL hLocal = InternetAlloc(Flags, blockLength);
  663. if (hLocal != NULL) {
  664. InterlockedIncrement((LPLONG)&GoodMemoryAllocations);
  665. } else {
  666. DEBUG_PRINT(MEMALLOC,
  667. ERROR,
  668. ("failed to allocate %u bytes memory\n",
  669. blockLength
  670. ));
  671. DEBUG_BREAK(MEMALLOC);
  672. //dprintf("NULL\n");
  673. return NULL;
  674. }
  675. SIZE_T actualLength = InternetSize(hLocal);
  676. SIZE_T requestedLength;
  677. if (bNoDebugAlloc) {
  678. blockLength = actualLength;
  679. requestedLength = actualLength;
  680. } else {
  681. requestedLength = Size;
  682. if (actualLength > LargestBlockAllocated) {
  683. LargestBlockAllocated = actualLength;
  684. } else if (actualLength < SmallestBlockAllocated) {
  685. SmallestBlockAllocated = actualLength;
  686. }
  687. }
  688. EnterCriticalSection(&MemoryVarsCritSec);
  689. TotalActualMemoryAllocated += actualLength;
  690. TotalBlockMemoryAllocated += blockLength;
  691. TotalRealMemoryAllocated += requestedLength;
  692. ActualMemoryAllocated += actualLength;
  693. BlockLengthAllocated += blockLength;
  694. RealLengthAllocated += requestedLength;
  695. LeaveCriticalSection(&MemoryVarsCritSec);
  696. if (bNoDebugAlloc || (hLocal == NULL)) {
  697. if ((hLocal != NULL) && !(Flags & LMEM_ZEROINIT) && bFillMemoryOnAlloc) {
  698. DebugFillMem(hLocal, Size, AllocMemoryFiller);
  699. }
  700. //dprintf("%#x\n", hLocal);
  701. return hLocal;
  702. }
  703. LPDEBUG_MEMORY_HEADER lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  704. //InitializeListHead(&lpHeader->List);
  705. lpHeader->ThreadId = GetCurrentThreadId();
  706. lpHeader->CreatedFile = File;
  707. lpHeader->CreatedLine = Line;
  708. lpHeader->AccessedFile = File;
  709. lpHeader->AccessedLine = Line;
  710. lpHeader->RequestedLength = Size;
  711. lpHeader->BlockLength = blockLength;
  712. lpHeader->ActualLength = actualLength;
  713. lpHeader->Signature = HEADER_SIGNATURE;
  714. lpHeader->Flags = Flags;
  715. lpHeader->TimeDeferred = 0;
  716. lpHeader->ClashTest = -1;
  717. lpHeader->LastAccessOperation = MemAllocate;
  718. #if DUMP_STACK
  719. #if ONE_STACK
  720. memset(lpHeader->Stack, 0, sizeof(lpHeader->Stack));
  721. GET_CALL_STACK(lpHeader->Stack);
  722. #else
  723. GET_CALLERS_ADDRESS(&lpHeader->CreateStack[0],
  724. &lpHeader->CreateStack[1]
  725. );
  726. memset(lpHeader->CreateStack, 0, sizeof(lpHeader->CreateStack));
  727. GET_CALL_STACK(lpHeader->CreateStack);
  728. memcpy(lpHeader->LastAccessStack,
  729. lpHeader->CreateStack,
  730. sizeof(lpHeader->LastAccessStack)
  731. );
  732. #endif // ONE_STACK
  733. #endif // DUMP_STACK
  734. UINT i;
  735. for (i = 0; i < ARRAY_ELEMENTS(lpHeader->Guard); ++i) {
  736. lpHeader->Guard[i] = GUARD_DWORD_FILL;
  737. }
  738. //
  739. // BUGBUG - should be using AllocAlignment - could be > sizeof(DWORD)
  740. //
  741. if (!(Flags & LMEM_ZEROINIT) && bFillMemoryOnAlloc) {
  742. DebugFillMem(lpHeader + 1, Size, AllocMemoryFiller);
  743. }
  744. UINT bFillLength2 = (Size % sizeof(DWORD)) ? (sizeof(DWORD) - (Size % sizeof(DWORD))) : 0;
  745. LPBYTE lpbUserPointer = (LPBYTE)(lpHeader + 1) + Size;
  746. for (i = 0; i < bFillLength2; ++i) {
  747. *lpbUserPointer++ = BYTE_ALLOC_FILL_EXTRA;
  748. }
  749. LPDEBUG_MEMORY_FOOTER lpFooter = (LPDEBUG_MEMORY_FOOTER)lpbUserPointer;
  750. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  751. lpFooter->Guard[i] = GUARD_DWORD_FILL;
  752. }
  753. lpFooter->BlockLength = blockLength;
  754. lpFooter->Signature = FOOTER_SIGNATURE;
  755. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  756. lpFooter->Guard2[i] = GUARD_DWORD_FILL;
  757. }
  758. if (!CheckEntryOnSerializedList(&AllocatedBlockList, &lpHeader->List, FALSE)) {
  759. DEBUG_PRINT(MEMALLOC,
  760. ERROR,
  761. ("InternetDebugAllocMem(%d): %#x already on list?\n",
  762. Size,
  763. lpHeader
  764. ));
  765. MEMORY_ASSERT(FALSE);
  766. }
  767. //
  768. // put at the tail of list so we can view unfreed blocks in chronological
  769. // order
  770. //
  771. if (!InsertAtTailOfSerializedList(&AllocatedBlockList, &lpHeader->List))
  772. {
  773. DEBUG_PRINT(MEMALLOC,
  774. ERROR,
  775. ("InternetDebugAllocMem(%d): %#x couldn't be appended to unfreed list\n",
  776. Size,
  777. lpHeader
  778. ));
  779. MEMORY_ASSERT(FALSE);
  780. }
  781. //dprintf("%#x\n", lpHeader + 1);
  782. return (HLOCAL)(lpHeader + 1);
  783. }
  784. HLOCAL
  785. InternetDebugFreeMem(
  786. IN HLOCAL hLocal,
  787. IN LPSTR File,
  788. IN DWORD Line
  789. )
  790. /*++
  791. Routine Description:
  792. Frees a block of memory allocated by InternetDebugAllocMem(). Checks that
  793. the block is on our allocated block list, and that the header and footer
  794. areas are still intact
  795. Arguments:
  796. hLocal - handle (pointer) of block to free
  797. File - from where alloc called
  798. Line - in File
  799. Return Value:
  800. HLOCAL
  801. Success - NULL
  802. Failure - hLocal
  803. --*/
  804. {
  805. if (!MemoryPackageInitialized) {
  806. return NULL;
  807. }
  808. //dprintf("InternetDebugFreeMem(%#x)\n", hLocal);
  809. InterlockedIncrement((LPLONG)&MemoryFrees);
  810. if (hLocal == NULL) {
  811. DEBUG_PRINT(MEMALLOC,
  812. ERROR,
  813. ("InternetDebugFreeMem(NULL)\n"
  814. ));
  815. MEMORY_ASSERT(FALSE);
  816. return InternetFree(hLocal);
  817. }
  818. HLOCAL hLocalOriginal = hLocal;
  819. SIZE_T actualLength;
  820. SIZE_T blockLength;
  821. SIZE_T realLength;
  822. if (bNoDebugAlloc) {
  823. actualLength = InternetSize(hLocal);
  824. blockLength = actualLength;
  825. realLength = actualLength;
  826. } else {
  827. hLocal = (HLOCAL)((LPDEBUG_MEMORY_HEADER)hLocal - 1);
  828. actualLength = InternetSize(hLocal);
  829. LPDEBUG_MEMORY_HEADER lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  830. if (CheckEntryOnSerializedList(&AllocatedBlockList, &lpHeader->List, TRUE) &&
  831. RemoveFromSerializedList(&AllocatedBlockList, &lpHeader->List)) {
  832. if (!((lpHeader->ActualLength == actualLength)
  833. && (lpHeader->BlockLength <= actualLength)
  834. && !(lpHeader->BlockLength & (sizeof(DWORD) - 1))
  835. && (lpHeader->RequestedLength < lpHeader->BlockLength))) {
  836. DEBUG_PRINT(MEMALLOC,
  837. ERROR,
  838. ("InternetDebugFreeMem(%#x): block lengths mismatch\n",
  839. hLocalOriginal
  840. ));
  841. MEMORY_ASSERT(FALSE);
  842. }
  843. if (InternetDebugCheckMemBlock(lpHeader)) {
  844. blockLength = lpHeader->BlockLength;
  845. realLength = lpHeader->RequestedLength;
  846. } else {
  847. blockLength = 0;
  848. realLength = 0;
  849. }
  850. if (bDeferFree) {
  851. #if DUMP_STACK
  852. #if ONE_STACK
  853. memset(lpHeader->Stack, 0, sizeof(lpHeader->Stack));
  854. GET_CALL_STACK(lpHeader->Stack);
  855. #else
  856. GET_CALLERS_ADDRESS(&lpHeader->CreateStack[0],
  857. &lpHeader->CreateStack[1]
  858. );
  859. memset(lpHeader->CreateStack, 0, sizeof(lpHeader->CreateStack));
  860. GET_CALL_STACK(lpHeader->CreateStack);
  861. memcpy(lpHeader->LastAccessStack,
  862. lpHeader->CreateStack,
  863. sizeof(lpHeader->LastAccessStack)
  864. );
  865. #endif // ONE_STACK
  866. #endif // DUMP_STACK
  867. if (!InsertAtTailOfSerializedList(&DeferredFreeList, &lpHeader->List))
  868. {
  869. DEBUG_PRINT(MEMALLOC,
  870. ERROR,
  871. ("InternetDebugFreeMem(%#x): couldn't add to deferred free list %#x\n",
  872. hLocalOriginal,
  873. &lpHeader->List
  874. ));
  875. MEMORY_ASSERT(FALSE);
  876. }
  877. hLocal = NULL;
  878. }
  879. } else {
  880. DEBUG_PRINT(MEMALLOC,
  881. ERROR,
  882. ("InternetDebugFreeMem(%#x): can't find %#x or couldn't free from list\n",
  883. hLocalOriginal,
  884. &lpHeader->List
  885. ));
  886. MEMORY_ASSERT(FALSE);
  887. FindAndDumpDeferredBlock(hLocal);
  888. }
  889. }
  890. if (hLocal && bFillMemoryOnFree) {
  891. DebugFillMem(hLocal, actualLength, FreeMemoryFiller);
  892. }
  893. hLocal = InternetFree(hLocal);
  894. if (hLocal == NULL) {
  895. InterlockedIncrement((LPLONG)&GoodMemoryFrees);
  896. EnterCriticalSection(&MemoryVarsCritSec);
  897. TotalActualMemoryFreed += actualLength;
  898. TotalBlockMemoryFreed += blockLength;
  899. TotalRealMemoryFreed += realLength;
  900. ActualMemoryAllocated -= actualLength;
  901. BlockLengthAllocated -= blockLength;
  902. RealLengthAllocated -= realLength;
  903. LeaveCriticalSection(&MemoryVarsCritSec);
  904. } else {
  905. DEBUG_PRINT(MEMALLOC,
  906. ERROR,
  907. ("InternetDebugFreeMem(%#x) failed\n",
  908. hLocalOriginal
  909. ));
  910. MEMORY_ASSERT(FALSE);
  911. hLocal = hLocalOriginal;
  912. }
  913. return hLocal;
  914. }
  915. HLOCAL
  916. InternetDebugReAllocMem(
  917. IN HLOCAL hLocal,
  918. IN UINT Size,
  919. IN UINT Flags,
  920. IN LPSTR File,
  921. IN DWORD Line
  922. )
  923. /*++
  924. Routine Description:
  925. Reallocates a debug memory block allocated by InternetDebugAllocMem()
  926. Arguments:
  927. hLocal - the handle (pointer) of the allocated block
  928. Size - requested size of new block; can be larger or smaller than current
  929. size
  930. Flags - controlling flags (normally passed to LocalReAlloc)
  931. File - from where alloc called
  932. Line - in File
  933. Return Value:
  934. HLOCAL
  935. Success - pointer to new block. May be same or different than previous
  936. pointer, depending on flags
  937. Failure - NULL
  938. --*/
  939. {
  940. if (!MemoryPackageInitialized) {
  941. return NULL;
  942. }
  943. //dprintf("InternetDebugReAllocMem(%#x, %d, %#x)\n", hLocal, Size, Flags);
  944. InterlockedIncrement((LPLONG)&MemoryReAllocations);
  945. //
  946. // we can't handle the following flags
  947. //
  948. INET_ASSERT(!(Flags & LMEM_MODIFY));
  949. //
  950. // can't handle reallocating down to zero
  951. //
  952. if (Size == 0) {
  953. MEMORY_ASSERT(FALSE);
  954. }
  955. HLOCAL hLocalOriginal = hLocal;
  956. LPDEBUG_MEMORY_HEADER lpHeader;
  957. SIZE_T actualLength;
  958. SIZE_T blockLength;
  959. SIZE_T requestedLength;
  960. SIZE_T oldRequestedLength;
  961. if (bNoDebugAlloc) {
  962. actualLength = InternetSize(hLocal);
  963. blockLength = actualLength;
  964. requestedLength = actualLength;
  965. } else {
  966. if (Size > LargestBlockRequested) {
  967. LargestBlockRequested = Size;
  968. LargestBlockRequestedFile = File;
  969. LargestBlockRequestedLine = Line;
  970. } else if (Size < SmallestBlockRequested) {
  971. SmallestBlockRequested = Size;
  972. SmallestBlockRequestedFile = File;
  973. SmallestBlockRequestedLine = Line;
  974. }
  975. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  976. hLocal = (HLOCAL)lpHeader;
  977. if (!CheckEntryOnSerializedList(&AllocatedBlockList, &lpHeader->List, TRUE) ||
  978. RemoveFromSerializedList(&AllocatedBlockList, &lpHeader->List)) {
  979. DEBUG_PRINT(MEMALLOC,
  980. ERROR,
  981. ("InternetDebugReAllocMem(%#x): can't find %#x or couldn't remove from list\n",
  982. hLocalOriginal
  983. ));
  984. MEMORY_ASSERT(FALSE);
  985. return hLocalOriginal;
  986. }
  987. InternetDebugCheckMemBlock(lpHeader);
  988. actualLength = InternetSize((HLOCAL)lpHeader);
  989. blockLength = lpHeader->BlockLength;
  990. requestedLength = lpHeader->RequestedLength;
  991. oldRequestedLength = requestedLength;
  992. if (!((lpHeader->ActualLength == actualLength)
  993. && (lpHeader->BlockLength <= actualLength)
  994. && !(lpHeader->BlockLength & (sizeof(DWORD) - 1))
  995. && (lpHeader->RequestedLength < lpHeader->BlockLength))) {
  996. DEBUG_PRINT(MEMALLOC,
  997. ERROR,
  998. ("InternetDebugReAllocMem(%#x): block lengths mismatch\n",
  999. hLocalOriginal
  1000. ));
  1001. MEMORY_ASSERT(FALSE);
  1002. }
  1003. }
  1004. EnterCriticalSection(&MemoryVarsCritSec);
  1005. ActualMemoryAllocated -= actualLength;
  1006. BlockLengthAllocated -= blockLength;
  1007. RealLengthAllocated -= requestedLength;
  1008. LeaveCriticalSection(&MemoryVarsCritSec);
  1009. requestedLength = Size;
  1010. if (bNoDebugAlloc) {
  1011. blockLength = Size;
  1012. } else {
  1013. blockLength = ROUND_UP_DWORD(Size)
  1014. + sizeof(DEBUG_MEMORY_HEADER)
  1015. + sizeof(DEBUG_MEMORY_FOOTER);
  1016. }
  1017. hLocal = InternetReAlloc(hLocal, blockLength, Flags);
  1018. if (hLocal != NULL) {
  1019. InterlockedIncrement((LPLONG)&GoodMemoryReAllocations);
  1020. actualLength = InternetSize(hLocal);
  1021. if (bNoDebugAlloc) {
  1022. blockLength = actualLength;
  1023. } else {
  1024. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  1025. //InitializeListHead(&lpHeader->List);
  1026. lpHeader->ThreadId = GetCurrentThreadId();
  1027. lpHeader->AccessedFile = File;
  1028. lpHeader->AccessedLine = Line;
  1029. lpHeader->RequestedLength = requestedLength;
  1030. lpHeader->BlockLength = blockLength;
  1031. lpHeader->ActualLength = actualLength;
  1032. lpHeader->Flags = Flags;
  1033. lpHeader->TimeDeferred = 0;
  1034. lpHeader->ClashTest = -1;
  1035. lpHeader->LastAccessOperation = MemReallocate;
  1036. #if DUMP_STACK
  1037. #if ONE_STACK
  1038. #else
  1039. //GET_CALLERS_ADDRESS(&lpHeader->LastAccessStack[0],
  1040. // &lpHeader->LastAccessStack[1]
  1041. // );
  1042. memset(lpHeader->LastAccessStack, 0, sizeof(lpHeader->LastAccessStack));
  1043. GET_CALL_STACK(lpHeader->LastAccessStack);
  1044. #endif // ONE_STACK
  1045. #endif // DUMP_STACK
  1046. LPBYTE extraPointer;
  1047. UINT dwFillLength;
  1048. UINT i;
  1049. if ((requestedLength > oldRequestedLength)
  1050. && bFillMemoryOnAlloc && !(Flags & LMEM_ZEROINIT)) {
  1051. extraPointer = (LPBYTE)(lpHeader + 1) + oldRequestedLength;
  1052. SIZE_T difference = requestedLength - oldRequestedLength;
  1053. DWORD dwFiller = AllocMemoryFiller;
  1054. SIZE_T syncLength = oldRequestedLength & (sizeof(DWORD) - 1);
  1055. if (syncLength) {
  1056. syncLength = sizeof(DWORD) - syncLength;
  1057. syncLength = min(syncLength, difference);
  1058. difference -= syncLength;
  1059. for (i = 0; i < syncLength; ++i) {
  1060. *extraPointer++ = ((LPBYTE)&dwFiller)[i];
  1061. }
  1062. }
  1063. //dwFillLength = difference / sizeof(DWORD);
  1064. //difference %= sizeof(DWORD);
  1065. //while (dwFillLength--) {
  1066. // *(LPDWORD)extraPointer = 0;
  1067. // extraPointer += sizeof(DWORD);
  1068. //}
  1069. //while (difference--) {
  1070. // *extraPointer++ = 0;
  1071. //}
  1072. if (difference) {
  1073. DebugFillMem(extraPointer, difference, dwFiller);
  1074. extraPointer += difference;
  1075. }
  1076. } else {
  1077. extraPointer = (LPBYTE)(lpHeader + 1) + requestedLength;
  1078. }
  1079. SIZE_T bFillLength = (sizeof(DWORD) - (requestedLength % sizeof(DWORD))) & (sizeof(DWORD) - 1);
  1080. while (bFillLength--) {
  1081. *extraPointer++ = BYTE_ALLOC_FILL_EXTRA;
  1082. }
  1083. LPDEBUG_MEMORY_FOOTER lpFooter = (LPDEBUG_MEMORY_FOOTER)extraPointer;
  1084. INET_ASSERT(lpFooter == (LPDEBUG_MEMORY_FOOTER)
  1085. ((LPBYTE)(lpHeader + 1) + ROUND_UP_DWORD(requestedLength)));
  1086. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  1087. lpFooter->Guard[i] = GUARD_DWORD_FILL;
  1088. }
  1089. lpFooter->Signature = FOOTER_SIGNATURE;
  1090. lpFooter->BlockLength = blockLength;
  1091. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  1092. lpFooter->Guard2[i] = GUARD_DWORD_FILL;
  1093. }
  1094. if (!InsertAtTailOfSerializedList(&AllocatedBlockList, &lpHeader->List)) {
  1095. DEBUG_PRINT(MEMALLOC,
  1096. ERROR,
  1097. ("failed to append to allocated block list.\n"
  1098. ));
  1099. DEBUG_BREAK(MEMALLOC);
  1100. }
  1101. hLocal = (HLOCAL)(lpHeader + 1);
  1102. }
  1103. EnterCriticalSection(&MemoryVarsCritSec);
  1104. ActualMemoryAllocated += actualLength;
  1105. BlockLengthAllocated += blockLength;
  1106. RealLengthAllocated += requestedLength;
  1107. LeaveCriticalSection(&MemoryVarsCritSec);
  1108. } else {
  1109. DEBUG_PRINT(MEMALLOC,
  1110. ERROR,
  1111. ("failed to reallocate %u bytes memory. Last error = %d\n",
  1112. Size,
  1113. GetLastError()
  1114. ));
  1115. DEBUG_BREAK(MEMALLOC);
  1116. }
  1117. return hLocal;
  1118. }
  1119. SIZE_T
  1120. InternetDebugSizeMem(
  1121. IN HLOCAL hLocal,
  1122. IN LPSTR File,
  1123. IN DWORD Line
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. Returns actual allocated block size
  1128. Arguments:
  1129. hLocal - pointer to allocated block
  1130. File - from where alloc called
  1131. Line - in File
  1132. Return Value:
  1133. SIZE_T
  1134. size of allocated block
  1135. --*/
  1136. {
  1137. if (!MemoryPackageInitialized) {
  1138. return 0;
  1139. }
  1140. //dprintf("InternetDebugSizeMem(%#x)\n", hLocal);
  1141. SIZE_T size = InternetSize(hLocal);
  1142. if (!bNoDebugAlloc) {
  1143. LPDEBUG_MEMORY_HEADER lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  1144. INET_ASSERT(lpHeader->Signature == HEADER_SIGNATURE);
  1145. SIZE_T sizeInHeader = lpHeader->BlockLength
  1146. - (sizeof(DEBUG_MEMORY_HEADER) + sizeof(DEBUG_MEMORY_FOOTER));
  1147. INET_ASSERT((sizeInHeader <= size)
  1148. && (size >= sizeof(DEBUG_MEMORY_HEADER) + sizeof(DEBUG_MEMORY_FOOTER))
  1149. && (lpHeader->ActualLength == size)
  1150. );
  1151. size = sizeInHeader;
  1152. }
  1153. return size;
  1154. }
  1155. BOOL
  1156. InternetDebugCheckMemFreed(
  1157. IN BOOL bReport
  1158. )
  1159. /*++
  1160. Routine Description:
  1161. Called when we're about to quit. Checks that all allocated memory has been
  1162. cleaned up
  1163. Arguments:
  1164. bReport - TRUE if in-use blocks reported
  1165. Return Value:
  1166. BOOL
  1167. TRUE - all allocated memory freed
  1168. FALSE - we failed to clean up
  1169. --*/
  1170. {
  1171. if (bReport) {
  1172. if (bReportMemoryUsage) {
  1173. ReportMemoryUsage();
  1174. }
  1175. if (bReportUnfreedBlocks) {
  1176. ReportMemoryBlocks();
  1177. }
  1178. }
  1179. if (ElementsOnSerializedList(&AllocatedBlockList) != 0) {
  1180. DEBUG_PRINT(MEMALLOC,
  1181. ERROR,
  1182. ("InternetDebugCheckMemFreed(): %d memory blocks still allocated\n",
  1183. MemoryAllocations - MemoryFrees
  1184. ));
  1185. MEMORY_ASSERT(FALSE);
  1186. return FALSE;
  1187. }
  1188. return TRUE;
  1189. }
  1190. BOOL
  1191. InternetDebugMemReport(
  1192. IN BOOL bTerminateSymbols,
  1193. IN BOOL bCloseFile
  1194. )
  1195. /*++
  1196. Routine Description:
  1197. Dumps in-use blocks to debugger and/or file
  1198. Arguments:
  1199. bTerminateSymbols - TRUE if we are to terminate symbols here
  1200. bCloseFile - TRUE if we are to close debug log file here
  1201. Return Value:
  1202. BOOL - TRUE if we opened debug log file
  1203. --*/
  1204. {
  1205. BOOL bOpened = FALSE;
  1206. if (bDumpToFile) {
  1207. bOpened = InternetOpenDebugFile();
  1208. if (bOpened) {
  1209. InternetDebugResetControlFlags(DBG_NO_DEBUG);
  1210. InternetDebugSetControlFlags(DBG_TO_FILE | DBG_NO_ASSERT_BREAK);
  1211. }
  1212. }
  1213. ReportMemoryUsage();
  1214. ReportMemoryBlocks();
  1215. if (bUseSymbols && bTerminateSymbols) {
  1216. TermSymLib();
  1217. }
  1218. if (bOpened && bCloseFile) {
  1219. InternetCloseDebugFile();
  1220. }
  1221. return bOpened;
  1222. }
  1223. //
  1224. // private functions
  1225. //
  1226. PRIVATE
  1227. VOID
  1228. DebugFillMem(
  1229. IN LPVOID Pointer,
  1230. IN SIZE_T Size,
  1231. IN DWORD dwFiller
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. Fills memory with repeating debug pattern. Performs DWORD fill then finishes
  1236. off any remaining bytes with character fill (rep movsd/rep movsb (ideally)
  1237. (x86!))
  1238. Arguments:
  1239. Pointer - memory to fill
  1240. Size - of Pointer in bytes
  1241. dwFiller - DWORD value to use
  1242. Return Value:
  1243. None.
  1244. --*/
  1245. {
  1246. INET_ASSERT(((DWORD_PTR)Pointer & (sizeof(DWORD) - 1)) == 0);
  1247. SIZE_T dwFillLength = Size / sizeof(DWORD);
  1248. SIZE_T bFillLength = Size % sizeof(DWORD);
  1249. //
  1250. // assume > 0 DWORDs to fill
  1251. //
  1252. LPDWORD lpdwPointer = (LPDWORD)Pointer;
  1253. SIZE_T i;
  1254. for (i = 0; i < dwFillLength; ++i) {
  1255. *lpdwPointer++ = dwFiller;
  1256. }
  1257. if (bFillLength) {
  1258. LPBYTE lpbPointer = (LPBYTE)lpdwPointer;
  1259. for (i = 0; i < bFillLength; ++i) {
  1260. *lpbPointer++ = ((LPBYTE)&dwFiller)[i];
  1261. }
  1262. }
  1263. }
  1264. PRIVATE
  1265. HLOCAL
  1266. InternetAlloc(
  1267. IN UINT Flags,
  1268. IN SIZE_T Size
  1269. )
  1270. /*++
  1271. Routine Description:
  1272. Allocator - uses process (local) heap or component (debug) heap based on
  1273. global flag setting
  1274. Arguments:
  1275. Flags - LocalAlloc flags
  1276. Size - of block to allocate
  1277. Return Value:
  1278. HLOCAL
  1279. Success - pointer to allocated block
  1280. Failure - NULL
  1281. --*/
  1282. {
  1283. if (bUseLocalAlloc) {
  1284. return LocalAlloc(Flags, Size);
  1285. } else {
  1286. return InternetHeapAlloc(Flags, Size);
  1287. }
  1288. }
  1289. PRIVATE
  1290. HLOCAL
  1291. InternetFree(
  1292. IN HLOCAL hLocal
  1293. )
  1294. /*++
  1295. Routine Description:
  1296. Deallocator - uses process (local) heap or component (debug) heap based on
  1297. global flag setting
  1298. Arguments:
  1299. hLocal - pointer to block to deallocate
  1300. Return Value:
  1301. HLOCAL
  1302. Success - NULL
  1303. Failure - pointer to still allocated block
  1304. --*/
  1305. {
  1306. if (bUseLocalAlloc) {
  1307. return LocalFree(hLocal);
  1308. } else {
  1309. return InternetHeapFree(hLocal);
  1310. }
  1311. }
  1312. PRIVATE
  1313. HLOCAL
  1314. InternetReAlloc(
  1315. IN HLOCAL hLocal,
  1316. IN SIZE_T Size,
  1317. IN UINT Flags
  1318. )
  1319. /*++
  1320. Routine Description:
  1321. Reallocator - uses process (local) heap or component (debug) heap based on
  1322. global flag setting
  1323. Arguments:
  1324. hLocal - pointer to block to reallocate
  1325. Flags - LocalAlloc flags
  1326. Size - of block to allocate
  1327. Return Value:
  1328. HLOCAL
  1329. Success - pointer to allocated block
  1330. Failure - NULL
  1331. --*/
  1332. {
  1333. if (bUseLocalAlloc) {
  1334. return LocalReAlloc(hLocal, Size, Flags);
  1335. } else {
  1336. return InternetHeapReAlloc(hLocal, Size, Flags);
  1337. }
  1338. }
  1339. PRIVATE
  1340. SIZE_T
  1341. InternetSize(
  1342. IN HLOCAL hLocal
  1343. )
  1344. /*++
  1345. Routine Description:
  1346. Block sizer - uses process (local) heap or component (debug) heap based on
  1347. global flag setting
  1348. Arguments:
  1349. hLocal - pointer to block to size
  1350. Return Value:
  1351. SIZE_T
  1352. Success - size of block
  1353. Failure - 0
  1354. --*/
  1355. {
  1356. if (bUseLocalAlloc) {
  1357. return LocalSize(hLocal);
  1358. } else {
  1359. return InternetHeapSize(hLocal);
  1360. }
  1361. }
  1362. PRIVATE
  1363. HLOCAL
  1364. InternetHeapAlloc(
  1365. IN UINT Flags,
  1366. IN SIZE_T Size
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. Allocate memory from debug heap
  1371. Arguments:
  1372. Flags - passed to LocalAlloc
  1373. Size - of block to allocate
  1374. Return Value:
  1375. HLOCAL
  1376. --*/
  1377. {
  1378. HLOCAL hLocal;
  1379. if (hDebugHeap != NULL) {
  1380. hLocal = (HLOCAL)HeapAlloc(hDebugHeap,
  1381. (bHeapNoSerialize
  1382. ? HEAP_NO_SERIALIZE
  1383. : 0)
  1384. | (bHeapGenerateExceptions
  1385. ? HEAP_GENERATE_EXCEPTIONS
  1386. : 0)
  1387. | ((Flags & LMEM_ZEROINIT)
  1388. ? HEAP_ZERO_MEMORY
  1389. : 0),
  1390. Size
  1391. );
  1392. } else {
  1393. DEBUG_PRINT(MEMALLOC,
  1394. ERROR,
  1395. ("InternetHeapAlloc(): hDebugHeap is NULL\n"
  1396. ));
  1397. MEMORY_ASSERT(FALSE);
  1398. hLocal = LocalAlloc(Flags, Size);
  1399. }
  1400. if (hLocal == NULL) {
  1401. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1402. }
  1403. return hLocal;
  1404. }
  1405. PRIVATE
  1406. HLOCAL
  1407. InternetHeapReAlloc(
  1408. IN HLOCAL hLocal,
  1409. IN SIZE_T Size,
  1410. IN UINT Flags
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Reallocate memory from debug heap
  1415. Arguments:
  1416. hLocal - pointer to block to reallocate
  1417. Size - new size
  1418. Flags - to LocalReAlloc
  1419. Return Value:
  1420. HLOCAL
  1421. Success - pointer to new block
  1422. Failure - NULL
  1423. --*/
  1424. {
  1425. if (hDebugHeap != NULL) {
  1426. hLocal = (HLOCAL)HeapReAlloc(hDebugHeap,
  1427. (bHeapNoSerialize
  1428. ? HEAP_NO_SERIALIZE
  1429. : 0)
  1430. | (bHeapGenerateExceptions
  1431. ? HEAP_GENERATE_EXCEPTIONS
  1432. : 0)
  1433. | ((Flags & LMEM_MOVEABLE)
  1434. ? 0
  1435. : HEAP_REALLOC_IN_PLACE_ONLY)
  1436. | ((Flags & LMEM_ZEROINIT)
  1437. ? HEAP_ZERO_MEMORY
  1438. : 0),
  1439. (LPVOID)hLocal,
  1440. Size
  1441. );
  1442. } else {
  1443. DEBUG_PRINT(MEMALLOC,
  1444. ERROR,
  1445. ("InternetHeapReAlloc(): hDebugHeap is NULL\n"
  1446. ));
  1447. MEMORY_ASSERT(FALSE);
  1448. //
  1449. // block still allocated
  1450. //
  1451. hLocal = NULL;
  1452. }
  1453. return hLocal;
  1454. }
  1455. PRIVATE
  1456. HLOCAL
  1457. InternetHeapFree(
  1458. IN HLOCAL hLocal
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. Free memory to debug heap
  1463. Arguments:
  1464. hLocal - to free
  1465. Return Value:
  1466. HLOCAL
  1467. Success - NULL
  1468. Failure - hLocal
  1469. --*/
  1470. {
  1471. BOOL ok;
  1472. if (hDebugHeap != NULL) {
  1473. ok = HeapFree(hDebugHeap,
  1474. bHeapNoSerialize ? HEAP_NO_SERIALIZE : 0,
  1475. (LPVOID)hLocal
  1476. );
  1477. if (!ok) {
  1478. DWORD error = GetLastError();
  1479. DEBUG_PRINT(MEMALLOC,
  1480. ERROR,
  1481. ("HeapFree() returns %s (%d)\n",
  1482. InternetMapError(error),
  1483. error
  1484. ));
  1485. MEMORY_ASSERT(FALSE);
  1486. }
  1487. } else {
  1488. DEBUG_PRINT(MEMALLOC,
  1489. ERROR,
  1490. ("InternetHeapFree(): hDebugHeap is NULL\n"
  1491. ));
  1492. MEMORY_ASSERT(FALSE);
  1493. ok = FALSE;
  1494. }
  1495. return ok ? NULL : hLocal;
  1496. }
  1497. PRIVATE
  1498. SIZE_T
  1499. InternetHeapSize(
  1500. IN HLOCAL hLocal
  1501. )
  1502. /*++
  1503. Routine Description:
  1504. Determines size of block allocated from debug heap
  1505. Arguments:
  1506. hLocal - handle (pointer) of block for which to get size
  1507. Return Value:
  1508. SIZE_T
  1509. Success - size of block
  1510. Failure - 0
  1511. --*/
  1512. {
  1513. SIZE_T size;
  1514. if (hDebugHeap != NULL) {
  1515. size = HeapSize(hDebugHeap,
  1516. bHeapNoSerialize ? HEAP_NO_SERIALIZE : 0,
  1517. (LPCVOID)hLocal
  1518. );
  1519. } else {
  1520. DEBUG_PRINT(MEMALLOC,
  1521. ERROR,
  1522. ("InternetHeapSize(): hDebugHeap is NULL\n"
  1523. ));
  1524. MEMORY_ASSERT(FALSE);
  1525. size = (SIZE_T)-1;
  1526. }
  1527. if (size == (SIZE_T)-1) {
  1528. SetLastError(ERROR_INVALID_HANDLE);
  1529. return 0;
  1530. } else {
  1531. return size;
  1532. }
  1533. }
  1534. PRIVATE
  1535. BOOL
  1536. InternetDebugCheckMemBlock(
  1537. IN LPDEBUG_MEMORY_HEADER lpHeader
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. Checks the consistency of a debug memory block
  1542. Arguments:
  1543. lpHeader - pointer to what we think is DEBUG_MEMORY_HEADER
  1544. Return Value:
  1545. None.
  1546. --*/
  1547. {
  1548. BOOL result;
  1549. __try {
  1550. LPDEBUG_MEMORY_FOOTER lpFooter = (LPDEBUG_MEMORY_FOOTER)
  1551. ((LPBYTE)lpHeader
  1552. + (lpHeader->BlockLength - sizeof(DEBUG_MEMORY_FOOTER)));
  1553. BOOL headerGuardOverrun = FALSE;
  1554. UINT i;
  1555. for (i = 0; i < ARRAY_ELEMENTS(lpHeader->Guard); ++i) {
  1556. if (lpHeader->Guard[i] != GUARD_DWORD_FILL) {
  1557. headerGuardOverrun = TRUE;
  1558. break;
  1559. }
  1560. }
  1561. BOOL footerGuardOverrun = FALSE;
  1562. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  1563. if (lpFooter->Guard[i] != GUARD_DWORD_FILL) {
  1564. footerGuardOverrun = TRUE;
  1565. break;
  1566. }
  1567. }
  1568. BOOL footerGuard2Overrun = FALSE;
  1569. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  1570. if (lpFooter->Guard2[i] != GUARD_DWORD_FILL) {
  1571. footerGuard2Overrun = TRUE;
  1572. break;
  1573. }
  1574. }
  1575. LPBYTE lpExtraMemory = (LPBYTE)(lpHeader + 1) + lpHeader->RequestedLength;
  1576. BOOL extraMemoryOverrun = FALSE;
  1577. SIZE_T byteLength = ROUND_UP_DWORD(lpHeader->RequestedLength) - lpHeader->RequestedLength;
  1578. for (i = 0; i < byteLength; ++i) {
  1579. if (lpExtraMemory[i] != BYTE_ALLOC_FILL_EXTRA) {
  1580. extraMemoryOverrun = TRUE;
  1581. break;
  1582. }
  1583. }
  1584. if (headerGuardOverrun
  1585. || footerGuardOverrun
  1586. || footerGuard2Overrun
  1587. || extraMemoryOverrun
  1588. || (lpHeader->Signature != HEADER_SIGNATURE)
  1589. || (lpFooter->Signature != FOOTER_SIGNATURE)
  1590. || (lpFooter->BlockLength != lpHeader->BlockLength)) {
  1591. DEBUG_PRINT(MEMALLOC,
  1592. ERROR,
  1593. ("Bad block: %#x\n",
  1594. lpHeader
  1595. ));
  1596. MEMORY_ASSERT(FALSE);
  1597. result = FALSE;
  1598. } else {
  1599. result = TRUE;
  1600. }
  1601. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1602. DEBUG_PRINT(MEMALLOC,
  1603. FATAL,
  1604. ("Invalid block %#x - exception occurred\n",
  1605. lpHeader
  1606. ));
  1607. MEMORY_ASSERT(FALSE);
  1608. result = FALSE;
  1609. }
  1610. return result;
  1611. }
  1612. PRIVATE
  1613. VOID
  1614. InternetDebugMemTest(
  1615. VOID
  1616. )
  1617. {
  1618. //
  1619. // test
  1620. //
  1621. LPVOID p;
  1622. p = (LPVOID)ALLOCATE_MEMORY(LMEM_FIXED, 1);
  1623. *((LPBYTE)p + 1) = 'X';
  1624. p = (LPVOID)FREE_MEMORY((HLOCAL)p);
  1625. INET_ASSERT(p == NULL);
  1626. p = (LPVOID)ALLOCATE_MEMORY(LMEM_FIXED, 1);
  1627. p = (LPVOID)REALLOCATE_MEMORY(p, 1111, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1628. p = (LPVOID)REALLOCATE_MEMORY(p, 439, LMEM_MOVEABLE);
  1629. p = (LPVOID)REALLOCATE_MEMORY(p, 720, LMEM_MOVEABLE);
  1630. p = (LPVOID)REALLOCATE_MEMORY(p, 256, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1631. p = (LPVOID)REALLOCATE_MEMORY(p, 16, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1632. p = (LPVOID)REALLOCATE_MEMORY(p, 128, LMEM_MOVEABLE);
  1633. p = (LPVOID)REALLOCATE_MEMORY(p, 32, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1634. p = (LPVOID)REALLOCATE_MEMORY(p, 4, LMEM_MOVEABLE);
  1635. p = (LPVOID)REALLOCATE_MEMORY(p, 64, LMEM_MOVEABLE);
  1636. p = (LPVOID)REALLOCATE_MEMORY(p, 63, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1637. p = (LPVOID)REALLOCATE_MEMORY(p, 64, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1638. p = (LPVOID)REALLOCATE_MEMORY(p, 65, LMEM_MOVEABLE | LMEM_ZEROINIT);
  1639. p = (LPVOID)REALLOCATE_MEMORY(p, 65, LMEM_MOVEABLE);
  1640. p = (LPVOID)REALLOCATE_MEMORY(p, 64, LMEM_MOVEABLE);
  1641. p = (LPVOID)REALLOCATE_MEMORY(p, 64, LMEM_MOVEABLE);
  1642. p = (LPVOID)FREE_MEMORY((HLOCAL)p);
  1643. INET_ASSERT(p == NULL);
  1644. p = (LPVOID)ALLOCATE_MEMORY(LMEM_FIXED, 8);
  1645. p = (LPVOID)REALLOCATE_MEMORY(p, 8, LMEM_FIXED);
  1646. p = (LPVOID)REALLOCATE_MEMORY(p, 100000, LMEM_FIXED);
  1647. p = (LPVOID)FREE_MEMORY((HLOCAL)p);
  1648. INET_ASSERT(p == NULL);
  1649. InternetDebugCheckMemFreed(TRUE);
  1650. }
  1651. PRIVATE
  1652. VOID
  1653. ReportMemoryUsage(
  1654. VOID
  1655. )
  1656. {
  1657. //
  1658. // make copies of variables in case debug print functions want to allocate
  1659. // debug memory (!)
  1660. //
  1661. SIZE_T totalActualMemoryAllocated;
  1662. SIZE_T totalBlockMemoryAllocated;
  1663. SIZE_T totalRealMemoryAllocated;
  1664. SIZE_T totalActualMemoryFreed;
  1665. SIZE_T totalBlockMemoryFreed;
  1666. SIZE_T totalRealMemoryFreed;
  1667. SIZE_T actualMemoryAllocated;
  1668. SIZE_T blockLengthAllocated;
  1669. SIZE_T realLengthAllocated;
  1670. DWORD memoryAllocations;
  1671. DWORD goodMemoryAllocations;
  1672. DWORD memoryReAllocations;
  1673. DWORD goodMemoryReAllocations;
  1674. DWORD memoryFrees;
  1675. DWORD goodMemoryFrees;
  1676. SIZE_T largestBlockRequested;
  1677. SIZE_T largestBlockAllocated;
  1678. SIZE_T smallestBlockRequested;
  1679. SIZE_T smallestBlockAllocated;
  1680. EnterCriticalSection(&MemoryVarsCritSec);
  1681. totalActualMemoryAllocated = TotalActualMemoryAllocated;
  1682. totalBlockMemoryAllocated = TotalBlockMemoryAllocated;
  1683. totalRealMemoryAllocated = TotalRealMemoryAllocated;
  1684. totalActualMemoryFreed = TotalActualMemoryFreed;
  1685. totalBlockMemoryFreed = TotalBlockMemoryFreed;
  1686. totalRealMemoryFreed = TotalRealMemoryFreed;
  1687. actualMemoryAllocated = ActualMemoryAllocated;
  1688. blockLengthAllocated = BlockLengthAllocated;
  1689. realLengthAllocated = RealLengthAllocated;
  1690. memoryAllocations = MemoryAllocations;
  1691. goodMemoryAllocations = GoodMemoryAllocations;
  1692. memoryReAllocations = MemoryReAllocations;
  1693. goodMemoryReAllocations = GoodMemoryReAllocations;
  1694. memoryFrees = MemoryFrees;
  1695. goodMemoryFrees = GoodMemoryFrees;
  1696. largestBlockRequested = LargestBlockRequested;
  1697. largestBlockAllocated = LargestBlockAllocated;
  1698. smallestBlockRequested = SmallestBlockRequested;
  1699. smallestBlockAllocated = SmallestBlockAllocated;
  1700. LeaveCriticalSection(&MemoryVarsCritSec);
  1701. #ifdef _WIN64
  1702. char numBuf[64];
  1703. #else
  1704. char numBuf[32];
  1705. #endif
  1706. DEBUG_PUT(("********************************************************************************\n"
  1707. "\n"
  1708. "WinHttp Debug Memory Usage:\n"
  1709. "\n"
  1710. "\tInternetDebugMemFlags = %#08x\n"
  1711. "\n",
  1712. InternetDebugMemFlags
  1713. ));
  1714. DEBUG_PUT(("\tTotal Memory Allocated. . . , . . . . %s\n", NiceNum(numBuf, totalActualMemoryAllocated, 0)));
  1715. DEBUG_PUT(("\tTotal Block Length Allocated. . . . . %s\n", NiceNum(numBuf, totalBlockMemoryAllocated, 0)));
  1716. DEBUG_PUT(("\tTotal User Length Allocated . . . . . %s\n", NiceNum(numBuf, totalRealMemoryAllocated, 0)));
  1717. DEBUG_PUT(("\tTotal Memory Freed. . . . . . . . . . %s\n", NiceNum(numBuf, totalActualMemoryFreed, 0)));
  1718. DEBUG_PUT(("\tTotal Block Length Freed. . . . . . . %s\n", NiceNum(numBuf, totalBlockMemoryFreed, 0)));
  1719. DEBUG_PUT(("\tTotal User Length Freed . . . . . . . %s\n", NiceNum(numBuf, totalRealMemoryFreed, 0)));
  1720. DEBUG_PUT(("\tMemory Still Allocated. . . . . . . . %s\n", NiceNum(numBuf, actualMemoryAllocated, 0)));
  1721. DEBUG_PUT(("\tBlock Length Still Allocated. . . . . %s\n", NiceNum(numBuf, blockLengthAllocated, 0)));
  1722. DEBUG_PUT(("\tUser Length Still Allocated . . . . . %s\n", NiceNum(numBuf, realLengthAllocated, 0)));
  1723. DEBUG_PUT(("\tAttempted Memory Allocations. . . . . %s\n", NiceNum(numBuf, memoryAllocations, 0)));
  1724. DEBUG_PUT(("\tGood Memory Allocations . . . . . . . %s\n", NiceNum(numBuf, goodMemoryAllocations, 0)));
  1725. DEBUG_PUT(("\tAttempted Memory Reallocations. . . . %s\n", NiceNum(numBuf, memoryReAllocations, 0)));
  1726. DEBUG_PUT(("\tGood Memory Reallocations . . . . . . %s\n", NiceNum(numBuf, goodMemoryReAllocations, 0)));
  1727. DEBUG_PUT(("\tAttempted Memory Frees. . . . . . . . %s\n", NiceNum(numBuf, memoryFrees, 0)));
  1728. DEBUG_PUT(("\tGood Memory Frees . . . . . . . . . . %s\n", NiceNum(numBuf, goodMemoryFrees, 0)));
  1729. DEBUG_PUT(("\tLargest Block Requested . . . . . . . %s\n", NiceNum(numBuf, largestBlockRequested, 0)));
  1730. DEBUG_PUT(("\tLargest Block Allocated . . . . . . . %s\n", NiceNum(numBuf, largestBlockAllocated, 0)));
  1731. DEBUG_PUT(("\tLargest Block Requested From. . . . . %s!%d\n", SourceFilename(LargestBlockRequestedFile), LargestBlockRequestedLine));
  1732. DEBUG_PUT(("\tSmallest Block Requested. . . . . . . %s\n", NiceNum(numBuf, smallestBlockRequested, 0)));
  1733. DEBUG_PUT(("\tSmallest Block Allocated. . . . . . . %s\n", NiceNum(numBuf, smallestBlockAllocated, 0)));
  1734. DEBUG_PUT(("\tSmallest Block Requested From . . . . %s!%d\n", SourceFilename(SmallestBlockRequestedFile), SmallestBlockRequestedLine));
  1735. DEBUG_PUT(("\n"
  1736. "\tBlocks Still Allocated. . . . . . . . %s\n", NiceNum(numBuf, goodMemoryAllocations - goodMemoryFrees, 0)));
  1737. DEBUG_PUT(("\tMemory Still Allocated. . . . . . . . %s\n", NiceNum(numBuf, totalActualMemoryAllocated - totalActualMemoryFreed, 0)));
  1738. DEBUG_PUT(("\n"
  1739. "********************************************************************************\n"
  1740. "\n"));
  1741. }
  1742. PRIVATE
  1743. VOID
  1744. ReportMemoryBlocks(
  1745. VOID
  1746. )
  1747. {
  1748. DEBUG_PUT(("ReportMemoryBlocks\n\n"));
  1749. DEBUG_PUT(("AllocatedBlockList:\n\n"));
  1750. DumpMemoryList(&AllocatedBlockList);
  1751. if (bDeferFree) {
  1752. DumpDeferredFreeList();
  1753. }
  1754. }
  1755. PRIVATE
  1756. VOID
  1757. DumpDeferredFreeList(
  1758. VOID
  1759. )
  1760. {
  1761. DEBUG_PUT(("DeferredFreeList:\n\n"));
  1762. DumpMemoryList(&DeferredFreeList);
  1763. }
  1764. PRIVATE
  1765. VOID
  1766. DumpMemoryList(
  1767. IN LPSERIALIZED_LIST lpList
  1768. )
  1769. {
  1770. LPDEBUG_MEMORY_HEADER lpHeader;
  1771. int counter = 1;
  1772. if (bUseSymbols) {
  1773. //
  1774. // have to load IMAGEHLP.DLL here because we're in DLL_PROCESS_DETACH
  1775. // and if we loaded it earlier, there's a good chance the system has
  1776. // already freed it
  1777. //
  1778. InitSymLib();
  1779. }
  1780. LockSerializedList(lpList);
  1781. lpHeader = (LPDEBUG_MEMORY_HEADER)HeadOfSerializedList(lpList);
  1782. while (lpHeader != (LPDEBUG_MEMORY_HEADER)SlSelf(lpList)) {
  1783. DEBUG_PUT(("Block # %d\n", counter));
  1784. if (!DumpBlock(lpHeader)) {
  1785. break;
  1786. }
  1787. DEBUG_PUT(("********************************************************************************\n\n"));
  1788. lpHeader = (LPDEBUG_MEMORY_HEADER)(lpHeader->List.Flink);
  1789. ++counter;
  1790. }
  1791. UnlockSerializedList(lpList);
  1792. }
  1793. PRIVATE
  1794. VOID
  1795. FindAndDumpDeferredBlock(
  1796. IN HLOCAL hLocal
  1797. )
  1798. {
  1799. LPDEBUG_MEMORY_HEADER lpHeader;
  1800. LockSerializedList(&DeferredFreeList);
  1801. lpHeader = (LPDEBUG_MEMORY_HEADER)HeadOfSerializedList(&DeferredFreeList);
  1802. while (lpHeader != (LPDEBUG_MEMORY_HEADER)SlSelf(&DeferredFreeList)) {
  1803. if (hLocal == (HLOCAL)lpHeader) {
  1804. DumpBlock(lpHeader);
  1805. break;
  1806. }
  1807. lpHeader = (LPDEBUG_MEMORY_HEADER)(lpHeader->List.Flink);
  1808. }
  1809. UnlockSerializedList(&DeferredFreeList);
  1810. }
  1811. PRIVATE
  1812. BOOL
  1813. DumpBlock(
  1814. IN LPDEBUG_MEMORY_HEADER lpHeader
  1815. )
  1816. {
  1817. BOOL ok = DumpDebugMemoryHeader(lpHeader);
  1818. if (!ok && bStopDumpIfBadBlock) {
  1819. DEBUG_PUT(("*** stopping block dump: header @ %#x is bad\n", lpHeader));
  1820. return FALSE;
  1821. }
  1822. if (bReportUserData) {
  1823. DumpUserData(lpHeader);
  1824. }
  1825. if (bReportMemoryFooters) {
  1826. LPDEBUG_MEMORY_FOOTER lpFooter;
  1827. lpFooter = (LPDEBUG_MEMORY_FOOTER)
  1828. ((LPBYTE)lpHeader
  1829. + sizeof(*lpHeader)
  1830. + ROUND_UP_DWORD(lpHeader->RequestedLength));
  1831. ok = DumpDebugMemoryFooter(lpFooter);
  1832. if (!ok && bStopDumpIfBadBlock) {
  1833. DEBUG_PUT(("*** stopping block dump: footer @ %#x is bad\n", lpFooter));
  1834. return FALSE;
  1835. }
  1836. }
  1837. return TRUE;
  1838. }
  1839. PRIVATE
  1840. BOOL
  1841. DumpDebugMemoryHeader(
  1842. LPDEBUG_MEMORY_HEADER lpHeader
  1843. )
  1844. {
  1845. char numBuf[32];
  1846. BOOL result;
  1847. LPSTR symbol;
  1848. DWORD offset;
  1849. int i;
  1850. char flagsBuf[256];
  1851. __try {
  1852. DEBUG_PUT(("DEBUG_MEMORY_HEADER @ %#x:\n"
  1853. "\n",
  1854. lpHeader
  1855. ));
  1856. DEBUG_PUT(("\tList. . . . . . . . . F=%#x B=%#x\n",
  1857. lpHeader->List.Flink,
  1858. lpHeader->List.Blink
  1859. ));
  1860. DEBUG_PUT(("\tThread. . . . . . . . %#x\n",
  1861. lpHeader->ThreadId
  1862. ));
  1863. DEBUG_PUT(("\tAllocated From. . . . %s!%d\n",
  1864. SourceFilename(lpHeader->CreatedFile),
  1865. lpHeader->CreatedLine
  1866. ));
  1867. DEBUG_PUT(("\tLast Accessed From. . %s!%d\n",
  1868. SourceFilename(lpHeader->AccessedFile),
  1869. lpHeader->AccessedLine
  1870. ));
  1871. DEBUG_PUT(("\tRequested Length. . . %s\n",
  1872. NiceNum(numBuf, lpHeader->RequestedLength, 0)
  1873. ));
  1874. DEBUG_PUT(("\tBlock Length. . . . . %s\n",
  1875. NiceNum(numBuf, lpHeader->BlockLength, 0)
  1876. ));
  1877. DEBUG_PUT(("\tActual Length . . . . %s\n",
  1878. NiceNum(numBuf, lpHeader->ActualLength, 0)
  1879. ));
  1880. DEBUG_PUT(("\tSignature . . . . . . %x (%s)\n",
  1881. lpHeader->Signature,
  1882. (lpHeader->Signature == HEADER_SIGNATURE) ? "Good" : "BAD!!!"
  1883. ));
  1884. DEBUG_PUT(("\tFlags . . . . . . . . %08x %s\n",
  1885. lpHeader->Flags,
  1886. MapMemoryFlags(lpHeader->Flags, flagsBuf)
  1887. ));
  1888. DEBUG_PUT(("\tTime Deferred . . . . %08x\n",
  1889. lpHeader->TimeDeferred
  1890. ));
  1891. DEBUG_PUT(("\tClash Test. . . . . . %d\n",
  1892. lpHeader->ClashTest
  1893. ));
  1894. DEBUG_PUT(("\tLast Operation. . . . %s\n",
  1895. MapLastAccessOperation(lpHeader->LastAccessOperation)
  1896. ));
  1897. #if DUMP_STACK
  1898. #if ONE_STACK
  1899. if (lpHeader->Stack[0]) {
  1900. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->Stack[0], &offset);
  1901. } else {
  1902. symbol = "";
  1903. offset = 0;
  1904. }
  1905. DEBUG_PUT(("\tStack . . . . . . . . %08x %s+%#x\n",
  1906. lpHeader->Stack[0],
  1907. symbol,
  1908. offset
  1909. ));
  1910. for (i = 1; i < ARRAY_ELEMENTS(lpHeader->Stack); ++i) {
  1911. //if (!lpHeader->lpHeader->Stack[i]) {
  1912. // break;
  1913. //}
  1914. if (lpHeader->Stack[i]) {
  1915. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->Stack[i], &offset);
  1916. } else {
  1917. symbol = "";
  1918. offset = 0;
  1919. }
  1920. DEBUG_PUT(("\t. . . . . . . . . . . %08x %s+%#x\n",
  1921. lpHeader->Stack[i],
  1922. symbol,
  1923. offset
  1924. ));
  1925. }
  1926. #else
  1927. if (lpHeader->LastAccessStack[0]) {
  1928. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->LastAccessStack[0], &offset);
  1929. } else {
  1930. symbol = "";
  1931. offset = 0;
  1932. }
  1933. DEBUG_PUT(("\tLastAccessStack . . . %08x %s+%#x\n",
  1934. lpHeader->LastAccessStack[0],
  1935. symbol,
  1936. offset
  1937. ));
  1938. for (i = 1; i < ARRAY_ELEMENTS(lpHeader->LastAccessStack); ++i) {
  1939. //if (!lpHeader->LastAccessStack[i]) {
  1940. // break;
  1941. //}
  1942. if (lpHeader->LastAccessStack[i]) {
  1943. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->LastAccessStack[i], &offset);
  1944. } else {
  1945. symbol = "";
  1946. offset = 0;
  1947. }
  1948. DEBUG_PUT(("\t. . . . . . . . . . . %08x %s+%#x\n",
  1949. lpHeader->LastAccessStack[i],
  1950. symbol,
  1951. offset
  1952. ));
  1953. }
  1954. if (lpHeader->CreateStack[0]) {
  1955. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->CreateStack[0], &offset);
  1956. } else {
  1957. symbol = "";
  1958. offset = 0;
  1959. }
  1960. DEBUG_PUT(("\tCreateStack . . . . . %08x %s+%#x\n",
  1961. lpHeader->CreateStack[0],
  1962. symbol,
  1963. offset
  1964. ));
  1965. for (i = 1; i < ARRAY_ELEMENTS(lpHeader->CreateStack); ++i) {
  1966. //if (!lpHeader->lpHeader->CreateStack[i]) {
  1967. // break;
  1968. //}
  1969. if (lpHeader->CreateStack[i]) {
  1970. symbol = DbgMemGetDebugSymbol((DWORD)lpHeader->CreateStack[i], &offset);
  1971. } else {
  1972. symbol = "";
  1973. offset = 0;
  1974. }
  1975. DEBUG_PUT(("\t. . . . . . . . . . . %08x %s+%#x\n",
  1976. lpHeader->CreateStack[i],
  1977. symbol,
  1978. offset
  1979. ));
  1980. }
  1981. #endif // ONE_STACK
  1982. #endif // DUMP_STACK
  1983. DEBUG_PUT(("\tGuard . . . . . . . . %08x\n"
  1984. "\n",
  1985. lpHeader->Guard[0]
  1986. ));
  1987. result = TRUE;
  1988. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1989. //DEBUG_PUT(("DEBUG_MEMORY_HEADER @ %#x is BAD\n", lpHeader));
  1990. result = FALSE;
  1991. }
  1992. return result;
  1993. }
  1994. PRIVATE
  1995. BOOL
  1996. DumpDebugMemoryFooter(
  1997. LPDEBUG_MEMORY_FOOTER lpFooter
  1998. )
  1999. {
  2000. char numBuf[32];
  2001. BOOL result;
  2002. _try {
  2003. DEBUG_PUT(("DEBUG_MEMORY_FOOTER @ %#x:\n"
  2004. "\n",
  2005. lpFooter
  2006. ));
  2007. DEBUG_PUT(("\tGuard . . . . . . . . %08x %08x %08x %08x\n",
  2008. lpFooter->Guard[0],
  2009. lpFooter->Guard[1],
  2010. lpFooter->Guard[2],
  2011. lpFooter->Guard[3]
  2012. ));
  2013. DEBUG_PUT(("\tSignature . . . . . . %x (%s)\n",
  2014. lpFooter->Signature,
  2015. (lpFooter->Signature == FOOTER_SIGNATURE) ? "Good" : "BAD!!!"
  2016. ));
  2017. DEBUG_PUT(("\tBlock Length. . . . . %s\n",
  2018. NiceNum(numBuf, lpFooter->BlockLength, 0)
  2019. ));
  2020. DEBUG_PUT(("\tGuard2. . . . . . . . %08x %08x\n"
  2021. "\n",
  2022. lpFooter->Guard2[0],
  2023. lpFooter->Guard2[1]
  2024. ));
  2025. result = TRUE;
  2026. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2027. //DEBUG_PUT(("DEBUG_MEMORY_FOOTER @ %#x is BAD\n", lpFooter));
  2028. result = FALSE;
  2029. }
  2030. return result;
  2031. }
  2032. PRIVATE
  2033. VOID
  2034. DumpUserData(
  2035. LPDEBUG_MEMORY_HEADER lpHeader
  2036. )
  2037. {
  2038. static char spaces[] = " "; // 15 * 3 + 2
  2039. SIZE_T userSize = lpHeader->RequestedLength;
  2040. SIZE_T Size = ROUND_UP_DWORD(userSize);
  2041. LPBYTE Address = (LPBYTE)(lpHeader + 1);
  2042. DEBUG_PUT(("\t%d (%#x) bytes of user data (rounded to %d (%#x)) @ %#x\n\n",
  2043. userSize,
  2044. userSize,
  2045. Size,
  2046. Size,
  2047. Address
  2048. ));
  2049. if (bLimitUserData && (Size > MaxUserDataDumped)) {
  2050. DEBUG_PUT(("*** User data length %d too large: limited to %d (probably bad block)\n",
  2051. Size,
  2052. MaxUserDataDumped
  2053. ));
  2054. Size = MaxUserDataDumped;
  2055. }
  2056. //
  2057. // dump out the data, debug style
  2058. //
  2059. while (Size) {
  2060. char buf[128];
  2061. int len;
  2062. int clen;
  2063. rsprintf(buf, "\t%08x ", Address);
  2064. clen = (int)min(Size, 16);
  2065. if (bDumpAsDwords) {
  2066. len = clen / 4;
  2067. } else {
  2068. len = clen;
  2069. }
  2070. //
  2071. // dump the hex representation of each character - up to 16 per line
  2072. //
  2073. int i;
  2074. for (i = 0; i < len; ++i) {
  2075. if (bDumpAsDwords) {
  2076. rsprintf(&buf[11 + i * 9], "%08x ", ((LPDWORD)Address)[i]);
  2077. } else {
  2078. rsprintf(&buf[11 + i * 3],
  2079. ((i & 15) == 7) ? "%02.2x-" : "%02.2x ",
  2080. Address[i] & 0xff
  2081. );
  2082. }
  2083. }
  2084. //
  2085. // write as many spaces as required to tab to ASCII field
  2086. //
  2087. int offset;
  2088. if (bDumpAsDwords) {
  2089. memcpy(&buf[11 + i * 9], spaces, (4 - len) * 9 + 2);
  2090. offset = 49;
  2091. } else {
  2092. memcpy(&buf[11 + i * 3], spaces, (16 - len) * 3 + 2);
  2093. offset = 60;
  2094. }
  2095. //
  2096. // dump ASCII representation of each character
  2097. //
  2098. for (i = 0; i < clen; ++i) {
  2099. char ch;
  2100. ch = Address[i];
  2101. buf[offset + i] = ((ch < 32) || (ch > 127)) ? '.' : ch;
  2102. }
  2103. buf[offset + i++] = '\r';
  2104. buf[offset + i++] = '\n';
  2105. buf[offset + i] = 0;
  2106. //
  2107. // InternetDebugOut() - no printf expansion (%s in data!), no prefixes
  2108. //
  2109. InternetDebugOut(buf, FALSE);
  2110. Address += clen;
  2111. Size -= clen;
  2112. }
  2113. InternetDebugOut("\r\n", FALSE);
  2114. }
  2115. PRIVATE
  2116. LPSTR
  2117. MapLastAccessOperation(
  2118. MEMORY_ACTION Action
  2119. )
  2120. {
  2121. switch (Action) {
  2122. case MemAllocate:
  2123. return "Alloc";
  2124. case MemReallocate:
  2125. return "Realloc";
  2126. case MemLock:
  2127. return "Lock";
  2128. case MemUnlock:
  2129. return "Unlock";
  2130. case MemFree:
  2131. return "Free";
  2132. case MemSize:
  2133. return "Size";
  2134. }
  2135. return "?";
  2136. }
  2137. PRIVATE
  2138. LPSTR
  2139. MapMemoryFlags(
  2140. DWORD Flags,
  2141. LPSTR Buffer
  2142. )
  2143. {
  2144. LPSTR buf = Buffer;
  2145. int i = 0;
  2146. *buf++ = '(';
  2147. if (Flags & LMEM_DISCARDABLE) {
  2148. buf += wsprintf(buf, "DISCARDABLE");
  2149. ++i;
  2150. }
  2151. if (Flags & LMEM_ZEROINIT) {
  2152. if (i) {
  2153. buf += wsprintf(buf, ", ");
  2154. }
  2155. ++i;
  2156. buf += wsprintf(buf, "ZEROINIT");
  2157. }
  2158. if (Flags & LMEM_NODISCARD) {
  2159. if (i) {
  2160. buf += wsprintf(buf, ", ");
  2161. }
  2162. ++i;
  2163. buf += wsprintf(buf, "NODISCARD");
  2164. }
  2165. if (Flags & LMEM_NOCOMPACT) {
  2166. if (i) {
  2167. buf += wsprintf(buf, ", ");
  2168. }
  2169. ++i;
  2170. buf += wsprintf(buf, "NOCOMPACT");
  2171. }
  2172. if (i) {
  2173. buf += wsprintf(buf, ", ");
  2174. }
  2175. ++i;
  2176. buf += wsprintf(buf, (Flags & LMEM_MOVEABLE) ? "MOVEABLE" : "FIXED");
  2177. *buf++ = ')';
  2178. *buf++ = '\0';
  2179. return Buffer;
  2180. }
  2181. PRIVATE
  2182. LPSTR
  2183. DbgMemGetDebugSymbol(
  2184. DWORD Address,
  2185. LPDWORD Offset
  2186. ) {
  2187. //if (!bUseSymbols) {
  2188. // return "?";
  2189. //}
  2190. //
  2191. // RLF 04/14/98 - IMAGEHLP blowing up probably because we are doing this at
  2192. // process detach time. Just return offset and run convsym
  2193. // utility on WinHttp.log
  2194. //
  2195. //return GetDebugSymbol(Address, Offset);
  2196. *Offset = Address;
  2197. return "";
  2198. }
  2199. #endif // defined(USE_DEBUG_MEMORY)