2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test driver for Read/Write operations
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
9 #include "IoReadWrite.h"
14 typedef struct _TEST_FCB
16 FSRTL_ADVANCED_FCB_HEADER Header
;
17 SECTION_OBJECT_POINTERS SectionObjectPointers
;
18 FAST_MUTEX HeaderMutex
;
20 } TEST_FCB
, *PTEST_FCB
;
22 static KMT_IRP_HANDLER TestIrpHandler
;
23 static FAST_IO_READ TestFastIoRead
;
24 static FAST_IO_WRITE TestFastIoWrite
;
26 static FAST_IO_DISPATCH TestFastIoDispatch
;
27 static ULONG TestLastFastReadKey
;
28 static ULONG TestLastFastWriteKey
;
29 static PFILE_OBJECT TestFileObject
;
30 static PDEVICE_OBJECT TestDeviceObject
;
34 _In_ PDRIVER_OBJECT DriverObject
,
35 _In_ PCUNICODE_STRING RegistryPath
,
36 _Out_ PCWSTR
*DeviceName
,
39 NTSTATUS Status
= STATUS_SUCCESS
;
43 UNREFERENCED_PARAMETER(RegistryPath
);
45 *DeviceName
= L
"IoReadWrite";
46 *Flags
= TESTENTRY_NO_EXCLUSIVE_DEVICE
|
47 TESTENTRY_BUFFERED_IO_DEVICE
|
48 TESTENTRY_NO_READONLY_DEVICE
;
50 TestFastIoDispatch
.FastIoRead
= TestFastIoRead
;
51 TestFastIoDispatch
.FastIoWrite
= TestFastIoWrite
;
52 DriverObject
->FastIoDispatch
= &TestFastIoDispatch
;
54 KmtRegisterIrpHandler(IRP_MJ_CREATE
, NULL
, TestIrpHandler
);
55 KmtRegisterIrpHandler(IRP_MJ_CLEANUP
, NULL
, TestIrpHandler
);
56 KmtRegisterIrpHandler(IRP_MJ_READ
, NULL
, TestIrpHandler
);
57 KmtRegisterIrpHandler(IRP_MJ_WRITE
, NULL
, TestIrpHandler
);
64 _In_ PDRIVER_OBJECT DriverObject
)
72 TestAcquireForLazyWrite(
76 ok_eq_pointer(Context
, NULL
);
77 ok(0, "Unexpected call to AcquireForLazyWrite\n");
84 TestReleaseFromLazyWrite(
87 ok_eq_pointer(Context
, NULL
);
88 ok(0, "Unexpected call to ReleaseFromLazyWrite\n");
94 TestAcquireForReadAhead(
98 ok_eq_pointer(Context
, NULL
);
99 ok(0, "Unexpected call to AcquireForReadAhead\n");
106 TestReleaseFromReadAhead(
109 ok_eq_pointer(Context
, NULL
);
110 ok(0, "Unexpected call to ReleaseFromReadAhead\n");
118 _In_ LONGLONG FileOffset
,
120 _Out_ PIO_STATUS_BLOCK IoStatus
)
122 if (FileOffset
>= TEST_FILE_SIZE
)
124 trace("FileOffset %I64d > file size\n", FileOffset
);
125 IoStatus
->Status
= STATUS_END_OF_FILE
;
126 IoStatus
->Information
= 0;
128 else if (Length
== 0 || Buffer
== NULL
)
130 IoStatus
->Status
= STATUS_BUFFER_OVERFLOW
;
131 IoStatus
->Information
= TEST_FILE_SIZE
- FileOffset
;
135 Length
= min(Length
, TEST_FILE_SIZE
- FileOffset
);
136 RtlFillMemory(Buffer
, Length
, KEY_GET_DATA(LockKey
));
137 IoStatus
->Status
= TestGetReturnStatus(LockKey
);
138 IoStatus
->Information
= Length
;
140 if (LockKey
& KEY_RETURN_PENDING
)
141 return STATUS_PENDING
;
142 return IoStatus
->Status
;
149 _In_ PFILE_OBJECT FileObject
,
150 _In_ PLARGE_INTEGER FileOffset
,
155 _Out_ PIO_STATUS_BLOCK IoStatus
,
156 _In_ PDEVICE_OBJECT DeviceObject
)
161 //trace("FastIoRead: %p %lx %I64d+%lu -> %p\n", FileObject, LockKey, FileOffset->QuadPart, Length, Buffer);
162 ok_eq_pointer(FileObject
, TestFileObject
);
163 ok_bool_true(Wait
, "Wait is");
164 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
165 Fcb
= FileObject
->FsContext
;
166 ok_bool_true(Fcb
->Cached
, "Cached is");
168 TestLastFastReadKey
= LockKey
;
169 ok((ULONG_PTR
)Buffer
< MM_USER_PROBE_ADDRESS
, "Buffer is %p\n", Buffer
);
170 ok((ULONG_PTR
)FileOffset
> MM_USER_PROBE_ADDRESS
, "FileOffset is %p\n", FileOffset
);
171 ok((ULONG_PTR
)IoStatus
> MM_USER_PROBE_ADDRESS
, "IoStatus is %p\n", IoStatus
);
174 Status
= TestCommonRead(Buffer
, Length
, FileOffset
->QuadPart
, LockKey
, IoStatus
);
176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
178 IoStatus
->Status
= _SEH2_GetExceptionCode();
183 if (Status
== STATUS_PENDING
)
186 if (LockKey
& KEY_USE_FASTIO
)
197 _In_ LONGLONG FileOffset
,
199 _Out_ PIO_STATUS_BLOCK IoStatus
)
202 PUCHAR BufferBytes
= Buffer
;
204 for (i
= 0; i
< Length
; i
++)
205 ok(BufferBytes
[i
] == KEY_GET_DATA(LockKey
), "Buffer[%lu] = 0x%x, expected 0x%x\n", i
, BufferBytes
[i
], KEY_GET_DATA(LockKey
));
206 IoStatus
->Status
= TestGetReturnStatus(LockKey
);
207 IoStatus
->Information
= Length
;
209 if (LockKey
& KEY_RETURN_PENDING
)
210 return STATUS_PENDING
;
211 return IoStatus
->Status
;
218 _In_ PFILE_OBJECT FileObject
,
219 _In_ PLARGE_INTEGER FileOffset
,
224 _Out_ PIO_STATUS_BLOCK IoStatus
,
225 _In_ PDEVICE_OBJECT DeviceObject
)
230 //trace("FastIoWrite: %p %lx %p -> %I64d+%lu\n", FileObject, LockKey, Buffer, FileOffset->QuadPart, Length);
231 ok_eq_pointer(FileObject
, TestFileObject
);
232 ok_bool_true(Wait
, "Wait is");
233 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
234 Fcb
= FileObject
->FsContext
;
235 ok_bool_true(Fcb
->Cached
, "Cached is");
237 TestLastFastWriteKey
= LockKey
;
238 ok((ULONG_PTR
)Buffer
< MM_USER_PROBE_ADDRESS
, "Buffer is %p\n", Buffer
);
239 ok((ULONG_PTR
)FileOffset
> MM_USER_PROBE_ADDRESS
, "FileOffset is %p\n", FileOffset
);
240 ok((ULONG_PTR
)IoStatus
> MM_USER_PROBE_ADDRESS
, "IoStatus is %p\n", IoStatus
);
243 Status
= TestCommonWrite(Buffer
, Length
, FileOffset
->QuadPart
, LockKey
, IoStatus
);
245 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
247 IoStatus
->Status
= _SEH2_GetExceptionCode();
252 if (Status
== STATUS_PENDING
)
255 if (LockKey
& KEY_USE_FASTIO
)
264 _In_ PDEVICE_OBJECT DeviceObject
,
266 _In_ PIO_STACK_LOCATION IoStack
)
270 CACHE_MANAGER_CALLBACKS Callbacks
;
271 CACHE_UNINITIALIZE_EVENT CacheUninitEvent
;
275 DPRINT("IRP %x/%x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
276 ASSERT(IoStack
->MajorFunction
== IRP_MJ_CREATE
||
277 IoStack
->MajorFunction
== IRP_MJ_CLEANUP
||
278 IoStack
->MajorFunction
== IRP_MJ_READ
||
279 IoStack
->MajorFunction
== IRP_MJ_WRITE
);
281 Status
= STATUS_NOT_SUPPORTED
;
282 Irp
->IoStatus
.Information
= 0;
284 if (IoStack
->MajorFunction
== IRP_MJ_CREATE
)
286 if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
))
288 TestDeviceObject
= DeviceObject
;
289 TestFileObject
= IoStack
->FileObject
;
291 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*Fcb
), 'FwrI');
292 RtlZeroMemory(Fcb
, sizeof(*Fcb
));
293 ExInitializeFastMutex(&Fcb
->HeaderMutex
);
294 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->HeaderMutex
);
295 Fcb
->Header
.AllocationSize
.QuadPart
= TEST_FILE_SIZE
;
296 Fcb
->Header
.FileSize
.QuadPart
= TEST_FILE_SIZE
;
297 Fcb
->Header
.ValidDataLength
.QuadPart
= TEST_FILE_SIZE
;
298 IoStack
->FileObject
->FsContext
= Fcb
;
299 IoStack
->FileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
300 if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
) &&
301 IoStack
->FileObject
->FileName
.Buffer
[1] != 'N')
304 Callbacks
.AcquireForLazyWrite
= TestAcquireForLazyWrite
;
305 Callbacks
.ReleaseFromLazyWrite
= TestReleaseFromLazyWrite
;
306 Callbacks
.AcquireForReadAhead
= TestAcquireForReadAhead
;
307 Callbacks
.ReleaseFromReadAhead
= TestReleaseFromReadAhead
;
308 CcInitializeCacheMap(IoStack
->FileObject
,
309 (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
314 Irp
->IoStatus
.Information
= FILE_OPENED
;
315 Status
= STATUS_SUCCESS
;
317 else if (IoStack
->MajorFunction
== IRP_MJ_CLEANUP
)
319 KeInitializeEvent(&CacheUninitEvent
.Event
, NotificationEvent
, FALSE
);
320 CcUninitializeCacheMap(IoStack
->FileObject
, NULL
, &CacheUninitEvent
);
321 KeWaitForSingleObject(&CacheUninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
322 Fcb
= IoStack
->FileObject
->FsContext
;
323 ExFreePoolWithTag(Fcb
, 'FwrI');
324 IoStack
->FileObject
->FsContext
= NULL
;
325 Status
= STATUS_SUCCESS
;
327 else if (IoStack
->MajorFunction
== IRP_MJ_READ
)
329 //trace("IRP_MJ_READ: %p %lx %I64d+%lu -> %p\n", IoStack->FileObject, IoStack->Parameters.Read.Key, IoStack->Parameters.Read.ByteOffset.QuadPart, IoStack->Parameters.Read.Length, Irp->AssociatedIrp.SystemBuffer);
330 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
331 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
332 Fcb
= IoStack
->FileObject
->FsContext
;
334 ok_eq_hex(IoStack
->Parameters
.Read
.Key
, TestLastFastReadKey
);
335 ok(Irp
->AssociatedIrp
.SystemBuffer
== NULL
||
336 (ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
> MM_USER_PROBE_ADDRESS
,
338 Irp
->AssociatedIrp
.SystemBuffer
);
339 Status
= TestCommonRead(Irp
->AssociatedIrp
.SystemBuffer
,
340 IoStack
->Parameters
.Read
.Length
,
341 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
,
342 IoStack
->Parameters
.Read
.Key
,
345 else if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
347 //trace("IRP_MJ_WRITE: %p %lx %I64d+%lu -> %p\n", IoStack->FileObject, IoStack->Parameters.Write.Key, IoStack->Parameters.Write.ByteOffset.QuadPart, IoStack->Parameters.Write.Length, Irp->AssociatedIrp.SystemBuffer);
348 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
349 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
350 Fcb
= IoStack
->FileObject
->FsContext
;
352 ok_eq_hex(IoStack
->Parameters
.Write
.Key
, TestLastFastWriteKey
);
353 ok(Irp
->AssociatedIrp
.SystemBuffer
== NULL
||
354 (ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
> MM_USER_PROBE_ADDRESS
,
356 Irp
->AssociatedIrp
.SystemBuffer
);
357 Status
= TestCommonWrite(Irp
->AssociatedIrp
.SystemBuffer
,
358 IoStack
->Parameters
.Write
.Length
,
359 IoStack
->Parameters
.Write
.ByteOffset
.QuadPart
,
360 IoStack
->Parameters
.Write
.Key
,
364 if (Status
== STATUS_PENDING
)
366 IoMarkIrpPending(Irp
);
367 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
368 Status
= STATUS_PENDING
;
372 Irp
->IoStatus
.Status
= Status
;
373 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);