321345761dd616083ea74db18835494c025593bf
[reactos.git] / rostests / kmtests / ntos_cc / CcCopyRead_drv.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test driver for CcCopyRead 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 typedef struct _TEST_FCB
14 {
15 FSRTL_ADVANCED_FCB_HEADER Header;
16 SECTION_OBJECT_POINTERS SectionObjectPointers;
17 FAST_MUTEX HeaderMutex;
18 } TEST_FCB, *PTEST_FCB;
19
20 static PFILE_OBJECT TestFileObject;
21 static PDEVICE_OBJECT TestDeviceObject;
22 static KMT_IRP_HANDLER TestIrpHandler;
23 static FAST_IO_DISPATCH TestFastIoDispatch;
24
25 static
26 BOOLEAN
27 NTAPI
28 FastIoRead(
29 _In_ PFILE_OBJECT FileObject,
30 _In_ PLARGE_INTEGER FileOffset,
31 _In_ ULONG Length,
32 _In_ BOOLEAN Wait,
33 _In_ ULONG LockKey,
34 _Out_ PVOID Buffer,
35 _Out_ PIO_STATUS_BLOCK IoStatus,
36 _In_ PDEVICE_OBJECT DeviceObject)
37 {
38 IoStatus->Status = STATUS_NOT_SUPPORTED;
39 return FALSE;
40 }
41
42 NTSTATUS
43 TestEntry(
44 _In_ PDRIVER_OBJECT DriverObject,
45 _In_ PCUNICODE_STRING RegistryPath,
46 _Out_ PCWSTR *DeviceName,
47 _Inout_ INT *Flags)
48 {
49 NTSTATUS Status = STATUS_SUCCESS;
50
51 PAGED_CODE();
52
53 UNREFERENCED_PARAMETER(RegistryPath);
54
55 *DeviceName = L"CcCopyRead";
56 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
57 TESTENTRY_BUFFERED_IO_DEVICE |
58 TESTENTRY_NO_READONLY_DEVICE;
59
60 KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
61 KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
62 KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
63
64 TestFastIoDispatch.FastIoRead = FastIoRead;
65 DriverObject->FastIoDispatch = &TestFastIoDispatch;
66
67
68 return Status;
69 }
70
71 VOID
72 TestUnload(
73 _In_ PDRIVER_OBJECT DriverObject)
74 {
75 PAGED_CODE();
76 }
77
78 BOOLEAN
79 NTAPI
80 AcquireForLazyWrite(
81 _In_ PVOID Context,
82 _In_ BOOLEAN Wait)
83 {
84 return TRUE;
85 }
86
87 VOID
88 NTAPI
89 ReleaseFromLazyWrite(
90 _In_ PVOID Context)
91 {
92 return;
93 }
94
95 BOOLEAN
96 NTAPI
97 AcquireForReadAhead(
98 _In_ PVOID Context,
99 _In_ BOOLEAN Wait)
100 {
101 return TRUE;
102 }
103
104 VOID
105 NTAPI
106 ReleaseFromReadAhead(
107 _In_ PVOID Context)
108 {
109 return;
110 }
111
112 static CACHE_MANAGER_CALLBACKS Callbacks = {
113 AcquireForLazyWrite,
114 ReleaseFromLazyWrite,
115 AcquireForReadAhead,
116 ReleaseFromReadAhead,
117 };
118
119 static
120 PVOID
121 MapUserBuffer(
122 _In_ _Out_ PIRP Irp)
123 {
124 if (Irp->MdlAddress == NULL)
125 {
126 return Irp->UserBuffer;
127 }
128 else
129 {
130 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
131 }
132 }
133
134
135 static
136 NTSTATUS
137 TestIrpHandler(
138 _In_ PDEVICE_OBJECT DeviceObject,
139 _In_ PIRP Irp,
140 _In_ PIO_STACK_LOCATION IoStack)
141 {
142 NTSTATUS Status;
143 PTEST_FCB Fcb;
144 CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
145
146 PAGED_CODE();
147
148 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
149 ASSERT(IoStack->MajorFunction == IRP_MJ_CLEANUP ||
150 IoStack->MajorFunction == IRP_MJ_CREATE ||
151 IoStack->MajorFunction == IRP_MJ_READ);
152
153 Status = STATUS_NOT_SUPPORTED;
154 Irp->IoStatus.Information = 0;
155
156 if (IoStack->MajorFunction == IRP_MJ_CREATE)
157 {
158 if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR))
159 {
160 TestDeviceObject = DeviceObject;
161 TestFileObject = IoStack->FileObject;
162 }
163 Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Fcb), 'FwrI');
164 RtlZeroMemory(Fcb, sizeof(*Fcb));
165 ExInitializeFastMutex(&Fcb->HeaderMutex);
166 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
167 if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
168 IoStack->FileObject->FileName.Buffer[1] == 'B')
169 {
170 Fcb->Header.AllocationSize.QuadPart = 1000000;
171 Fcb->Header.FileSize.QuadPart = 1000000;
172 Fcb->Header.ValidDataLength.QuadPart = 1000000;
173 }
174 else if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) &&
175 IoStack->FileObject->FileName.Buffer[1] == 'S')
176 {
177 Fcb->Header.AllocationSize.QuadPart = 3000;
178 Fcb->Header.FileSize.QuadPart = 3000;
179 Fcb->Header.ValidDataLength.QuadPart = 3000;
180 }
181 else
182 {
183 Fcb->Header.AllocationSize.QuadPart = 512;
184 Fcb->Header.FileSize.QuadPart = 512;
185 Fcb->Header.ValidDataLength.QuadPart = 512;
186 }
187 Fcb->Header.IsFastIoPossible = FALSE;
188 IoStack->FileObject->FsContext = Fcb;
189 IoStack->FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
190
191 CcInitializeCacheMap(IoStack->FileObject,
192 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
193 FALSE, &Callbacks, NULL);
194
195 Irp->IoStatus.Information = FILE_OPENED;
196 Status = STATUS_SUCCESS;
197 }
198 else if (IoStack->MajorFunction == IRP_MJ_READ)
199 {
200 BOOLEAN Ret;
201 ULONG Length;
202 PVOID Buffer;
203 LARGE_INTEGER Offset;
204
205 Offset = IoStack->Parameters.Read.ByteOffset;
206 Length = IoStack->Parameters.Read.Length;
207 Fcb = IoStack->FileObject->FsContext;
208
209 ok_eq_pointer(DeviceObject, TestDeviceObject);
210 ok_eq_pointer(IoStack->FileObject, TestFileObject);
211
212 if (!FlagOn(Irp->Flags, IRP_NOCACHE))
213 {
214 ok(Offset.QuadPart % 512 != 0, "Offset is aligned: %I64i\n", Offset.QuadPart);
215 ok(Length % 512 != 0, "Length is aligned: %I64i\n", Length);
216
217 Buffer = MapUserBuffer(Irp);
218 ok(Buffer != NULL, "Null pointer!\n");
219
220 _SEH2_TRY
221 {
222 Ret = CcCopyRead(IoStack->FileObject, &Offset, Length, TRUE, Buffer,
223 &Irp->IoStatus);
224 ok_bool_true(Ret, "CcCopyRead");
225 }
226 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
227 {
228 Irp->IoStatus.Status = _SEH2_GetExceptionCode();
229 }
230 _SEH2_END;
231
232 Status = Irp->IoStatus.Status;
233 }
234 else
235 {
236 ok(Offset.QuadPart % 512 == 0, "Offset is not aligned: %I64i\n", Offset.QuadPart);
237 ok(Length % 512 == 0, "Length is not aligned: %I64i\n", Length);
238
239 Status = STATUS_SUCCESS;
240 }
241
242 if (NT_SUCCESS(Status))
243 {
244 Irp->IoStatus.Information = Length;
245 IoStack->FileObject->CurrentByteOffset.QuadPart = Offset.QuadPart + Length;
246 }
247 }
248 else if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
249 {
250 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
251 CcUninitializeCacheMap(IoStack->FileObject, NULL, &CacheUninitEvent);
252 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
253 Fcb = IoStack->FileObject->FsContext;
254 ExFreePoolWithTag(Fcb, 'FwrI');
255 IoStack->FileObject->FsContext = NULL;
256 Status = STATUS_SUCCESS;
257 }
258
259 if (Status == STATUS_PENDING)
260 {
261 IoMarkIrpPending(Irp);
262 IoCompleteRequest(Irp, IO_NO_INCREMENT);
263 Status = STATUS_PENDING;
264 }
265 else
266 {
267 Irp->IoStatus.Status = Status;
268 IoCompleteRequest(Irp, IO_NO_INCREMENT);
269 }
270
271 return Status;
272 }