[KMTESTS:CC] Properly check for memory allocations
[reactos.git] / modules / rostests / kmtests / ntos_cc / CcPinRead_drv.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test driver for CcPinRead function
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define IOCTL_START_TEST 1
14 #define IOCTL_FINISH_TEST 2
15
16 typedef struct _TEST_FCB
17 {
18 FSRTL_ADVANCED_FCB_HEADER Header;
19 SECTION_OBJECT_POINTERS SectionObjectPointers;
20 FAST_MUTEX HeaderMutex;
21 } TEST_FCB, *PTEST_FCB;
22
23 typedef struct _TEST_CONTEXT
24 {
25 PVOID Bcb;
26 PVOID Buffer;
27 ULONG Length;
28 } TEST_CONTEXT, *PTEST_CONTEXT;
29
30 static ULONG TestTestId = -1;
31 static PFILE_OBJECT TestFileObject;
32 static PDEVICE_OBJECT TestDeviceObject;
33 static KMT_IRP_HANDLER TestIrpHandler;
34 static KMT_MESSAGE_HANDLER TestMessageHandler;
35
36 NTSTATUS
37 TestEntry(
38 _In_ PDRIVER_OBJECT DriverObject,
39 _In_ PCUNICODE_STRING RegistryPath,
40 _Out_ PCWSTR *DeviceName,
41 _Inout_ INT *Flags)
42 {
43 NTSTATUS Status = STATUS_SUCCESS;
44
45 PAGED_CODE();
46
47 UNREFERENCED_PARAMETER(RegistryPath);
48
49 *DeviceName = L"CcPinRead";
50 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
51 TESTENTRY_BUFFERED_IO_DEVICE |
52 TESTENTRY_NO_READONLY_DEVICE;
53
54 KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
55 KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
56
57
58 return Status;
59 }
60
61 VOID
62 TestUnload(
63 _In_ PDRIVER_OBJECT DriverObject)
64 {
65 PAGED_CODE();
66 }
67
68 BOOLEAN
69 NTAPI
70 AcquireForLazyWrite(
71 _In_ PVOID Context,
72 _In_ BOOLEAN Wait)
73 {
74 return TRUE;
75 }
76
77 VOID
78 NTAPI
79 ReleaseFromLazyWrite(
80 _In_ PVOID Context)
81 {
82 return;
83 }
84
85 BOOLEAN
86 NTAPI
87 AcquireForReadAhead(
88 _In_ PVOID Context,
89 _In_ BOOLEAN Wait)
90 {
91 return TRUE;
92 }
93
94 VOID
95 NTAPI
96 ReleaseFromReadAhead(
97 _In_ PVOID Context)
98 {
99 return;
100 }
101
102 static CACHE_MANAGER_CALLBACKS Callbacks = {
103 AcquireForLazyWrite,
104 ReleaseFromLazyWrite,
105 AcquireForReadAhead,
106 ReleaseFromReadAhead,
107 };
108
109 static CC_FILE_SIZES FileSizes = {
110 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .AllocationSize
111 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000), // .FileSize
112 RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0x4000) // .ValidDataLength
113 };
114
115 static
116 PVOID
117 MapAndLockUserBuffer(
118 _In_ _Out_ PIRP Irp,
119 _In_ ULONG BufferLength)
120 {
121 PMDL Mdl;
122
123 if (Irp->MdlAddress == NULL)
124 {
125 Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
126 if (Mdl == NULL)
127 {
128 return NULL;
129 }
130
131 _SEH2_TRY
132 {
133 MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess);
134 }
135 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
136 {
137 IoFreeMdl(Mdl);
138 Irp->MdlAddress = NULL;
139 _SEH2_YIELD(return NULL);
140 }
141 _SEH2_END;
142 }
143
144 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
145 }
146
147 static
148 VOID
149 NTAPI
150 PinInAnotherThread(IN PVOID Context)
151 {
152 BOOLEAN Ret;
153 PULONG Buffer;
154 PVOID Bcb;
155 LARGE_INTEGER Offset;
156 PTEST_CONTEXT TestContext;
157
158 ok(TestFileObject != NULL, "Called in invalid context!\n");
159 ok_eq_ulong(TestTestId, 3);
160
161 TestContext = Context;
162 ok(TestContext != NULL, "Called in invalid context!\n");
163 ok(TestContext->Bcb != NULL, "Called in invalid context!\n");
164 ok(TestContext->Buffer != NULL, "Called in invalid context!\n");
165 ok(TestContext->Length != 0, "Called in invalid context!\n");
166
167 Ret = FALSE;
168 Offset.QuadPart = 0x1000;
169 KmtStartSeh();
170 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
171 KmtEndSeh(STATUS_SUCCESS);
172
173 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
174 {
175 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
176 ok_eq_pointer(Bcb, TestContext->Bcb);
177 ok_eq_pointer(Buffer, TestContext->Buffer);
178
179 CcUnpinData(Bcb);
180 }
181
182 KmtStartSeh();
183 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
184 KmtEndSeh(STATUS_SUCCESS);
185
186 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
187 {
188 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
189 ok_eq_pointer(Bcb, TestContext->Bcb);
190 ok_eq_pointer(Buffer, TestContext->Buffer);
191
192 CcUnpinData(Bcb);
193 }
194
195 KmtStartSeh();
196 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
197 KmtEndSeh(STATUS_SUCCESS);
198
199 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
200 {
201 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
202 ok_eq_pointer(Bcb, TestContext->Bcb);
203 ok_eq_pointer(Buffer, TestContext->Buffer);
204
205 CcUnpinData(Bcb);
206 }
207
208 KmtStartSeh();
209 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
210 KmtEndSeh(STATUS_SUCCESS);
211
212 if (!skip(Ret == TRUE, "CcMapData failed\n"))
213 {
214 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
215 ok_eq_pointer(Buffer, TestContext->Buffer);
216
217 CcUnpinData(Bcb);
218 }
219
220 Offset.QuadPart = 0x1500;
221 TestContext->Length -= 0x500;
222
223 KmtStartSeh();
224 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
225 KmtEndSeh(STATUS_SUCCESS);
226
227 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
228 {
229 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
230 ok_eq_pointer(Bcb, TestContext->Bcb);
231 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
232
233 CcUnpinData(Bcb);
234 }
235
236 KmtStartSeh();
237 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
238 KmtEndSeh(STATUS_SUCCESS);
239
240 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
241 {
242 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
243 ok_eq_pointer(Bcb, TestContext->Bcb);
244 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
245
246 CcUnpinData(Bcb);
247 }
248
249 KmtStartSeh();
250 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
251 KmtEndSeh(STATUS_SUCCESS);
252
253 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
254 {
255 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
256 ok_eq_pointer(Bcb, TestContext->Bcb);
257 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
258
259 CcUnpinData(Bcb);
260 }
261
262 return;
263 }
264
265 static
266 VOID
267 NTAPI
268 PinInAnotherThreadExclusive(IN PVOID Context)
269 {
270 BOOLEAN Ret;
271 PULONG Buffer;
272 PVOID Bcb;
273 LARGE_INTEGER Offset;
274 PTEST_CONTEXT TestContext;
275
276 ok(TestFileObject != NULL, "Called in invalid context!\n");
277 ok_eq_ulong(TestTestId, 3);
278
279 TestContext = Context;
280 ok(TestContext != NULL, "Called in invalid context!\n");
281 ok(TestContext->Bcb != NULL, "Called in invalid context!\n");
282 ok(TestContext->Buffer != NULL, "Called in invalid context!\n");
283 ok(TestContext->Length != 0, "Called in invalid context!\n");
284
285 Ret = FALSE;
286 Offset.QuadPart = 0x1000;
287 KmtStartSeh();
288 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_EXCLUSIVE, &Bcb, (PVOID *)&Buffer);
289 KmtEndSeh(STATUS_SUCCESS);
290 ok(Ret == FALSE, "CcPinRead succeed\n");
291
292 if (Ret)
293 {
294 CcUnpinData(Bcb);
295 }
296
297 KmtStartSeh();
298 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
299 KmtEndSeh(STATUS_SUCCESS);
300
301 if (!skip(Ret == TRUE, "CcMapData failed\n"))
302 {
303 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
304 ok_eq_pointer(Buffer, TestContext->Buffer);
305
306 CcUnpinData(Bcb);
307 }
308
309 Offset.QuadPart = 0x1500;
310 TestContext->Length -= 0x500;
311
312 KmtStartSeh();
313 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
314 KmtEndSeh(STATUS_SUCCESS);
315 ok(Ret == FALSE, "CcPinRead succeed\n");
316
317 if (Ret)
318 {
319 CcUnpinData(Bcb);
320 }
321
322 KmtStartSeh();
323 Ret = CcPinRead(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
324 KmtEndSeh(STATUS_SUCCESS);
325 ok(Ret == FALSE, "CcPinRead succeed\n");
326
327 if (Ret)
328 {
329 CcUnpinData(Bcb);
330 }
331
332 KmtStartSeh();
333 Ret = CcMapData(TestFileObject, &Offset, TestContext->Length, 0, &Bcb, (PVOID *)&Buffer);
334 KmtEndSeh(STATUS_SUCCESS);
335
336 if (!skip(Ret == TRUE, "CcMapData failed\n"))
337 {
338 ok(Bcb != TestContext->Bcb, "Returned same BCB!\n");
339 ok_eq_pointer(Buffer, (PVOID)((ULONG_PTR)TestContext->Buffer + 0x500));
340
341 CcUnpinData(Bcb);
342 }
343
344 return;
345 }
346
347 static
348 VOID
349 PerformTest(
350 ULONG TestId,
351 PDEVICE_OBJECT DeviceObject)
352 {
353 PVOID Bcb;
354 BOOLEAN Ret;
355 PULONG Buffer;
356 PTEST_FCB Fcb;
357 LARGE_INTEGER Offset;
358
359 ok_eq_pointer(TestFileObject, NULL);
360 ok_eq_pointer(TestDeviceObject, NULL);
361 ok_eq_ulong(TestTestId, -1);
362
363 TestDeviceObject = DeviceObject;
364 TestTestId = TestId;
365 TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject);
366 if (!skip(TestFileObject != NULL, "Failed to allocate FO\n"))
367 {
368 Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB));
369 if (!skip(Fcb != NULL, "ExAllocatePool failed\n"))
370 {
371 BOOLEAN PinAccess = (TestId != 4);
372
373 RtlZeroMemory(Fcb, sizeof(TEST_FCB));
374 ExInitializeFastMutex(&Fcb->HeaderMutex);
375 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
376
377 TestFileObject->FsContext = Fcb;
378 TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
379
380 KmtStartSeh();
381 CcInitializeCacheMap(TestFileObject, &FileSizes, PinAccess, &Callbacks, NULL);
382 KmtEndSeh(STATUS_SUCCESS);
383
384 if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n"))
385 {
386 if (TestId < 3)
387 {
388 Ret = FALSE;
389 Offset.QuadPart = TestId * 0x1000;
390 KmtStartSeh();
391 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
392 KmtEndSeh(STATUS_SUCCESS);
393
394 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
395 {
396 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
397 ok_eq_ulong(Buffer[(0x3000 - TestId * 0x1000) / sizeof(ULONG)], 0xDEADBABE);
398
399 CcUnpinData(Bcb);
400 }
401 }
402 else if (TestId == 3)
403 {
404 PTEST_CONTEXT TestContext;
405
406 TestContext = ExAllocatePool(NonPagedPool, sizeof(TEST_CONTEXT));
407 if (!skip(TestContext != NULL, "ExAllocatePool failed\n"))
408 {
409 Ret = FALSE;
410 Offset.QuadPart = 0x1000;
411
412 /* Try enforce BCB first */
413 KmtStartSeh();
414 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_IF_BCB, &Bcb, (PVOID *)&Buffer);
415 KmtEndSeh(STATUS_SUCCESS);
416 ok(Ret == FALSE, "CcPinRead succeed\n");
417 if (Ret)
418 {
419 CcUnpinData(Bcb);
420 }
421
422 KmtStartSeh();
423 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &TestContext->Bcb, &TestContext->Buffer);
424 KmtEndSeh(STATUS_SUCCESS);
425
426 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
427 {
428 PKTHREAD ThreadHandle;
429
430 ok(*(PUSHORT)TestContext->Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)TestContext->Bcb);
431
432 #ifdef _X86_
433 /* FIXME: Should be fixed, will fail under certains conditions */
434 ok(TestContext->Buffer > (PVOID)0xC1000000 && TestContext->Buffer < (PVOID)0xDCFFFFFF,
435 "Buffer %p not mapped in system space\n", TestContext->Buffer);
436 #else
437 #ifdef _M_AMD64
438 ok(TestContext->Buffer > (PVOID)0xFFFFF98000000000 && TestContext->Buffer < (PVOID)0xFFFFFA8000000000,
439 "Buffer %p not mapped in system space\n", TestContext->Buffer);
440 #else
441 skip(FALSE, "System space mapping not defined\n");
442 #endif
443 #endif
444 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart;
445 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext);
446 KmtFinishThread(ThreadHandle, NULL);
447
448 TestContext->Length = FileSizes.FileSize.QuadPart - 2 * Offset.QuadPart;
449 ThreadHandle = KmtStartThread(PinInAnotherThread, TestContext);
450 KmtFinishThread(ThreadHandle, NULL);
451
452 CcUnpinData(TestContext->Bcb);
453 }
454
455 KmtStartSeh();
456 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT | PIN_EXCLUSIVE, &TestContext->Bcb, &TestContext->Buffer);
457 KmtEndSeh(STATUS_SUCCESS);
458
459 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
460 {
461 PKTHREAD ThreadHandle;
462
463 ok(*(PUSHORT)TestContext->Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)TestContext->Bcb);
464
465 TestContext->Length = FileSizes.FileSize.QuadPart - Offset.QuadPart;
466 ThreadHandle = KmtStartThread(PinInAnotherThreadExclusive, TestContext);
467 KmtFinishThread(ThreadHandle, NULL);
468
469 CcUnpinData(TestContext->Bcb);
470 }
471
472 ExFreePool(TestContext);
473 }
474 }
475 else if (TestId == 4)
476 {
477 Ret = FALSE;
478 Offset.QuadPart = 0x1000;
479 KmtStartSeh();
480 Ret = CcPinRead(TestFileObject, &Offset, FileSizes.FileSize.QuadPart - Offset.QuadPart, PIN_WAIT, &Bcb, (PVOID *)&Buffer);
481 KmtEndSeh(STATUS_SUCCESS);
482
483 if (!skip(Ret == TRUE, "CcPinRead failed\n"))
484 {
485 ok(*(PUSHORT)Bcb == 0x2FD, "Not a BCB: %x\n", *(PUSHORT)Bcb);
486 ok_eq_ulong(Buffer[0x2000 / sizeof(ULONG)], 0);
487
488 CcUnpinData(Bcb);
489 }
490 }
491 else if (TestId == 5)
492 {
493 /* Pin after EOF */
494 Ret = FALSE;
495 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000;
496
497 KmtStartSeh();
498 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
499 KmtEndSeh(STATUS_SUCCESS);
500 ok(Ret == FALSE, "CcPinRead succeed\n");
501
502 if (Ret)
503 {
504 CcUnpinData(Bcb);
505 }
506
507 /* Pin a VACB after EOF */
508 Ret = FALSE;
509 Offset.QuadPart = FileSizes.FileSize.QuadPart + 0x1000 + VACB_MAPPING_GRANULARITY;
510
511 KmtStartSeh();
512 Ret = CcPinRead(TestFileObject, &Offset, 0x1000, 0, &Bcb, (PVOID *)&Buffer);
513 KmtEndSeh(STATUS_ACCESS_VIOLATION);
514 ok(Ret == FALSE, "CcPinRead succeed\n");
515
516 if (Ret)
517 {
518 CcUnpinData(Bcb);
519 }
520
521 /* Pin more than a VACB */
522 Ret = FALSE;
523 Offset.QuadPart = 0x0;
524
525 KmtStartSeh();
526 Ret = CcPinRead(TestFileObject, &Offset, 0x1000 + VACB_MAPPING_GRANULARITY, 0, &Bcb, (PVOID *)&Buffer);
527 KmtEndSeh(STATUS_SUCCESS);
528 ok(Ret == FALSE, "CcPinRead succeed\n");
529
530 if (Ret)
531 {
532 CcUnpinData(Bcb);
533 }
534 }
535 }
536 }
537 }
538 }
539
540
541 static
542 VOID
543 CleanupTest(
544 ULONG TestId,
545 PDEVICE_OBJECT DeviceObject)
546 {
547 LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL);
548 CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
549
550 ok_eq_pointer(TestDeviceObject, DeviceObject);
551 ok_eq_ulong(TestTestId, TestId);
552
553 if (!skip(TestFileObject != NULL, "No test FO\n"))
554 {
555 if (CcIsFileCached(TestFileObject))
556 {
557 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
558 CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent);
559 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
560 }
561
562 if (TestFileObject->FsContext != NULL)
563 {
564 ExFreePool(TestFileObject->FsContext);
565 TestFileObject->FsContext = NULL;
566 TestFileObject->SectionObjectPointer = NULL;
567 }
568
569 ObDereferenceObject(TestFileObject);
570 }
571
572 TestFileObject = NULL;
573 TestDeviceObject = NULL;
574 TestTestId = -1;
575 }
576
577
578 static
579 NTSTATUS
580 TestMessageHandler(
581 _In_ PDEVICE_OBJECT DeviceObject,
582 _In_ ULONG ControlCode,
583 _In_opt_ PVOID Buffer,
584 _In_ SIZE_T InLength,
585 _Inout_ PSIZE_T OutLength)
586 {
587 NTSTATUS Status = STATUS_SUCCESS;
588
589 FsRtlEnterFileSystem();
590
591 switch (ControlCode)
592 {
593 case IOCTL_START_TEST:
594 ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
595 PerformTest(*(PULONG)Buffer, DeviceObject);
596 break;
597
598 case IOCTL_FINISH_TEST:
599 ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
600 CleanupTest(*(PULONG)Buffer, DeviceObject);
601 break;
602
603 default:
604 Status = STATUS_NOT_IMPLEMENTED;
605 break;
606 }
607
608 FsRtlExitFileSystem();
609
610 return Status;
611 }
612
613 static
614 NTSTATUS
615 TestIrpHandler(
616 _In_ PDEVICE_OBJECT DeviceObject,
617 _In_ PIRP Irp,
618 _In_ PIO_STACK_LOCATION IoStack)
619 {
620 NTSTATUS Status;
621
622 PAGED_CODE();
623
624 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
625 ASSERT(IoStack->MajorFunction == IRP_MJ_READ);
626
627 FsRtlEnterFileSystem();
628
629 Status = STATUS_NOT_SUPPORTED;
630 Irp->IoStatus.Information = 0;
631
632 if (IoStack->MajorFunction == IRP_MJ_READ)
633 {
634 PMDL Mdl;
635 ULONG Length;
636 PVOID Buffer;
637 LARGE_INTEGER Offset;
638
639 Offset = IoStack->Parameters.Read.ByteOffset;
640 Length = IoStack->Parameters.Read.Length;
641
642 ok_eq_pointer(DeviceObject, TestDeviceObject);
643 ok_eq_pointer(IoStack->FileObject, TestFileObject);
644
645 ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
646
647 ok_irql(APC_LEVEL);
648 ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart);
649 ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
650
651 ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
652 Buffer = MapAndLockUserBuffer(Irp, Length);
653 ok(Buffer != NULL, "Null pointer!\n");
654 RtlFillMemory(Buffer, Length, 0xBA);
655
656 Status = STATUS_SUCCESS;
657 if (Offset.QuadPart <= 0x3000 && Offset.QuadPart + Length > 0x3000)
658 {
659 *(PULONG)((ULONG_PTR)Buffer + (ULONG_PTR)(0x3000 - Offset.QuadPart)) = 0xDEADBABE;
660 }
661
662 Mdl = Irp->MdlAddress;
663 ok(Mdl != NULL, "Null pointer for MDL!\n");
664 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
665 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
666 ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0, "Non paging IO\n");
667 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
668
669 Irp->IoStatus.Information = Length;
670 }
671
672 if (Status == STATUS_PENDING)
673 {
674 IoMarkIrpPending(Irp);
675 IoCompleteRequest(Irp, IO_NO_INCREMENT);
676 Status = STATUS_PENDING;
677 }
678 else
679 {
680 Irp->IoStatus.Status = Status;
681 IoCompleteRequest(Irp, IO_NO_INCREMENT);
682 }
683
684 FsRtlExitFileSystem();
685
686 return Status;
687 }