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.

2040 lines
51 KiB

  1. //
  2. // Template Driver
  3. // Copyright (c) Microsoft Corporation, 1999.
  4. //
  5. // Module: tdriver.c
  6. // Author: Silviu Calinoiu (SilviuC)
  7. // Created: 4/20/1999 2:39pm
  8. //
  9. // This module contains a template driver.
  10. //
  11. // --- History ---
  12. //
  13. // 4/20/1999 (SilviuC): initial version.
  14. //
  15. // 10/25/1999 (DMihai): Aded tests for:
  16. // - paged pool size
  17. // - non paged pool size
  18. // - number of free system PTEs
  19. //
  20. #include <ntddk.h>
  21. #include "active.h"
  22. #include "mmtests.h"
  23. #include "physmem.h"
  24. #include "tdriver.h"
  25. #if !MMTESTS_ACTIVE
  26. //
  27. // Dummy implementation if the module is inactive
  28. //
  29. VOID MmTestDisabled (VOID)
  30. {
  31. DbgPrint ("Buggy: mmtests module is disabled (check \\driver\\active.h header) \n");
  32. }
  33. VOID MmTestProbeLockForEverStress (
  34. IN PVOID NotUsed
  35. )
  36. {
  37. MmTestDisabled ();
  38. }
  39. VOID MmTestNameToAddressStress (
  40. IN PVOID IrpAddress
  41. )
  42. {
  43. MmTestDisabled ();
  44. }
  45. VOID MmTestEccBadStress (
  46. IN PVOID IrpAddress
  47. )
  48. {
  49. MmTestDisabled ();
  50. }
  51. VOID
  52. TdSysPagedPoolMaxTest(
  53. IN PVOID IrpAddress
  54. )
  55. {
  56. MmTestDisabled ();
  57. }
  58. VOID
  59. TdSysPagedPoolTotalTest(
  60. IN PVOID IrpAddress
  61. )
  62. {
  63. MmTestDisabled ();
  64. }
  65. VOID
  66. TdNonPagedPoolMaxTest(
  67. IN PVOID IrpAddress
  68. )
  69. {
  70. MmTestDisabled ();
  71. }
  72. VOID
  73. TdNonPagedPoolTotalTest(
  74. IN PVOID IrpAddress
  75. )
  76. {
  77. MmTestDisabled ();
  78. }
  79. VOID
  80. TdFreeSystemPtesTest(
  81. IN PVOID IrpAddress
  82. )
  83. {
  84. MmTestDisabled ();
  85. }
  86. VOID
  87. StressPoolFlag (
  88. PVOID NotUsed
  89. )
  90. {
  91. MmTestDisabled ();
  92. }
  93. VOID
  94. StressPoolTagTableExtension (
  95. PVOID NotUsed
  96. )
  97. {
  98. MmTestDisabled ();
  99. }
  100. #else
  101. //
  102. // Real implementation if the module is active
  103. //
  104. ULONG BuggyPP = (96 * 1024 * 1024);
  105. PVOID BuggyOld;
  106. SIZE_T UserVaSize = (50 * 1024 * 1024);
  107. ULONG BuggyHold = 1;
  108. ULONG OverrideStart;
  109. ULONG OverrideSize;
  110. ULONG OverrideCount;
  111. #define VERBOSITY_PRINT 0x0001
  112. #define VERBOSITY_BREAK 0x0002
  113. ULONG Verbosity = 0x0003;
  114. NTSYSCALLAPI
  115. NTSTATUS
  116. NTAPI
  117. ZwAllocateVirtualMemory(
  118. IN HANDLE ProcessHandle,
  119. IN OUT PVOID *BaseAddress,
  120. IN ULONG_PTR ZeroBits,
  121. IN OUT PSIZE_T RegionSize,
  122. IN ULONG AllocationType,
  123. IN ULONG Protect
  124. );
  125. NTSTATUS
  126. MmMarkPhysicalMemoryAsBad (
  127. IN PPHYSICAL_ADDRESS StartAddress,
  128. IN OUT PLARGE_INTEGER NumberOfBytes
  129. );
  130. NTSTATUS
  131. MmMarkPhysicalMemoryAsGood (
  132. IN PPHYSICAL_ADDRESS StartAddress,
  133. IN OUT PLARGE_INTEGER NumberOfBytes
  134. );
  135. VOID MmTestProbeLockForEverStress (
  136. IN PVOID IrpAddress
  137. )
  138. {
  139. PIRP Irp = (PIRP) IrpAddress;
  140. PIO_STACK_LOCATION IrpStack;
  141. ULONG InputBufferLength;
  142. ULONG OutputBufferLength;
  143. ULONG Ioctl;
  144. NTSTATUS Status;
  145. ULONG BufferSize;
  146. ULONG ReturnedSize;
  147. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  148. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  149. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  150. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  151. {
  152. SIZE_T RegionSize;
  153. PVOID UserVa;
  154. PMDL Mdl;
  155. UserVa = NULL;
  156. RegionSize = UserVaSize;
  157. Status = ZwAllocateVirtualMemory (NtCurrentProcess(),
  158. (PVOID *)&UserVa,
  159. 0,
  160. &RegionSize,
  161. MEM_COMMIT,
  162. PAGE_READWRITE);
  163. if (NT_SUCCESS(Status)) {
  164. Mdl = IoAllocateMdl (
  165. UserVa,
  166. (ULONG)RegionSize,
  167. FALSE, // not secondary buffer
  168. FALSE, // do not charge quota
  169. NULL); // no irp
  170. if (Mdl != NULL) {
  171. try {
  172. MmProbeAndLockPages (Mdl,
  173. KernelMode,
  174. IoReadAccess);
  175. DbgPrint ("Buggy: locked pages in MDL %p\n", Mdl);
  176. DbgBreakPoint ();
  177. //
  178. // Don't exit now without unlocking !
  179. //
  180. while (BuggyHold != 0) {
  181. KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
  182. }
  183. MmUnlockPages (Mdl);
  184. IoFreeMdl (Mdl);
  185. }
  186. except (EXCEPTION_EXECUTE_HANDLER) {
  187. DbgPrint ("Buggy: exception raised while locking %p\n", Mdl);
  188. DbgBreakPoint ();
  189. }
  190. }
  191. }
  192. }
  193. DbgPrint ("Buggy: finish with probe-and-lock forever ioctl \n");
  194. Status = STATUS_SUCCESS;
  195. }
  196. VOID MmTestNameToAddressStress (
  197. IN PVOID IrpAddress
  198. )
  199. {
  200. PIRP Irp = (PIRP) IrpAddress;
  201. PIO_STACK_LOCATION IrpStack;
  202. ULONG InputBufferLength;
  203. ULONG OutputBufferLength;
  204. ULONG Ioctl;
  205. NTSTATUS Status;
  206. ULONG BufferSize;
  207. ULONG ReturnedSize;
  208. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  209. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  210. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  211. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  212. {
  213. #define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
  214. const UNICODE_STRING RoutineA = CONSTANT_UNICODE_STRING( L"KfRaiseIrql" );
  215. const UNICODE_STRING RoutineList[] = {
  216. CONSTANT_UNICODE_STRING( L"KeBugCheckEx" ),
  217. CONSTANT_UNICODE_STRING( L"KiBugCheckData" ),
  218. CONSTANT_UNICODE_STRING( L"KeWaitForSingleObject" ),
  219. CONSTANT_UNICODE_STRING( L"KeWaitForMutexObject" ),
  220. CONSTANT_UNICODE_STRING( L"Junk1" ),
  221. CONSTANT_UNICODE_STRING( L"CcCanIWrite" ),
  222. CONSTANT_UNICODE_STRING( L"Junk" ),
  223. };
  224. PVOID Addr;
  225. ULONG i;
  226. Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineA);
  227. DbgPrint ("Addr is %p\n", Addr);
  228. for (i = 0; i < sizeof (RoutineList) / sizeof (UNICODE_STRING); i += 1) {
  229. Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineList[i]);
  230. DbgPrint ("Addr0 is %p\n", Addr);
  231. }
  232. }
  233. }
  234. VOID MmTestEccBadStress (
  235. IN PVOID IrpAddress
  236. )
  237. {
  238. PIRP Irp = (PIRP) IrpAddress;
  239. PIO_STACK_LOCATION IrpStack;
  240. ULONG InputBufferLength;
  241. ULONG OutputBufferLength;
  242. ULONG Ioctl;
  243. NTSTATUS Status;
  244. ULONG BufferSize;
  245. ULONG ReturnedSize;
  246. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  247. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  248. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  249. Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  250. DbgPrint ("Buggy: mark physical memory ECC bad ioctl \n");
  251. {
  252. ULONG i;
  253. PPHYSICAL_MEMORY_RANGE Ranges;
  254. PPHYSICAL_MEMORY_RANGE p;
  255. PHYSICAL_ADDRESS StartAddress;
  256. LARGE_INTEGER NumberOfBytes;
  257. PHYSICAL_ADDRESS InputAddress;
  258. LARGE_INTEGER InputBytes;
  259. Ranges = MmGetPhysicalMemoryRanges ();
  260. if (Ranges == NULL) {
  261. DbgPrint ("Buggy: MmRemovePhysicalMemory cannot get ranges\n");
  262. Status = STATUS_INSUFFICIENT_RESOURCES;
  263. return;
  264. }
  265. i = 0;
  266. DbgPrint("StartAddress @ %p, OverrideSize @ %p, OverrideCount @ %p\n", &OverrideStart, &OverrideSize, &OverrideCount);
  267. DbgBreakPoint();
  268. p = Ranges;
  269. while (p->BaseAddress.QuadPart != 0 && p->NumberOfBytes.QuadPart != 0) {
  270. StartAddress.QuadPart = p->BaseAddress.QuadPart;
  271. NumberOfBytes.QuadPart = p->NumberOfBytes.QuadPart;
  272. if (OverrideStart != 0) {
  273. StartAddress.LowPart = OverrideStart;
  274. }
  275. InputAddress.QuadPart = StartAddress.QuadPart;
  276. InputBytes.QuadPart = NumberOfBytes.QuadPart;
  277. #ifdef BIG_REMOVES
  278. if (InputBytes.QuadPart > (64 * 1024)) {
  279. InputBytes.QuadPart = (64 * 1024);
  280. }
  281. #else
  282. if (InputBytes.QuadPart > (4 * 1024)) {
  283. InputBytes.QuadPart = (4 * 1024);
  284. }
  285. #endif
  286. if (OverrideSize != 0) {
  287. InputBytes.LowPart = OverrideSize;
  288. }
  289. while (InputAddress.QuadPart + InputBytes.QuadPart <=
  290. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  291. if (OverrideCount != 0 && i > OverrideCount) {
  292. break;
  293. }
  294. i += 1;
  295. DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x\n",
  296. InputAddress.HighPart,
  297. InputAddress.LowPart,
  298. InputBytes.HighPart,
  299. InputBytes.LowPart);
  300. Status = MmMarkPhysicalMemoryAsBad (&InputAddress,
  301. &InputBytes);
  302. DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x %x\n\n",
  303. Status,
  304. InputAddress.HighPart,
  305. InputAddress.LowPart,
  306. InputBytes.HighPart,
  307. InputBytes.LowPart);
  308. KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
  309. if (NT_SUCCESS(Status)) {
  310. DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood %x %x %x %x\n",
  311. InputAddress.HighPart,
  312. InputAddress.LowPart,
  313. InputBytes.HighPart,
  314. InputBytes.LowPart);
  315. Status = MmMarkPhysicalMemoryAsGood (&InputAddress,
  316. &InputBytes);
  317. if (NT_SUCCESS(Status)) {
  318. DbgPrint ("\n\n***************\nbuggy: MmMarkPhysicalMemoryAsGood WORKED %x %x %x %x %x\n****************\n",
  319. Status,
  320. InputAddress.HighPart,
  321. InputAddress.LowPart,
  322. InputBytes.HighPart,
  323. InputBytes.LowPart);
  324. }
  325. else {
  326. DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood FAILED %x %x %x %x %x\n\n",
  327. Status,
  328. InputAddress.HighPart,
  329. InputAddress.LowPart,
  330. InputBytes.HighPart,
  331. InputBytes.LowPart);
  332. DbgBreakPoint ();
  333. }
  334. }
  335. if (InputAddress.QuadPart + InputBytes.QuadPart ==
  336. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  337. break;
  338. }
  339. InputAddress.QuadPart += InputBytes.QuadPart;
  340. if (InputAddress.QuadPart + InputBytes.QuadPart >
  341. StartAddress.QuadPart + NumberOfBytes.QuadPart) {
  342. InputBytes.QuadPart = StartAddress.QuadPart + NumberOfBytes.QuadPart - InputAddress.QuadPart;
  343. }
  344. }
  345. if (OverrideCount != 0 && i > OverrideCount) {
  346. break;
  347. }
  348. p += 1;
  349. }
  350. ExFreePool (Ranges);
  351. DbgPrint ("Buggy: MmMarkPhysicalMemory Ecc BAD test finished\n");
  352. }
  353. }
  354. ////////////////////////////////////////////////////////////////////////////
  355. typedef struct
  356. {
  357. LIST_ENTRY List;
  358. PVOID ChunkPointers[ ( 63 * 1024 ) / sizeof( PVOID ) ];
  359. } ALLOCATION_TABLE, *PALLOCATION_TABLE;
  360. LIST_ENTRY PagedPoolAllocationListHead;
  361. LIST_ENTRY NonPagedPoolAllocationListHead;
  362. LIST_ENTRY SessionPoolAllocationListHead;
  363. const SIZE_T PoolChunkSize = 64 * 1024 - 32;
  364. //
  365. //
  366. //
  367. VOID
  368. TdpWriteSignature(
  369. PVOID Allocation,
  370. SIZE_T CurrentSize
  371. )
  372. {
  373. PSIZE_T CrtSignature;
  374. SIZE_T CrtSignatureValue;
  375. CrtSignature = (PSIZE_T)Allocation;
  376. CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
  377. if( CurrentSize > 100 * 1024 * 1024 )
  378. {
  379. DbgPrint( "Buggy: Writing signature %p from address %p, size %p\n",
  380. CrtSignatureValue,
  381. CrtSignature,
  382. CurrentSize );
  383. }
  384. while( 100 * PAGE_SIZE <= CurrentSize )
  385. {
  386. *CrtSignature = CrtSignatureValue;
  387. CrtSignatureValue +=1;
  388. CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + 100 * PAGE_SIZE );
  389. CurrentSize -= 100 * PAGE_SIZE;
  390. }
  391. }
  392. //
  393. //
  394. //
  395. VOID
  396. TdpVerifySignature(
  397. PVOID Allocation,
  398. SIZE_T CurrentSize )
  399. {
  400. PSIZE_T CrtSignature;
  401. SIZE_T CrtSignatureValue;
  402. CrtSignature = (PSIZE_T)Allocation;
  403. CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
  404. if( CurrentSize > 100 * 1024 * 1024 )
  405. {
  406. DbgPrint( "Buggy: Verifying signature %p from address %p, size %p\n",
  407. CrtSignatureValue,
  408. CrtSignature,
  409. CurrentSize );
  410. }
  411. while( 100 * PAGE_SIZE <= CurrentSize )
  412. {
  413. if( *CrtSignature != CrtSignatureValue )
  414. {
  415. DbgPrint ("Buggy: Signature at %p is incorrect, expected %p, base allocation %p\n",
  416. CrtSignature,
  417. CrtSignatureValue,
  418. Allocation );
  419. DbgBreakPoint ();
  420. }
  421. CrtSignatureValue +=1;
  422. CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + 100 * PAGE_SIZE );
  423. CurrentSize -= 100 * PAGE_SIZE;
  424. }
  425. }
  426. //
  427. //
  428. //
  429. VOID
  430. TdpCleanupPoolAllocationTable(
  431. PLIST_ENTRY ListHead,
  432. SIZE_T Allocations
  433. )
  434. {
  435. PLIST_ENTRY NextEntry;
  436. PALLOCATION_TABLE AllocationTable;
  437. SIZE_T ChunksPerAllocationEntry;
  438. SIZE_T CrtChunksIndex;
  439. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationTable->ChunkPointers );
  440. NextEntry = ListHead->Flink;
  441. while( NextEntry != ListHead )
  442. {
  443. RemoveEntryList( NextEntry );
  444. AllocationTable = CONTAINING_RECORD( NextEntry, ALLOCATION_TABLE, List );
  445. DbgPrint( "Buggy: Current allocation table = %p\n",
  446. AllocationTable );
  447. for( CrtChunksIndex = 0; CrtChunksIndex < ChunksPerAllocationEntry; CrtChunksIndex++ )
  448. {
  449. if( 0 == Allocations )
  450. {
  451. //
  452. // Freed them all
  453. //
  454. break;
  455. }
  456. else
  457. {
  458. Allocations -= 1;
  459. if( 0 == Allocations % 0x100 )
  460. {
  461. //
  462. // Let the user know that we are still working on something
  463. //
  464. DbgPrint( "Buggy: cleaning up allocation index %p\n",
  465. Allocations );
  466. }
  467. /*
  468. DbgPrint( "Buggy: Verify and free chunk index %p (from the end) at address %p\n",
  469. Allocations,
  470. AllocationTable->ChunkPointers[ CrtChunksIndex ] );
  471. */
  472. TdpVerifySignature(
  473. AllocationTable->ChunkPointers[ CrtChunksIndex ],
  474. PoolChunkSize );
  475. ExFreePoolWithTag(
  476. AllocationTable->ChunkPointers[ CrtChunksIndex ],
  477. TD_POOL_TAG );
  478. }
  479. }
  480. //
  481. // Free the table as well
  482. //
  483. ExFreePoolWithTag(
  484. AllocationTable,
  485. TD_POOL_TAG );
  486. //
  487. // Go to the next allocations table
  488. //
  489. NextEntry = ListHead->Flink;
  490. }
  491. //
  492. // At this point, Allocations should be zero and the
  493. // list should be empty
  494. //
  495. if( 0 != Allocations )
  496. {
  497. DbgPrint ("Buggy: Emptied the allocation table list but still have %p allocations - this is a bug\n",
  498. Allocations );
  499. DbgBreakPoint();
  500. }
  501. if( ! IsListEmpty( ListHead ) )
  502. {
  503. DbgPrint ("Buggy: No allocations left but the list at %p is not empty yet - this is a bug\n",
  504. ListHead );
  505. DbgBreakPoint();
  506. }
  507. }
  508. //
  509. // Delay execution for a few seconds so we can get a chance to use
  510. // !poolused, poolmon.exe, etc.
  511. //
  512. VOID
  513. TdpSleep( ULONG Seconds )
  514. {
  515. LARGE_INTEGER Interval = {(ULONG)(-1000 * 1000 * 10), -1}; // One second.
  516. DbgPrint( "Buggy: Sleeping for %u seconds\n",
  517. Seconds );
  518. Interval.QuadPart *= Seconds;
  519. KeDelayExecutionThread( KernelMode,
  520. FALSE,
  521. &Interval );
  522. }
  523. //
  524. // Determine the maximum size of a block of paged pool currently available
  525. //
  526. VOID
  527. TdSysPagedPoolMaxTest(
  528. IN PVOID IrpAddress
  529. )
  530. {
  531. SIZE_T CurrentSize;
  532. SIZE_T SizeIncrement;
  533. ULONG Increment;
  534. PVOID Allocation;
  535. #ifdef _WIN64
  536. CurrentSize = 0xFFFFFFFF00000000;
  537. #else
  538. CurrentSize = 0xFFFFFFFF;
  539. #endif //#ifdef _WIN64
  540. do
  541. {
  542. DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n",
  543. CurrentSize );
  544. Allocation = ExAllocatePoolWithTag(
  545. PagedPool,
  546. CurrentSize,
  547. TD_POOL_TAG );
  548. if( NULL != Allocation )
  549. {
  550. DbgPrint ("Buggy: allocated %p bytes paged pool at %p\n",
  551. CurrentSize,
  552. Allocation);
  553. TdpWriteSignature(
  554. Allocation,
  555. CurrentSize );
  556. TdpVerifySignature(
  557. Allocation,
  558. CurrentSize );
  559. ExFreePoolWithTag(
  560. Allocation,
  561. TD_POOL_TAG );
  562. }
  563. else
  564. {
  565. CurrentSize /= 2;
  566. }
  567. }
  568. while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
  569. if( NULL != Allocation )
  570. {
  571. //
  572. // Try to find an even bigger size in 10% increments
  573. //
  574. SizeIncrement = CurrentSize / 10;
  575. if( PAGE_SIZE <= SizeIncrement )
  576. {
  577. for( Increment = 0; Increment < 10; Increment += 1 )
  578. {
  579. CurrentSize += SizeIncrement;
  580. DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n",
  581. CurrentSize );
  582. Allocation = ExAllocatePoolWithTag(
  583. PagedPool,
  584. CurrentSize,
  585. TD_POOL_TAG );
  586. if( NULL != Allocation )
  587. {
  588. DbgPrint ("Buggy: Better result of the test: allocated %p bytes paged pool at %p\n",
  589. CurrentSize,
  590. Allocation);
  591. TdpSleep( 15 );
  592. TdpWriteSignature(
  593. Allocation,
  594. CurrentSize );
  595. TdpVerifySignature(
  596. Allocation,
  597. CurrentSize );
  598. ExFreePoolWithTag(
  599. Allocation,
  600. TD_POOL_TAG );
  601. }
  602. else
  603. {
  604. DbgPrint ("Buggy: could not allocate %p bytes paged pool - done\n",
  605. CurrentSize );
  606. break;
  607. }
  608. }
  609. }
  610. }
  611. }
  612. //
  613. // Determine the total size of the paged pool currently available (64 Kb - 32 bytes blocks)
  614. //
  615. VOID
  616. TdSysPagedPoolTotalTest(
  617. IN PVOID IrpAddress
  618. )
  619. {
  620. SIZE_T CurrentChunkIndex;
  621. SIZE_T ChunksPerAllocationEntry;
  622. SIZE_T TotalBytes;
  623. PALLOCATION_TABLE AllocationListEntry;
  624. PVOID Allocation;
  625. //
  626. // No allocations yet
  627. //
  628. InitializeListHead(
  629. &PagedPoolAllocationListHead );
  630. //
  631. // We want to allocate 64 k chunks but leave space for the pool block header
  632. //
  633. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
  634. CurrentChunkIndex = 0;
  635. do
  636. {
  637. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  638. {
  639. //
  640. // Need a new allocation entry structure
  641. //
  642. AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag(
  643. PagedPool,
  644. sizeof( ALLOCATION_TABLE ),
  645. TD_POOL_TAG );
  646. if( NULL == AllocationListEntry )
  647. {
  648. DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" );
  649. break;
  650. }
  651. RtlZeroMemory(
  652. AllocationListEntry,
  653. sizeof( ALLOCATION_TABLE ) );
  654. DbgPrint( "Buggy: New allocation table = %p\n",
  655. AllocationListEntry );
  656. }
  657. //
  658. // Try to allocate a new chunk
  659. //
  660. Allocation = ExAllocatePoolWithTag(
  661. PagedPool,
  662. PoolChunkSize,
  663. TD_POOL_TAG );
  664. if( NULL == Allocation )
  665. {
  666. DbgPrint ("Buggy: could not allocate paged pool chunk index %p - done\n",
  667. CurrentChunkIndex );
  668. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  669. {
  670. //
  671. // We are using a new list entry - free it now because
  672. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  673. //
  674. ExFreePoolWithTag(
  675. AllocationListEntry,
  676. TD_POOL_TAG );
  677. }
  678. }
  679. else
  680. {
  681. if( 0 == CurrentChunkIndex % 0x100 )
  682. {
  683. //
  684. // Let the user know that we are still working on something
  685. //
  686. DbgPrint( "Buggy: Allocated pool chunk index = %p\n",
  687. CurrentChunkIndex );
  688. }
  689. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  690. {
  691. //
  692. // We are using a new list entry - add it to our list only now because
  693. // we don't want to have empty tables in the list so we didn't insert it yet
  694. //
  695. InsertTailList(
  696. &PagedPoolAllocationListHead,
  697. &AllocationListEntry->List );
  698. }
  699. AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
  700. TdpWriteSignature(
  701. Allocation,
  702. PoolChunkSize );
  703. /*
  704. DbgPrint( "Buggy: Written signature to chunk index %p at address %p\n",
  705. CurrentChunkIndex,
  706. Allocation );
  707. */
  708. CurrentChunkIndex += 1;
  709. }
  710. }
  711. while( NULL != Allocation );
  712. TotalBytes = CurrentChunkIndex * 64 * 1024;
  713. DbgPrint ("Buggy: Result of the test: approx. %p total bytes of paged pool allocated\n",
  714. TotalBytes );
  715. //
  716. // Clean-up what we have allocated
  717. //
  718. TdpCleanupPoolAllocationTable(
  719. &PagedPoolAllocationListHead,
  720. CurrentChunkIndex );
  721. }
  722. VOID
  723. TdNonPagedPoolMaxTest(
  724. IN PVOID IrpAddress
  725. )
  726. {
  727. SIZE_T CurrentSize;
  728. SIZE_T SizeIncrement;
  729. ULONG Increment;
  730. PVOID Allocation;
  731. #ifdef _WIN64
  732. CurrentSize = 0xFFFFFFFF00000000;
  733. #else
  734. CurrentSize = 0xFFFFFFFF;
  735. #endif //#ifdef _WIN64
  736. do
  737. {
  738. DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n",
  739. CurrentSize );
  740. Allocation = ExAllocatePoolWithTag(
  741. NonPagedPool,
  742. CurrentSize,
  743. TD_POOL_TAG );
  744. if( NULL != Allocation )
  745. {
  746. DbgPrint ("Buggy: allocated %p bytes non-paged pool at %p\n",
  747. CurrentSize,
  748. Allocation);
  749. TdpWriteSignature(
  750. Allocation,
  751. CurrentSize );
  752. ExFreePoolWithTag(
  753. Allocation,
  754. TD_POOL_TAG );
  755. }
  756. else
  757. {
  758. CurrentSize /= 2;
  759. }
  760. }
  761. while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
  762. if( NULL != Allocation )
  763. {
  764. //
  765. // Try to find an even bigger size in 10% increments
  766. //
  767. SizeIncrement = CurrentSize / 10;
  768. if( PAGE_SIZE <= SizeIncrement )
  769. {
  770. for( Increment = 0; Increment < 10; Increment += 1 )
  771. {
  772. CurrentSize += SizeIncrement;
  773. DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n",
  774. CurrentSize );
  775. Allocation = ExAllocatePoolWithTag(
  776. NonPagedPool,
  777. CurrentSize,
  778. TD_POOL_TAG );
  779. if( NULL != Allocation )
  780. {
  781. DbgPrint ("Buggy: Better result of the test: allocated %p bytes non-paged pool at %p\n",
  782. CurrentSize,
  783. Allocation);
  784. TdpSleep( 15 );
  785. TdpWriteSignature(
  786. Allocation,
  787. CurrentSize );
  788. TdpVerifySignature(
  789. Allocation,
  790. CurrentSize );
  791. ExFreePoolWithTag(
  792. Allocation,
  793. TD_POOL_TAG );
  794. }
  795. else
  796. {
  797. DbgPrint ("Buggy: could not allocate %p bytes non-paged pool - done\n",
  798. CurrentSize );
  799. break;
  800. }
  801. }
  802. }
  803. }
  804. }
  805. //
  806. // Determine the total size of the non-paged pool currently available (64 Kb - 32 bytes blocks)
  807. //
  808. VOID
  809. TdNonPagedPoolTotalTest(
  810. IN PVOID IrpAddress
  811. )
  812. {
  813. SIZE_T CurrentChunkIndex;
  814. SIZE_T ChunksPerAllocationEntry;
  815. SIZE_T TotalBytes;
  816. PALLOCATION_TABLE AllocationListEntry;
  817. PVOID Allocation;
  818. //
  819. // No allocations yet
  820. //
  821. InitializeListHead(
  822. &NonPagedPoolAllocationListHead );
  823. //
  824. // We want to allocate 64 k chunks but leave space for the pool block header
  825. //
  826. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
  827. CurrentChunkIndex = 0;
  828. do
  829. {
  830. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  831. {
  832. //
  833. // Need a new allocation entry structure
  834. //
  835. AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag(
  836. PagedPool,
  837. sizeof( ALLOCATION_TABLE ),
  838. TD_POOL_TAG );
  839. if( NULL == AllocationListEntry )
  840. {
  841. DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" );
  842. break;
  843. }
  844. }
  845. //
  846. // Try to allocate a new chunk
  847. //
  848. Allocation = ExAllocatePoolWithTag(
  849. NonPagedPool,
  850. PoolChunkSize,
  851. TD_POOL_TAG );
  852. if( NULL == Allocation )
  853. {
  854. DbgPrint ("Buggy: could not allocate non-paged pool chunk index %p - done\n",
  855. CurrentChunkIndex );
  856. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  857. {
  858. //
  859. // We are using a new list entry - free it now because
  860. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  861. //
  862. ExFreePoolWithTag(
  863. AllocationListEntry,
  864. TD_POOL_TAG );
  865. }
  866. }
  867. else
  868. {
  869. if( 0 == CurrentChunkIndex % 0x100 )
  870. {
  871. //
  872. // Let the user know that we are still working on something
  873. //
  874. DbgPrint( "Buggy: Allocated pool chunk index = %p\n",
  875. CurrentChunkIndex );
  876. }
  877. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  878. {
  879. //
  880. // We are using a new list entry - add it to our list only now because
  881. // we don't want to have empty tables in the list so we didn't insert it yet
  882. //
  883. InsertTailList(
  884. &NonPagedPoolAllocationListHead,
  885. &AllocationListEntry->List );
  886. }
  887. AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
  888. TdpWriteSignature(
  889. Allocation,
  890. PoolChunkSize );
  891. CurrentChunkIndex += 1;
  892. }
  893. }
  894. while( NULL != Allocation );
  895. TotalBytes = CurrentChunkIndex * 64 * 1024;
  896. DbgPrint ("Buggy: Result of the test: approx. %p total bytes of non-paged pool allocated\n",
  897. TotalBytes );
  898. //
  899. // Clean-up what we have allocated
  900. //
  901. TdpCleanupPoolAllocationTable(
  902. &NonPagedPoolAllocationListHead,
  903. CurrentChunkIndex );
  904. }
  905. /////////////////////////////////////////////////////////////////////////////////////
  906. typedef struct
  907. {
  908. LIST_ENTRY List;
  909. PMDL Mappings[ ( 63 * 1024 ) / sizeof( PMDL ) ];
  910. } MAPPING_TABLE_ENTRY, *PMAPPING_TABLE_ENTRY;
  911. LIST_ENTRY IoMappingsListHead;
  912. ULONG BytesPerIoMapping = 1024 * 1024;
  913. //
  914. //
  915. //
  916. VOID
  917. TdpCleanupMappingsAllocationTable(
  918. PLIST_ENTRY ListHead,
  919. SIZE_T Mappings
  920. )
  921. {
  922. PLIST_ENTRY NextEntry;
  923. PMAPPING_TABLE_ENTRY MappingTableEntry;
  924. SIZE_T MappingsPerMappingTableEntry;
  925. SIZE_T CrtMappingIndex;
  926. MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
  927. NextEntry = ListHead->Flink;
  928. while( NextEntry != ListHead )
  929. {
  930. RemoveEntryList( NextEntry );
  931. MappingTableEntry = CONTAINING_RECORD( NextEntry, MAPPING_TABLE_ENTRY, List );
  932. for( CrtMappingIndex = 0; CrtMappingIndex < MappingsPerMappingTableEntry; CrtMappingIndex++ )
  933. {
  934. if( 0 == Mappings )
  935. {
  936. //
  937. // Freed them all
  938. //
  939. break;
  940. }
  941. else
  942. {
  943. Mappings -= 1;
  944. if( 0 == Mappings % 0x100 )
  945. {
  946. //
  947. // Let the user know that we are still working on something
  948. //
  949. DbgPrint( "Buggy: cleaning up mapping index %p\n",
  950. Mappings );
  951. }
  952. //
  953. // Unmap
  954. //
  955. MmUnmapIoSpace(
  956. MappingTableEntry->Mappings[ CrtMappingIndex ],
  957. BytesPerIoMapping );
  958. }
  959. }
  960. //
  961. // Free the table as well
  962. //
  963. ExFreePoolWithTag(
  964. MappingTableEntry,
  965. TD_POOL_TAG );
  966. //
  967. // Go to the next allocations table
  968. //
  969. NextEntry = ListHead->Flink;
  970. }
  971. //
  972. // At this point, Mappings should be zero and the
  973. // list should be empty
  974. //
  975. if( 0 != Mappings )
  976. {
  977. DbgPrint ("Buggy: Emptied the mappings table list but still have %p allocations - this is a bug\n",
  978. Mappings );
  979. DbgBreakPoint();
  980. }
  981. if( ! IsListEmpty( ListHead ) )
  982. {
  983. DbgPrint ("Buggy: No mappings left but the list at %p is not empty yet - this is a bug\n",
  984. ListHead );
  985. DbgBreakPoint();
  986. }
  987. }
  988. //
  989. // Determine the total amount of memory that can be mapped using system PTEs (1 Mb chunks)
  990. //
  991. VOID
  992. TdFreeSystemPtesTest(
  993. IN PVOID IrpAddress
  994. )
  995. {
  996. ULONG MemType;
  997. PHYSICAL_ADDRESS PortAddress;
  998. PHYSICAL_ADDRESS MyPhysicalAddress;
  999. SIZE_T CurrentMappingIndex;
  1000. SIZE_T MappingsPerMappingTableEntry;
  1001. SIZE_T TotalBytes;
  1002. PVOID NewMapping;
  1003. PMAPPING_TABLE_ENTRY MappingTableEntry;
  1004. PMDL NewMdl;
  1005. NTSTATUS Status;
  1006. //
  1007. // Use some joystick port address
  1008. //
  1009. MemType = 1; // IO space
  1010. PortAddress.LowPart = 0x200;
  1011. PortAddress.HighPart = 0;
  1012. HalTranslateBusAddress(
  1013. Isa,
  1014. 0,
  1015. PortAddress,
  1016. &MemType,
  1017. &MyPhysicalAddress);
  1018. //
  1019. // No Mappings allocated yet
  1020. //
  1021. InitializeListHead(
  1022. &IoMappingsListHead );
  1023. //
  1024. // Map a ~64 Kb chunk over and over again to consume system PTEs
  1025. //
  1026. MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
  1027. CurrentMappingIndex = 0;
  1028. do
  1029. {
  1030. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  1031. {
  1032. //
  1033. // Need a new allocation entry structure
  1034. //
  1035. MappingTableEntry = (PMAPPING_TABLE_ENTRY) ExAllocatePoolWithTag(
  1036. PagedPool,
  1037. sizeof( MAPPING_TABLE_ENTRY ),
  1038. TD_POOL_TAG );
  1039. if( NULL == MappingTableEntry )
  1040. {
  1041. DbgPrint ("Buggy: could not allocate new MAPPING_TABLE_ENTRY - aborting test here\n" );
  1042. break;
  1043. }
  1044. }
  1045. NewMapping = MmMapIoSpace(
  1046. MyPhysicalAddress,
  1047. BytesPerIoMapping,
  1048. MmNonCached );
  1049. if( NULL == NewMapping )
  1050. {
  1051. DbgPrint ("Buggy: could not create mapping index %p\n",
  1052. CurrentMappingIndex );
  1053. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  1054. {
  1055. //
  1056. // We are using a new list entry - free it now because
  1057. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  1058. //
  1059. ExFreePoolWithTag(
  1060. MappingTableEntry,
  1061. TD_POOL_TAG );
  1062. }
  1063. }
  1064. else
  1065. {
  1066. //DbgPrint ("Buggy: created Mapping index %p at address %p\n",
  1067. // CurrentMappingIndex,
  1068. // NewMapping );
  1069. if( 0 == CurrentMappingIndex % 0x100 )
  1070. {
  1071. //
  1072. // Let the user know that we are still working on something
  1073. //
  1074. DbgPrint( "Buggy: mapped chunk index = %p\n",
  1075. CurrentMappingIndex );
  1076. }
  1077. if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry )
  1078. {
  1079. //
  1080. // We are using a new list entry - add it to our list only now because
  1081. // we don't want to have empty tables in the list so we didn't insert it yet
  1082. //
  1083. InsertTailList(
  1084. &IoMappingsListHead,
  1085. &MappingTableEntry->List );
  1086. }
  1087. MappingTableEntry->Mappings[ CurrentMappingIndex % MappingsPerMappingTableEntry ] = NewMapping;
  1088. CurrentMappingIndex += 1;
  1089. }
  1090. }
  1091. while( NULL != NewMapping );
  1092. TotalBytes = CurrentMappingIndex * BytesPerIoMapping;
  1093. DbgPrint( "Buggy: Result of the test: %p total bytes mapped\n",
  1094. TotalBytes );
  1095. //
  1096. // Clean-up what we have allocated and locked
  1097. //
  1098. TdpCleanupMappingsAllocationTable(
  1099. &IoMappingsListHead,
  1100. CurrentMappingIndex );
  1101. }
  1102. //
  1103. // Function:
  1104. //
  1105. // GetTag
  1106. //
  1107. // Description:
  1108. //
  1109. // This function transforms an integer into a four letter
  1110. // string. This is useful for the pool tag dynamic table
  1111. // in order to populate it with many different tags.
  1112. //
  1113. ULONG
  1114. GetTag (
  1115. ULONG Index
  1116. )
  1117. {
  1118. UCHAR Value[4];
  1119. Value[0] = (UCHAR)(((Index & 0x000F) >> 0 )) + 'A';
  1120. Value[1] = (UCHAR)(((Index & 0x00F0) >> 4 )) + 'A';
  1121. Value[2] = (UCHAR)(((Index & 0x0F00) >> 8 )) + 'A';
  1122. Value[3] = (UCHAR)(((Index & 0xF000) >> 12)) + 'A';
  1123. return *((PULONG)Value);
  1124. }
  1125. VOID
  1126. StressPoolFlag (
  1127. PVOID NotUsed
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. This function iterates through all the pool types, pool flags
  1132. and pool sizes (1 .. 8 * PAGE_SIZE).
  1133. Arguments:
  1134. None.
  1135. Return Value:
  1136. None.
  1137. Environment:
  1138. Kernel mode.
  1139. --*/
  1140. {
  1141. POOL_TYPE PoolType;
  1142. SIZE_T NumberOfBytes;
  1143. EX_POOL_PRIORITY Priority;
  1144. PVOID Va;
  1145. ULONG i;
  1146. for (PoolType = NonPagedPool; PoolType < 0xff; PoolType += 1) {
  1147. for (Priority = LowPoolPriority; Priority < LowPoolPriority + 2; Priority += 1) {
  1148. for (i = 1; i < 8 * PAGE_SIZE; i += 1) {
  1149. NumberOfBytes = i;
  1150. if (PoolType & 0x40) {
  1151. break;
  1152. }
  1153. if ((NumberOfBytes > PAGE_SIZE) && (PoolType & 0x2)) {
  1154. break;
  1155. }
  1156. try {
  1157. Va = ExAllocatePoolWithTagPriority (
  1158. PoolType,
  1159. NumberOfBytes,
  1160. 'ZXCV',
  1161. Priority);
  1162. }
  1163. except (EXCEPTION_EXECUTE_HANDLER) {
  1164. if (Verbosity & VERBOSITY_PRINT) {
  1165. DbgPrint( "buggy: ExAllocatePool exceptioned %x %x %x\n",
  1166. PoolType, NumberOfBytes, Priority);
  1167. }
  1168. if (Verbosity & VERBOSITY_BREAK) {
  1169. DbgBreakPoint ();
  1170. }
  1171. Va = NULL;
  1172. }
  1173. if (Va) {
  1174. ExFreePool (Va);
  1175. }
  1176. else {
  1177. if (Verbosity & VERBOSITY_PRINT) {
  1178. DbgPrint( "buggy: ExAllocatePool failed %x %x %x\n",
  1179. PoolType, NumberOfBytes, Priority);
  1180. }
  1181. if (Verbosity & VERBOSITY_BREAK) {
  1182. DbgBreakPoint ();
  1183. }
  1184. }
  1185. }
  1186. }
  1187. }
  1188. DbgPrint ("Buggy: ExAllocatePoolFlag test finished\n");
  1189. }
  1190. VOID
  1191. StressPoolTagTableExtension (
  1192. PVOID NotUsed
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function stresses the pool tag table dynamic extension.
  1197. Arguments:
  1198. None.
  1199. Return Value:
  1200. None.
  1201. Environment:
  1202. Kernel mode.
  1203. --*/
  1204. {
  1205. PVOID * Blocks;
  1206. ULONG Index;
  1207. Blocks = ExAllocatePoolWithTag (
  1208. NonPagedPool,
  1209. 16384 * sizeof(PVOID),
  1210. 'tguB');
  1211. if (Blocks == NULL) {
  1212. DbgPrint ("Buggy: cannot allocate pool buffer\n");
  1213. }
  1214. else {
  1215. //
  1216. // Loop with 8 byte size.
  1217. //
  1218. for (Index = 0; Index < 10000; Index++) {
  1219. if (Index && Index % 100 == 0) {
  1220. DbgPrint ("Index(a): %u \n", Index);
  1221. }
  1222. Blocks[Index] = ExAllocatePoolWithTag (
  1223. NonPagedPool,
  1224. 8,
  1225. GetTag(Index));
  1226. }
  1227. for (Index = 0; Index < 10000; Index++) {
  1228. if (Index && Index % 100 == 0) {
  1229. DbgPrint ("Index(f): %u \n", Index);
  1230. }
  1231. if (Blocks[Index]) {
  1232. ExFreePool (Blocks[Index]);
  1233. }
  1234. }
  1235. //
  1236. // Loop with PAGE_SIZE byte size.
  1237. //
  1238. for (Index = 0; Index < 4000; Index++) {
  1239. if (Index && Index % 100 == 0) {
  1240. DbgPrint ("Index(A): %u \n", Index);
  1241. }
  1242. Blocks[Index] = ExAllocatePoolWithTag (
  1243. NonPagedPool,
  1244. PAGE_SIZE,
  1245. GetTag(Index + 16384));
  1246. }
  1247. for (Index = 0; Index < 4000; Index++) {
  1248. if (Index && Index % 100 == 0) {
  1249. DbgPrint ("Index(F): %u \n", Index);
  1250. }
  1251. if (Blocks[Index]) {
  1252. ExFreePool (Blocks[Index]);
  1253. }
  1254. }
  1255. //
  1256. // Free block info.
  1257. //
  1258. ExFreePool (Blocks);
  1259. }
  1260. }
  1261. //
  1262. // Determine the maximum size of a block of session pool currently available
  1263. //
  1264. VOID
  1265. TdSessionPoolMaxTest(
  1266. IN PVOID IrpAddress
  1267. )
  1268. {
  1269. SIZE_T CurrentSize;
  1270. SIZE_T SizeIncrement;
  1271. ULONG Increment;
  1272. PVOID Allocation;
  1273. #ifdef _WIN64
  1274. CurrentSize = 0xFFFFFFFF00000000;
  1275. #else
  1276. CurrentSize = 0xFFFFFFFF;
  1277. #endif //#ifdef _WIN64
  1278. do
  1279. {
  1280. DbgPrint ("Buggy: Trying to allocate %p bytes session pool\n",
  1281. CurrentSize );
  1282. Allocation = ExAllocatePoolWithTag(
  1283. PagedPool | SESSION_POOL_MASK,
  1284. CurrentSize,
  1285. TD_POOL_TAG );
  1286. if( NULL != Allocation )
  1287. {
  1288. DbgPrint ("Buggy: allocated %p bytes session pool at %p\n",
  1289. CurrentSize,
  1290. Allocation);
  1291. TdpWriteSignature(
  1292. Allocation,
  1293. CurrentSize );
  1294. ExFreePoolWithTag(
  1295. Allocation,
  1296. TD_POOL_TAG );
  1297. }
  1298. else
  1299. {
  1300. CurrentSize /= 2;
  1301. }
  1302. }
  1303. while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
  1304. if( NULL != Allocation )
  1305. {
  1306. //
  1307. // Try to find an even bigger size in 10% increments
  1308. //
  1309. SizeIncrement = CurrentSize / 10;
  1310. if( PAGE_SIZE <= SizeIncrement )
  1311. {
  1312. for( Increment = 0; Increment < 10; Increment += 1 )
  1313. {
  1314. CurrentSize += SizeIncrement;
  1315. DbgPrint ("Buggy: Trying to allocate %p bytes session pool\n",
  1316. CurrentSize );
  1317. Allocation = ExAllocatePoolWithTag(
  1318. PagedPool | SESSION_POOL_MASK,
  1319. CurrentSize,
  1320. TD_POOL_TAG );
  1321. if( NULL != Allocation )
  1322. {
  1323. DbgPrint ("Buggy: Better result of the test: allocated %p bytes sesssion pool at %p\n",
  1324. CurrentSize,
  1325. Allocation);
  1326. TdpSleep( 15 );
  1327. TdpWriteSignature(
  1328. Allocation,
  1329. CurrentSize );
  1330. TdpVerifySignature(
  1331. Allocation,
  1332. CurrentSize );
  1333. ExFreePoolWithTag(
  1334. Allocation,
  1335. TD_POOL_TAG );
  1336. }
  1337. else
  1338. {
  1339. DbgPrint ("Buggy: could not allocate %p bytes session pool - done\n",
  1340. CurrentSize );
  1341. break;
  1342. }
  1343. }
  1344. }
  1345. }
  1346. }
  1347. //
  1348. // Determine the total size of the session pool currently available (64 Kb - 32 bytes blocks)
  1349. //
  1350. VOID
  1351. TdSessionPoolTotalTest(
  1352. IN PVOID IrpAddress
  1353. )
  1354. {
  1355. SIZE_T CurrentChunkIndex;
  1356. SIZE_T ChunksPerAllocationEntry;
  1357. SIZE_T TotalBytes;
  1358. PALLOCATION_TABLE AllocationListEntry;
  1359. PVOID Allocation;
  1360. //
  1361. // No allocations yet
  1362. //
  1363. InitializeListHead(
  1364. &SessionPoolAllocationListHead );
  1365. //
  1366. // We want to allocate 64 k chunks but leave space for the pool block header
  1367. //
  1368. ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
  1369. CurrentChunkIndex = 0;
  1370. do
  1371. {
  1372. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  1373. {
  1374. //
  1375. // Need a new allocation entry structure
  1376. //
  1377. AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag(
  1378. PagedPool | SESSION_POOL_MASK,
  1379. sizeof( ALLOCATION_TABLE ),
  1380. TD_POOL_TAG );
  1381. if( NULL == AllocationListEntry )
  1382. {
  1383. DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" );
  1384. break;
  1385. }
  1386. RtlZeroMemory(
  1387. AllocationListEntry,
  1388. sizeof( ALLOCATION_TABLE ) );
  1389. DbgPrint( "Buggy: New allocation table = %p\n",
  1390. AllocationListEntry );
  1391. }
  1392. //
  1393. // Try to allocate a new chunk
  1394. //
  1395. Allocation = ExAllocatePoolWithTag(
  1396. PagedPool | SESSION_POOL_MASK,
  1397. PoolChunkSize,
  1398. TD_POOL_TAG );
  1399. if( NULL == Allocation )
  1400. {
  1401. DbgPrint ("Buggy: could not allocate session pool chunk index %p - done\n",
  1402. CurrentChunkIndex );
  1403. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  1404. {
  1405. //
  1406. // We are using a new list entry - free it now because
  1407. // we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
  1408. //
  1409. ExFreePoolWithTag(
  1410. AllocationListEntry,
  1411. TD_POOL_TAG );
  1412. }
  1413. }
  1414. else
  1415. {
  1416. if( 0 == CurrentChunkIndex % 0x100 )
  1417. {
  1418. //
  1419. // Let the user know that we are still working on something
  1420. //
  1421. DbgPrint( "Buggy: Allocated pool chunk index = %p\n",
  1422. CurrentChunkIndex );
  1423. }
  1424. if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry )
  1425. {
  1426. //
  1427. // We are using a new list entry - add it to our list only now because
  1428. // we don't want to have empty tables in the list so we didn't insert it yet
  1429. //
  1430. InsertTailList(
  1431. &SessionPoolAllocationListHead,
  1432. &AllocationListEntry->List );
  1433. }
  1434. AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
  1435. TdpWriteSignature(
  1436. Allocation,
  1437. PoolChunkSize );
  1438. /*
  1439. DbgPrint( "Buggy: Written signature to chunk index %p at address %p\n",
  1440. CurrentChunkIndex,
  1441. Allocation );
  1442. */
  1443. CurrentChunkIndex += 1;
  1444. }
  1445. }
  1446. while( NULL != Allocation );
  1447. TotalBytes = CurrentChunkIndex * 64 * 1024;
  1448. DbgPrint ("Buggy: Result of the test: approx. %p total bytes of session pool allocated\n",
  1449. TotalBytes );
  1450. //
  1451. // Clean-up what we have allocated
  1452. //
  1453. TdpCleanupPoolAllocationTable(
  1454. &SessionPoolAllocationListHead,
  1455. CurrentChunkIndex );
  1456. }
  1457. //
  1458. //
  1459. //
  1460. #define BUGGY_PAGE_DIRECTORY_BOUNDARY ((PVOID)0x40000000)
  1461. #define BUGGY_VAD_GRANULARITY (64 * 1024)
  1462. #if defined( _IA64_ )
  1463. #define BUGGY_PDE_GRANULARITY (8 * 1024 * 1024)
  1464. #elif defined( _AMD64_ )
  1465. #define BUGGY_PDE_GRANULARITY (2 * 1024 * 1024)
  1466. #else
  1467. #define BUGGY_PDE_GRANULARITY (4 * 1024 * 1024)
  1468. #endif
  1469. typedef struct _BUGGY_PAGEDPOOLMDLTEST {
  1470. PVOID RequestedUserVa;
  1471. PMDL Mdl;
  1472. PVOID MappedAddress;
  1473. ULONG NumberOfPages;
  1474. } BUGGY_PAGEDPOOLMDLTEST, *PBUGGY_PAGEDPOOLMDLTEST;
  1475. BUGGY_PAGEDPOOLMDLTEST PagedPoolMdlTestArray [] =
  1476. {
  1477. {BUGGY_PAGE_DIRECTORY_BOUNDARY, NULL, NULL, 3},
  1478. {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY + BUGGY_VAD_GRANULARITY, NULL, NULL, 3},
  1479. {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY - BUGGY_VAD_GRANULARITY, NULL, NULL, 3},
  1480. {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY + BUGGY_PDE_GRANULARITY - BUGGY_VAD_GRANULARITY,
  1481. NULL, NULL, (2 * BUGGY_VAD_GRANULARITY) / PAGE_SIZE}
  1482. };
  1483. VOID
  1484. TdNonPagedPoolMdlTestMap(
  1485. IN PVOID IrpAddress
  1486. )
  1487. {
  1488. PVOID VirtualAddress;
  1489. ULONG MapIndex;
  1490. ULONG SizeToMap;
  1491. #if defined( _IA64_ )
  1492. //
  1493. // IA64
  1494. //
  1495. // 0xe0000168`02000000 maps NonCached 0x800 pages starting with PFN 0x78000 on dmihai-ita.
  1496. //
  1497. VirtualAddress = (PVOID)0xe000016802000000;
  1498. #elif defined( _AMD64_ )
  1499. //
  1500. // AMD64
  1501. //
  1502. // 0xfffffadf`f0a91000 maps WriteCombined 0x100 pages starting with PFN 0xd0200 on dmihai-amd64.
  1503. //
  1504. //VirtualAddress = (PVOID)0xffffffffffd00000;
  1505. VirtualAddress = (PVOID)0xfffffadff0a91000;
  1506. #else
  1507. //
  1508. // X86
  1509. //
  1510. // f1000000 maps NonChached 0x800 pages starting with PFN f5000 on dmihai-amd.
  1511. //
  1512. VirtualAddress = (PVOID)0xf1000000;
  1513. #endif
  1514. for (MapIndex = 0 ; MapIndex < ARRAY_LENGTH (PagedPoolMdlTestArray); MapIndex += 1)
  1515. {
  1516. //
  1517. //
  1518. //
  1519. SizeToMap = PAGE_SIZE * PagedPoolMdlTestArray [MapIndex].NumberOfPages;
  1520. PagedPoolMdlTestArray [MapIndex].Mdl = IoAllocateMdl (VirtualAddress,
  1521. SizeToMap,
  1522. FALSE,
  1523. FALSE,
  1524. NULL);
  1525. if (PagedPoolMdlTestArray [MapIndex].Mdl == NULL)
  1526. {
  1527. DbgPrint ("IoAllocateMdl failed\n");
  1528. return;
  1529. }
  1530. DbgPrint ("Mdl %p allocated\n",
  1531. PagedPoolMdlTestArray [MapIndex].Mdl);
  1532. //
  1533. //
  1534. //
  1535. MmBuildMdlForNonPagedPool (PagedPoolMdlTestArray [MapIndex].Mdl);
  1536. //
  1537. //
  1538. //
  1539. /*
  1540. UserVANonPagedPoolMdlTest = MmMapLockedPages (MdlNonPagedPoolMdlTest,
  1541. UserMode);
  1542. */
  1543. PagedPoolMdlTestArray [MapIndex].MappedAddress = MmMapLockedPagesSpecifyCache (
  1544. PagedPoolMdlTestArray [MapIndex].Mdl,
  1545. UserMode,
  1546. MmNonCached,
  1547. PagedPoolMdlTestArray [MapIndex].RequestedUserVa,
  1548. FALSE,
  1549. HighPagePriority);
  1550. DbgPrint ("Mapped %p bytes at address %p\n",
  1551. SizeToMap,
  1552. PagedPoolMdlTestArray [MapIndex].MappedAddress);
  1553. }
  1554. //DbgBreakPoint ();
  1555. }
  1556. VOID
  1557. TdNonPagedPoolMdlTestUnMap(
  1558. IN PVOID IrpAddress
  1559. )
  1560. {
  1561. ULONG MapIndex;
  1562. for (MapIndex = 0 ; MapIndex < ARRAY_LENGTH (PagedPoolMdlTestArray); MapIndex += 1)
  1563. {
  1564. if (PagedPoolMdlTestArray [MapIndex].MappedAddress != NULL)
  1565. {
  1566. //
  1567. // Unmap
  1568. //
  1569. MmUnmapLockedPages (PagedPoolMdlTestArray [MapIndex].MappedAddress,
  1570. PagedPoolMdlTestArray [MapIndex].Mdl);
  1571. PagedPoolMdlTestArray [MapIndex].MappedAddress = NULL;
  1572. }
  1573. if (PagedPoolMdlTestArray [MapIndex].Mdl != NULL)
  1574. {
  1575. //
  1576. // Free Mdl
  1577. //
  1578. IoFreeMdl (PagedPoolMdlTestArray [MapIndex].Mdl);
  1579. PagedPoolMdlTestArray [MapIndex].Mdl = NULL;
  1580. }
  1581. }
  1582. }
  1583. #endif // #if !MMTESTS_ACTIVE
  1584. //
  1585. // End of file
  1586. //