ReactOS 0.4.15-dev-7887-g64a59a1
IoReadWrite_drv.c
Go to the documentation of this file.
1/*
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>
6 */
7
8#include <kmt_test.h>
9#include "IoReadWrite.h"
10
11#define NDEBUG
12#include <debug.h>
13
14typedef struct _TEST_FCB
15{
21
22static KMT_IRP_HANDLER TestIrpHandler;
23static FAST_IO_READ TestFastIoRead;
24static FAST_IO_WRITE TestFastIoWrite;
25
31
38{
40
41 PAGED_CODE();
42
44
45 *DeviceName = L"IoReadWrite";
46 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
47 TESTENTRY_BUFFERED_IO_DEVICE |
48 TESTENTRY_NO_READONLY_DEVICE;
49
52 DriverObject->FastIoDispatch = &TestFastIoDispatch;
53
58
59 return Status;
60}
61
62VOID
65{
66 PAGED_CODE();
67}
68
69static
75{
77 ok(0, "Unexpected call to AcquireForLazyWrite\n");
78 return TRUE;
79}
80
81static
82VOID
86{
88 ok(0, "Unexpected call to ReleaseFromLazyWrite\n");
89}
90
91static
97{
99 ok(0, "Unexpected call to AcquireForReadAhead\n");
100 return TRUE;
101}
102
103static
104VOID
105NTAPI
108{
110 ok(0, "Unexpected call to ReleaseFromReadAhead\n");
111}
112
113static
121{
123 {
124 trace("FileOffset %I64d > file size\n", FileOffset);
126 IoStatus->Information = 0;
127 }
128 else if (Length == 0 || Buffer == NULL)
129 {
131 IoStatus->Information = TEST_FILE_SIZE - FileOffset;
132 }
133 else
134 {
138 IoStatus->Information = Length;
139 }
141 return STATUS_PENDING;
142 return IoStatus->Status;
143}
144
145static
147NTAPI
157{
160
161 //trace("FastIoRead: %p %lx %I64d+%lu -> %p\n", FileObject, LockKey, FileOffset->QuadPart, Length, Buffer);
163 ok_bool_true(Wait, "Wait is");
165 Fcb = FileObject->FsContext;
166 ok_bool_true(Fcb->Cached, "Cached is");
167
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);
173 {
175 }
177 {
179 return FALSE;
180 }
181 _SEH2_END;
182
183 if (Status == STATUS_PENDING)
184 return FALSE;
185
187 return TRUE;
188 else
189 return FALSE;
190}
191
192static
200{
201 ULONG i;
202 PUCHAR BufferBytes = Buffer;
203
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));
207 IoStatus->Information = Length;
208
210 return STATUS_PENDING;
211 return IoStatus->Status;
212}
213
214static
216NTAPI
226{
229
230 //trace("FastIoWrite: %p %lx %p -> %I64d+%lu\n", FileObject, LockKey, Buffer, FileOffset->QuadPart, Length);
232 ok_bool_true(Wait, "Wait is");
234 Fcb = FileObject->FsContext;
235 ok_bool_true(Fcb->Cached, "Cached is");
236
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);
242 {
244 }
246 {
248 return FALSE;
249 }
250 _SEH2_END;
251
252 if (Status == STATUS_PENDING)
253 return FALSE;
254
256 return TRUE;
257 else
258 return FALSE;
259}
260
261static
265 _In_ PIRP Irp,
266 _In_ PIO_STACK_LOCATION IoStack)
267{
271 CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
272
273 PAGED_CODE();
274
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);
280
282 Irp->IoStatus.Information = 0;
283
284 if (IoStack->MajorFunction == IRP_MJ_CREATE)
285 {
286 if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR))
287 {
289 TestFileObject = IoStack->FileObject;
290 }
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')
302 {
303 Fcb->Cached = TRUE;
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,
310 FALSE,
311 &Callbacks,
312 NULL);
313 }
314 Irp->IoStatus.Information = FILE_OPENED;
316 }
317 else if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
318 {
319 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
320 CcUninitializeCacheMap(IoStack->FileObject, NULL, &CacheUninitEvent);
322 Fcb = IoStack->FileObject->FsContext;
323 ExFreePoolWithTag(Fcb, 'FwrI');
324 IoStack->FileObject->FsContext = NULL;
326 }
327 else if (IoStack->MajorFunction == IRP_MJ_READ)
328 {
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);
331 ok_eq_pointer(IoStack->FileObject, TestFileObject);
332 Fcb = IoStack->FileObject->FsContext;
333 if (Fcb->Cached)
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,
337 "Buffer is %p\n",
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,
343 &Irp->IoStatus);
344 }
345 else if (IoStack->MajorFunction == IRP_MJ_WRITE)
346 {
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);
349 ok_eq_pointer(IoStack->FileObject, TestFileObject);
350 Fcb = IoStack->FileObject->FsContext;
351 if (Fcb->Cached)
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,
355 "Buffer is %p\n",
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,
361 &Irp->IoStatus);
362 }
363
364 if (Status == STATUS_PENDING)
365 {
369 }
370 else
371 {
372 Irp->IoStatus.Status = Status;
374 }
375
376 return Status;
377}
#define PAGED_CODE()
#define KEY_RETURN_PENDING
Definition: IoReadWrite.h:86
#define KEY_USE_FASTIO
Definition: IoReadWrite.h:85
static NTSTATUS TestGetReturnStatus(_In_ ULONG LockKey)
Definition: IoReadWrite.h:41
#define TEST_FILE_SIZE
Definition: IoReadWrite.h:11
#define KEY_GET_DATA(key)
Definition: IoReadWrite.h:89
static NTSTATUS TestCommonRead(_In_ PVOID Buffer, _In_ ULONG Length, _In_ LONGLONG FileOffset, _In_ ULONG LockKey, _Out_ PIO_STATUS_BLOCK IoStatus)
static PDEVICE_OBJECT TestDeviceObject
static PFILE_OBJECT TestFileObject
static FAST_IO_DISPATCH TestFastIoDispatch
struct _TEST_FCB TEST_FCB
struct _TEST_FCB * PTEST_FCB
VOID TestUnload(_In_ PDRIVER_OBJECT DriverObject)
static ULONG TestLastFastWriteKey
static ULONG TestLastFastReadKey
static FAST_IO_READ TestFastIoRead
static FAST_IO_WRITE TestFastIoWrite
static VOID NTAPI TestReleaseFromLazyWrite(_In_ PVOID Context)
static BOOLEAN NTAPI TestAcquireForReadAhead(_In_ PVOID Context, _In_ BOOLEAN Wait)
static BOOLEAN NTAPI TestAcquireForLazyWrite(_In_ PVOID Context, _In_ BOOLEAN Wait)
NTSTATUS TestEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PCUNICODE_STRING RegistryPath, _Out_ PCWSTR *DeviceName, _Inout_ INT *Flags)
static VOID NTAPI TestReleaseFromReadAhead(_In_ PVOID Context)
static KMT_IRP_HANDLER TestIrpHandler
static NTSTATUS TestCommonWrite(_In_ PVOID Buffer, _In_ ULONG Length, _In_ LONGLONG FileOffset, _In_ ULONG LockKey, _Out_ PIO_STATUS_BLOCK IoStatus)
unsigned char BOOLEAN
#define ok_eq_pointer(value, expected)
Definition: apitest.h:59
#define ok_eq_hex(value, expected)
Definition: apitest.h:77
#define ok_bool_true(value, desc)
Definition: apitest.h:78
#define MM_USER_PROBE_ADDRESS
Definition: armddk.h:19
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
LONG NTSTATUS
Definition: precomp.h:26
const struct winhelp_callbacks Callbacks
Definition: callback.c:161
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB Fcb
Definition: cdprocs.h:159
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NonPagedPool
Definition: env_spec_w32.h:307
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG LockKey
Definition: fatprocs.h:2665
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
IoMarkIrpPending(Irp)
NTSTATUS KmtRegisterIrpHandler(IN UCHAR MajorFunction, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_IRP_HANDLER IrpHandler)
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define min(a, b)
Definition: monoChain.cc:55
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:34
#define FILE_OPENED
Definition: nt_native.h:769
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define L(x)
Definition: ntvdm.h:50
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:71
PFAST_IO_WRITE FastIoWrite
Definition: iotypes.h:1736
PFAST_IO_READ FastIoRead
Definition: iotypes.h:1735
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: ntfs.h:518
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
PFILE_OBJECT FileObject
Definition: ntfs.h:520
BOOLEAN Cached
SECTION_OBJECT_POINTERS SectionObjectPointers
FAST_MUTEX HeaderMutex
FSRTL_ADVANCED_FCB_HEADER Header
const uint16_t * PCWSTR
Definition: typedefs.h:57
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
#define IO_NO_INCREMENT
Definition: iotypes.h:598
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MJ_CLEANUP
@ Executive
Definition: ketypes.h:415
__wchar_t WCHAR
Definition: xmlstorage.h:180