1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test driver for CcSetFileSizes 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 static ULONG TestTestId = -1;
24 static PFILE_OBJECT TestFileObject;
25 static PDEVICE_OBJECT TestDeviceObject;
26 static KMT_IRP_HANDLER TestIrpHandler;
27 static KMT_MESSAGE_HANDLER TestMessageHandler;
28 static BOOLEAN TestUnpin = FALSE;
29 static BOOLEAN TestSizing = FALSE;
30 static BOOLEAN TestDirtying = FALSE;
31 static BOOLEAN TestUncaching = FALSE;
32 static BOOLEAN TestWritten = FALSE;
33 
34 NTSTATUS
TestEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PCUNICODE_STRING RegistryPath,_Out_ PCWSTR * DeviceName,_Inout_ INT * Flags)35 TestEntry(
36     _In_ PDRIVER_OBJECT DriverObject,
37     _In_ PCUNICODE_STRING RegistryPath,
38     _Out_ PCWSTR *DeviceName,
39     _Inout_ INT *Flags)
40 {
41     NTSTATUS Status = STATUS_SUCCESS;
42 
43     PAGED_CODE();
44 
45     UNREFERENCED_PARAMETER(RegistryPath);
46 
47     *DeviceName = L"CcSetFileSizes";
48     *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
49              TESTENTRY_BUFFERED_IO_DEVICE |
50              TESTENTRY_NO_READONLY_DEVICE;
51 
52     KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
53     KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
54     KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
55 
56     return Status;
57 }
58 
59 VOID
TestUnload(_In_ PDRIVER_OBJECT DriverObject)60 TestUnload(
61     _In_ PDRIVER_OBJECT DriverObject)
62 {
63     PAGED_CODE();
64 }
65 
66 BOOLEAN
67 NTAPI
AcquireForLazyWrite(_In_ PVOID Context,_In_ BOOLEAN Wait)68 AcquireForLazyWrite(
69     _In_ PVOID Context,
70     _In_ BOOLEAN Wait)
71 {
72     return TRUE;
73 }
74 
75 VOID
76 NTAPI
ReleaseFromLazyWrite(_In_ PVOID Context)77 ReleaseFromLazyWrite(
78     _In_ PVOID Context)
79 {
80     return;
81 }
82 
83 BOOLEAN
84 NTAPI
AcquireForReadAhead(_In_ PVOID Context,_In_ BOOLEAN Wait)85 AcquireForReadAhead(
86     _In_ PVOID Context,
87     _In_ BOOLEAN Wait)
88 {
89     return TRUE;
90 }
91 
92 VOID
93 NTAPI
ReleaseFromReadAhead(_In_ PVOID Context)94 ReleaseFromReadAhead(
95     _In_ PVOID Context)
96 {
97     return;
98 }
99 
100 static CACHE_MANAGER_CALLBACKS Callbacks = {
101     AcquireForLazyWrite,
102     ReleaseFromLazyWrite,
103     AcquireForReadAhead,
104     ReleaseFromReadAhead,
105 };
106 
107 static CC_FILE_SIZES NewFileSizes = {
108     RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY), // .AllocationSize
109     RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY), // .FileSize
110     RTL_CONSTANT_LARGE_INTEGER((LONGLONG)VACB_MAPPING_GRANULARITY)  // .ValidDataLength
111 };
112 
113 static
114 PVOID
MapAndLockUserBuffer(_In_ _Out_ PIRP Irp,_In_ ULONG BufferLength)115 MapAndLockUserBuffer(
116     _In_ _Out_ PIRP Irp,
117     _In_ ULONG BufferLength)
118 {
119     PMDL Mdl;
120 
121     if (Irp->MdlAddress == NULL)
122     {
123         Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
124         if (Mdl == NULL)
125         {
126             return NULL;
127         }
128 
129         _SEH2_TRY
130         {
131             MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess);
132         }
133         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
134         {
135             IoFreeMdl(Mdl);
136             Irp->MdlAddress = NULL;
137             _SEH2_YIELD(return NULL);
138         }
139         _SEH2_END;
140     }
141 
142     return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
143 }
144 
145 static
146 VOID
PerformTest(ULONG TestId,PDEVICE_OBJECT DeviceObject)147 PerformTest(
148     ULONG TestId,
149     PDEVICE_OBJECT DeviceObject)
150 {
151     PVOID Bcb;
152     BOOLEAN Ret;
153     PULONG Buffer;
154     PTEST_FCB Fcb;
155     LARGE_INTEGER Offset;
156     IO_STATUS_BLOCK IoStatus;
157 
158     ok_eq_pointer(TestFileObject, NULL);
159     ok_eq_pointer(TestDeviceObject, NULL);
160     ok_eq_ulong(TestTestId, -1);
161 
162     TestWritten = FALSE;
163     TestDeviceObject = DeviceObject;
164     TestTestId = TestId;
165     TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject);
166     if (!skip(TestFileObject != NULL, "Failed to allocate FO\n"))
167     {
168         Fcb = ExAllocatePool(NonPagedPool, sizeof(TEST_FCB));
169         if (!skip(Fcb != NULL, "ExAllocatePool failed\n"))
170         {
171             RtlZeroMemory(Fcb, sizeof(TEST_FCB));
172             ExInitializeFastMutex(&Fcb->HeaderMutex);
173             FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
174 
175             TestFileObject->FsContext = Fcb;
176             TestFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
177             Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY;
178             Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
179             Fcb->Header.ValidDataLength.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
180 
181             if ((TestId > 1 && TestId < 4) || TestId >= 5)
182             {
183                 Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
184             }
185 
186             KmtStartSeh();
187             CcInitializeCacheMap(TestFileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize, TRUE, &Callbacks, NULL);
188             KmtEndSeh(STATUS_SUCCESS);
189 
190             if (!skip(CcIsFileCached(TestFileObject) == TRUE, "CcInitializeCacheMap failed\n"))
191             {
192                 trace("Starting test: %d\n", TestId);
193 
194                 if (TestId == 0 || TestId == 2)
195                 {
196                     Offset.QuadPart = 0;
197                     KmtStartSeh();
198                     Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY - PAGE_SIZE, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
199                     KmtEndSeh(STATUS_SUCCESS);
200 
201                     if (!skip(Ret == TRUE, "CcMapData failed\n"))
202                     {
203                         ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
204                         CcUnpinData(Bcb);
205                     }
206 
207                     KmtStartSeh();
208                     CcSetFileSizes(TestFileObject, &NewFileSizes);
209                     KmtEndSeh(STATUS_SUCCESS);
210 
211                     Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY;
212                     Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY;
213 
214                     Offset.QuadPart = 0;
215                     KmtStartSeh();
216                     Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
217                     KmtEndSeh(STATUS_SUCCESS);
218 
219                     if (!skip(Ret == TRUE, "CcMapData failed\n"))
220                     {
221                         ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY  - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
222 
223                         CcUnpinData(Bcb);
224                     }
225                 }
226                 else if (TestId == 1 || TestId == 3)
227                 {
228                     Buffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
229                     if (!skip(Buffer != NULL, "ExAllocatePool failed\n"))
230                     {
231                         Ret = FALSE;
232                         Offset.QuadPart = VACB_MAPPING_GRANULARITY - 2 * PAGE_SIZE;
233 
234                         KmtStartSeh();
235                         Ret = CcCopyRead(TestFileObject, &Offset, PAGE_SIZE, TRUE, Buffer, &IoStatus);
236                         KmtEndSeh(STATUS_SUCCESS);
237 
238                         ok_eq_ulong(Buffer[(PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
239 
240                         KmtStartSeh();
241                         CcSetFileSizes(TestFileObject, &NewFileSizes);
242                         KmtEndSeh(STATUS_SUCCESS);
243 
244                         Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY;
245                         Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY;
246                         RtlZeroMemory(Buffer, PAGE_SIZE);
247 
248                         Offset.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
249 
250                         KmtStartSeh();
251                         Ret = CcCopyRead(TestFileObject, &Offset, PAGE_SIZE, TRUE, Buffer, &IoStatus);
252                         KmtEndSeh(STATUS_SUCCESS);
253 
254                         ok_eq_ulong(Buffer[(PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
255 
256                         ExFreePool(Buffer);
257                     }
258                 }
259                 else if (TestId == 4 || TestId == 5)
260                 {
261                     /* Kill lazy writer */
262                     CcSetAdditionalCacheAttributes(TestFileObject, FALSE, TRUE);
263 
264                     Offset.QuadPart = 0;
265                     KmtStartSeh();
266                     Ret = CcPinRead(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY - PAGE_SIZE, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
267                     KmtEndSeh(STATUS_SUCCESS);
268 
269                     if (!skip(Ret == TRUE, "CcPinRead failed\n"))
270                     {
271                         LARGE_INTEGER Flushed;
272 
273                         ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
274                         Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)] = 0xDADADADA;
275 
276                         TestDirtying = TRUE;
277                         CcSetDirtyPinnedData(Bcb, NULL);
278                         TestDirtying = FALSE;
279 
280                         ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly written!\n");
281 
282                         TestSizing = TRUE;
283                         KmtStartSeh();
284                         CcSetFileSizes(TestFileObject, &NewFileSizes);
285                         KmtEndSeh(STATUS_SUCCESS);
286                         TestSizing = FALSE;
287 
288                         ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly written!\n");
289 
290                         Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY;
291                         Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY;
292 
293                         Flushed = CcGetFlushedValidData(TestFileObject->SectionObjectPointer, FALSE);
294                         ok(Flushed.QuadPart == 0, "Flushed: %I64d\n", Flushed.QuadPart);
295 
296                         TestUnpin = TRUE;
297                         CcUnpinData(Bcb);
298                         TestUnpin = FALSE;
299 
300                         ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly written!\n");
301 
302                         Offset.QuadPart = 0;
303                         KmtStartSeh();
304                         Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
305                         KmtEndSeh(STATUS_SUCCESS);
306 
307                         if (!skip(Ret == TRUE, "CcMapData failed\n"))
308                         {
309                             ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xDADADADA);
310                             ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY  - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
311 
312                             CcUnpinData(Bcb);
313 
314                             ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly written!\n");
315                         }
316                     }
317                 }
318                 else if (TestId == 6)
319                 {
320                     Offset.QuadPart = 0;
321                     KmtStartSeh();
322                     Ret = CcMapData(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY - PAGE_SIZE, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
323                     KmtEndSeh(STATUS_SUCCESS);
324 
325                     if (!skip(Ret == TRUE, "CcMapData failed\n"))
326                     {
327                         ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
328                     }
329 
330                     KmtStartSeh();
331                     CcSetFileSizes(TestFileObject, &NewFileSizes);
332                     KmtEndSeh(STATUS_SUCCESS);
333 
334                     if (Ret == TRUE)
335                         CcUnpinData(Bcb);
336                 }
337             }
338         }
339     }
340 }
341 
342 
343 static
344 VOID
CleanupTest(ULONG TestId,PDEVICE_OBJECT DeviceObject)345 CleanupTest(
346     ULONG TestId,
347     PDEVICE_OBJECT DeviceObject)
348 {
349     LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL);
350     CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
351 
352     ok_eq_pointer(TestDeviceObject, DeviceObject);
353     ok_eq_ulong(TestTestId, TestId);
354 
355     if (!skip(TestFileObject != NULL, "No test FO\n"))
356     {
357         if (CcIsFileCached(TestFileObject))
358         {
359             TestUncaching = TRUE;
360             KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
361             CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent);
362             KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
363             TestUncaching = FALSE;
364         }
365 
366         if (TestFileObject->FsContext != NULL)
367         {
368             ExFreePool(TestFileObject->FsContext);
369             TestFileObject->FsContext = NULL;
370             TestFileObject->SectionObjectPointer = NULL;
371         }
372 
373         ObDereferenceObject(TestFileObject);
374     }
375 
376     TestFileObject = NULL;
377     TestDeviceObject = NULL;
378     TestTestId = -1;
379 }
380 
381 
382 static
383 NTSTATUS
TestMessageHandler(_In_ PDEVICE_OBJECT DeviceObject,_In_ ULONG ControlCode,_In_opt_ PVOID Buffer,_In_ SIZE_T InLength,_Inout_ PSIZE_T OutLength)384 TestMessageHandler(
385     _In_ PDEVICE_OBJECT DeviceObject,
386     _In_ ULONG ControlCode,
387     _In_opt_ PVOID Buffer,
388     _In_ SIZE_T InLength,
389     _Inout_ PSIZE_T OutLength)
390 {
391     NTSTATUS Status = STATUS_SUCCESS;
392 
393     FsRtlEnterFileSystem();
394 
395     switch (ControlCode)
396     {
397         case IOCTL_START_TEST:
398             ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
399             PerformTest(*(PULONG)Buffer, DeviceObject);
400             break;
401 
402         case IOCTL_FINISH_TEST:
403             ok_eq_ulong((ULONG)InLength, sizeof(ULONG));
404             CleanupTest(*(PULONG)Buffer, DeviceObject);
405             break;
406 
407         default:
408             Status = STATUS_NOT_IMPLEMENTED;
409             break;
410     }
411 
412     FsRtlExitFileSystem();
413 
414     return Status;
415 }
416 
417 static
418 NTSTATUS
TestIrpHandler(_In_ PDEVICE_OBJECT DeviceObject,_In_ PIRP Irp,_In_ PIO_STACK_LOCATION IoStack)419 TestIrpHandler(
420     _In_ PDEVICE_OBJECT DeviceObject,
421     _In_ PIRP Irp,
422     _In_ PIO_STACK_LOCATION IoStack)
423 {
424     NTSTATUS Status;
425 
426     PAGED_CODE();
427 
428     DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
429     ASSERT(IoStack->MajorFunction == IRP_MJ_READ ||
430            IoStack->MajorFunction == IRP_MJ_WRITE);
431 
432     FsRtlEnterFileSystem();
433 
434     Status = STATUS_NOT_SUPPORTED;
435     Irp->IoStatus.Information = 0;
436 
437     if (IoStack->MajorFunction == IRP_MJ_READ)
438     {
439         PMDL Mdl;
440         ULONG Length;
441         PTEST_FCB Fcb;
442         LARGE_INTEGER Offset;
443         PVOID Buffer, OrigBuffer;
444 
445         Offset = IoStack->Parameters.Read.ByteOffset;
446         Length = IoStack->Parameters.Read.Length;
447         Fcb = IoStack->FileObject->FsContext;
448 
449         ok_eq_pointer(DeviceObject, TestDeviceObject);
450         ok_eq_pointer(IoStack->FileObject, TestFileObject);
451         ok(Fcb != NULL, "Null FCB\n");
452 
453         ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
454 
455         ok_irql(APC_LEVEL);
456         ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart);
457         ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
458 
459         ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
460         OrigBuffer = Buffer = MapAndLockUserBuffer(Irp, Length);
461         ok(Buffer != NULL, "Null pointer!\n");
462         if (Buffer == NULL)
463         {
464             Status = STATUS_UNSUCCESSFUL;
465             goto Exit;
466         }
467 
468         if (Offset.QuadPart < Fcb->Header.FileSize.QuadPart)
469         {
470             RtlFillMemory(Buffer, min(Length, Fcb->Header.FileSize.QuadPart - Offset.QuadPart), 0xBA);
471             Buffer = (PVOID)((ULONG_PTR)Buffer + (ULONG_PTR)min(Length, Fcb->Header.FileSize.QuadPart - Offset.QuadPart));
472 
473             if (Length > (Fcb->Header.FileSize.QuadPart - Offset.QuadPart))
474             {
475                 RtlFillMemory(Buffer, Length - (Fcb->Header.FileSize.QuadPart - Offset.QuadPart), 0xBD);
476             }
477         }
478         else
479         {
480             RtlFillMemory(Buffer, Length, 0xBD);
481         }
482 
483         if ((TestTestId == 4 || TestTestId == 5) && TestWritten &&
484             Offset.QuadPart <= VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG) &&
485             Offset.QuadPart + Length >= VACB_MAPPING_GRANULARITY - PAGE_SIZE)
486         {
487             Buffer = (PVOID)((ULONG_PTR)OrigBuffer + (VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)));
488             RtlFillMemory(Buffer, sizeof(ULONG), 0xDA);
489         }
490 
491         Status = STATUS_SUCCESS;
492 
493         Mdl = Irp->MdlAddress;
494         ok(Mdl != NULL, "Null pointer for MDL!\n");
495         ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
496         ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
497         ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0, "Non paging IO\n");
498         ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
499 
500         Irp->IoStatus.Information = Length;
501     }
502     else if (IoStack->MajorFunction == IRP_MJ_WRITE)
503     {
504         PMDL Mdl;
505         ULONG Length;
506         PVOID Buffer;
507         LARGE_INTEGER Offset;
508 
509         Offset = IoStack->Parameters.Write.ByteOffset;
510         Length = IoStack->Parameters.Write.Length;
511 
512         ok((TestTestId == 4 || TestTestId == 5), "Unexpected test id: %d\n", TestTestId);
513         ok_eq_pointer(DeviceObject, TestDeviceObject);
514         ok_eq_pointer(IoStack->FileObject, TestFileObject);
515 
516         ok_bool_false(TestUnpin, "Write triggered while unpinning!\n");
517         ok_bool_false(TestSizing, "Write triggered while sizing!\n");
518         ok_bool_false(TestDirtying, "Write triggered while dirtying!\n");
519         ok_bool_true(TestUncaching, "Write not triggered while uncaching!\n");
520 
521         ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
522 
523         ok_irql(PASSIVE_LEVEL);
524         ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is not aligned: %I64i\n", Offset.QuadPart);
525         ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
526 
527         Buffer = MapAndLockUserBuffer(Irp, Length);
528         ok(Buffer != NULL, "Null pointer!\n");
529 
530         Mdl = Irp->MdlAddress;
531         ok(Mdl != NULL, "Null pointer for MDL!\n");
532         ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
533         ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
534         ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
535 
536         TestWritten = TRUE;
537         Status = STATUS_SUCCESS;
538         Irp->IoStatus.Information = Length;
539     }
540 
541     if (Status == STATUS_PENDING)
542     {
543         IoMarkIrpPending(Irp);
544         IoCompleteRequest(Irp, IO_NO_INCREMENT);
545         Status = STATUS_PENDING;
546     }
547     else
548     {
549         Irp->IoStatus.Status = Status;
550         IoCompleteRequest(Irp, IO_NO_INCREMENT);
551     }
552 
553 Exit:
554     FsRtlExitFileSystem();
555 
556     return Status;
557 }
558