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.

2441 lines
63 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. llcmem.c
  5. Abstract:
  6. Functions for allocating & freeing memory. Split out from llclib.c. The
  7. reasons this module created are to isolate the memory allocators and to
  8. convert from using the Zone package to just using non-paged pool for all
  9. of DLC's memory requirements.
  10. Functions in this module are used by both DLC & LLC. These functions must
  11. go into a statically-linked library if DLC is ever divorced from LLC
  12. We use pools to avoid the overhead of calling the system allocation & free
  13. functions (although in practice, we end up allocating additional memory
  14. because the packet count in the pool is usually insufficient). The downside
  15. is that we may allocate memory that in the majority of situations is not
  16. used, but the packets in pools tend to be small and few in number
  17. To aid in tracking memory resources, DLC/LLC now defines the following
  18. memory categories:
  19. Memory
  20. - arbitrary sized blocks allocated out of non-paged pool using
  21. ExAllocatePool(NonPagedPool, ...)
  22. ZeroMemory
  23. - arbitrary sized blocks allocated out of non-paged pool using
  24. ExAllocatePool(NonPagedPool, ...) and initialized to zeroes
  25. Pool
  26. - small sets of (relatively) small packets are allocated in one
  27. block from Memory or ZeroMemory as a Pool and then subdivided
  28. into packets (CreatePacketPool, DeletePacketPool, AllocatePacket,
  29. DeallocatePacket)
  30. Object
  31. - structures which may be packets allocated from Pool which have
  32. a known size and initialization values. Pseudo-category mainly
  33. for debugging purposes
  34. Contents:
  35. InitializeMemoryPackage (DEBUG)
  36. PullEntryList (DEBUG)
  37. LinkMemoryUsage (DEBUG)
  38. UnlinkMemoryUsage (DEBUG)
  39. ChargeNonPagedPoolUsage (DEBUG)
  40. RefundNonPagedPoolUsage (DEBUG)
  41. AllocateMemory (DEBUG)
  42. AllocateZeroMemory
  43. DeallocateMemory (DEBUG)
  44. AllocateObject (DEBUG)
  45. FreeObject (DEBUG)
  46. ValidateObject (DEBUG)
  47. GetObjectSignature (DEBUG)
  48. GetObjectBaseSize (DEBUG)
  49. CreatePacketPool
  50. DeletePacketPool
  51. AllocatePacket
  52. DeallocatePacket
  53. CreateObjectPool (DEBUG)
  54. AllocatePoolObject (DEBUG)
  55. DeallocatePoolObject (DEBUG)
  56. DeleteObjectPool (DEBUG)
  57. CheckMemoryReturned (DEBUG)
  58. CheckDriverMemoryUsage (DEBUG)
  59. MemoryAllocationError (DEBUG)
  60. UpdateCounter (DEBUG)
  61. MemoryCounterOverflow (DEBUG)
  62. DumpMemoryMetrics (DEBUG)
  63. DumpPoolStats (DEBUG)
  64. MapObjectId (DEBUG)
  65. DumpPool (DEBUG)
  66. DumpPoolList (DEBUG)
  67. DumpPacketHead (DEBUG)
  68. DumpMemoryUsageList (DEBUG)
  69. DumpMemoryUsage (DEBUG)
  70. x86SleazeCallersAddress (DEBUG)
  71. CollectReturnAddresses (DEBUG)
  72. GetLastReturnAddress (DEBUG)
  73. VerifyElementOnList (DEBUG)
  74. CheckList (DEBUG)
  75. CheckEntryOnList (DEBUG)
  76. DumpPrivateMemoryHeader (DEBUG)
  77. ReportSwitchSettings (DEBUG)
  78. Author:
  79. Richard L Firth (rfirth) 10-Mar-1993
  80. Environment:
  81. kernel mode only.
  82. Notes:
  83. In non-debug version, DeallocateMemory is replaced with a macro which calls
  84. ExFreePool(...) and AllocateMemory is replaced by a macro which calls
  85. ExAllocatePool(NonPagedPool, ...)
  86. Revision History:
  87. 09-Mar-1993 RFirth
  88. Created
  89. --*/
  90. #ifndef i386
  91. #define LLC_PRIVATE_PROTOTYPES
  92. #endif
  93. #include <ntddk.h>
  94. #include <ndis.h>
  95. #define APIENTRY
  96. #include <dlcapi.h>
  97. #include <dlcio.h>
  98. #include "llcapi.h"
  99. #include "dlcdef.h"
  100. #include "dlcreg.h"
  101. #include "dlctyp.h"
  102. #include "llcdef.h"
  103. #include "llcmem.h"
  104. #include "llctyp.h"
  105. #define DWORD_ROUNDUP(d) (((d) + 3) & ~3)
  106. #define YES_NO(thing) ((thing) ? "Yes" : "No")
  107. #if DBG
  108. //
  109. // some variables to keep track of memory allocations from non-paged pool. These
  110. // are the cumulative totals for all of DLC's non-paged pool memory usage
  111. //
  112. KSPIN_LOCK MemoryCountersLock;
  113. KIRQL MemoryCountersIrql;
  114. ULONG GoodNonPagedPoolAllocs = 0;
  115. ULONG BadNonPagedPoolAllocs = 0;
  116. ULONG GoodNonPagedPoolFrees = 0;
  117. ULONG BadNonPagedPoolFrees = 0;
  118. ULONG NonPagedPoolRequested = 0;
  119. ULONG NonPagedPoolAllocated = 0;
  120. ULONG TotalNonPagedPoolRequested = 0;
  121. ULONG TotalNonPagedPoolAllocated = 0;
  122. ULONG TotalNonPagedPoolFreed = 0;
  123. KSPIN_LOCK MemoryAllocatorLock;
  124. ULONG InMemoryAllocator = 0;
  125. KSPIN_LOCK PoolCreatorLock;
  126. ULONG InPoolCreator = 0;
  127. //
  128. // MemoryUsageList - linked list of all MEMORY_USAGE structures in driver. If we
  129. // allocate something that has a MEMORY_USAGE structure (& what doesn't?) then
  130. // don't delete it, we can later scan this list to find out what is still allocated
  131. //
  132. PMEMORY_USAGE MemoryUsageList = NULL;
  133. KSPIN_LOCK MemoryUsageLock;
  134. //
  135. // flags to aid in debugging - change states via debugger
  136. //
  137. //BOOLEAN DebugDump = TRUE;
  138. BOOLEAN DebugDump = FALSE;
  139. //BOOLEAN DeleteBusyListAnyway = TRUE;
  140. BOOLEAN DeleteBusyListAnyway = FALSE;
  141. BOOLEAN MemoryCheckNotify = TRUE;
  142. //BOOLEAN MemoryCheckNotify = FALSE;
  143. BOOLEAN MemoryCheckStop = TRUE;
  144. //BOOLEAN MemoryCheckStop = FALSE;
  145. BOOLEAN MaintainPrivateLists = TRUE;
  146. //BOOLEAN MaintainPrivateLists = FALSE;
  147. BOOLEAN MaintainGlobalLists = TRUE;
  148. //BOOLEAN MaintainGlobalLists = FALSE;
  149. BOOLEAN ZapDeallocatedPackets = TRUE;
  150. //BOOLEAN ZapDeallocatedPackets = FALSE;
  151. BOOLEAN ZapFreedMemory = TRUE;
  152. //BOOLEAN ZapFreedMemory = FALSE;
  153. //
  154. // DlcGlobalMemoryList - every block that is allocated is linked to this list
  155. // and removed when deleted. Helps us keep track of who allocated which block
  156. //
  157. KSPIN_LOCK DlcGlobalMemoryListLock;
  158. LIST_ENTRY DlcGlobalMemoryList;
  159. ULONG DlcGlobalMemoryListCount = 0;
  160. //
  161. // local function prototypes
  162. //
  163. VOID MemoryAllocationError(PCHAR, PVOID);
  164. VOID UpdateCounter(PULONG, LONG);
  165. VOID MemoryCounterOverflow(PULONG, LONG);
  166. VOID DumpMemoryMetrics(VOID);
  167. VOID DumpPoolStats(PCHAR, PPACKET_POOL);
  168. PCHAR MapObjectId(DLC_OBJECT_TYPE);
  169. VOID DumpPool(PPACKET_POOL);
  170. VOID DumpPoolList(PCHAR, PSINGLE_LIST_ENTRY);
  171. VOID DumpPacketHead(PPACKET_HEAD, ULONG);
  172. VOID DumpMemoryUsageList(VOID);
  173. VOID DumpMemoryUsage(PMEMORY_USAGE, BOOLEAN);
  174. VOID CollectReturnAddresses(PVOID*, ULONG, ULONG);
  175. PVOID* GetLastReturnAddress(PVOID**);
  176. VOID x86SleazeCallersAddress(PVOID*, PVOID*);
  177. BOOLEAN VerifyElementOnList(PSINGLE_LIST_ENTRY, PSINGLE_LIST_ENTRY);
  178. VOID CheckList(PSINGLE_LIST_ENTRY, ULONG);
  179. VOID CheckEntryOnList(PLIST_ENTRY, PLIST_ENTRY, BOOLEAN);
  180. VOID DumpPrivateMemoryHeader(PPRIVATE_NON_PAGED_POOL_HEAD);
  181. VOID ReportSwitchSettings(PSTR);
  182. #define GRAB_SPINLOCK() KeAcquireSpinLock(&MemoryCountersLock, &MemoryCountersIrql)
  183. #define FREE_SPINLOCK() KeReleaseSpinLock(&MemoryCountersLock, MemoryCountersIrql)
  184. #ifdef i386
  185. #define GET_CALLERS_ADDRESS x86SleazeCallersAddress
  186. #else
  187. #define GET_CALLERS_ADDRESS RtlGetCallersAddress
  188. #endif
  189. //
  190. // private prototypes
  191. //
  192. ULONG
  193. GetObjectSignature(
  194. IN DLC_OBJECT_TYPE ObjectType
  195. );
  196. ULONG
  197. GetObjectBaseSize(
  198. IN DLC_OBJECT_TYPE ObjectType
  199. );
  200. #else
  201. #define GRAB_SPINLOCK()
  202. #define FREE_SPINLOCK()
  203. #endif
  204. //
  205. // functions
  206. //
  207. #if DBG
  208. VOID
  209. InitializeMemoryPackage(
  210. VOID
  211. )
  212. /*++
  213. Routine Description:
  214. Performs initialization for memory allocation functions
  215. Arguments:
  216. None.
  217. Return Value:
  218. None.
  219. --*/
  220. {
  221. KeInitializeSpinLock(&MemoryCountersLock);
  222. KeInitializeSpinLock(&MemoryAllocatorLock);
  223. KeInitializeSpinLock(&PoolCreatorLock);
  224. KeInitializeSpinLock(&MemoryUsageLock);
  225. KeInitializeSpinLock(&DlcGlobalMemoryListLock);
  226. DriverMemoryUsage.OwnerObjectId = DlcDriverObject;
  227. DriverMemoryUsage.OwnerInstance = 0x4D454D; // 'MEM'
  228. InitializeListHead(&DriverMemoryUsage.PrivateList);
  229. LinkMemoryUsage(&DriverMemoryUsage);
  230. DriverStringUsage.OwnerObjectId = DlcDriverObject;
  231. DriverStringUsage.OwnerInstance = 0x535452; // 'STR'
  232. InitializeListHead(&DriverStringUsage.PrivateList);
  233. LinkMemoryUsage(&DriverStringUsage);
  234. InitializeListHead(&DlcGlobalMemoryList);
  235. ReportSwitchSettings("DLC.InitializeMemoryPackage (DEBUG version only)");
  236. }
  237. PSINGLE_LIST_ENTRY
  238. PullEntryList(
  239. IN PSINGLE_LIST_ENTRY List,
  240. IN PSINGLE_LIST_ENTRY Element
  241. )
  242. /*++
  243. Routine Description:
  244. The missing SINGLE_LIST_ENTRY function. Removes an entry from a single-linked
  245. list. The entry can be anywhere on the list. Reduces size of list elements
  246. by one pointer, at expense of increased time to traverse list.
  247. This function SHOULD NOT return NULL: if it does then the code is broken
  248. since it assumes that an element is on a list, when it ain't
  249. Arguments:
  250. List - pointer to singly-linked list anchor. This MUST be the address of
  251. the pointer to the list, not the first element in the list
  252. Element - pointer to element to remove from List
  253. Return Value:
  254. PSINGLE_LIST_ENTRY
  255. Success - Element
  256. Failure - NULL
  257. --*/
  258. {
  259. PSINGLE_LIST_ENTRY prev = List;
  260. ASSERT(List);
  261. ASSERT(Element);
  262. while (List = List->Next) {
  263. if (List == Element) {
  264. prev->Next = Element->Next;
  265. return Element;
  266. }
  267. prev = List;
  268. }
  269. return NULL;
  270. }
  271. VOID
  272. LinkMemoryUsage(
  273. IN PMEMORY_USAGE pMemoryUsage
  274. )
  275. /*++
  276. Routine Description:
  277. Add pMemoryUsage to linked list of MEMORY_USAGE structures
  278. Arguments:
  279. pMemoryUsage - pointer to MEMORY_USAGE structure to add
  280. Return Value:
  281. None.
  282. --*/
  283. {
  284. KIRQL irql;
  285. KeAcquireSpinLock(&MemoryUsageLock, &irql);
  286. PushEntryList((PSINGLE_LIST_ENTRY)&MemoryUsageList, (PSINGLE_LIST_ENTRY)pMemoryUsage);
  287. KeReleaseSpinLock(&MemoryUsageLock, irql);
  288. }
  289. VOID
  290. UnlinkMemoryUsage(
  291. IN PMEMORY_USAGE pMemoryUsage
  292. )
  293. /*++
  294. Routine Description:
  295. Remove pMemoryUsage from linked list of MEMORY_USAGE structures
  296. Arguments:
  297. pMemoryUsage - pointer to MEMORY_USAGE structure to remove
  298. Return Value:
  299. None.
  300. --*/
  301. {
  302. KIRQL irql;
  303. ASSERT(pMemoryUsage);
  304. CheckMemoryReturned(pMemoryUsage);
  305. KeAcquireSpinLock(&MemoryUsageLock, &irql);
  306. ASSERT(PullEntryList((PSINGLE_LIST_ENTRY)&MemoryUsageList, (PSINGLE_LIST_ENTRY)pMemoryUsage));
  307. KeReleaseSpinLock(&MemoryUsageLock, irql);
  308. }
  309. VOID
  310. ChargeNonPagedPoolUsage(
  311. IN PMEMORY_USAGE pMemoryUsage,
  312. IN ULONG Size,
  313. IN PPRIVATE_NON_PAGED_POOL_HEAD Block
  314. )
  315. /*++
  316. Routine Description:
  317. Charges this non-paged pool allocation to a specific memory user
  318. Arguments:
  319. pMemoryUsage - pointer to structure recording memory usage
  320. Size - size of block allocated
  321. Block - pointer to private header of allocated block
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. KIRQL irql;
  327. KeAcquireSpinLock(&pMemoryUsage->SpinLock, &irql);
  328. if (pMemoryUsage->NonPagedPoolAllocated + Size < pMemoryUsage->NonPagedPoolAllocated) {
  329. if (MemoryCheckNotify) {
  330. DbgPrint("DLC.ChargeNonPagedPoolUsage: Overcharged? Usage @ %08x\n", pMemoryUsage);
  331. }
  332. if (MemoryCheckStop) {
  333. DumpMemoryUsage(pMemoryUsage, TRUE);
  334. DbgBreakPoint();
  335. }
  336. }
  337. pMemoryUsage->NonPagedPoolAllocated += Size;
  338. ++pMemoryUsage->AllocateCount;
  339. //
  340. // link this block to the memory usage private list
  341. //
  342. if (MaintainPrivateLists) {
  343. if (pMemoryUsage->PrivateList.Flink == NULL) {
  344. //
  345. // slight hack to make initializing MEMORY_USAGEs easier...
  346. //
  347. InitializeListHead(&pMemoryUsage->PrivateList);
  348. }
  349. InsertTailList(&pMemoryUsage->PrivateList, &Block->PrivateList);
  350. }
  351. KeReleaseSpinLock(&pMemoryUsage->SpinLock, irql);
  352. }
  353. VOID
  354. RefundNonPagedPoolUsage(
  355. IN PMEMORY_USAGE pMemoryUsage,
  356. IN ULONG Size,
  357. IN PPRIVATE_NON_PAGED_POOL_HEAD Block
  358. )
  359. /*++
  360. Routine Description:
  361. Refunds a non-paged pool allocation to a specific memory user
  362. Arguments:
  363. pMemoryUsage - pointer to structure recording memory usage
  364. Size - size of block allocated
  365. Block - pointer to private header of allocated block
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. KIRQL irql;
  371. KeAcquireSpinLock(&pMemoryUsage->SpinLock, &irql);
  372. if (pMemoryUsage->NonPagedPoolAllocated - Size > pMemoryUsage->NonPagedPoolAllocated) {
  373. if (MemoryCheckNotify) {
  374. DbgPrint("DLC.RefundNonPagedPoolUsage: Error: Freeing unallocated memory? Usage @ %08x, %d\n",
  375. pMemoryUsage,
  376. Size
  377. );
  378. }
  379. if (MemoryCheckStop) {
  380. DumpMemoryUsage(pMemoryUsage, TRUE);
  381. DbgBreakPoint();
  382. }
  383. }
  384. //
  385. // unlink this block from the memory usage private list
  386. //
  387. if (MaintainPrivateLists) {
  388. CheckEntryOnList(&Block->PrivateList, &pMemoryUsage->PrivateList, TRUE);
  389. RemoveEntryList(&Block->PrivateList);
  390. }
  391. pMemoryUsage->NonPagedPoolAllocated -= Size;
  392. ++pMemoryUsage->FreeCount;
  393. KeReleaseSpinLock(&pMemoryUsage->SpinLock, irql);
  394. }
  395. PVOID
  396. AllocateMemory(
  397. IN PMEMORY_USAGE pMemoryUsage,
  398. IN ULONG Size
  399. )
  400. /*++
  401. Routine Description:
  402. Allocates memory out of non-paged pool. For the debug version, we round up
  403. the requested size to the next 4-byte boundary and we add header and tail
  404. sections which contain a signature to check for over-write, and in-use and
  405. size information
  406. In the non-debug version, this function is replaced by a call to
  407. ExAllocatePool(NonPagedPool, ...)
  408. Arguments:
  409. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  410. Size - number of bytes to allocate
  411. Return Value:
  412. PVOID
  413. Success - pointer to allocated memory
  414. Failure - NULL
  415. --*/
  416. {
  417. PVOID pMem;
  418. ULONG OriginalSize = Size;
  419. PUCHAR pMemEnd;
  420. /*
  421. KIRQL irql;
  422. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  423. if (InMemoryAllocator) {
  424. DbgPrint("DLC.AllocateMemory: Error: Memory allocator clash on entry. Count = %d\n",
  425. InMemoryAllocator
  426. );
  427. // DbgBreakPoint();
  428. }
  429. ++InMemoryAllocator;
  430. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  431. */
  432. Size = DWORD_ROUNDUP(Size)
  433. + sizeof(PRIVATE_NON_PAGED_POOL_HEAD)
  434. + sizeof(PRIVATE_NON_PAGED_POOL_TAIL);
  435. pMem = ExAllocatePoolWithTag(NonPagedPool, (ULONG)Size, DLC_POOL_TAG);
  436. if (pMem) {
  437. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Size = Size;
  438. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->OriginalSize = OriginalSize;
  439. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Flags = MEM_FLAGS_IN_USE;
  440. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Signature = SIGNATURE1;
  441. pMemEnd = (PUCHAR)pMem
  442. + DWORD_ROUNDUP(OriginalSize)
  443. + sizeof(PRIVATE_NON_PAGED_POOL_HEAD);
  444. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Size = Size;
  445. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Signature = SIGNATURE2;
  446. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Pattern1 = PATTERN1;
  447. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Pattern2 = PATTERN2;
  448. GRAB_SPINLOCK();
  449. UpdateCounter(&GoodNonPagedPoolAllocs, 1);
  450. UpdateCounter(&NonPagedPoolAllocated, (LONG)Size);
  451. UpdateCounter(&NonPagedPoolRequested, (LONG)OriginalSize);
  452. UpdateCounter(&TotalNonPagedPoolRequested, (LONG)OriginalSize);
  453. UpdateCounter(&TotalNonPagedPoolAllocated, (LONG)Size);
  454. FREE_SPINLOCK();
  455. if (MaintainGlobalLists) {
  456. KIRQL irql;
  457. //
  458. // record the caller and add this block to the global list
  459. //
  460. GET_CALLERS_ADDRESS(&((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Stack[0],
  461. &((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Stack[1]
  462. );
  463. KeAcquireSpinLock(&DlcGlobalMemoryListLock, &irql);
  464. InsertTailList(&DlcGlobalMemoryList,
  465. &((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->GlobalList
  466. );
  467. ++DlcGlobalMemoryListCount;
  468. KeReleaseSpinLock(&DlcGlobalMemoryListLock, irql);
  469. }
  470. ChargeNonPagedPoolUsage(pMemoryUsage, Size, (PPRIVATE_NON_PAGED_POOL_HEAD)pMem);
  471. pMem = (PVOID)((PUCHAR)pMem + sizeof(PRIVATE_NON_PAGED_POOL_HEAD));
  472. } else {
  473. GRAB_SPINLOCK();
  474. UpdateCounter(&BadNonPagedPoolAllocs, 1);
  475. FREE_SPINLOCK();
  476. }
  477. /*
  478. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  479. --InMemoryAllocator;
  480. if (InMemoryAllocator) {
  481. DbgPrint("DLC.AllocateMemory: Error: Memory allocator clash on exit. Count = %d\n",
  482. InMemoryAllocator
  483. );
  484. // DbgBreakPoint();
  485. }
  486. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  487. */
  488. return pMem;
  489. }
  490. VOID
  491. DeallocateMemory(
  492. IN PMEMORY_USAGE pMemoryUsage,
  493. IN PVOID Pointer
  494. )
  495. /*++
  496. Routine Description:
  497. frees memory to non-paged pool
  498. Arguments:
  499. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  500. Pointer - pointer to previously allocated non-paged pool memory
  501. Return Value:
  502. None.
  503. --*/
  504. {
  505. PPRIVATE_NON_PAGED_POOL_HEAD pHead;
  506. PPRIVATE_NON_PAGED_POOL_TAIL pTail;
  507. /*
  508. KIRQL irql;
  509. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  510. if (InMemoryAllocator) {
  511. DbgPrint("DLC.DeallocateMemory: Error: Memory allocator clash on entry. Count = %d\n",
  512. InMemoryAllocator
  513. );
  514. // DbgBreakPoint();
  515. }
  516. ++InMemoryAllocator;
  517. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  518. */
  519. pHead = (PPRIVATE_NON_PAGED_POOL_HEAD)((PUCHAR)Pointer - sizeof(PRIVATE_NON_PAGED_POOL_HEAD));
  520. pTail = (PPRIVATE_NON_PAGED_POOL_TAIL)((PUCHAR)pHead + pHead->Size - sizeof(PRIVATE_NON_PAGED_POOL_TAIL));
  521. if (MaintainGlobalLists) {
  522. CheckEntryOnList(&pHead->GlobalList, &DlcGlobalMemoryList, TRUE);
  523. if (pHead->GlobalList.Flink == NULL
  524. || pHead->GlobalList.Blink == NULL) {
  525. if (MemoryCheckNotify) {
  526. DbgPrint("DLC.DeallocateMemory: Error: Block already globally freed: %08x\n", pHead);
  527. }
  528. if (MemoryCheckStop) {
  529. DbgBreakPoint();
  530. }
  531. }
  532. }
  533. if (pHead->Signature != SIGNATURE1
  534. || !(pHead->Flags & MEM_FLAGS_IN_USE)
  535. || pTail->Size != pHead->Size
  536. || pTail->Signature != SIGNATURE2
  537. || pTail->Pattern1 != PATTERN1
  538. || pTail->Pattern2 != PATTERN2) {
  539. if (MemoryCheckNotify || MemoryCheckStop) {
  540. MemoryAllocationError("DeallocateMemory", (PVOID)pHead);
  541. }
  542. GRAB_SPINLOCK();
  543. UpdateCounter(&BadNonPagedPoolFrees, 1);
  544. FREE_SPINLOCK();
  545. } else {
  546. GRAB_SPINLOCK();
  547. UpdateCounter(&GoodNonPagedPoolFrees, 1);
  548. FREE_SPINLOCK();
  549. }
  550. GRAB_SPINLOCK();
  551. UpdateCounter(&NonPagedPoolRequested, -(LONG)pHead->OriginalSize);
  552. UpdateCounter(&NonPagedPoolAllocated, -(LONG)pHead->Size);
  553. UpdateCounter(&TotalNonPagedPoolFreed, (LONG)pHead->Size);
  554. FREE_SPINLOCK();
  555. //
  556. // access Size field before ExFreePool zaps it/somebody else allocates memory
  557. //
  558. RefundNonPagedPoolUsage(pMemoryUsage, pHead->Size, pHead);
  559. if (MaintainGlobalLists) {
  560. //
  561. // remove this block from the global list
  562. //
  563. RemoveEntryList(&pHead->GlobalList);
  564. --DlcGlobalMemoryListCount;
  565. pHead->GlobalList.Flink = pHead->GlobalList.Flink = NULL;
  566. }
  567. if (ZapFreedMemory) {
  568. RtlFillMemory(pHead + 1,
  569. DWORD_ROUNDUP(pHead->OriginalSize),
  570. ZAP_EX_FREE_VALUE
  571. );
  572. }
  573. ExFreePool((PVOID)pHead);
  574. /*
  575. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  576. --InMemoryAllocator;
  577. if (InMemoryAllocator) {
  578. DbgPrint("DLC.DeallocateMemory: Error: Memory allocator clash on exit. Count = %d\n",
  579. InMemoryAllocator
  580. );
  581. // DbgBreakPoint();
  582. }
  583. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  584. */
  585. }
  586. PVOID
  587. AllocateObject(
  588. IN PMEMORY_USAGE pMemoryUsage,
  589. IN DLC_OBJECT_TYPE ObjectType,
  590. IN ULONG ObjectSize
  591. )
  592. /*++
  593. Routine Description:
  594. Allocates a pseudo-object
  595. Arguments:
  596. ObjectType - type of object to allocate
  597. ObjectSize - size of object; mainly because some objects have variable size
  598. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  599. Return Value:
  600. PVOID
  601. Success - pointer to object allocated from non-paged pool
  602. Failure - NULL
  603. --*/
  604. {
  605. POBJECT_ID pObject;
  606. ULONG signature;
  607. ULONG baseSize;
  608. signature = GetObjectSignature(ObjectType);
  609. baseSize = GetObjectBaseSize(ObjectType);
  610. if (baseSize < ObjectSize) {
  611. DbgPrint("DLC.AllocateObject: Error: Invalid size %d for ObjectType %08x (should be >= %d)\n",
  612. ObjectSize,
  613. ObjectType,
  614. baseSize
  615. );
  616. DbgBreakPoint();
  617. }
  618. pObject = (POBJECT_ID)AllocateZeroMemory(pMemoryUsage, ObjectSize);
  619. if (pObject) {
  620. pObject->Signature = signature;
  621. pObject->Type = ObjectType;
  622. pObject->Size = baseSize;
  623. pObject->Extra = ObjectSize - baseSize;
  624. }
  625. return (PVOID)pObject;
  626. }
  627. VOID
  628. FreeObject(
  629. IN PMEMORY_USAGE pMemoryUsage,
  630. IN PVOID pObject,
  631. IN DLC_OBJECT_TYPE ObjectType
  632. )
  633. /*++
  634. Routine Description:
  635. Deallocates a pseudo-object
  636. Arguments:
  637. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  638. pObject - pointer to object allocated with AllocateObject
  639. ObjectType - type of object pObject supposed to be
  640. Return Value:
  641. None.
  642. --*/
  643. {
  644. ValidateObject(pObject, ObjectType);
  645. DeallocateMemory(pMemoryUsage, pObject);
  646. }
  647. VOID
  648. ValidateObject(
  649. IN POBJECT_ID pObject,
  650. IN DLC_OBJECT_TYPE ObjectType
  651. )
  652. /*++
  653. Routine Description:
  654. Checks that an object is what its supposed to be
  655. Arguments:
  656. pObject - pointer to object to check
  657. ObjectType - type of object pObject supposed to point to
  658. Return Value:
  659. None.
  660. --*/
  661. {
  662. ULONG signature = GetObjectSignature(ObjectType);
  663. ULONG baseSize = GetObjectBaseSize(ObjectType);
  664. if (pObject->Signature != signature
  665. || pObject->Type != ObjectType
  666. || pObject->Size != baseSize) {
  667. DbgPrint("DLC.ValidateObject: Error: InvalidObject %08x, Type=%08x\n",
  668. pObject,
  669. ObjectType
  670. );
  671. DbgBreakPoint();
  672. }
  673. }
  674. ULONG
  675. GetObjectSignature(
  676. IN DLC_OBJECT_TYPE ObjectType
  677. )
  678. /*++
  679. Routine Description:
  680. returns the signature for an object type
  681. Arguments:
  682. ObjectType - type of object to return signature for
  683. Return Value:
  684. ULONG
  685. --*/
  686. {
  687. switch (ObjectType) {
  688. case FileContextObject:
  689. return SIGNATURE_FILE;
  690. case AdapterContextObject:
  691. return SIGNATURE_ADAPTER;
  692. case BindingContextObject:
  693. return SIGNATURE_BINDING;
  694. case DlcSapObject:
  695. case DlcGroupSapObject:
  696. return SIGNATURE_DLC_SAP;
  697. case DlcLinkObject:
  698. return SIGNATURE_DLC_LINK;
  699. case DlcDixObject:
  700. return SIGNATURE_DIX;
  701. case LlcDataLinkObject:
  702. return SIGNATURE_LLC_LINK;
  703. case LlcSapObject:
  704. case LlcGroupSapObject:
  705. return SIGNATURE_LLC_SAP;
  706. default:
  707. DbgPrint("DLC.GetObjectSignature: Error: unknown object type %08x\n", ObjectType);
  708. DbgBreakPoint();
  709. return 0;
  710. }
  711. }
  712. ULONG
  713. GetObjectBaseSize(
  714. IN DLC_OBJECT_TYPE ObjectType
  715. )
  716. /*++
  717. Routine Description:
  718. returns the base size for an object
  719. Arguments:
  720. ObjectType - type of object to return base size for
  721. Return Value:
  722. ULONG
  723. --*/
  724. {
  725. switch (ObjectType) {
  726. case FileContextObject:
  727. return sizeof(DLC_FILE_CONTEXT);
  728. case AdapterContextObject:
  729. return sizeof(ADAPTER_CONTEXT);
  730. case BindingContextObject:
  731. return sizeof(BINDING_CONTEXT);
  732. case DlcSapObject:
  733. case DlcGroupSapObject:
  734. return sizeof(DLC_OBJECT);
  735. case DlcLinkObject:
  736. return sizeof(DLC_OBJECT);
  737. case DlcDixObject:
  738. return sizeof(DLC_OBJECT);
  739. case LlcDataLinkObject:
  740. return sizeof(DATA_LINK);
  741. case LlcSapObject:
  742. case LlcGroupSapObject:
  743. return sizeof(LLC_OBJECT);
  744. default:
  745. DbgPrint("DLC.GetObjectBaseSize: Error: unknown object type %08x\n", ObjectType);
  746. DbgBreakPoint();
  747. return 0;
  748. }
  749. }
  750. #endif
  751. PVOID
  752. AllocateZeroMemory(
  753. #if DBG
  754. IN PMEMORY_USAGE pMemoryUsage,
  755. #endif
  756. IN ULONG Size
  757. )
  758. /*++
  759. Routine Description:
  760. Allocates memory out of non-paged pool. For the debug version, we round up
  761. the requested size to the next 4-byte boundary and we add header and tail
  762. sections which contain a signature to check for over-write, and in-use and
  763. size information
  764. The memory is zeroed before being returned to the caller
  765. Arguments:
  766. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  767. Size - number of bytes to allocate
  768. Return Value:
  769. PVOID
  770. Success - pointer to allocated memory
  771. Failure - NULL
  772. --*/
  773. {
  774. PVOID pMem;
  775. #if DBG
  776. ULONG OriginalSize = Size;
  777. PUCHAR pMemEnd;
  778. /*
  779. KIRQL irql;
  780. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  781. if (InMemoryAllocator) {
  782. DbgPrint("DLC.AllocateZeroMemory: Error: Memory allocator clash on entry. Count = %d\n",
  783. InMemoryAllocator
  784. );
  785. // DbgBreakPoint();
  786. }
  787. ++InMemoryAllocator;
  788. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  789. */
  790. Size = DWORD_ROUNDUP(Size)
  791. + sizeof(PRIVATE_NON_PAGED_POOL_HEAD)
  792. + sizeof(PRIVATE_NON_PAGED_POOL_TAIL);
  793. #endif
  794. pMem = ExAllocatePoolWithTag(NonPagedPool, (ULONG)Size, DLC_POOL_TAG);
  795. if (pMem) {
  796. LlcZeroMem(pMem, Size);
  797. #if DBG
  798. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Size = Size;
  799. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->OriginalSize = OriginalSize;
  800. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Flags = MEM_FLAGS_IN_USE;
  801. ((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Signature = SIGNATURE1;
  802. pMemEnd = (PUCHAR)pMem
  803. + DWORD_ROUNDUP(OriginalSize)
  804. + sizeof(PRIVATE_NON_PAGED_POOL_HEAD);
  805. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Size = Size;
  806. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Signature = SIGNATURE2;
  807. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Pattern1 = PATTERN1;
  808. ((PPRIVATE_NON_PAGED_POOL_TAIL)pMemEnd)->Pattern2 = PATTERN2;
  809. GRAB_SPINLOCK();
  810. UpdateCounter(&GoodNonPagedPoolAllocs, 1);
  811. UpdateCounter(&NonPagedPoolAllocated, (LONG)Size);
  812. UpdateCounter(&NonPagedPoolRequested, (LONG)OriginalSize);
  813. UpdateCounter(&TotalNonPagedPoolRequested, (LONG)OriginalSize);
  814. UpdateCounter(&TotalNonPagedPoolAllocated, (LONG)Size);
  815. FREE_SPINLOCK();
  816. if (MaintainGlobalLists) {
  817. KIRQL irql;
  818. //
  819. // record the caller and add this block to the global list
  820. //
  821. GET_CALLERS_ADDRESS(&((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Stack[0],
  822. &((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->Stack[1]
  823. );
  824. KeAcquireSpinLock(&DlcGlobalMemoryListLock, &irql);
  825. InsertTailList(&DlcGlobalMemoryList,
  826. &((PPRIVATE_NON_PAGED_POOL_HEAD)pMem)->GlobalList
  827. );
  828. ++DlcGlobalMemoryListCount;
  829. KeReleaseSpinLock(&DlcGlobalMemoryListLock, irql);
  830. }
  831. ChargeNonPagedPoolUsage(pMemoryUsage, Size, (PPRIVATE_NON_PAGED_POOL_HEAD)pMem);
  832. pMem = (PVOID)((PUCHAR)pMem + sizeof(PRIVATE_NON_PAGED_POOL_HEAD));
  833. } else {
  834. GRAB_SPINLOCK();
  835. UpdateCounter(&BadNonPagedPoolAllocs, 1);
  836. FREE_SPINLOCK();
  837. }
  838. /*
  839. KeAcquireSpinLock(&MemoryAllocatorLock, &irql);
  840. --InMemoryAllocator;
  841. if (InMemoryAllocator) {
  842. DbgPrint("DLC.AllocateZeroMemory: Error: Memory allocator clash on exit. Count = %d\n",
  843. InMemoryAllocator
  844. );
  845. // DbgBreakPoint();
  846. }
  847. KeReleaseSpinLock(&MemoryAllocatorLock, irql);
  848. */
  849. #else
  850. }
  851. #endif
  852. return pMem;
  853. }
  854. PPACKET_POOL
  855. CreatePacketPool(
  856. #if DBG
  857. IN PMEMORY_USAGE pMemoryUsage,
  858. IN PVOID pOwner,
  859. IN DLC_OBJECT_TYPE ObjectType,
  860. #endif
  861. IN ULONG PacketSize,
  862. IN ULONG NumberOfPackets
  863. )
  864. /*++
  865. Routine Description:
  866. creates a packet pool. A packet pool is a collection of same-sized packets
  867. Arguments:
  868. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  869. pOwner - pointer to owner object
  870. ObjectType - type of object for owner
  871. PacketSize - size of packet in bytes
  872. NumberOfPackets - initial number of packets in pool
  873. Return Value:
  874. PPACKET_POOL
  875. Success - pointer to PACKET_POOL structure allocated from non-paged pool
  876. Failure - NULL
  877. --*/
  878. {
  879. PPACKET_POOL pPacketPool;
  880. PPACKET_HEAD pPacketHead;
  881. #if DBG
  882. /*
  883. // DbgPrint("DLC.CreatePacketPool(%d, %d)\n", PacketSize, NumberOfPackets);
  884. if (InPoolCreator) {
  885. DbgPrint("DLC.CreatePacketPool: Error: Pool Creator clash on entry. Count = %d\n",
  886. InPoolCreator
  887. );
  888. // DbgBreakPoint();
  889. }
  890. ++InPoolCreator;
  891. */
  892. pPacketPool = AllocateZeroMemory(pMemoryUsage, sizeof(PACKET_POOL));
  893. #else
  894. pPacketPool = AllocateZeroMemory(sizeof(PACKET_POOL));
  895. #endif
  896. if (pPacketPool) {
  897. #if DBG
  898. pPacketPool->OriginalPacketCount = NumberOfPackets;
  899. pPacketPool->MemoryUsage.Owner = pPacketPool;
  900. pPacketPool->MemoryUsage.OwnerObjectId = ObjectType;
  901. #endif
  902. while (NumberOfPackets--) {
  903. #if DBG
  904. //
  905. // charge memory for individual packets to the pool
  906. //
  907. pPacketHead = (PPACKET_HEAD)AllocateZeroMemory(&pPacketPool->MemoryUsage,
  908. sizeof(PACKET_HEAD) + PacketSize
  909. );
  910. #else
  911. pPacketHead = (PPACKET_HEAD)AllocateZeroMemory(sizeof(PACKET_HEAD) + PacketSize);
  912. #endif
  913. if (pPacketHead) {
  914. #if DBG
  915. pPacketHead->Signature = PACKET_HEAD_SIGNATURE;
  916. pPacketHead->pPacketPool = pPacketPool;
  917. ++pPacketPool->FreeCount;
  918. #endif
  919. pPacketHead->Flags = PACKET_FLAGS_FREE;
  920. PushEntryList(&pPacketPool->FreeList, (PSINGLE_LIST_ENTRY)pPacketHead);
  921. } else {
  922. while (pPacketPool->FreeList.Next) {
  923. PVOID ptr = (PVOID)PopEntryList(&pPacketPool->FreeList);
  924. #if DBG
  925. DeallocateMemory(&pPacketPool->MemoryUsage, ptr);
  926. #else
  927. DeallocateMemory(ptr);
  928. #endif
  929. }
  930. #if DBG
  931. DbgPrint("DLC.CreatePacketPool: Error: couldn't allocate %d packets\n",
  932. pPacketPool->OriginalPacketCount
  933. );
  934. DeallocateMemory(pMemoryUsage, pPacketPool);
  935. /*
  936. --InPoolCreator;
  937. if (InPoolCreator) {
  938. DbgPrint("DLC.CreatePacketPool: Error: Pool Creator clash on exit. Count = %d\n",
  939. InPoolCreator
  940. );
  941. // DbgBreakPoint();
  942. }
  943. */
  944. #else
  945. DeallocateMemory(pPacketPool);
  946. #endif
  947. return NULL;
  948. }
  949. }
  950. KeInitializeSpinLock(&pPacketPool->PoolLock);
  951. pPacketPool->PacketSize = PacketSize;
  952. #if DBG
  953. pPacketPool->Signature = PACKET_POOL_SIGNATURE;
  954. pPacketPool->Viable = TRUE;
  955. pPacketPool->CurrentPacketCount = pPacketPool->OriginalPacketCount;
  956. pPacketPool->Flags = POOL_FLAGS_IN_USE;
  957. pPacketPool->pMemoryUsage = pMemoryUsage;
  958. //
  959. // add the memory usage structure for this pool to the memory usage
  960. // list
  961. //
  962. LinkMemoryUsage(&pPacketPool->MemoryUsage);
  963. if (DebugDump) {
  964. DbgPrint("DLC.CreatePacketPool: %08x\n", pPacketPool);
  965. DumpPool(pPacketPool);
  966. }
  967. } else {
  968. DbgPrint("DLC.CreatePacketPool: Error: couldn't allocate memory for PACKET_POOL\n");
  969. }
  970. //
  971. // debug counters in PACKET_POOL structure are already zero thanks to
  972. // AllocateZeroMemory automatically zeroing all memory allocated from
  973. // non-paged pool
  974. //
  975. /*
  976. --InPoolCreator;
  977. if (InPoolCreator) {
  978. DbgPrint("DLC.CreatePacketPool: Error: Pool Creator clash on exit. Count = %d\n",
  979. InPoolCreator
  980. );
  981. // DbgBreakPoint();
  982. }
  983. */
  984. #else
  985. }
  986. #endif
  987. return pPacketPool;
  988. }
  989. VOID
  990. DeletePacketPool(
  991. #if DBG
  992. IN PMEMORY_USAGE pMemoryUsage,
  993. #endif
  994. IN PPACKET_POOL* ppPacketPool
  995. )
  996. /*++
  997. Routine Description:
  998. frees a previously created packet pool
  999. Arguments:
  1000. pMemoryUsage - pointer to MEMORY_USAGE structure for charging mem usage
  1001. ppPacketPool - pointer to pointer to PACKET_POOL structure. Zero on return
  1002. Return Value:
  1003. None.
  1004. --*/
  1005. {
  1006. KIRQL irql;
  1007. PPACKET_HEAD pPacketHead;
  1008. PPACKET_POOL pPacketPool = *ppPacketPool;
  1009. #if DBG
  1010. ULONG packetCount;
  1011. #endif
  1012. //
  1013. // for various reasons, we can receive a NULL pointer. No action in this case
  1014. //
  1015. if (pPacketPool == NULL) {
  1016. #if DBG
  1017. PVOID callerAddress, callersCaller;
  1018. GET_CALLERS_ADDRESS(&callerAddress, &callersCaller);
  1019. DbgPrint("DLC.DeletePacketPool: NULL pointer. Caller = %x (caller's caller = %x)\n",
  1020. callerAddress,
  1021. callersCaller
  1022. );
  1023. #endif
  1024. return;
  1025. }
  1026. #if DBG
  1027. // DbgPrint("DLC.DeletePacketPool(%08x)\n", pPacketPool);
  1028. // DumpPool(pPacketPool);
  1029. if (pPacketPool->ClashCount) {
  1030. DbgPrint("DLC.DeletePacketPool: Error: Memory allocator clash on entry: Pool %08x\n", pPacketPool);
  1031. DbgBreakPoint();
  1032. }
  1033. ++pPacketPool->ClashCount;
  1034. if (pPacketPool->Signature != PACKET_POOL_SIGNATURE) {
  1035. DbgPrint("DLC.DeletePacketPool: Error: Invalid Pool Handle %08x\n", pPacketPool);
  1036. DbgBreakPoint();
  1037. }
  1038. if (!pPacketPool->Viable) {
  1039. DbgPrint("DLC.DeletePacketPool: Error: Unviable Packet Pool %08x\n", pPacketPool);
  1040. DbgBreakPoint();
  1041. }
  1042. #endif
  1043. KeAcquireSpinLock(&pPacketPool->PoolLock, &irql);
  1044. #if DBG
  1045. //
  1046. // mark the packet pool structure as unviable: if anybody tries to allocate
  1047. // or deallocate while we are destroying the pool, we will break into debugger
  1048. //
  1049. pPacketPool->Viable = FALSE;
  1050. pPacketPool->Signature = 0xFFFFFFFF;
  1051. //
  1052. // assert that the busy list is empty
  1053. //
  1054. if (pPacketPool->BusyList.Next != NULL) {
  1055. DbgPrint("DLC.DeletePacketPool: Error: %d packets busy. Pool = %08x\n",
  1056. pPacketPool->BusyCount,
  1057. pPacketPool
  1058. );
  1059. if (!DeleteBusyListAnyway) {
  1060. DumpPool(pPacketPool);
  1061. DbgBreakPoint();
  1062. } else {
  1063. DbgPrint("DLC.DeletePacketPool: Deleting BusyList anyway\n");
  1064. }
  1065. }
  1066. packetCount = 0;
  1067. #endif
  1068. while (pPacketPool->FreeList.Next != NULL) {
  1069. pPacketHead = (PPACKET_HEAD)PopEntryList(&pPacketPool->FreeList);
  1070. #if DBG
  1071. if (pPacketHead->Signature != PACKET_HEAD_SIGNATURE
  1072. || pPacketHead->pPacketPool != pPacketPool
  1073. || (pPacketHead->Flags & PACKET_FLAGS_BUSY)
  1074. || !(pPacketHead->Flags & PACKET_FLAGS_FREE)) {
  1075. DbgPrint("DLC.DeletePacketPool: Error: Bad packet %08x. Pool = %08x\n",
  1076. pPacketHead,
  1077. pPacketPool
  1078. );
  1079. DbgBreakPoint();
  1080. }
  1081. ++packetCount;
  1082. DeallocateMemory(&pPacketPool->MemoryUsage, pPacketHead);
  1083. #else
  1084. DeallocateMemory(pPacketHead);
  1085. #endif
  1086. }
  1087. #if DBG
  1088. if (DeleteBusyListAnyway) {
  1089. while (pPacketPool->BusyList.Next != NULL) {
  1090. pPacketHead = (PPACKET_HEAD)PopEntryList(&pPacketPool->BusyList);
  1091. if (pPacketHead->Signature != PACKET_HEAD_SIGNATURE
  1092. || pPacketHead->pPacketPool != pPacketPool
  1093. || (pPacketHead->Flags & PACKET_FLAGS_FREE)
  1094. || !(pPacketHead->Flags & PACKET_FLAGS_BUSY)) {
  1095. DbgPrint("DLC.DeletePacketPool: Error: Bad packet %08x. Pool = %08x\n",
  1096. pPacketHead,
  1097. pPacketPool
  1098. );
  1099. DbgBreakPoint();
  1100. }
  1101. ++packetCount;
  1102. DeallocateMemory(&pPacketPool->MemoryUsage, pPacketHead);
  1103. }
  1104. }
  1105. //
  1106. // did any packets get unwittingly added or removed?
  1107. //
  1108. if (packetCount != pPacketPool->CurrentPacketCount) {
  1109. DbgPrint("DLC.DeletePacketPool: Error: PacketCount (%d) != PoolCount (%d)\n",
  1110. packetCount,
  1111. pPacketPool->CurrentPacketCount
  1112. );
  1113. DumpPool(pPacketPool);
  1114. DbgBreakPoint();
  1115. }
  1116. //
  1117. // ensure we returned all the memory allocated to this pool
  1118. //
  1119. CheckMemoryReturned(&pPacketPool->MemoryUsage);
  1120. //
  1121. // dump the counters every time we delete a pool
  1122. //
  1123. // DumpPoolStats("DeletePacketPool", pPacketPool);
  1124. //
  1125. // remove the pool's memory usage structure - all memory allocated has been
  1126. // freed, so we're in the clear for this one
  1127. //
  1128. UnlinkMemoryUsage(&pPacketPool->MemoryUsage);
  1129. #endif
  1130. KeReleaseSpinLock(&pPacketPool->PoolLock, irql);
  1131. #if DBG
  1132. DeallocateMemory(pMemoryUsage, pPacketPool);
  1133. #else
  1134. DeallocateMemory(pPacketPool);
  1135. #endif
  1136. *ppPacketPool = NULL;
  1137. }
  1138. PVOID
  1139. AllocatePacket(
  1140. IN PPACKET_POOL pPacketPool
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. allocates a packet from a packet pool. We expect that we can always get a
  1145. packet from the previously allocated pool. However, if all packets are
  1146. currently in use, allocate another from non-paged pool
  1147. Arguments:
  1148. pPacketPool - pointer to PACKET_POOL structure
  1149. Return Value:
  1150. PVOID
  1151. Success - pointer to allocated packet
  1152. Failure - NULL
  1153. --*/
  1154. {
  1155. KIRQL irql;
  1156. PPACKET_HEAD pPacketHead;
  1157. #if DBG
  1158. if (pPacketPool->ClashCount) {
  1159. DbgPrint("DLC.AllocatePacket: Error: Memory allocator clash on entry: Pool %08x, Count %d\n",
  1160. pPacketPool,
  1161. pPacketPool->ClashCount
  1162. );
  1163. // DbgBreakPoint();
  1164. }
  1165. ++pPacketPool->ClashCount;
  1166. #endif
  1167. KeAcquireSpinLock(&pPacketPool->PoolLock, &irql);
  1168. #if DBG
  1169. if (pPacketPool->Signature != PACKET_POOL_SIGNATURE) {
  1170. DbgPrint("DLC.AllocatePacket: Error: Invalid Pool Handle %08x\n", pPacketPool);
  1171. DbgBreakPoint();
  1172. }
  1173. if (!pPacketPool->Viable) {
  1174. DbgPrint("DLC.AllocatePacket: Error: Unviable Packet Pool %08x\n", pPacketPool);
  1175. DbgBreakPoint();
  1176. }
  1177. #endif
  1178. if (pPacketPool->FreeList.Next != NULL) {
  1179. pPacketHead = (PPACKET_HEAD)PopEntryList(&pPacketPool->FreeList);
  1180. #if DBG
  1181. --pPacketPool->FreeCount;
  1182. if (pPacketHead->Flags & PACKET_FLAGS_BUSY
  1183. || !(pPacketHead->Flags & PACKET_FLAGS_FREE)) {
  1184. DbgPrint("DLC.AllocatePacket: Error: BUSY packet %08x on FreeList; Pool=%08x\n",
  1185. pPacketHead,
  1186. pPacketPool
  1187. );
  1188. DumpPacketHead(pPacketHead, 0);
  1189. DbgBreakPoint();
  1190. }
  1191. #endif
  1192. } else {
  1193. //
  1194. // Miscalculated pool usage
  1195. //
  1196. #if DBG
  1197. pPacketHead = (PPACKET_HEAD)AllocateZeroMemory(&pPacketPool->MemoryUsage,
  1198. sizeof(PACKET_HEAD) + pPacketPool->PacketSize
  1199. );
  1200. #else
  1201. pPacketHead = (PPACKET_HEAD)AllocateZeroMemory(sizeof(PACKET_HEAD) + pPacketPool->PacketSize);
  1202. #endif
  1203. if (pPacketHead) {
  1204. //
  1205. // mark this packet as allocated after the pool was created - this
  1206. // means our initial estimation of packet requirement for this
  1207. // pool was inadequate
  1208. //
  1209. pPacketHead->Flags = PACKET_FLAGS_POST_ALLOC | PACKET_FLAGS_FREE;
  1210. }
  1211. #if DBG
  1212. ++pPacketPool->NoneFreeCount;
  1213. if (pPacketHead) {
  1214. PVOID caller;
  1215. PVOID callersCaller;
  1216. GET_CALLERS_ADDRESS(&caller, &callersCaller);
  1217. if (DebugDump) {
  1218. DbgPrint("DLC.AllocatePacket: Adding new packet %08x to pool %08x. ret=%08x,%08x\n",
  1219. pPacketHead,
  1220. pPacketPool,
  1221. caller,
  1222. callersCaller
  1223. );
  1224. }
  1225. pPacketHead->Signature = PACKET_HEAD_SIGNATURE;
  1226. pPacketHead->pPacketPool = pPacketPool;
  1227. ++pPacketPool->CurrentPacketCount;
  1228. DumpPoolStats("AllocatePacket", pPacketPool);
  1229. } else {
  1230. DbgPrint("DLC.AllocatePacket: Error: couldn't allocate packet for Pool %08x\n",
  1231. pPacketPool
  1232. );
  1233. }
  1234. #endif
  1235. }
  1236. if (pPacketHead) {
  1237. //
  1238. // turn on BUSY flag, turn off FREE flag
  1239. //
  1240. pPacketHead->Flags ^= (PACKET_FLAGS_FREE | PACKET_FLAGS_BUSY);
  1241. //
  1242. // zero the contents of the packet!
  1243. //
  1244. LlcZeroMem((PVOID)(pPacketHead + 1), pPacketPool->PacketSize);
  1245. PushEntryList(&pPacketPool->BusyList, (PSINGLE_LIST_ENTRY)pPacketHead);
  1246. #if DBG
  1247. GET_CALLERS_ADDRESS(&pPacketHead->CallersAddress_A,
  1248. &pPacketHead->CallersCaller_A
  1249. );
  1250. ++pPacketPool->BusyCount;
  1251. ++pPacketPool->Allocations;
  1252. ++pPacketPool->MaxInUse;
  1253. #endif
  1254. }
  1255. KeReleaseSpinLock(&pPacketPool->PoolLock, irql);
  1256. #if DBG
  1257. --pPacketPool->ClashCount;
  1258. if (pPacketPool->ClashCount) {
  1259. DbgPrint("DLC.AllocatePacket: Error: Memory allocator clash on exit: Pool %08x\n", pPacketPool);
  1260. DbgBreakPoint();
  1261. }
  1262. #endif
  1263. //
  1264. // return pointer to packet body, not packet header
  1265. //
  1266. return pPacketHead ? (PVOID)(pPacketHead + 1) : (PVOID)pPacketHead;
  1267. }
  1268. VOID
  1269. DeallocatePacket(
  1270. IN PPACKET_POOL pPacketPool,
  1271. IN PVOID pPacket
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. Returns a packet to its pool
  1276. Arguments:
  1277. pPacketPool - pointer to PACKET_POOL structure describing this pool
  1278. pPacket - pointer to previously allocated packet
  1279. Return Value:
  1280. None.
  1281. --*/
  1282. {
  1283. KIRQL irql;
  1284. PPACKET_HEAD pPacketHead = ((PPACKET_HEAD)pPacket) - 1;
  1285. PSINGLE_LIST_ENTRY p;
  1286. PSINGLE_LIST_ENTRY prev;
  1287. #if DBG
  1288. if (pPacketPool->ClashCount) {
  1289. DbgPrint("DLC.DeallocatePacket: Error: Memory allocator clash on entry: Pool %08x\n", pPacketPool);
  1290. DbgBreakPoint();
  1291. }
  1292. ++pPacketPool->ClashCount;
  1293. #endif
  1294. KeAcquireSpinLock(&pPacketPool->PoolLock, &irql);
  1295. #if DBG
  1296. if (pPacketPool->Signature != PACKET_POOL_SIGNATURE) {
  1297. DbgPrint("DLC.DeallocatePacket: Error: Invalid Pool Handle %08x\n", pPacketPool);
  1298. DbgBreakPoint();
  1299. }
  1300. if (!pPacketPool->Viable) {
  1301. DbgPrint("DLC.DeallocatePacket: Error: Unviable Packet Pool %08x\n", pPacketPool);
  1302. DbgBreakPoint();
  1303. }
  1304. if (pPacketHead->Signature != PACKET_HEAD_SIGNATURE
  1305. || pPacketHead->pPacketPool != pPacketPool
  1306. || !(pPacketHead->Flags & PACKET_FLAGS_BUSY)
  1307. || pPacketHead->Flags & PACKET_FLAGS_FREE) {
  1308. DbgPrint("DLC.DeallocatePacket: Error: Invalid Packet Header %08x, Pool = %08x\n",
  1309. pPacketHead,
  1310. pPacketPool
  1311. );
  1312. DbgBreakPoint();
  1313. }
  1314. #endif
  1315. //
  1316. // remove this packet from single linked list on BusyList
  1317. //
  1318. prev = (PSINGLE_LIST_ENTRY)&pPacketPool->BusyList;
  1319. for (p = prev->Next; p; p = p->Next) {
  1320. if (p == (PSINGLE_LIST_ENTRY)pPacketHead) {
  1321. break;
  1322. } else {
  1323. prev = p;
  1324. }
  1325. }
  1326. #if DBG
  1327. if (!p) {
  1328. DbgPrint("DLC.DeallocatePacket: Error: packet %08x not on BusyList of pool %08x\n",
  1329. pPacketHead,
  1330. pPacketPool
  1331. );
  1332. DumpPool(pPacketPool);
  1333. DbgBreakPoint();
  1334. }
  1335. #endif
  1336. prev->Next = pPacketHead->List.Next;
  1337. #if DBG
  1338. if (ZapDeallocatedPackets) {
  1339. //
  1340. // fill the deallocated packet with 'Z's. This will quickly tell us if
  1341. // the packet is still being used after it is deallocated
  1342. //
  1343. RtlFillMemory(pPacketHead + 1, pPacketPool->PacketSize, ZAP_DEALLOC_VALUE);
  1344. }
  1345. #endif
  1346. PushEntryList(&pPacketPool->FreeList, (PSINGLE_LIST_ENTRY)pPacketHead);
  1347. //
  1348. // turn off BUSY flag, turn on FREE flag
  1349. //
  1350. pPacketHead->Flags ^= (PACKET_FLAGS_BUSY | PACKET_FLAGS_FREE);
  1351. #if DBG
  1352. ++pPacketPool->FreeCount;
  1353. --pPacketPool->BusyCount;
  1354. ++pPacketPool->Frees;
  1355. --pPacketPool->MaxInUse;
  1356. // pPacketHead->CallersAddress_A = (PVOID)-1;
  1357. // pPacketHead->CallersCaller_A = (PVOID)-1;
  1358. GET_CALLERS_ADDRESS(&pPacketHead->CallersAddress_D,
  1359. &pPacketHead->CallersCaller_D
  1360. );
  1361. #endif
  1362. KeReleaseSpinLock(&pPacketPool->PoolLock, irql);
  1363. #if DBG
  1364. --pPacketPool->ClashCount;
  1365. if (pPacketPool->ClashCount) {
  1366. DbgPrint("DLC.DeallocatePacket: Error: Memory allocator clash on exit: Pool %08x\n", pPacketPool);
  1367. DbgBreakPoint();
  1368. }
  1369. #endif
  1370. }
  1371. #if DBG
  1372. #ifdef TRACK_DLC_OBJECTS
  1373. POBJECT_POOL
  1374. CreateObjectPool(
  1375. IN PMEMORY_USAGE pMemoryUsage,
  1376. IN DLC_OBJECT_TYPE ObjectType,
  1377. IN ULONG SizeOfObject,
  1378. IN ULONG NumberOfObjects
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. description-of-function.
  1383. Arguments:
  1384. pMemoryUsage -
  1385. ObjectType -
  1386. SizeOfObject -
  1387. NumberOfObjects -
  1388. Return Value:
  1389. POBJECT_POOL
  1390. --*/
  1391. {
  1392. }
  1393. VOID
  1394. DeleteObjectPool(
  1395. IN PMEMORY_USAGE pMemoryUsage,
  1396. IN DLC_OBJECT_TYPE ObjectType,
  1397. IN POBJECT_POOL pObjectPool
  1398. )
  1399. /*++
  1400. Routine Description:
  1401. description-of-function.
  1402. Arguments:
  1403. pMemoryUsage -
  1404. ObjectType -
  1405. pObjectPool -
  1406. Return Value:
  1407. None.
  1408. --*/
  1409. {
  1410. }
  1411. POBJECT_HEAD
  1412. AllocatePoolObject(
  1413. IN POBJECT_POOL pObjectPool
  1414. )
  1415. /*++
  1416. Routine Description:
  1417. description-of-function.
  1418. Arguments:
  1419. pObjectPool -
  1420. Return Value:
  1421. POBJECT_HEAD
  1422. --*/
  1423. {
  1424. }
  1425. POBJECT_POOL
  1426. FreePoolObject(
  1427. IN DLC_OBJECT_TYPE ObjectType,
  1428. IN POBJECT_HEAD pObjectHead
  1429. )
  1430. /*++
  1431. Routine Description:
  1432. description-of-function.
  1433. Arguments:
  1434. ObjectType -
  1435. pObjectHead -
  1436. Return Value:
  1437. POBJECT_POOL
  1438. --*/
  1439. {
  1440. }
  1441. #endif // TRACK_DLC_OBJECTS
  1442. VOID
  1443. CheckMemoryReturned(
  1444. IN PMEMORY_USAGE pMemoryUsage
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Called when a 'handle' which owns a MEMORY_USAGE structure is being closed.
  1449. Checks that all memory has been returned and that number of allocations is
  1450. the same as number of frees
  1451. Arguments:
  1452. pMemoryUsage - pointer to MEMORY_USAGE structure to check
  1453. Return Value:
  1454. None.
  1455. --*/
  1456. {
  1457. if (pMemoryUsage->AllocateCount != pMemoryUsage->FreeCount || pMemoryUsage->NonPagedPoolAllocated) {
  1458. if (MemoryCheckNotify) {
  1459. if (pMemoryUsage->AllocateCount != pMemoryUsage->FreeCount) {
  1460. DbgPrint("DLC.CheckMemoryReturned: Error: AllocateCount != FreeCount. Usage @ %08x\n",
  1461. pMemoryUsage
  1462. );
  1463. } else {
  1464. DbgPrint("DLC.CheckMemoryReturned: Error: NonPagedPoolAllocated != 0. Usage @ %08x\n",
  1465. pMemoryUsage
  1466. );
  1467. }
  1468. }
  1469. if (MemoryCheckStop) {
  1470. DumpMemoryUsage(pMemoryUsage, TRUE);
  1471. DbgBreakPoint();
  1472. }
  1473. }
  1474. }
  1475. VOID
  1476. CheckDriverMemoryUsage(
  1477. IN BOOLEAN Break
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. Checks if the driver has allocated memory & dumps usage to debugger
  1482. Arguments:
  1483. Break - if true && driver has memory, breaks into debugger
  1484. Return Value:
  1485. None.
  1486. --*/
  1487. {
  1488. DbgPrint("DLC.CheckDriverMemoryUsage\n");
  1489. DumpMemoryMetrics();
  1490. if (Break && NonPagedPoolAllocated) {
  1491. if (MemoryCheckNotify) {
  1492. DbgPrint("DLC.CheckDriverMemoryUsage: Error: Driver still has memory allocated\n");
  1493. }
  1494. if (MemoryCheckStop) {
  1495. DbgBreakPoint();
  1496. }
  1497. }
  1498. }
  1499. VOID MemoryAllocationError(PCHAR Routine, PVOID Address) {
  1500. DbgPrint("DLC.%s: Error: Memory Allocation error in block @ %08x\n", Routine, Address);
  1501. DumpMemoryMetrics();
  1502. DbgBreakPoint();
  1503. }
  1504. VOID UpdateCounter(PULONG pCounter, LONG Value) {
  1505. if (Value > 0) {
  1506. if (*pCounter + Value < *pCounter) {
  1507. MemoryCounterOverflow(pCounter, Value);
  1508. }
  1509. } else {
  1510. if (*pCounter + Value > *pCounter) {
  1511. MemoryCounterOverflow(pCounter, Value);
  1512. }
  1513. }
  1514. *pCounter += Value;
  1515. }
  1516. VOID MemoryCounterOverflow(PULONG pCounter, LONG Value) {
  1517. DbgPrint("DLC: Memory Counter Overflow: &Counter=%08x, Count=%d, Value=%d\n",
  1518. pCounter,
  1519. *pCounter,
  1520. Value
  1521. );
  1522. DumpMemoryMetrics();
  1523. }
  1524. VOID DumpMemoryMetrics() {
  1525. DbgPrint("DLC Device Driver Non-Paged Pool Usage:\n"
  1526. "\tNumber Of Good Non-Paged Pool Allocations. : %d\n"
  1527. "\tNumber Of Bad Non-Paged Pool Allocations. : %d\n"
  1528. "\tNumber Of Good Non-Paged Pool Frees. . . . : %d\n"
  1529. "\tNumber Of Bad Non-Paged Pool Frees. . . . : %d\n",
  1530. GoodNonPagedPoolAllocs,
  1531. BadNonPagedPoolAllocs,
  1532. GoodNonPagedPoolFrees,
  1533. BadNonPagedPoolFrees
  1534. );
  1535. DbgPrint("\tTotal Non-Paged Pool Currently Requested . : %d\n"
  1536. "\tTotal Non-Paged Pool Currently Allocated . : %d\n"
  1537. "\tCumulative Total Non-Paged Pool Requested. : %d\n"
  1538. "\tCumulative Total Non-Paged Pool Allocated. : %d\n"
  1539. "\tCumulative Total Non-Paged Pool Freed. . . : %d\n"
  1540. "\n",
  1541. NonPagedPoolRequested,
  1542. NonPagedPoolAllocated,
  1543. TotalNonPagedPoolRequested,
  1544. TotalNonPagedPoolAllocated,
  1545. TotalNonPagedPoolFreed
  1546. );
  1547. DumpMemoryUsageList();
  1548. }
  1549. VOID DumpPoolStats(PCHAR Routine, PPACKET_POOL pPacketPool) {
  1550. if (!DebugDump) {
  1551. return;
  1552. }
  1553. DbgPrint("DLC.%s: Stats For Pool %08x:\n"
  1554. "\tPool Owner . . . . . . . . . . . . . . . . . . . : %08x\n"
  1555. "\tPool Owner Object ID . . . . . . . . . . . . . . : %08x [%s]\n",
  1556. Routine,
  1557. pPacketPool,
  1558. pPacketPool->pMemoryUsage->Owner,
  1559. pPacketPool->pMemoryUsage->OwnerObjectId,
  1560. MapObjectId(pPacketPool->pMemoryUsage->OwnerObjectId)
  1561. );
  1562. DbgPrint("\tFree List. . . . . . . . . . . . . . . . . . . . : %08x\n"
  1563. "\tBusy List. . . . . . . . . . . . . . . . . . . . : %08x\n",
  1564. pPacketPool->FreeList,
  1565. pPacketPool->BusyList
  1566. );
  1567. DbgPrint("\tPacket Size. . . . . . . . . . . . . . . . . . . : %d\n"
  1568. "\tOriginal Number Of Packets In Pool . . . . . . . : %d\n"
  1569. "\tCurrent Number Of Packets In Pool. . . . . . . . : %d\n"
  1570. "\tNumber Of Allocations From Pool. . . . . . . . . : %d\n"
  1571. "\tNumber Of Deallocations To Pool. . . . . . . . . : %d\n"
  1572. "\tNumber Of Times No Available Packets On Allocate : %d\n"
  1573. "\tMax. Number Of Packets Allocated At Any One Time : %d\n"
  1574. "\tNumber Of Packets On Free List . . . . . . . . . : %d\n"
  1575. "\tNumber Of Packets On Busy List . . . . . . . . . : %d\n"
  1576. "\n",
  1577. pPacketPool->PacketSize,
  1578. pPacketPool->OriginalPacketCount,
  1579. pPacketPool->CurrentPacketCount,
  1580. pPacketPool->Allocations,
  1581. pPacketPool->Frees,
  1582. pPacketPool->NoneFreeCount,
  1583. pPacketPool->MaxInUse,
  1584. pPacketPool->FreeCount,
  1585. pPacketPool->BusyCount
  1586. );
  1587. DumpMemoryUsage(&pPacketPool->MemoryUsage, FALSE);
  1588. }
  1589. PCHAR MapObjectId(DLC_OBJECT_TYPE ObjectType) {
  1590. switch (ObjectType) {
  1591. case DlcDriverObject:
  1592. return "DlcDriverObject";
  1593. case FileContextObject:
  1594. return "FileContextObject";
  1595. case AdapterContextObject:
  1596. return "AdapterContextObject";
  1597. case BindingContextObject:
  1598. return "BindingContextObject";
  1599. case DlcSapObject:
  1600. return "DlcSapObject";
  1601. case DlcGroupSapObject:
  1602. return "DlcGroupSapObject";
  1603. case DlcLinkObject:
  1604. return "DlcLinkObject";
  1605. case DlcDixObject:
  1606. return "DlcDixObject";
  1607. case LlcDataLinkObject:
  1608. return "LlcDataLinkObject";
  1609. case LLcDirectObject:
  1610. return "LLcDirectObject";
  1611. case LlcSapObject:
  1612. return "LlcSapObject";
  1613. case LlcGroupSapObject:
  1614. return "LlcGroupSapObject";
  1615. case DlcBufferPoolObject:
  1616. return "DlcBufferPoolObject";
  1617. case DlcLinkPoolObject:
  1618. return "DlcLinkPoolObject";
  1619. case DlcPacketPoolObject:
  1620. return "DlcPacketPoolObject";
  1621. case LlcLinkPoolObject:
  1622. return "LlcLinkPoolObject";
  1623. case LlcPacketPoolObject:
  1624. return "LlcPacketPoolObject";
  1625. default:
  1626. return "*** UNKNOWN OBJECT TYPE ***";
  1627. }
  1628. }
  1629. VOID DumpPool(PPACKET_POOL pPacketPool) {
  1630. if (!DebugDump) {
  1631. return;
  1632. }
  1633. DumpPoolStats("DumpPool", pPacketPool);
  1634. DumpPoolList("Free", &pPacketPool->FreeList);
  1635. DumpPoolList("Busy", &pPacketPool->BusyList);
  1636. }
  1637. VOID DumpPoolList(PCHAR Name, PSINGLE_LIST_ENTRY List) {
  1638. ULONG count = 0;
  1639. if (List->Next) {
  1640. DbgPrint("\n%s List @ %08x:\n", Name, List);
  1641. while (List->Next) {
  1642. List = List->Next;
  1643. DumpPacketHead((PPACKET_HEAD)List, ++count);
  1644. }
  1645. } else {
  1646. DbgPrint("%s List is EMPTY\n\n", Name);
  1647. }
  1648. }
  1649. VOID DumpPacketHead(PPACKET_HEAD pPacketHead, ULONG Number) {
  1650. CHAR numbuf[5];
  1651. if (!DebugDump) {
  1652. return;
  1653. }
  1654. if (Number) {
  1655. int i;
  1656. ULONG div = 1000; // 1000 packets in a pool?
  1657. while (!(Number / div)) {
  1658. div /= 10;
  1659. }
  1660. for (i = 0; Number; ++i) {
  1661. numbuf[i] = (CHAR)('0' + Number / div);
  1662. Number %= div;
  1663. div /= 10;
  1664. }
  1665. numbuf[i] = 0;
  1666. Number = 1; // flag
  1667. }
  1668. DbgPrint("%s\tPACKET_HEAD @ %08x:\n"
  1669. "\tList . . . . . . . . : %08x\n"
  1670. "\tFlags. . . . . . . . : %08x\n"
  1671. "\tSignature. . . . . . : %08x\n"
  1672. "\tpPacketPool. . . . . : %08x\n"
  1673. "\tCallers Address (A). : %08x\n"
  1674. "\tCallers Caller (A) . : %08x\n"
  1675. "\tCallers Address (D). : %08x\n"
  1676. "\tCallers Caller (D) . : %08x\n"
  1677. "\n",
  1678. Number ? numbuf : "",
  1679. pPacketHead,
  1680. pPacketHead->List,
  1681. pPacketHead->Flags,
  1682. pPacketHead->Signature,
  1683. pPacketHead->pPacketPool,
  1684. pPacketHead->CallersAddress_A,
  1685. pPacketHead->CallersCaller_A,
  1686. pPacketHead->CallersAddress_D,
  1687. pPacketHead->CallersCaller_D
  1688. );
  1689. }
  1690. VOID DumpMemoryUsageList() {
  1691. PMEMORY_USAGE pMemoryUsage;
  1692. KIRQL irql;
  1693. BOOLEAN allocatedMemoryFound = FALSE;
  1694. KeAcquireSpinLock(&MemoryUsageLock, &irql);
  1695. for (pMemoryUsage = MemoryUsageList; pMemoryUsage; pMemoryUsage = pMemoryUsage->List) {
  1696. if (pMemoryUsage->NonPagedPoolAllocated) {
  1697. allocatedMemoryFound = TRUE;
  1698. DbgPrint("DLC.DumpMemoryUsageList: %08x: %d bytes memory allocated\n",
  1699. pMemoryUsage,
  1700. pMemoryUsage->NonPagedPoolAllocated
  1701. );
  1702. DumpMemoryUsage(pMemoryUsage, FALSE);
  1703. }
  1704. }
  1705. KeReleaseSpinLock(&MemoryUsageLock, irql);
  1706. if (!allocatedMemoryFound) {
  1707. DbgPrint("DLC.DumpMemoryUsageList: No allocated memory found\n");
  1708. }
  1709. }
  1710. VOID DumpMemoryUsage(PMEMORY_USAGE pMemoryUsage, BOOLEAN Override) {
  1711. if (!DebugDump && !Override) {
  1712. return;
  1713. }
  1714. DbgPrint("MEMORY_USAGE @ %08x:\n"
  1715. "\tOwner. . . . . . . . . . . . . : %08x\n"
  1716. "\tOwner Object ID. . . . . . . . : %08x [%s]\n"
  1717. "\tOwner Instance . . . . . . . . : %x\n",
  1718. pMemoryUsage,
  1719. pMemoryUsage->Owner,
  1720. pMemoryUsage->OwnerObjectId,
  1721. MapObjectId(pMemoryUsage->OwnerObjectId),
  1722. pMemoryUsage->OwnerInstance
  1723. );
  1724. DbgPrint("\tNon Paged Pool Allocated . . . : %d\n"
  1725. "\tNumber Of Allocations. . . . . : %d\n"
  1726. "\tNumber Of Frees. . . . . . . . : %d\n"
  1727. "\tPrivate Allocation List Flink. : %08x\n"
  1728. "\tPrivate Allocation List Blink. : %08x\n"
  1729. "\n",
  1730. pMemoryUsage->NonPagedPoolAllocated,
  1731. pMemoryUsage->AllocateCount,
  1732. pMemoryUsage->FreeCount,
  1733. pMemoryUsage->PrivateList.Flink,
  1734. pMemoryUsage->PrivateList.Blink
  1735. );
  1736. }
  1737. VOID
  1738. CollectReturnAddresses(
  1739. OUT PVOID* ReturnAddresses,
  1740. IN ULONG AddressesToCollect,
  1741. IN ULONG AddressesToSkip
  1742. )
  1743. {
  1744. PVOID* ebp = (PVOID*)*(PVOID**)&ReturnAddresses - 2;
  1745. while (AddressesToSkip--) {
  1746. GetLastReturnAddress(&ebp);
  1747. }
  1748. while (AddressesToCollect--) {
  1749. *ReturnAddresses++ = GetLastReturnAddress(&ebp);
  1750. }
  1751. }
  1752. PVOID* GetLastReturnAddress(PVOID** pEbp) {
  1753. PVOID* returnAddress = *(*pEbp + 1);
  1754. *pEbp = **pEbp;
  1755. return returnAddress;
  1756. }
  1757. #ifdef i386
  1758. VOID x86SleazeCallersAddress(PVOID* pCaller, PVOID* pCallerCaller) {
  1759. //
  1760. // this only works on x86 and only if not fpo functions!
  1761. //
  1762. PVOID* ebp;
  1763. ebp = (PVOID*)&pCaller - 2; // told you it was sleazy
  1764. ebp = (PVOID*)*(PVOID*)ebp;
  1765. *pCaller = *(ebp + 1);
  1766. ebp = (PVOID*)*(PVOID*)ebp;
  1767. *pCallerCaller = *(ebp + 1);
  1768. }
  1769. #endif
  1770. BOOLEAN VerifyElementOnList(PSINGLE_LIST_ENTRY List, PSINGLE_LIST_ENTRY Element) {
  1771. while (List) {
  1772. if (List == Element) {
  1773. return TRUE;
  1774. }
  1775. List = List->Next;
  1776. }
  1777. return FALSE;
  1778. }
  1779. VOID CheckList(PSINGLE_LIST_ENTRY List, ULONG NumberOfElements) {
  1780. PSINGLE_LIST_ENTRY originalList = List;
  1781. while (NumberOfElements--) {
  1782. if (List->Next == NULL) {
  1783. DbgPrint("DLC.CheckList: Error: too few entries on list %08x\n", originalList);
  1784. DbgBreakPoint();
  1785. } else {
  1786. List = List->Next;
  1787. }
  1788. }
  1789. if (List->Next != NULL) {
  1790. DbgPrint("DLC.CheckList: Error: too many entries on list %08x\n", originalList);
  1791. DbgBreakPoint();
  1792. }
  1793. }
  1794. VOID CheckEntryOnList(PLIST_ENTRY Entry, PLIST_ENTRY List, BOOLEAN Sense) {
  1795. BOOLEAN found = FALSE;
  1796. PLIST_ENTRY p;
  1797. if (!IsListEmpty(List)) {
  1798. for (p = List->Flink; p != List; p = p->Flink) {
  1799. if (p == Entry) {
  1800. found = TRUE;
  1801. break;
  1802. }
  1803. }
  1804. }
  1805. if (found != Sense) {
  1806. if (found) {
  1807. DbgPrint("DLC.CheckEntryOnList: Error: Entry %08x found on list %08x. Not supposed to be there\n",
  1808. Entry,
  1809. List
  1810. );
  1811. } else {
  1812. DbgPrint("DLC.CheckEntryOnList: Error: Entry %08x not found on list %08x\n",
  1813. Entry,
  1814. List
  1815. );
  1816. }
  1817. if (MemoryCheckStop) {
  1818. DbgBreakPoint();
  1819. }
  1820. }
  1821. }
  1822. VOID DumpPrivateMemoryHeader(PPRIVATE_NON_PAGED_POOL_HEAD pHead) {
  1823. DbgPrint("Private Non Paged Pool Header @ %08x:\n"
  1824. "\tSize . . . . . . . : %d\n"
  1825. "\tOriginal Size. . . : %d\n"
  1826. "\tFlags. . . . . . . : %08x\n"
  1827. "\tSignature. . . . . : %08x\n"
  1828. "\tGlobalList.Flink . : %08x\n"
  1829. "\tGlobalList.Blink . : %08x\n"
  1830. "\tPrivateList.Flink. : %08x\n"
  1831. "\tPrivateList.Blink. : %08x\n"
  1832. "\tStack[0] . . . . . : %08x\n"
  1833. "\tStack[1] . . . . . : %08x\n"
  1834. "\tStack[2] . . . . . : %08x\n"
  1835. "\tStack[3] . . . . . : %08x\n"
  1836. "\n",
  1837. pHead->Size,
  1838. pHead->OriginalSize,
  1839. pHead->Flags,
  1840. pHead->Signature,
  1841. pHead->GlobalList.Flink,
  1842. pHead->GlobalList.Blink,
  1843. pHead->PrivateList.Flink,
  1844. pHead->PrivateList.Blink,
  1845. pHead->Stack[0],
  1846. pHead->Stack[1],
  1847. pHead->Stack[2],
  1848. pHead->Stack[3]
  1849. );
  1850. }
  1851. VOID ReportSwitchSettings(PSTR str) {
  1852. DbgPrint("%s: LLCMEM Switches:\n"
  1853. "\tDebugDump . . . . . . : %s\n"
  1854. "\tDeleteBusyListAnyway. : %s\n"
  1855. "\tMemoryCheckNotify . . : %s\n"
  1856. "\tMemoryCheckStop . . . : %s\n"
  1857. "\tMaintainGlobalLists . : %s\n"
  1858. "\tMaintainPrivateLists. : %s\n"
  1859. "\tZapDeallocatedPackets : %s\n"
  1860. "\tZapFreedMemory. . . . : %s\n"
  1861. "\n",
  1862. str,
  1863. YES_NO(DebugDump),
  1864. YES_NO(DeleteBusyListAnyway),
  1865. YES_NO(MemoryCheckNotify),
  1866. YES_NO(MemoryCheckStop),
  1867. YES_NO(MaintainGlobalLists),
  1868. YES_NO(MaintainPrivateLists),
  1869. YES_NO(ZapDeallocatedPackets),
  1870. YES_NO(ZapFreedMemory)
  1871. );
  1872. }
  1873. #endif