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.

1217 lines
28 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. if (!InsertAtHeadOfSerializedList(&AllocatedBlockList, &lpHeader->List)) {
  342. DEBUG_PRINT(MEMALLOC,
  343. ERROR,
  344. ("InetAllocateMemory(%x): Unable to insert to allocated block list\n",
  345. hLocal
  346. ));
  347. DEBUG_BREAK(MEMALLOC);
  348. }
  349. }
  350. if (isMoveable) {
  351. if (LocalUnlock(hLocal)) {
  352. DEBUG_PRINT(MEMALLOC,
  353. ERROR,
  354. ("LocalUnlock(%x): memory still locked\n",
  355. hLocal
  356. ));
  357. DEBUG_BREAK(MEMALLOC);
  358. } else {
  359. DWORD err;
  360. err = GetLastError();
  361. if (err != NO_ERROR) {
  362. DEBUG_PRINT(MEMALLOC,
  363. ERROR,
  364. ("LocalUnlock(%x) returns %d\n",
  365. hLocal,
  366. err
  367. ));
  368. DEBUG_BREAK(MEMALLOC);
  369. }
  370. }
  371. } else {
  372. hLocal = (HLOCAL)(lpHeader + 1);
  373. }
  374. } else {
  375. DEBUG_PRINT(MEMALLOC,
  376. ERROR,
  377. ("failed to allocate %u bytes memory\n",
  378. blockLength
  379. ));
  380. DEBUG_BREAK(MEMALLOC);
  381. }
  382. return hLocal;
  383. }
  384. HLOCAL
  385. InetReallocateMemory(
  386. IN HLOCAL hLocal,
  387. IN UINT Size,
  388. IN UINT Flags,
  389. IN BOOL IsMoveable
  390. )
  391. /*++
  392. Routine Description:
  393. Reallocates previously allocated block
  394. BUGBUG - this doesn't handle the more exotic LocalReAlloc stuff, like
  395. DISCARDABLE memory, allocating/freeing through realloc etc
  396. Arguments:
  397. hLocal - block to reallocate
  398. Size - new size
  399. Flags - new flags
  400. IsMoveable - TRUE if this is moveable memory. We need this help because
  401. there is no good way to find out from hLocal whether this
  402. memory is moveable or fixed
  403. Return Value:
  404. HLOCAL
  405. --*/
  406. {
  407. LPDEBUG_MEMORY_HEADER lpHeader;
  408. UINT realLength;
  409. UINT heapLength;
  410. //
  411. // can't handle reallocating down to zero
  412. //
  413. INET_ASSERT(Size != 0);
  414. if (IsMoveable) {
  415. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  416. heapLength = LocalSize(hLocal);
  417. } else {
  418. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  419. heapLength = LocalSize((HLOCAL)lpHeader);
  420. }
  421. InetCheckBlockConsistency((LPVOID)lpHeader);
  422. if (IsMoveable) {
  423. LocalUnlock(hLocal);
  424. }
  425. realLength = Size;
  426. Size = ROUND_UP_DWORD(Size)
  427. + sizeof(DEBUG_MEMORY_HEADER)
  428. + sizeof(DEBUG_MEMORY_FOOTER)
  429. ;
  430. ActualMemoryAllocated -= heapLength;
  431. BlockLengthAllocated -= lpHeader->BlockLength;
  432. RealLengthAllocated -= lpHeader->RealLength;
  433. hLocal = LocalReAlloc(hLocal, Size, Flags);
  434. if (hLocal != NULL) {
  435. LPBYTE extraPointer;
  436. UINT extraLength;
  437. UINT i;
  438. LPDEBUG_MEMORY_FOOTER lpFooter;
  439. if (IsMoveable) {
  440. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  441. } else {
  442. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  443. }
  444. lpHeader->BlockLength = Size;
  445. lpHeader->RealLength = realLength;
  446. lpHeader->Flags = Flags;
  447. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  448. &lpHeader->LastAccessReturnAddress[1]
  449. );
  450. lpHeader->LastAccessOperation = MemReallocate;
  451. extraPointer = (LPBYTE)(lpHeader + 1) + realLength;
  452. extraLength = (sizeof(DWORD) - (realLength % sizeof(DWORD)))
  453. & (sizeof(DWORD) - 1)
  454. ;
  455. for (i = 0; i < extraLength; ++i) {
  456. *extraPointer++ = BYTE_FILL_EXTRA;
  457. }
  458. lpFooter = (LPDEBUG_MEMORY_FOOTER)((LPBYTE)(lpHeader + 1)
  459. + ROUND_UP_DWORD(realLength)
  460. );
  461. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  462. lpFooter->Guard[i] = GUARD_DWORD_FILL;
  463. }
  464. lpFooter->Signature = FOOTER_SIGNATURE;
  465. lpFooter->BlockLength = Size;
  466. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  467. lpFooter->Guard2[i] = GUARD_DWORD_FILL;
  468. }
  469. ActualMemoryAllocated += LocalSize(hLocal);
  470. BlockLengthAllocated += Size;
  471. RealLengthAllocated += lpHeader->RealLength;
  472. if (IsMoveable) {
  473. LocalUnlock(hLocal);
  474. } else {
  475. hLocal = (HLOCAL)(lpHeader + 1);
  476. }
  477. } else {
  478. DEBUG_PRINT(MEMALLOC,
  479. ERROR,
  480. ("failed to reallocate %u bytes memory. Last error = %d\n",
  481. Size,
  482. GetLastError()
  483. ));
  484. DEBUG_BREAK(MEMALLOC);
  485. }
  486. return hLocal;
  487. }
  488. PRIVATE
  489. BOOL
  490. InetIsBlockMoveable(
  491. IN HLOCAL hLocal
  492. )
  493. /*++
  494. Routine Description:
  495. Determines if hLocal is moveable or fixed memory
  496. Arguments:
  497. hLocal -
  498. Return Value:
  499. BOOL
  500. --*/
  501. {
  502. LPDEBUG_MEMORY_HEADER lpHeader;
  503. BOOL isMoveable;
  504. //
  505. // BUGBUG - this method won't work for Win32s unless it supports SEH. But
  506. // there is another method...
  507. //
  508. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  509. __try {
  510. if (lpHeader->Signature == HEADER_SIGNATURE) {
  511. isMoveable = FALSE;
  512. } else {
  513. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  514. INET_ASSERT(lpHeader != NULL);
  515. isMoveable = (BOOL)(lpHeader->Signature == HEADER_SIGNATURE);
  516. LocalUnlock(hLocal);
  517. }
  518. } __except(EXCEPTION_EXECUTE_HANDLER) {
  519. //
  520. // yeowww! hLocal must be a handle to moveable memory. Either that, or
  521. // it is completely bogus
  522. //
  523. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  524. INET_ASSERT(lpHeader != NULL);
  525. isMoveable = (BOOL)(lpHeader->Signature == HEADER_SIGNATURE);
  526. LocalUnlock(hLocal);
  527. }
  528. return isMoveable;
  529. }
  530. HLOCAL
  531. InetFreeMemory(
  532. IN HLOCAL hLocal,
  533. IN BOOL IsMoveable
  534. )
  535. /*++
  536. Routine Description:
  537. Debug memory deallocator: checks memory is already allocated and that the
  538. head and tail structures are still ok. Fills freed memory with signature
  539. Arguments:
  540. hLocal - address/handle of memory to free
  541. IsMoveable - TRUE if this is moveable memory. We need this help because
  542. there is no good way to determine if the memory is moveable
  543. or fixed
  544. Return Value:
  545. HLOCAL
  546. Success - NULL
  547. Failure - hLocal
  548. --*/
  549. {
  550. UINT memFlags;
  551. LPDEBUG_MEMORY_HEADER lpHeader;
  552. BOOL isMoveable;
  553. UINT memSize;
  554. UINT blockLength;
  555. UINT realLength;
  556. if (!IsMoveable) {
  557. hLocal = (HLOCAL)((LPDEBUG_MEMORY_HEADER)hLocal - 1);
  558. }
  559. memFlags = LocalFlags(hLocal);
  560. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  561. INET_ASSERT((memFlags & LMEM_LOCKCOUNT) == 0);
  562. if (IsMoveable) {
  563. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  564. INET_ASSERT(lpHeader != NULL);
  565. } else {
  566. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal;
  567. }
  568. memSize = LocalSize(hLocal);
  569. INET_ASSERT((lpHeader->BlockLength <= memSize)
  570. && !(lpHeader->BlockLength & (sizeof(DWORD) - 1))
  571. && (lpHeader->RealLength < lpHeader->BlockLength)
  572. );
  573. InetCheckBlockConsistency((LPVOID)lpHeader);
  574. //
  575. // if this is moveable memory then we didn't link it to the allocated
  576. // block list, but allocated a DEBUG_MOVEABLE_TAG to do the job. We
  577. // must remove it
  578. //
  579. if (IsMoveable) {
  580. LPDEBUG_MOVEABLE_TAG lpTag;
  581. lpTag = lpHeader->Tag;
  582. INET_ASSERT(lpTag->hMoveable == hLocal);
  583. InetFreeMemory(lpTag, FALSE);
  584. } else {
  585. if (!RemoveFromSerializedList(&AllocatedBlockList, &lpHeader->List)) {
  586. DEBUG_PRINT(MEMALLOC,
  587. ERROR,
  588. ("Couldn't remove %#x from allocated block list\n",
  589. hLocal
  590. ));
  591. DEBUG_BREAK(MEMALLOC);
  592. return hLocal;
  593. }
  594. }
  595. if (IsMoveable) {
  596. BOOL stillLocked;
  597. stillLocked = LocalUnlock(hLocal);
  598. INET_ASSERT(!stillLocked);
  599. INET_ASSERT(GetLastError() == NO_ERROR);
  600. }
  601. blockLength = lpHeader->BlockLength;
  602. realLength = lpHeader->RealLength;
  603. hLocal = LocalFree(hLocal);
  604. INET_ASSERT(hLocal == NULL);
  605. ActualMemoryAllocated -= memSize;
  606. BlockLengthAllocated -= blockLength;
  607. RealLengthAllocated -= realLength;
  608. ++MemoryFrees;
  609. return hLocal;
  610. }
  611. PRIVATE
  612. VOID
  613. InetCheckBlockConsistency(
  614. IN LPVOID lpMemory
  615. )
  616. /*++
  617. Routine Description:
  618. Checks that what we think is a valid allocated block (allocated by
  619. InetAllocateMemory), really is
  620. Arguments:
  621. lpMemory - pointer to what we think is DEBUG_MEMORY_HEADER
  622. Return Value:
  623. None.
  624. --*/
  625. {
  626. LPDEBUG_MEMORY_HEADER lpHeader;
  627. LPDEBUG_MEMORY_FOOTER lpFooter;
  628. UINT i;
  629. BOOL headerGuardOverrun;
  630. BOOL footerGuardOverrun;
  631. BOOL footerGuard2Overrun;
  632. BOOL extraMemoryOverrun;
  633. LPBYTE lpExtraMemory;
  634. UINT byteLength;
  635. __try {
  636. lpHeader = (LPDEBUG_MEMORY_HEADER)lpMemory;
  637. lpFooter = (LPDEBUG_MEMORY_FOOTER)((LPBYTE)lpMemory
  638. + (lpHeader->BlockLength - sizeof(DEBUG_MEMORY_FOOTER)))
  639. ;
  640. headerGuardOverrun = FALSE;
  641. for (i = 0; i < ARRAY_ELEMENTS(lpHeader->Guard); ++i) {
  642. if (lpHeader->Guard[i] != GUARD_DWORD_FILL) {
  643. headerGuardOverrun = TRUE;
  644. break;
  645. }
  646. }
  647. footerGuardOverrun = FALSE;
  648. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard); ++i) {
  649. if (lpFooter->Guard[i] != GUARD_DWORD_FILL) {
  650. footerGuardOverrun = TRUE;
  651. break;
  652. }
  653. }
  654. footerGuard2Overrun = FALSE;
  655. for (i = 0; i < ARRAY_ELEMENTS(lpFooter->Guard2); ++i) {
  656. if (lpFooter->Guard2[i] != GUARD_DWORD_FILL) {
  657. footerGuard2Overrun = TRUE;
  658. break;
  659. }
  660. }
  661. lpExtraMemory = (LPBYTE)(lpHeader + 1) + lpHeader->RealLength;
  662. extraMemoryOverrun = FALSE;
  663. byteLength = ROUND_UP_DWORD(lpHeader->RealLength) - lpHeader->RealLength;
  664. for (i = 0; i < byteLength; ++i) {
  665. if (lpExtraMemory[i] != BYTE_FILL_EXTRA) {
  666. extraMemoryOverrun = TRUE;
  667. break;
  668. }
  669. }
  670. if (headerGuardOverrun
  671. || footerGuardOverrun
  672. || footerGuard2Overrun
  673. || extraMemoryOverrun
  674. || (lpHeader->Signature != HEADER_SIGNATURE)
  675. || (lpFooter->Signature != FOOTER_SIGNATURE)
  676. || (lpFooter->BlockLength != lpHeader->BlockLength)) {
  677. DEBUG_PRINT(MEMALLOC,
  678. ERROR,
  679. ("Bad block: %x\n",
  680. lpMemory
  681. ));
  682. DEBUG_BREAK(MEMALLOC);
  683. }
  684. } __except(EXCEPTION_EXECUTE_HANDLER) {
  685. DEBUG_PRINT(MEMALLOC,
  686. FATAL,
  687. ("Invalid block %x - exception occurred\n",
  688. lpMemory
  689. ));
  690. DEBUG_BREAK(MEMALLOC);
  691. }
  692. }
  693. LPVOID
  694. InetLockMemory(
  695. IN HLOCAL hLocal
  696. )
  697. /*++
  698. Routine Description:
  699. Locks a moveable memory block and increments the lock count. Checks block
  700. consistency
  701. Arguments:
  702. hLocal - handle of moveable memory to lock
  703. Return Value:
  704. LPVOID
  705. pointer to locked memory
  706. --*/
  707. {
  708. LPDEBUG_MEMORY_HEADER lpHeader = NULL;
  709. UINT memFlags;
  710. memFlags = LocalFlags(hLocal);
  711. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  712. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  713. INET_ASSERT(lpHeader != NULL);
  714. InetCheckBlockConsistency((LPVOID)lpHeader);
  715. ++lpHeader->LockCount;
  716. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  717. &lpHeader->LastAccessReturnAddress[1]
  718. );
  719. lpHeader->LastAccessOperation = MemLock;
  720. memFlags = LocalFlags(hLocal);
  721. INET_ASSERT((memFlags != LMEM_INVALID_HANDLE)
  722. && (lpHeader->LockCount == (LONG)(memFlags & LMEM_LOCKCOUNT))
  723. );
  724. return ++lpHeader;
  725. }
  726. BOOL
  727. InetUnlockMemory(
  728. IN HLOCAL hLocal
  729. )
  730. /*++
  731. Routine Description:
  732. Unlocks a (locked!) moveable memory block
  733. Arguments:
  734. hLocal - handle (pointer) of block to unlock
  735. Return Value:
  736. None.
  737. --*/
  738. {
  739. UINT memFlags;
  740. BOOL stillLocked;
  741. LPDEBUG_MEMORY_HEADER lpHeader;
  742. DWORD lockCount;
  743. memFlags = LocalFlags(hLocal);
  744. INET_ASSERT(memFlags != LMEM_INVALID_HANDLE);
  745. INET_ASSERT((memFlags & LMEM_LOCKCOUNT) >= 1);
  746. //
  747. // memory must be locked or LocalFlags would have returned error.
  748. // Lock memory again to get pointer to block, then unlock it.
  749. // There should still be at least one lock on the block
  750. //
  751. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  752. LocalUnlock(hLocal);
  753. InetCheckBlockConsistency((LPVOID)lpHeader);
  754. GET_CALLERS_ADDRESS(&lpHeader->LastAccessReturnAddress[0],
  755. &lpHeader->LastAccessReturnAddress[1]
  756. );
  757. lpHeader->LastAccessOperation = MemUnlock;
  758. lockCount = --lpHeader->LockCount;
  759. stillLocked = LocalUnlock(hLocal);
  760. INET_ASSERT(stillLocked ? (lockCount > 0) : GetLastError() == NO_ERROR);
  761. return stillLocked;
  762. }
  763. UINT
  764. InetMemorySize(
  765. IN HLOCAL hLocal,
  766. IN BOOL IsMoveable
  767. )
  768. /*++
  769. Routine Description:
  770. Returns allocated block size
  771. Arguments:
  772. hLocal - memory handle
  773. IsMoveable - TRUE if hLocal is a handle to moveable memory >>> THAT IS NOT
  774. LOCKED <<<
  775. Return Value:
  776. UINT
  777. --*/
  778. {
  779. UINT size;
  780. UINT sizeInHeader;
  781. LPDEBUG_MEMORY_HEADER lpHeader;
  782. if (IsMoveable) {
  783. lpHeader = (LPDEBUG_MEMORY_HEADER)LocalLock(hLocal);
  784. INET_ASSERT(lpHeader != NULL);
  785. sizeInHeader = lpHeader->RealLength;
  786. size = LocalSize(hLocal);
  787. LocalUnlock(hLocal);
  788. } else {
  789. lpHeader = (LPDEBUG_MEMORY_HEADER)hLocal - 1;
  790. INET_ASSERT(lpHeader->Signature == HEADER_SIGNATURE);
  791. sizeInHeader = lpHeader->RealLength;
  792. size = LocalSize((HLOCAL)lpHeader);
  793. }
  794. INET_ASSERT((sizeInHeader <= size)
  795. && (size >= sizeof(DEBUG_MEMORY_HEADER) + sizeof(DEBUG_MEMORY_FOOTER))
  796. );
  797. return sizeInHeader;
  798. }
  799. BOOL
  800. InetCheckDebugMemoryFreed(
  801. VOID
  802. )
  803. /*++
  804. Routine Description:
  805. Check that we don't have any memory allocated
  806. Arguments:
  807. None.
  808. Return Value:
  809. BOOL
  810. --*/
  811. {
  812. if (ActualMemoryAllocated || (MemoryFrees != MemoryAllocations)) {
  813. DEBUG_PRINT(MEMALLOC,
  814. ERROR,
  815. ("MemoryAllocated = %ld, MemoryAllocations = %lu, MemoryFrees = %lu\n",
  816. ActualMemoryAllocated,
  817. MemoryAllocations,
  818. MemoryFrees
  819. ));
  820. DEBUG_BREAK(MEMALLOC);
  821. return FALSE;
  822. }
  823. return TRUE;
  824. }
  825. #if defined(i386)
  826. VOID
  827. x86SleazeCallersAddress(
  828. LPVOID* pCaller,
  829. LPVOID* pCallersCaller
  830. )
  831. /*++
  832. Routine Description:
  833. This is a sleazy function that reads return addresses out of the stack/
  834. frame pointer (ebp). We pluck out the return address of the function
  835. that called THE FUNCTION THAT CALLED THIS FUNCTION, and the caller of
  836. that function. Returning the return address of the function that called
  837. this function is not interesting to that caller (almost worthy of Sir
  838. Humphrey Appleby isn't it?)
  839. Assumes:
  840. my ebp => | caller's ebp |
  841. | caller's eip |
  842. | arg #1 | (pCaller)
  843. | arg #2 | (pCallersCaller
  844. Arguments:
  845. pCaller - place where we return addres of function that called
  846. the function that called this function
  847. pCallersCaller - place where we return caller of above
  848. Return Value:
  849. None.
  850. --*/
  851. {
  852. //
  853. // this only works on x86 and only if not fpo functions!
  854. //
  855. LPVOID* ebp;
  856. ebp = (PVOID*)&pCaller - 2; // told you it was sleazy
  857. ebp = (PVOID*)*(PVOID*)ebp;
  858. *pCaller = *(ebp + 1);
  859. ebp = (PVOID*)*(PVOID*)ebp;
  860. *pCallersCaller = *(ebp + 1);
  861. }
  862. #endif // defined(i386)
  863. #endif // INET_DEBUG