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.

1199 lines
27 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. memalloc.cxx
  5. Abstract:
  6. Debug-only memory allocation routines
  7. Contents:
  8. InetInitializeDebugMemoryPackage
  9. InetTerminateDebugMemoryPackage
  10. InetAllocateMemory
  11. InetReallocateMemory
  12. (InetIsBlockMoveable)
  13. InetFreeMemory
  14. (InetCheckBlockConsistency)
  15. InetLockMemory
  16. InetUnlockMemory
  17. InetMemorySize
  18. InetCheckDebugMemoryFreed
  19. (x86SleazeCallersAddress)
  20. Author:
  21. Richard L Firth (rfirth) 02-Feb-1995
  22. Environment:
  23. Win32 user mode
  24. Revision History:
  25. 02-Feb-1995
  26. Created
  27. --*/
  28. #include <wininetp.h>
  29. #include "rprintf.h"
  30. #if INET_DEBUG
  31. //
  32. // manifests
  33. //
  34. #define HEADER_SIGNATURE 0x414d454d // 'MEMA'
  35. #define FOOTER_SIGNATURE 0x434f4c4c // 'LLOC'
  36. #define DWORD_FILL 0xa9a9a9a9
  37. #define BYTE_FILL 0xa9
  38. #define BYTE_FILL_EXTRA 0xcb
  39. #define GUARD_DWORD_FILL 0xcccd21f4
  40. #define DWORD_FREE_FILL 0xb7b7b7b7
  41. #define BYTE_FREE_FILL 0xb7
  42. //
  43. // private types
  44. //
  45. typedef struct {
  46. //
  47. // hMoveable - local handle of moveable memory that this tag links
  48. //
  49. HLOCAL hMoveable;
  50. } DEBUG_MOVEABLE_TAG, *LPDEBUG_MOVEABLE_TAG;
  51. typedef struct {
  52. //
  53. // List - maintains a list of allocated blocks
  54. //
  55. LIST_ENTRY List;
  56. //
  57. // BlockLength - the size of this block, *including* all headers, footers
  58. // and padding
  59. //
  60. UINT BlockLength;
  61. //
  62. // RealLength - the original caller request
  63. //
  64. UINT RealLength;
  65. //
  66. // Signature - just used as a sanity check to ensure that what we are
  67. // dealing with is actually a block we allocated
  68. //
  69. DWORD Signature;
  70. //
  71. // LockCount - if this is moveable memory, keeps the number of times this
  72. // block has been locked
  73. //
  74. LONG LockCount;
  75. //
  76. // Flags - what type of memory this is, etc.
  77. //
  78. DWORD Flags;
  79. //
  80. // LastAccessOperation - the operation caller at LastAccessReturnAddress
  81. // performed
  82. //
  83. MEMALLOC_ACTION LastAccessOperation;
  84. //
  85. // LastAccessReturnAddress - caller of last function to perform memory
  86. // function operation (alloc, lock, realloc, unlock, etc) on this block
  87. //
  88. LPVOID LastAccessReturnAddress[2];
  89. //
  90. // CreatorReturnAddress - return EIP (x86-only) of caller of allocator
  91. // and caller of caller
  92. //
  93. LPVOID CreatorReturnAddress[2];
  94. //
  95. // Tag - if this is moveable memory, we can't add this block to the allocated
  96. // block list, we have to allocate a DEBUG_MOVEABLE_TAG, link that and point
  97. // to it from here
  98. //
  99. LPDEBUG_MOVEABLE_TAG Tag;
  100. //
  101. // Guard - just a sentinel to find out if the caller is writing before the
  102. // start of this block
  103. //
  104. DWORD Guard[4];
  105. //
  106. // sizeof(MEMORY_SIGNATURE) currently 17 DWORDs
  107. //
  108. } DEBUG_MEMORY_HEADER, *LPDEBUG_MEMORY_HEADER;
  109. typedef struct {
  110. //
  111. // Guard - allows us to determine if the end of allocated memory was
  112. // overwritten
  113. //
  114. DWORD Guard[4];
  115. //
  116. // Signature - should be the footer signature
  117. //
  118. DWORD Signature;
  119. //
  120. // BlockLength - should be the same as the header
  121. //
  122. DWORD BlockLength;
  123. //
  124. // Guard2 - to make sure the end of the block is coherent
  125. //
  126. DWORD Guard2[2];
  127. //
  128. // sizeof(DEBUG_MEMORY_FOOTER) currently 8 DWORDs
  129. //
  130. } DEBUG_MEMORY_FOOTER, *LPDEBUG_MEMORY_FOOTER;
  131. //
  132. // data
  133. //
  134. LONG ActualMemoryAllocated = 0;
  135. LONG BlockLengthAllocated = 0;
  136. LONG RealLengthAllocated = 0;
  137. DWORD MemoryAllocations = 0;
  138. DWORD MemoryFrees = 0;
  139. SERIALIZED_LIST AllocatedBlockList;
  140. //
  141. // macros
  142. //
  143. #if defined(i386)
  144. #define GET_CALLERS_ADDRESS(p, pp) x86SleazeCallersAddress(p, pp)
  145. #else
  146. #define GET_CALLERS_ADDRESS(p, pp)
  147. #endif // defined(i386)
  148. //
  149. // private prototypes
  150. //
  151. PRIVATE
  152. BOOL
  153. InetIsBlockMoveable(
  154. IN HLOCAL hLocal
  155. );
  156. PRIVATE
  157. VOID
  158. InetCheckBlockConsistency(
  159. IN LPVOID lpMemory
  160. );
  161. PRIVATE
  162. VOID
  163. x86SleazeCallersAddress(
  164. LPVOID* pCaller,
  165. LPVOID* pCallersCaller
  166. );
  167. //
  168. // functions
  169. //
  170. VOID
  171. InetInitializeDebugMemoryPackage(
  172. VOID
  173. )
  174. /*++
  175. Routine Description:
  176. Just initializes data items in this module
  177. Arguments:
  178. None.
  179. Return Value:
  180. None.
  181. --*/
  182. {
  183. static BOOL MemoryPackageInitialized = FALSE;
  184. if (!MemoryPackageInitialized) {
  185. InitializeSerializedList(&AllocatedBlockList);
  186. MemoryPackageInitialized = TRUE;
  187. } else {
  188. DEBUG_PRINT(MEMALLOC,
  189. ERROR,
  190. ("Memory package already initialized\n"
  191. ));
  192. DEBUG_BREAK(MEMALLOC);
  193. }
  194. }
  195. VOID
  196. InetTerminateDebugMemoryPackage(
  197. VOID
  198. )
  199. /*++
  200. Routine Description:
  201. Undoes any resource allocation in InetInitializeDebugMemoryPackage, after
  202. checking that all memory is freed
  203. Arguments:
  204. None.
  205. Return Value:
  206. None.
  207. --*/
  208. {
  209. InetCheckDebugMemoryFreed();
  210. TerminateSerializedList(&AllocatedBlockList);
  211. }
  212. HLOCAL
  213. InetAllocateMemory(
  214. IN UINT LocalAllocFlags,
  215. IN UINT NumberOfBytes
  216. )
  217. /*++
  218. Routine Description:
  219. Debug memory allocator: allocates memory with head & tail. Fills memory
  220. with signature unless otherwise requested. If this is moveable memory
  221. then the caller must lock the memory with InetLockMemory(), else a pointer
  222. will be returned to the head of the heap's real start-of-block, and the
  223. caller will probably nuke the signature contents (but we should discover
  224. this when the block is freed)
  225. Arguments:
  226. LocalAllocFlags - flags to be passed on to LocalAlloc
  227. NumberOfBytes - to allocate for caller
  228. Return Value:
  229. LPVOID
  230. Success - pointer to memory after DEBUG_MEMORY_HEADER
  231. Failure - NULL
  232. --*/
  233. {
  234. HLOCAL hLocal;
  235. UINT blockLength;
  236. BOOL isMoveable;
  237. isMoveable = (LocalAllocFlags & LMEM_MOVEABLE) ? TRUE : FALSE;
  238. blockLength = ROUND_UP_DWORD(NumberOfBytes)
  239. + sizeof(DEBUG_MEMORY_HEADER)
  240. + sizeof(DEBUG_MEMORY_FOOTER)
  241. ;
  242. //
  243. // possible problem: if NumberOfBytes + signatures would overflow UINT.
  244. // Only really problematic on 16-bit platforms
  245. //
  246. if (blockLength < NumberOfBytes) {
  247. DEBUG_PRINT(MEMALLOC,
  248. ERROR,
  249. ("can't allocate %lu bytes: would overflow\n",
  250. (DWORD)NumberOfBytes
  251. ));
  252. DEBUG_BREAK(MEMALLOC);
  253. return (HLOCAL)NULL;
  254. }
  255. hLocal = LocalAlloc(LocalAllocFlags, blockLength);
  256. if (hLocal != NULL) {
  257. LPVOID lpMem;
  258. LPDEBUG_MEMORY_HEADER lpHeader;
  259. DWORD dwFiller;
  260. BYTE bFiller;
  261. UINT dwFillLength;
  262. UINT bFillLength1;
  263. UINT bFillLength2;
  264. UINT i;
  265. LPVOID userPointer;
  266. ActualMemoryAllocated += LocalSize(hLocal);
  267. BlockLengthAllocated += blockLength;
  268. RealLengthAllocated += NumberOfBytes;
  269. ++MemoryAllocations;
  270. if (isMoveable) {
  271. lpMem = (LPVOID)LocalLock(hLocal);
  272. if (lpMem == NULL) {
  273. DEBUG_PRINT(MEMALLOC,
  274. ERROR,
  275. ("LocalLock(%x) failed: %d\n",
  276. hLocal,
  277. GetLastError()
  278. ));
  279. DEBUG_BREAK(MEMALLOC);
  280. }
  281. } else {
  282. lpMem = (LPVOID)hLocal;
  283. }
  284. lpHeader = (LPDEBUG_MEMORY_HEADER)lpMem;
  285. InitializeListHead(&lpHeader->List);
  286. lpHeader->BlockLength = blockLength;
  287. lpHeader->RealLength = NumberOfBytes;
  288. lpHeader->Signature = HEADER_SIGNATURE;
  289. lpHeader->LockCount = 0;
  290. lpHeader->Flags = LocalAllocFlags;
  291. GET_CALLERS_ADDRESS(&lpHeader->CreatorReturnAddress[0],
  292. &lpHeader->CreatorReturnAddress[1]
  293. );
  294. lpHeader->LastAccessOperation = MemAllocate;
  295. for (i = 0; i < ARRAY_ELEMENTS(lpHeader->Guard); ++i) {
  296. lpHeader->Guard[i] = GUARD_DWORD_FILL;
  297. }
  298. if (LocalAllocFlags & LMEM_ZEROINIT) {
  299. dwFiller = 0;
  300. bFiller = 0;
  301. } else {
  302. dwFiller = DWORD_FILL;
  303. bFiller = BYTE_FILL;
  304. }
  305. dwFillLength = NumberOfBytes / sizeof(DWORD);
  306. bFillLength1 = NumberOfBytes % sizeof(DWORD);
  307. bFillLength2 = bFillLength1 ? (sizeof(DWORD) - bFillLength1) : 0;
  308. userPointer = (LPVOID)(lpHeader + 1);
  309. LPDWORD lpdwUserPointer = (LPDWORD)userPointer;
  310. for (i = 0; i < dwFillLength; ++i) {
  311. *lpdwUserPointer++ = dwFiller;
  312. }
  313. LPBYTE lpbUserPointer = (LPBYTE)lpdwUserPointer;
  314. for (i = 0; i < bFillLength1; ++i) {
  315. *lpbUserPointer++ = bFiller;
  316. }
  317. for (i = 0; i < bFillLength2; ++i) {
  318. *lpbUserPointer++ = BYTE_FILL_EXTRA;
  319. }
  320. userPointer = (LPVOID)lpbUserPointer;
  321. for (i = 0; i < ARRAY_ELEMENTS(((LPDEBUG_MEMORY_FOOTER)userPointer)->Guard); ++i) {
  322. ((LPDEBUG_MEMORY_FOOTER)userPointer)->Guard[i] = GUARD_DWORD_FILL;
  323. }
  324. ((LPDEBUG_MEMORY_FOOTER)userPointer)->BlockLength = blockLength;
  325. ((LPDEBUG_MEMORY_FOOTER)userPointer)->Signature = FOOTER_SIGNATURE;
  326. for (i = 0; i < ARRAY_ELEMENTS(((LPDEBUG_MEMORY_FOOTER)userPointer)->Guard2); ++i) {
  327. ((LPDEBUG_MEMORY_FOOTER)userPointer)->Guard2[i] = GUARD_DWORD_FILL;
  328. }
  329. //
  330. // if this is moveable memory, then we can't link it into the allocated
  331. // block list because if it moves, the list gets nuked. So we have to
  332. // allocate a DEBUG_MOVEABLE_TAG, link that and point to it from here
  333. //
  334. if (isMoveable) {
  335. LPDEBUG_MOVEABLE_TAG lpTag;
  336. lpTag = (LPDEBUG_MOVEABLE_TAG)InetAllocateMemory(LMEM_FIXED, sizeof(DEBUG_MOVEABLE_TAG));
  337. INET_ASSERT(lpTag != NULL);
  338. lpTag->hMoveable = hLocal;
  339. lpHeader->Tag = lpTag;
  340. } else {
  341. InsertAtHeadOfSerializedList(&AllocatedBlockList, &lpHeader->List);
  342. }
  343. if (isMoveable) {
  344. if (LocalUnlock(hLocal)) {
  345. DEBUG_PRINT(MEMALLOC,
  346. ERROR,
  347. ("LocalUnlock(%x): memory still locked\n",
  348. hLocal
  349. ));
  350. DEBUG_BREAK(MEMALLOC);
  351. } else {
  352. DWORD err;
  353. err = GetLastError();
  354. if (err != NO_ERROR) {
  355. DEBUG_PRINT(MEMALLOC,
  356. ERROR,
  357. ("LocalUnlock(%x) returns %d\n",
  358. hLocal,
  359. err
  360. ));
  361. DEBUG_BREAK(MEMALLOC);
  362. }
  363. }
  364. } else {
  365. hLocal = (HLOCAL)(lpHeader + 1);
  366. }
  367. } else {
  368. DEBUG_PRINT(MEMALLOC,
  369. ERROR,
  370. ("failed to allocate %u bytes memory\n",
  371. blockLength
  372. ));
  373. DEBUG_BREAK(MEMALLOC);
  374. }
  375. return hLocal;
  376. }
  377. HLOCAL
  378. InetReallocateMemory(
  379. IN HLOCAL hLocal,
  380. IN UINT Size,
  381. IN UINT Flags,
  382. IN BOOL IsMoveable
  383. )
  384. /*++
  385. Routine Description:
  386. Reallocates previously allocated block
  387. BUGBUG - this doesn't handle the more exotic LocalReAlloc stuff, like
  388. DISCARDABLE memory, allocating/freeing through realloc etc
  389. Arguments:
  390. hLocal - block to reallocate
  391. Size - new size
  392. Flags - new flags
  393. IsMoveable - TRUE if this is moveable memory. We need this help because
  394. there is no good way to find out from hLocal whether this
  395. memory is moveable or fixed
  396. Return Value:
  397. HLOCAL
  398. --*/
  399. {
  400. LPDEBUG_MEMORY_HEADER lpHeader;
  401. UINT realLength;
  402. UINT heapLength;
  403. //
  404. // can't handle reallocating down to zero
  405. //
  406. INET_ASSERT(Size != 0);
  407. if (IsMoveable) {
  408. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  409. heapLength = LocalSize(hLocal);
  410. } else {
  411. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  412. heapLength = LocalSize((HLOCAL)lpHeader);
  413. }
  414. InetCheckBlockConsistency((LPVOID)lpHeader);
  415. if (IsMoveable) {
  416. LocalUnlock(hLocal);
  417. }
  418. realLength = Size;
  419. Size = ROUND_UP_DWORD(Size)
  420. + sizeof(DEBUG_MEMORY_HEADER)
  421. + sizeof(DEBUG_MEMORY_FOOTER)
  422. ;
  423. ActualMemoryAllocated -= heapLength;
  424. BlockLengthAllocated -= lpHeader->BlockLength;
  425. RealLengthAllocated -= lpHeader->RealLength;
  426. hLocal = LocalReAlloc(hLocal, Size, Flags);
  427. if (hLocal != NULL) {
  428. LPBYTE extraPointer;
  429. UINT extraLength;
  430. UINT i;
  431. LPDEBUG_MEMORY_FOOTER lpFooter;
  432. if (IsMoveable) {
  433. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  434. } else {
  435. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  436. }
  437. lpHeader->BlockLength = Size;
  438. lpHeader->RealLength = realLength;
  439. lpHeader->Flags = Flags;
  440. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  441. &lpHeader->LastAccessReturnAddress[1]
  442. );
  443. lpHeader->LastAccessOperation = MemReallocate;
  444. extraPointer = (LPBYTE)(lpHeader + 1) + realLength;
  445. extraLength = (sizeof(DWORD) - (realLength % sizeof(DWORD)))
  446. & (sizeof(DWORD) - 1)
  447. ;
  448. for (i = 0; i < extraLength; ++i) {
  449. *extraPointer++ = BYTE_FILL_EXTRA;
  450. }
  451. lpFooter = (LPDEBUG_MEMORY_FOOTER)((LPBYTE)(lpHeader + 1)
  452. + ROUND_UP_DWORD(realLength)
  453. );
  454. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  455. lpFooter->Guard[i] = GUARD_DWORD_FILL;
  456. }
  457. lpFooter->Signature = FOOTER_SIGNATURE;
  458. lpFooter->BlockLength = Size;
  459. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  460. lpFooter->Guard2[i] = GUARD_DWORD_FILL;
  461. }
  462. ActualMemoryAllocated += LocalSize(hLocal);
  463. BlockLengthAllocated += Size;
  464. RealLengthAllocated += lpHeader->RealLength;
  465. if (IsMoveable) {
  466. LocalUnlock(hLocal);
  467. } else {
  468. hLocal = (HLOCAL)(lpHeader + 1);
  469. }
  470. } else {
  471. DEBUG_PRINT(MEMALLOC,
  472. ERROR,
  473. ("failed to reallocate %u bytes memory. Last error = %d\n",
  474. Size,
  475. GetLastError()
  476. ));
  477. DEBUG_BREAK(MEMALLOC);
  478. }
  479. return hLocal;
  480. }
  481. PRIVATE
  482. BOOL
  483. InetIsBlockMoveable(
  484. IN HLOCAL hLocal
  485. )
  486. /*++
  487. Routine Description:
  488. Determines if hLocal is moveable or fixed memory
  489. Arguments:
  490. hLocal -
  491. Return Value:
  492. BOOL
  493. --*/
  494. {
  495. LPDEBUG_MEMORY_HEADER lpHeader;
  496. BOOL isMoveable;
  497. //
  498. // BUGBUG - this method won't work for Win32s unless it supports SEH. But
  499. // there is another method...
  500. //
  501. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  502. __try {
  503. if (lpHeader->Signature == HEADER_SIGNATURE) {
  504. isMoveable = FALSE;
  505. } else {
  506. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  507. INET_ASSERT(lpHeader != NULL);
  508. isMoveable = (BOOL)(lpHeader->Signature == HEADER_SIGNATURE);
  509. LocalUnlock(hLocal);
  510. }
  511. } __except(EXCEPTION_EXECUTE_HANDLER) {
  512. //
  513. // yeowww! hLocal must be a handle to moveable memory. Either that, or
  514. // it is completely bogus
  515. //
  516. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  517. INET_ASSERT(lpHeader != NULL);
  518. isMoveable = (BOOL)(lpHeader->Signature == HEADER_SIGNATURE);
  519. LocalUnlock(hLocal);
  520. }
  521. return isMoveable;
  522. }
  523. HLOCAL
  524. InetFreeMemory(
  525. IN HLOCAL hLocal,
  526. IN BOOL IsMoveable
  527. )
  528. /*++
  529. Routine Description:
  530. Debug memory deallocator: checks memory is already allocated and that the
  531. head and tail structures are still ok. Fills freed memory with signature
  532. Arguments:
  533. hLocal - address/handle of memory to free
  534. IsMoveable - TRUE if this is moveable memory. We need this help because
  535. there is no good way to determine if the memory is moveable
  536. or fixed
  537. Return Value:
  538. HLOCAL
  539. Success - NULL
  540. Failure - hLocal
  541. --*/
  542. {
  543. UINT memFlags;
  544. LPDEBUG_MEMORY_HEADER lpHeader;
  545. BOOL isMoveable;
  546. UINT memSize;
  547. UINT blockLength;
  548. UINT realLength;
  549. if (!IsMoveable) {
  550. hLocal = (HLOCAL)((LPDEBUG_MEMORY_HEADER)hLocal - 1);
  551. }
  552. memFlags = LocalFlags(hLocal);
  553. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  554. INET_ASSERT((memFlags & LMEM_LOCKCOUNT) == 0);
  555. if (IsMoveable) {
  556. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  557. INET_ASSERT(lpHeader != NULL);
  558. } else {
  559. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  560. }
  561. memSize = LocalSize(hLocal);
  562. INET_ASSERT((lpHeader->BlockLength <= memSize)
  563. && !(lpHeader->BlockLength & (sizeof(DWORD) - 1))
  564. && (lpHeader->RealLength < lpHeader->BlockLength)
  565. );
  566. InetCheckBlockConsistency((LPVOID)lpHeader);
  567. //
  568. // if this is moveable memory then we didn't link it to the allocated
  569. // block list, but allocated a DEBUG_MOVEABLE_TAG to do the job. We
  570. // must remove it
  571. //
  572. if (IsMoveable) {
  573. LPDEBUG_MOVEABLE_TAG lpTag;
  574. lpTag = lpHeader->Tag;
  575. INET_ASSERT(lpTag->hMoveable == hLocal);
  576. InetFreeMemory(lpTag, FALSE);
  577. } else {
  578. RemoveFromSerializedList(&AllocatedBlockList, &lpHeader->List);
  579. }
  580. if (IsMoveable) {
  581. BOOL stillLocked;
  582. stillLocked = LocalUnlock(hLocal);
  583. INET_ASSERT(!stillLocked);
  584. INET_ASSERT(GetLastError() == NO_ERROR);
  585. }
  586. blockLength = lpHeader->BlockLength;
  587. realLength = lpHeader->RealLength;
  588. hLocal = LocalFree(hLocal);
  589. INET_ASSERT(hLocal == NULL);
  590. ActualMemoryAllocated -= memSize;
  591. BlockLengthAllocated -= blockLength;
  592. RealLengthAllocated -= realLength;
  593. ++MemoryFrees;
  594. return hLocal;
  595. }
  596. PRIVATE
  597. VOID
  598. InetCheckBlockConsistency(
  599. IN LPVOID lpMemory
  600. )
  601. /*++
  602. Routine Description:
  603. Checks that what we think is a valid allocated block (allocated by
  604. InetAllocateMemory), really is
  605. Arguments:
  606. lpMemory - pointer to what we think is DEBUG_MEMORY_HEADER
  607. Return Value:
  608. None.
  609. --*/
  610. {
  611. LPDEBUG_MEMORY_HEADER lpHeader;
  612. LPDEBUG_MEMORY_FOOTER lpFooter;
  613. UINT i;
  614. BOOL headerGuardOverrun;
  615. BOOL footerGuardOverrun;
  616. BOOL footerGuard2Overrun;
  617. BOOL extraMemoryOverrun;
  618. LPBYTE lpExtraMemory;
  619. UINT byteLength;
  620. __try {
  621. lpHeader = (LPDEBUG_MEMORY_HEADER)lpMemory;
  622. lpFooter = (LPDEBUG_MEMORY_FOOTER)((LPBYTE)lpMemory
  623. + (lpHeader->BlockLength - sizeof(DEBUG_MEMORY_FOOTER)))
  624. ;
  625. headerGuardOverrun = FALSE;
  626. for (i = 0; i < ARRAY_ELEMENTS(lpHeader->Guard); ++i) {
  627. if (lpHeader->Guard[i] != GUARD_DWORD_FILL) {
  628. headerGuardOverrun = TRUE;
  629. break;
  630. }
  631. }
  632. footerGuardOverrun = FALSE;
  633. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  634. if (lpFooter->Guard[i] != GUARD_DWORD_FILL) {
  635. footerGuardOverrun = TRUE;
  636. break;
  637. }
  638. }
  639. footerGuard2Overrun = FALSE;
  640. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  641. if (lpFooter->Guard2[i] != GUARD_DWORD_FILL) {
  642. footerGuard2Overrun = TRUE;
  643. break;
  644. }
  645. }
  646. lpExtraMemory = (LPBYTE)(lpHeader + 1) + lpHeader->RealLength;
  647. extraMemoryOverrun = FALSE;
  648. byteLength = ROUND_UP_DWORD(lpHeader->RealLength) - lpHeader->RealLength;
  649. for (i = 0; i < byteLength; ++i) {
  650. if (lpExtraMemory[i] != BYTE_FILL_EXTRA) {
  651. extraMemoryOverrun = TRUE;
  652. break;
  653. }
  654. }
  655. if (headerGuardOverrun
  656. || footerGuardOverrun
  657. || footerGuard2Overrun
  658. || extraMemoryOverrun
  659. || (lpHeader->Signature != HEADER_SIGNATURE)
  660. || (lpFooter->Signature != FOOTER_SIGNATURE)
  661. || (lpFooter->BlockLength != lpHeader->BlockLength)) {
  662. DEBUG_PRINT(MEMALLOC,
  663. ERROR,
  664. ("Bad block: %x\n",
  665. lpMemory
  666. ));
  667. DEBUG_BREAK(MEMALLOC);
  668. }
  669. } __except(EXCEPTION_EXECUTE_HANDLER) {
  670. DEBUG_PRINT(MEMALLOC,
  671. FATAL,
  672. ("Invalid block %x - exception occurred\n",
  673. lpMemory
  674. ));
  675. DEBUG_BREAK(MEMALLOC);
  676. }
  677. }
  678. LPVOID
  679. InetLockMemory(
  680. IN HLOCAL hLocal
  681. )
  682. /*++
  683. Routine Description:
  684. Locks a moveable memory block and increments the lock count. Checks block
  685. consistency
  686. Arguments:
  687. hLocal - handle of moveable memory to lock
  688. Return Value:
  689. LPVOID
  690. pointer to locked memory
  691. --*/
  692. {
  693. LPDEBUG_MEMORY_HEADER lpHeader = NULL;
  694. UINT memFlags;
  695. memFlags = LocalFlags(hLocal);
  696. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  697. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  698. INET_ASSERT(lpHeader != NULL);
  699. InetCheckBlockConsistency((LPVOID)lpHeader);
  700. ++lpHeader->LockCount;
  701. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  702. &lpHeader->LastAccessReturnAddress[1]
  703. );
  704. lpHeader->LastAccessOperation = MemLock;
  705. memFlags = LocalFlags(hLocal);
  706. INET_ASSERT((memFlags != LMEM_INVALID_HANDLE)
  707. && (lpHeader->LockCount == (LONG)(memFlags & LMEM_LOCKCOUNT))
  708. );
  709. return ++lpHeader;
  710. }
  711. BOOL
  712. InetUnlockMemory(
  713. IN HLOCAL hLocal
  714. )
  715. /*++
  716. Routine Description:
  717. Unlocks a (locked!) moveable memory block
  718. Arguments:
  719. hLocal - handle (pointer) of block to unlock
  720. Return Value:
  721. None.
  722. --*/
  723. {
  724. UINT memFlags;
  725. BOOL stillLocked;
  726. LPDEBUG_MEMORY_HEADER lpHeader;
  727. DWORD lockCount;
  728. memFlags = LocalFlags(hLocal);
  729. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  730. INET_ASSERT((memFlags & LMEM_LOCKCOUNT) >= 1);
  731. //
  732. // memory must be locked or LocalFlags would have returned error.
  733. // Lock memory again to get pointer to block, then unlock it.
  734. // There should still be at least one lock on the block
  735. //
  736. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  737. LocalUnlock(hLocal);
  738. InetCheckBlockConsistency((LPVOID)lpHeader);
  739. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  740. &lpHeader->LastAccessReturnAddress[1]
  741. );
  742. lpHeader->LastAccessOperation = MemUnlock;
  743. lockCount = --lpHeader->LockCount;
  744. stillLocked = LocalUnlock(hLocal);
  745. INET_ASSERT(stillLocked ? (lockCount > 0) : GetLastError() == NO_ERROR);
  746. return stillLocked;
  747. }
  748. UINT
  749. InetMemorySize(
  750. IN HLOCAL hLocal,
  751. IN BOOL IsMoveable
  752. )
  753. /*++
  754. Routine Description:
  755. Returns allocated block size
  756. Arguments:
  757. hLocal - memory handle
  758. IsMoveable - TRUE if hLocal is a handle to moveable memory >>> THAT IS NOT
  759. LOCKED <<<
  760. Return Value:
  761. UINT
  762. --*/
  763. {
  764. UINT size;
  765. UINT sizeInHeader;
  766. LPDEBUG_MEMORY_HEADER lpHeader;
  767. if (IsMoveable) {
  768. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  769. INET_ASSERT(lpHeader != NULL);
  770. sizeInHeader = lpHeader->RealLength;
  771. size = LocalSize(hLocal);
  772. LocalUnlock(hLocal);
  773. } else {
  774. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  775. INET_ASSERT(lpHeader->Signature == HEADER_SIGNATURE);
  776. sizeInHeader = lpHeader->RealLength;
  777. size = LocalSize((HLOCAL)lpHeader);
  778. }
  779. INET_ASSERT((sizeInHeader <= size)
  780. && (size >= sizeof(DEBUG_MEMORY_HEADER) + sizeof(DEBUG_MEMORY_FOOTER))
  781. );
  782. return sizeInHeader;
  783. }
  784. BOOL
  785. InetCheckDebugMemoryFreed(
  786. VOID
  787. )
  788. /*++
  789. Routine Description:
  790. Check that we don't have any memory allocated
  791. Arguments:
  792. None.
  793. Return Value:
  794. BOOL
  795. --*/
  796. {
  797. if (ActualMemoryAllocated || (MemoryFrees != MemoryAllocations)) {
  798. DEBUG_PRINT(MEMALLOC,
  799. ERROR,
  800. ("MemoryAllocated = %ld, MemoryAllocations = %lu, MemoryFrees = %lu\n",
  801. ActualMemoryAllocated,
  802. MemoryAllocations,
  803. MemoryFrees
  804. ));
  805. DEBUG_BREAK(MEMALLOC);
  806. return FALSE;
  807. }
  808. return TRUE;
  809. }
  810. #if defined(i386)
  811. VOID
  812. x86SleazeCallersAddress(
  813. LPVOID* pCaller,
  814. LPVOID* pCallersCaller
  815. )
  816. /*++
  817. Routine Description:
  818. This is a sleazy function that reads return addresses out of the stack/
  819. frame pointer (ebp). We pluck out the return address of the function
  820. that called THE FUNCTION THAT CALLED THIS FUNCTION, and the caller of
  821. that function. Returning the return address of the function that called
  822. this function is not interesting to that caller (almost worthy of Sir
  823. Humphrey Appleby isn't it?)
  824. Assumes:
  825. my ebp => | caller's ebp |
  826. | caller's eip |
  827. | arg #1 | (pCaller)
  828. | arg #2 | (pCallersCaller
  829. Arguments:
  830. pCaller - place where we return addres of function that called
  831. the function that called this function
  832. pCallersCaller - place where we return caller of above
  833. Return Value:
  834. None.
  835. --*/
  836. {
  837. //
  838. // this only works on x86 and only if not fpo functions!
  839. //
  840. LPVOID* ebp;
  841. ebp = (PVOID*)&pCaller - 2; // told you it was sleazy
  842. ebp = (PVOID*)*(PVOID*)ebp;
  843. *pCaller = *(ebp + 1);
  844. ebp = (PVOID*)*(PVOID*)ebp;
  845. *pCallersCaller = *(ebp + 1);
  846. }
  847. #endif // defined(i386)
  848. #endif // INET_DEBUG