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>
13 #define IOCTL_START_TEST 1
14 #define IOCTL_FINISH_TEST 2
16 typedef struct _TEST_FCB
18 FSRTL_ADVANCED_FCB_HEADER Header
;
19 SECTION_OBJECT_POINTERS SectionObjectPointers
;
20 FAST_MUTEX HeaderMutex
;
21 } TEST_FCB
, *PTEST_FCB
;
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
;
36 _In_ PDRIVER_OBJECT DriverObject
,
37 _In_ PCUNICODE_STRING RegistryPath
,
38 _Out_ PCWSTR
*DeviceName
,
41 NTSTATUS Status
= STATUS_SUCCESS
;
45 UNREFERENCED_PARAMETER(RegistryPath
);
47 *DeviceName
= L
"CcSetFileSizes";
48 *Flags
= TESTENTRY_NO_EXCLUSIVE_DEVICE
|
49 TESTENTRY_BUFFERED_IO_DEVICE
|
50 TESTENTRY_NO_READONLY_DEVICE
;
52 KmtRegisterIrpHandler(IRP_MJ_READ
, NULL
, TestIrpHandler
);
53 KmtRegisterIrpHandler(IRP_MJ_WRITE
, NULL
, TestIrpHandler
);
54 KmtRegisterMessageHandler(0, NULL
, TestMessageHandler
);
61 _In_ PDRIVER_OBJECT DriverObject
)
100 static CACHE_MANAGER_CALLBACKS Callbacks
= {
102 ReleaseFromLazyWrite
,
104 ReleaseFromReadAhead
,
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
115 MapAndLockUserBuffer(
117 _In_ ULONG BufferLength
)
121 if (Irp
->MdlAddress
== NULL
)
123 Mdl
= IoAllocateMdl(Irp
->UserBuffer
, BufferLength
, FALSE
, FALSE
, Irp
);
131 MmProbeAndLockPages(Mdl
, Irp
->RequestorMode
, IoWriteAccess
);
133 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
136 Irp
->MdlAddress
= NULL
;
137 _SEH2_YIELD(return NULL
);
142 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
149 PDEVICE_OBJECT DeviceObject
)
155 LARGE_INTEGER Offset
;
156 IO_STATUS_BLOCK IoStatus
;
158 ok_eq_pointer(TestFileObject
, NULL
);
159 ok_eq_pointer(TestDeviceObject
, NULL
);
160 ok_eq_ulong(TestTestId
, -1);
163 TestDeviceObject
= DeviceObject
;
165 TestFileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
166 if (!skip(TestFileObject
!= NULL
, "Failed to allocate FO\n"))
168 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(TEST_FCB
));
169 if (!skip(Fcb
!= NULL
, "ExAllocatePool failed\n"))
171 RtlZeroMemory(Fcb
, sizeof(TEST_FCB
));
172 ExInitializeFastMutex(&Fcb
->HeaderMutex
);
173 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->HeaderMutex
);
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
;
181 if ((TestId
> 1 && TestId
< 4) || TestId
>= 5)
183 Fcb
->Header
.AllocationSize
.QuadPart
= VACB_MAPPING_GRANULARITY
- PAGE_SIZE
;
187 CcInitializeCacheMap(TestFileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
, TRUE
, &Callbacks
, NULL
);
188 KmtEndSeh(STATUS_SUCCESS
);
190 if (!skip(CcIsFileCached(TestFileObject
) == TRUE
, "CcInitializeCacheMap failed\n"))
192 trace("Starting test: %d\n", TestId
);
194 if (TestId
== 0 || TestId
== 2)
198 Ret
= CcMapData(TestFileObject
, &Offset
, VACB_MAPPING_GRANULARITY
- PAGE_SIZE
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
199 KmtEndSeh(STATUS_SUCCESS
);
201 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
203 ok_eq_ulong(Buffer
[(VACB_MAPPING_GRANULARITY
- PAGE_SIZE
- sizeof(ULONG
)) / sizeof(ULONG
)], 0xBABABABA);
208 CcSetFileSizes(TestFileObject
, &NewFileSizes
);
209 KmtEndSeh(STATUS_SUCCESS
);
211 Fcb
->Header
.AllocationSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
212 Fcb
->Header
.FileSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
216 Ret
= CcMapData(TestFileObject
, &Offset
, VACB_MAPPING_GRANULARITY
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
217 KmtEndSeh(STATUS_SUCCESS
);
219 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
221 ok_eq_ulong(Buffer
[(VACB_MAPPING_GRANULARITY
- sizeof(ULONG
)) / sizeof(ULONG
)], 0xBABABABA);
226 else if (TestId
== 1 || TestId
== 3)
228 Buffer
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
229 if (!skip(Buffer
!= NULL
, "ExAllocatePool failed\n"))
232 Offset
.QuadPart
= VACB_MAPPING_GRANULARITY
- 2 * PAGE_SIZE
;
235 Ret
= CcCopyRead(TestFileObject
, &Offset
, PAGE_SIZE
, TRUE
, Buffer
, &IoStatus
);
236 KmtEndSeh(STATUS_SUCCESS
);
238 ok_eq_ulong(Buffer
[(PAGE_SIZE
- sizeof(ULONG
)) / sizeof(ULONG
)], 0xBABABABA);
241 CcSetFileSizes(TestFileObject
, &NewFileSizes
);
242 KmtEndSeh(STATUS_SUCCESS
);
244 Fcb
->Header
.AllocationSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
245 Fcb
->Header
.FileSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
246 RtlZeroMemory(Buffer
, PAGE_SIZE
);
248 Offset
.QuadPart
= VACB_MAPPING_GRANULARITY
- PAGE_SIZE
;
251 Ret
= CcCopyRead(TestFileObject
, &Offset
, PAGE_SIZE
, TRUE
, Buffer
, &IoStatus
);
252 KmtEndSeh(STATUS_SUCCESS
);
254 ok_eq_ulong(Buffer
[(PAGE_SIZE
- sizeof(ULONG
)) / sizeof(ULONG
)], 0xBABABABA);
259 else if (TestId
== 4 || TestId
== 5)
261 /* Kill lazy writer */
262 CcSetAdditionalCacheAttributes(TestFileObject
, FALSE
, TRUE
);
266 Ret
= CcPinRead(TestFileObject
, &Offset
, VACB_MAPPING_GRANULARITY
- PAGE_SIZE
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
267 KmtEndSeh(STATUS_SUCCESS
);
269 if (!skip(Ret
== TRUE
, "CcPinRead failed\n"))
271 LARGE_INTEGER Flushed
;
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;
277 CcSetDirtyPinnedData(Bcb
, NULL
);
278 TestDirtying
= FALSE
;
280 ok_bool_false(TestWritten
, "Dirty VACB has been unexpectedly written!\n");
284 CcSetFileSizes(TestFileObject
, &NewFileSizes
);
285 KmtEndSeh(STATUS_SUCCESS
);
288 ok_bool_false(TestWritten
, "Dirty VACB has been unexpectedly written!\n");
290 Fcb
->Header
.AllocationSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
291 Fcb
->Header
.FileSize
.QuadPart
= VACB_MAPPING_GRANULARITY
;
293 Flushed
= CcGetFlushedValidData(TestFileObject
->SectionObjectPointer
, FALSE
);
294 ok(Flushed
.QuadPart
== 0, "Flushed: %I64d\n", Flushed
.QuadPart
);
300 ok_bool_false(TestWritten
, "Dirty VACB has been unexpectedly written!\n");
304 Ret
= CcMapData(TestFileObject
, &Offset
, VACB_MAPPING_GRANULARITY
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
305 KmtEndSeh(STATUS_SUCCESS
);
307 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
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);
314 ok_bool_false(TestWritten
, "Dirty VACB has been unexpectedly written!\n");
318 else if (TestId
== 6)
322 Ret
= CcMapData(TestFileObject
, &Offset
, VACB_MAPPING_GRANULARITY
- PAGE_SIZE
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
323 KmtEndSeh(STATUS_SUCCESS
);
325 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
327 ok_eq_ulong(Buffer
[(VACB_MAPPING_GRANULARITY
- PAGE_SIZE
- sizeof(ULONG
)) / sizeof(ULONG
)], 0xBABABABA);
331 CcSetFileSizes(TestFileObject
, &NewFileSizes
);
332 KmtEndSeh(STATUS_SUCCESS
);
347 PDEVICE_OBJECT DeviceObject
)
349 LARGE_INTEGER Zero
= RTL_CONSTANT_LARGE_INTEGER(0LL);
350 CACHE_UNINITIALIZE_EVENT CacheUninitEvent
;
352 ok_eq_pointer(TestDeviceObject
, DeviceObject
);
353 ok_eq_ulong(TestTestId
, TestId
);
355 if (!skip(TestFileObject
!= NULL
, "No test FO\n"))
357 if (CcIsFileCached(TestFileObject
))
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
;
366 if (TestFileObject
->FsContext
!= NULL
)
368 ExFreePool(TestFileObject
->FsContext
);
369 TestFileObject
->FsContext
= NULL
;
370 TestFileObject
->SectionObjectPointer
= NULL
;
373 ObDereferenceObject(TestFileObject
);
376 TestFileObject
= NULL
;
377 TestDeviceObject
= NULL
;
385 _In_ PDEVICE_OBJECT DeviceObject
,
386 _In_ ULONG ControlCode
,
387 _In_opt_ PVOID Buffer
,
388 _In_ SIZE_T InLength
,
389 _Inout_ PSIZE_T OutLength
)
391 NTSTATUS Status
= STATUS_SUCCESS
;
393 FsRtlEnterFileSystem();
397 case IOCTL_START_TEST
:
398 ok_eq_ulong((ULONG
)InLength
, sizeof(ULONG
));
399 PerformTest(*(PULONG
)Buffer
, DeviceObject
);
402 case IOCTL_FINISH_TEST
:
403 ok_eq_ulong((ULONG
)InLength
, sizeof(ULONG
));
404 CleanupTest(*(PULONG
)Buffer
, DeviceObject
);
408 Status
= STATUS_NOT_IMPLEMENTED
;
412 FsRtlExitFileSystem();
420 _In_ PDEVICE_OBJECT DeviceObject
,
422 _In_ PIO_STACK_LOCATION IoStack
)
428 DPRINT("IRP %x/%x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
429 ASSERT(IoStack
->MajorFunction
== IRP_MJ_READ
||
430 IoStack
->MajorFunction
== IRP_MJ_WRITE
);
432 FsRtlEnterFileSystem();
434 Status
= STATUS_NOT_SUPPORTED
;
435 Irp
->IoStatus
.Information
= 0;
437 if (IoStack
->MajorFunction
== IRP_MJ_READ
)
442 LARGE_INTEGER Offset
;
443 PVOID Buffer
, OrigBuffer
;
445 Offset
= IoStack
->Parameters
.Read
.ByteOffset
;
446 Length
= IoStack
->Parameters
.Read
.Length
;
447 Fcb
= IoStack
->FileObject
->FsContext
;
449 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
450 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
451 ok(Fcb
!= NULL
, "Null FCB\n");
453 ok(FlagOn(Irp
->Flags
, IRP_NOCACHE
), "Not coming from Cc\n");
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
);
459 ok(Irp
->AssociatedIrp
.SystemBuffer
== NULL
, "A SystemBuffer was allocated!\n");
460 OrigBuffer
= Buffer
= MapAndLockUserBuffer(Irp
, Length
);
461 ok(Buffer
!= NULL
, "Null pointer!\n");
464 Status
= STATUS_UNSUCCESSFUL
;
468 if (Offset
.QuadPart
< Fcb
->Header
.FileSize
.QuadPart
)
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
));
473 if (Length
> (Fcb
->Header
.FileSize
.QuadPart
- Offset
.QuadPart
))
475 RtlFillMemory(Buffer
, Length
- (Fcb
->Header
.FileSize
.QuadPart
- Offset
.QuadPart
), 0xBD);
480 RtlFillMemory(Buffer
, Length
, 0xBD);
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
)
487 Buffer
= (PVOID
)((ULONG_PTR
)OrigBuffer
+ (VACB_MAPPING_GRANULARITY
- PAGE_SIZE
- sizeof(ULONG
)));
488 RtlFillMemory(Buffer
, sizeof(ULONG
), 0xDA);
491 Status
= STATUS_SUCCESS
;
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");
500 Irp
->IoStatus
.Information
= Length
;
502 else if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
507 LARGE_INTEGER Offset
;
509 Offset
= IoStack
->Parameters
.Write
.ByteOffset
;
510 Length
= IoStack
->Parameters
.Write
.Length
;
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
);
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");
521 ok(FlagOn(Irp
->Flags
, IRP_NOCACHE
), "Not coming from Cc\n");
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
);
527 Buffer
= MapAndLockUserBuffer(Irp
, Length
);
528 ok(Buffer
!= NULL
, "Null pointer!\n");
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");
537 Status
= STATUS_SUCCESS
;
538 Irp
->IoStatus
.Information
= Length
;
541 if (Status
== STATUS_PENDING
)
543 IoMarkIrpPending(Irp
);
544 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
545 Status
= STATUS_PENDING
;
549 Irp
->IoStatus
.Status
= Status
;
550 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
554 FsRtlExitFileSystem();