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>
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 typedef struct _TEST_CONTEXT
28 } TEST_CONTEXT
, *PTEST_CONTEXT
;
30 static BOOLEAN TestMap
= FALSE
;
31 static ULONG TestTestId
= -1;
32 static PFILE_OBJECT TestFileObject
;
33 static PDEVICE_OBJECT TestDeviceObject
;
34 static KMT_IRP_HANDLER TestIrpHandler
;
35 static KMT_MESSAGE_HANDLER TestMessageHandler
;
39 _In_ PDRIVER_OBJECT DriverObject
,
40 _In_ PCUNICODE_STRING RegistryPath
,
41 _Out_ PCWSTR
*DeviceName
,
44 NTSTATUS Status
= STATUS_SUCCESS
;
48 UNREFERENCED_PARAMETER(RegistryPath
);
50 *DeviceName
= L
"CcMapData";
51 *Flags
= TESTENTRY_NO_EXCLUSIVE_DEVICE
|
52 TESTENTRY_BUFFERED_IO_DEVICE
|
53 TESTENTRY_NO_READONLY_DEVICE
;
55 KmtRegisterIrpHandler(IRP_MJ_READ
, NULL
, TestIrpHandler
);
56 KmtRegisterMessageHandler(0, NULL
, TestMessageHandler
);
64 _In_ PDRIVER_OBJECT DriverObject
)
103 static CACHE_MANAGER_CALLBACKS Callbacks
= {
105 ReleaseFromLazyWrite
,
107 ReleaseFromReadAhead
,
110 static CC_FILE_SIZES FileSizes
= {
111 RTL_CONSTANT_LARGE_INTEGER((LONGLONG
)0x4000), // .AllocationSize
112 RTL_CONSTANT_LARGE_INTEGER((LONGLONG
)0x4000), // .FileSize
113 RTL_CONSTANT_LARGE_INTEGER((LONGLONG
)0x4000) // .ValidDataLength
118 MapAndLockUserBuffer(
120 _In_ ULONG BufferLength
)
124 if (Irp
->MdlAddress
== NULL
)
126 Mdl
= IoAllocateMdl(Irp
->UserBuffer
, BufferLength
, FALSE
, FALSE
, Irp
);
134 MmProbeAndLockPages(Mdl
, Irp
->RequestorMode
, IoWriteAccess
);
136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
139 Irp
->MdlAddress
= NULL
;
140 _SEH2_YIELD(return NULL
);
145 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
151 MapInAnotherThread(IN PVOID Context
)
156 LARGE_INTEGER Offset
;
157 PTEST_CONTEXT TestContext
;
159 ok(TestFileObject
!= NULL
, "Called in invalid context!\n");
160 ok_eq_ulong(TestTestId
, 3);
162 TestContext
= Context
;
163 ok(TestContext
!= NULL
, "Called in invalid context!\n");
164 ok(TestContext
->Bcb
!= NULL
, "Called in invalid context!\n");
165 ok(TestContext
->Buffer
!= NULL
, "Called in invalid context!\n");
166 ok(TestContext
->Length
!= 0, "Called in invalid context!\n");
169 Offset
.QuadPart
= 0x1000;
172 Ret
= CcMapData(TestFileObject
, &Offset
, TestContext
->Length
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
174 KmtEndSeh(STATUS_SUCCESS
);
176 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
178 ok_eq_pointer(Bcb
, TestContext
->Bcb
);
179 ok_eq_pointer(Buffer
, TestContext
->Buffer
);
191 PDEVICE_OBJECT DeviceObject
)
197 LARGE_INTEGER Offset
;
199 ok_eq_pointer(TestFileObject
, NULL
);
200 ok_eq_pointer(TestDeviceObject
, NULL
);
201 ok_eq_ulong(TestTestId
, -1);
203 TestDeviceObject
= DeviceObject
;
205 TestFileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
206 if (!skip(TestFileObject
!= NULL
, "Failed to allocate FO\n"))
208 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(TEST_FCB
));
209 if (!skip(Fcb
!= NULL
, "ExAllocatePool failed\n"))
211 RtlZeroMemory(Fcb
, sizeof(TEST_FCB
));
212 ExInitializeFastMutex(&Fcb
->HeaderMutex
);
213 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->HeaderMutex
);
215 TestFileObject
->FsContext
= Fcb
;
216 TestFileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
219 CcInitializeCacheMap(TestFileObject
, &FileSizes
, FALSE
, &Callbacks
, NULL
);
220 KmtEndSeh(STATUS_SUCCESS
);
222 if (!skip(CcIsFileCached(TestFileObject
) == TRUE
, "CcInitializeCacheMap failed\n"))
227 Offset
.QuadPart
= TestId
* 0x1000;
229 Ret
= CcMapData(TestFileObject
, &Offset
, FileSizes
.FileSize
.QuadPart
- Offset
.QuadPart
, MAP_WAIT
, &Bcb
, (PVOID
*)&Buffer
);
230 KmtEndSeh(STATUS_SUCCESS
);
232 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
234 ok_eq_ulong(Buffer
[(0x3000 - TestId
* 0x1000) / sizeof(ULONG
)], 0xDEADBABE);
239 else if (TestId
== 3)
241 PTEST_CONTEXT TestContext
;
243 TestContext
= ExAllocatePool(NonPagedPool
, sizeof(TEST_CONTEXT
));
244 if (!skip(Fcb
!= NULL
, "ExAllocatePool failed\n"))
247 Offset
.QuadPart
= 0x1000;
250 Ret
= CcMapData(TestFileObject
, &Offset
, FileSizes
.FileSize
.QuadPart
- Offset
.QuadPart
, MAP_WAIT
, &TestContext
->Bcb
, &TestContext
->Buffer
);
252 KmtEndSeh(STATUS_SUCCESS
);
254 if (!skip(Ret
== TRUE
, "CcMapData failed\n"))
256 PKTHREAD ThreadHandle
;
259 /* FIXME: Should be fixed, will fail under certains conditions */
260 ok(TestContext
->Buffer
> (PVOID
)0xC1000000 && TestContext
->Buffer
< (PVOID
)0xDCFFFFFF,
261 "Buffer %p not mapped in system space\n", TestContext
->Buffer
);
264 ok(TestContext
->Buffer
> (PVOID
)0xFFFFF98000000000 && TestContext
->Buffer
< (PVOID
)0xFFFFFA8000000000,
265 "Buffer %p not mapped in system space\n", TestContext
->Buffer
);
267 skip(FALSE
, "System space mapping not defined\n");
271 TestContext
->Length
= FileSizes
.FileSize
.QuadPart
- Offset
.QuadPart
;
272 ThreadHandle
= KmtStartThread(MapInAnotherThread
, TestContext
);
273 KmtFinishThread(ThreadHandle
, NULL
);
275 TestContext
->Length
= FileSizes
.FileSize
.QuadPart
- 2 * Offset
.QuadPart
;
276 ThreadHandle
= KmtStartThread(MapInAnotherThread
, TestContext
);
277 KmtFinishThread(ThreadHandle
, NULL
);
279 CcUnpinData(TestContext
->Bcb
);
282 ExFreePool(TestContext
);
295 PDEVICE_OBJECT DeviceObject
)
297 LARGE_INTEGER Zero
= RTL_CONSTANT_LARGE_INTEGER(0LL);
298 CACHE_UNINITIALIZE_EVENT CacheUninitEvent
;
300 ok_eq_pointer(TestDeviceObject
, DeviceObject
);
301 ok_eq_ulong(TestTestId
, TestId
);
303 if (!skip(TestFileObject
!= NULL
, "No test FO\n"))
305 if (CcIsFileCached(TestFileObject
))
307 KeInitializeEvent(&CacheUninitEvent
.Event
, NotificationEvent
, FALSE
);
308 CcUninitializeCacheMap(TestFileObject
, &Zero
, &CacheUninitEvent
);
309 KeWaitForSingleObject(&CacheUninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
312 if (TestFileObject
->FsContext
!= NULL
)
314 ExFreePool(TestFileObject
->FsContext
);
315 TestFileObject
->FsContext
= NULL
;
316 TestFileObject
->SectionObjectPointer
= NULL
;
319 ObDereferenceObject(TestFileObject
);
322 TestFileObject
= NULL
;
323 TestDeviceObject
= NULL
;
331 _In_ PDEVICE_OBJECT DeviceObject
,
332 _In_ ULONG ControlCode
,
333 _In_opt_ PVOID Buffer
,
334 _In_ SIZE_T InLength
,
335 _Inout_ PSIZE_T OutLength
)
337 NTSTATUS Status
= STATUS_SUCCESS
;
341 case IOCTL_START_TEST
:
342 ok_eq_ulong((ULONG
)InLength
, sizeof(ULONG
));
343 PerformTest(*(PULONG
)Buffer
, DeviceObject
);
346 case IOCTL_FINISH_TEST
:
347 ok_eq_ulong((ULONG
)InLength
, sizeof(ULONG
));
348 CleanupTest(*(PULONG
)Buffer
, DeviceObject
);
352 Status
= STATUS_NOT_IMPLEMENTED
;
362 _In_ PDEVICE_OBJECT DeviceObject
,
364 _In_ PIO_STACK_LOCATION IoStack
)
370 DPRINT("IRP %x/%x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
371 ASSERT(IoStack
->MajorFunction
== IRP_MJ_READ
);
373 Status
= STATUS_NOT_SUPPORTED
;
374 Irp
->IoStatus
.Information
= 0;
376 if (IoStack
->MajorFunction
== IRP_MJ_READ
)
381 LARGE_INTEGER Offset
;
383 Offset
= IoStack
->Parameters
.Read
.ByteOffset
;
384 Length
= IoStack
->Parameters
.Read
.Length
;
386 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
387 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
389 ok(FlagOn(Irp
->Flags
, IRP_NOCACHE
), "Not coming from Cc\n");
392 ok((Offset
.QuadPart
% PAGE_SIZE
== 0 || Offset
.QuadPart
== 0), "Offset is not aligned: %I64i\n", Offset
.QuadPart
);
393 ok(Length
% PAGE_SIZE
== 0, "Length is not aligned: %I64i\n", Length
);
395 ok(Irp
->AssociatedIrp
.SystemBuffer
== NULL
, "A SystemBuffer was allocated!\n");
396 Buffer
= MapAndLockUserBuffer(Irp
, Length
);
397 ok(Buffer
!= NULL
, "Null pointer!\n");
398 RtlFillMemory(Buffer
, Length
, 0xBA);
400 Status
= STATUS_SUCCESS
;
401 if (Offset
.QuadPart
<= 0x3000 && Offset
.QuadPart
+ Length
> 0x3000)
403 *(PULONG
)((ULONG_PTR
)Buffer
+ (ULONG_PTR
)(0x3000 - Offset
.QuadPart
)) = 0xDEADBABE;
406 Mdl
= Irp
->MdlAddress
;
407 ok(Mdl
!= NULL
, "Null pointer for MDL!\n");
408 ok((Mdl
->MdlFlags
& MDL_PAGES_LOCKED
) != 0, "MDL not locked\n");
409 ok((Mdl
->MdlFlags
& MDL_SOURCE_IS_NONPAGED_POOL
) == 0, "MDL from non paged\n");
410 ok((Mdl
->MdlFlags
& MDL_IO_PAGE_READ
) != 0, "Non paging IO\n");
411 ok((Irp
->Flags
& IRP_PAGING_IO
) != 0, "Non paging IO\n");
413 Irp
->IoStatus
.Information
= Length
;
416 if (Status
== STATUS_PENDING
)
418 IoMarkIrpPending(Irp
);
419 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
420 Status
= STATUS_PENDING
;
424 Irp
->IoStatus
.Status
= Status
;
425 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);