947997346d8956d792dd9e8e072c7e925b4a93cc
[reactos.git] / rostests / kmtests / ntos_mm / NtCreateSection_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 NtCreateSection 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 UNICODE_STRING InitOnCreate = RTL_CONSTANT_STRING(L"\\InitOnCreate");
26 static UNICODE_STRING InitOnRW = RTL_CONSTANT_STRING(L"\\InitOnRW");
27 static UNICODE_STRING InvalidInit = RTL_CONSTANT_STRING(L"\\InvalidInit");
28
29 static
30 BOOLEAN
31 NTAPI
32 FastIoRead(
33 _In_ PFILE_OBJECT FileObject,
34 _In_ PLARGE_INTEGER FileOffset,
35 _In_ ULONG Length,
36 _In_ BOOLEAN Wait,
37 _In_ ULONG LockKey,
38 _Out_ PVOID Buffer,
39 _Out_ PIO_STATUS_BLOCK IoStatus,
40 _In_ PDEVICE_OBJECT DeviceObject)
41 {
42 IoStatus->Status = STATUS_NOT_SUPPORTED;
43 return FALSE;
44 }
45
46 static
47 BOOLEAN
48 NTAPI
49 FastIoWrite(
50 _In_ PFILE_OBJECT FileObject,
51 _In_ PLARGE_INTEGER FileOffset,
52 _In_ ULONG Length,
53 _In_ BOOLEAN Wait,
54 _In_ ULONG LockKey,
55 _Out_ PVOID Buffer,
56 _Out_ PIO_STATUS_BLOCK IoStatus,
57 _In_ PDEVICE_OBJECT DeviceObject)
58 {
59 IoStatus->Status = STATUS_NOT_SUPPORTED;
60 return FALSE;
61 }
62
63 static
64 BOOLEAN
65 NTAPI
66 FastIoQueryStandardInfo(
67 _In_ PFILE_OBJECT FileObject,
68 _In_ BOOLEAN Wait,
69 _Out_ PFILE_STANDARD_INFORMATION Buffer,
70 _Out_ PIO_STATUS_BLOCK IoStatus,
71 _In_ PDEVICE_OBJECT DeviceObject)
72 {
73 IoStatus->Status = STATUS_NOT_SUPPORTED;
74 return FALSE;
75 }
76
77 NTSTATUS
78 TestEntry(
79 _In_ PDRIVER_OBJECT DriverObject,
80 _In_ PCUNICODE_STRING RegistryPath,
81 _Out_ PCWSTR *DeviceName,
82 _Inout_ INT *Flags)
83 {
84 NTSTATUS Status = STATUS_SUCCESS;
85
86 PAGED_CODE();
87
88 UNREFERENCED_PARAMETER(RegistryPath);
89
90 *DeviceName = L"NtCreateSection";
91 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
92 TESTENTRY_BUFFERED_IO_DEVICE |
93 TESTENTRY_NO_READONLY_DEVICE;
94
95 KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
96 KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
97 KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
98 KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
99 KmtRegisterIrpHandler(IRP_MJ_QUERY_INFORMATION, NULL, TestIrpHandler);
100 KmtRegisterIrpHandler(IRP_MJ_SET_INFORMATION, NULL, TestIrpHandler);
101
102 TestFastIoDispatch.FastIoRead = FastIoRead;
103 TestFastIoDispatch.FastIoWrite = FastIoWrite;
104 TestFastIoDispatch.FastIoQueryStandardInfo = FastIoQueryStandardInfo;
105 DriverObject->FastIoDispatch = &TestFastIoDispatch;
106
107
108 return Status;
109 }
110
111 VOID
112 TestUnload(
113 _In_ PDRIVER_OBJECT DriverObject)
114 {
115 PAGED_CODE();
116 }
117
118 BOOLEAN
119 NTAPI
120 AcquireForLazyWrite(
121 _In_ PVOID Context,
122 _In_ BOOLEAN Wait)
123 {
124 return TRUE;
125 }
126
127 VOID
128 NTAPI
129 ReleaseFromLazyWrite(
130 _In_ PVOID Context)
131 {
132 return;
133 }
134
135 BOOLEAN
136 NTAPI
137 AcquireForReadAhead(
138 _In_ PVOID Context,
139 _In_ BOOLEAN Wait)
140 {
141 return TRUE;
142 }
143
144 VOID
145 NTAPI
146 ReleaseFromReadAhead(
147 _In_ PVOID Context)
148 {
149 return;
150 }
151
152 static CACHE_MANAGER_CALLBACKS Callbacks = {
153 AcquireForLazyWrite,
154 ReleaseFromLazyWrite,
155 AcquireForReadAhead,
156 ReleaseFromReadAhead,
157 };
158
159 static
160 PVOID
161 MapAndLockUserBuffer(
162 _In_ _Out_ PIRP Irp,
163 _In_ ULONG BufferLength)
164 {
165 PMDL Mdl;
166
167 if (Irp->MdlAddress == NULL)
168 {
169 Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
170 if (Mdl == NULL)
171 {
172 return NULL;
173 }
174
175 _SEH2_TRY
176 {
177 MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoWriteAccess);
178 }
179 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
180 {
181 IoFreeMdl(Mdl);
182 Irp->MdlAddress = NULL;
183 _SEH2_YIELD(return NULL);
184 }
185 _SEH2_END;
186 }
187
188 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
189 }
190
191
192 static
193 NTSTATUS
194 TestIrpHandler(
195 _In_ PDEVICE_OBJECT DeviceObject,
196 _In_ PIRP Irp,
197 _In_ PIO_STACK_LOCATION IoStack)
198 {
199 NTSTATUS Status;
200 PTEST_FCB Fcb;
201 CACHE_UNINITIALIZE_EVENT CacheUninitEvent;
202
203 PAGED_CODE();
204
205 DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
206 ASSERT(IoStack->MajorFunction == IRP_MJ_CLEANUP ||
207 IoStack->MajorFunction == IRP_MJ_CREATE ||
208 IoStack->MajorFunction == IRP_MJ_READ ||
209 IoStack->MajorFunction == IRP_MJ_WRITE ||
210 IoStack->MajorFunction == IRP_MJ_QUERY_INFORMATION ||
211 IoStack->MajorFunction == IRP_MJ_SET_INFORMATION);
212
213 Status = STATUS_NOT_SUPPORTED;
214 Irp->IoStatus.Information = 0;
215
216 if (IoStack->MajorFunction == IRP_MJ_CREATE)
217 {
218 ULONG RequestedDisposition = ((IoStack->Parameters.Create.Options >> 24) & 0xff);
219 ok(RequestedDisposition == FILE_CREATE || RequestedDisposition == FILE_OPEN, "Invalid disposition: %lu\n", RequestedDisposition);
220
221 if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR))
222 {
223 TestDeviceObject = DeviceObject;
224 TestFileObject = IoStack->FileObject;
225 }
226 Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Fcb), 'FwrI');
227 RtlZeroMemory(Fcb, sizeof(*Fcb));
228 ExInitializeFastMutex(&Fcb->HeaderMutex);
229 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
230
231 /* Consider file/dir doesn't exist */
232 if (RequestedDisposition == FILE_CREATE)
233 {
234 Fcb->Header.AllocationSize.QuadPart = 0;
235 Fcb->Header.FileSize.QuadPart = 0;
236 Fcb->Header.ValidDataLength.QuadPart = 0;
237 }
238 else
239 {
240 Fcb->Header.AllocationSize.QuadPart = 512;
241 Fcb->Header.FileSize.QuadPart = 512;
242 Fcb->Header.ValidDataLength.QuadPart = 512;
243 }
244 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
245
246 DPRINT1("File: %wZ\n", &IoStack->FileObject->FileName);
247
248 IoStack->FileObject->FsContext = Fcb;
249 if (RtlCompareUnicodeString(&IoStack->FileObject->FileName, &InvalidInit, FALSE) != 0)
250 {
251 IoStack->FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
252 }
253
254 if (IoStack->FileObject->FileName.Length == 0 ||
255 RtlCompareUnicodeString(&IoStack->FileObject->FileName, &InitOnCreate, FALSE) == 0)
256 {
257 DPRINT1("Init\n");
258
259 CcInitializeCacheMap(IoStack->FileObject,
260 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
261 FALSE, &Callbacks, NULL);
262 }
263
264 Irp->IoStatus.Information = (RequestedDisposition == FILE_CREATE) ? FILE_CREATED : FILE_OPENED;
265 Status = STATUS_SUCCESS;
266 }
267 else if (IoStack->MajorFunction == IRP_MJ_READ)
268 {
269 BOOLEAN Ret;
270 ULONG Length;
271 PVOID Buffer;
272 LARGE_INTEGER Offset;
273
274 Offset = IoStack->Parameters.Read.ByteOffset;
275 Length = IoStack->Parameters.Read.Length;
276 Fcb = IoStack->FileObject->FsContext;
277
278 ok_eq_pointer(DeviceObject, TestDeviceObject);
279 ok_eq_pointer(IoStack->FileObject, TestFileObject);
280
281 if (Offset.QuadPart + Length > Fcb->Header.FileSize.QuadPart)
282 {
283 Status = STATUS_END_OF_FILE;
284 }
285 else if (Length == 0)
286 {
287 Status = STATUS_SUCCESS;
288 }
289 else
290 {
291 if (!FlagOn(Irp->Flags, IRP_NOCACHE))
292 {
293 Buffer = Irp->AssociatedIrp.SystemBuffer;
294 ok(Buffer != NULL, "Null pointer!\n");
295
296 _SEH2_TRY
297 {
298 if (IoStack->FileObject->PrivateCacheMap == NULL)
299 {
300 DPRINT1("Init\n");
301 ok_eq_ulong(RtlCompareUnicodeString(&IoStack->FileObject->FileName, &InitOnRW, FALSE), 0);
302 CcInitializeCacheMap(IoStack->FileObject,
303 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
304 FALSE, &Callbacks, Fcb);
305 }
306
307 Ret = CcCopyRead(IoStack->FileObject, &Offset, Length, TRUE, Buffer,
308 &Irp->IoStatus);
309 ok_bool_true(Ret, "CcCopyRead");
310 }
311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
312 {
313 Irp->IoStatus.Status = _SEH2_GetExceptionCode();
314 }
315 _SEH2_END;
316
317 Status = Irp->IoStatus.Status;
318 }
319 else
320 {
321 PMDL Mdl;
322
323 ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
324 Buffer = MapAndLockUserBuffer(Irp, Length);
325 ok(Buffer != NULL, "Null pointer!\n");
326 RtlFillMemory(Buffer, Length, 0xBA);
327
328 Mdl = Irp->MdlAddress;
329 ok(Mdl != NULL, "Null pointer for MDL!\n");
330 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
331 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
332 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
333
334 Status = STATUS_SUCCESS;
335 }
336 }
337
338 if (NT_SUCCESS(Status))
339 {
340 Irp->IoStatus.Information = Length;
341 IoStack->FileObject->CurrentByteOffset.QuadPart = Offset.QuadPart + Length;
342 }
343 }
344 else if (IoStack->MajorFunction == IRP_MJ_WRITE)
345 {
346 BOOLEAN Ret;
347 ULONG Length;
348 PVOID Buffer;
349 LARGE_INTEGER Offset;
350
351 Offset = IoStack->Parameters.Write.ByteOffset;
352 Length = IoStack->Parameters.Write.Length;
353 Fcb = IoStack->FileObject->FsContext;
354
355 ok_eq_pointer(DeviceObject, TestDeviceObject);
356 ok_eq_pointer(IoStack->FileObject, TestFileObject);
357
358 if (Length == 0)
359 {
360 Status = STATUS_SUCCESS;
361 }
362 else
363 {
364 if (!FlagOn(Irp->Flags, IRP_NOCACHE))
365 {
366 Buffer = Irp->AssociatedIrp.SystemBuffer;
367 ok(Buffer != NULL, "Null pointer!\n");
368
369 _SEH2_TRY
370 {
371 if (IoStack->FileObject->PrivateCacheMap == NULL)
372 {
373 ok_eq_ulong(RtlCompareUnicodeString(&IoStack->FileObject->FileName, &InitOnRW, FALSE), 0);
374 CcInitializeCacheMap(IoStack->FileObject,
375 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
376 FALSE, &Callbacks, Fcb);
377 }
378
379 Ret = CcCopyWrite(IoStack->FileObject, &Offset, Length, TRUE, Buffer);
380 ok_bool_true(Ret, "CcCopyWrite");
381 }
382 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
383 {
384 Irp->IoStatus.Status = _SEH2_GetExceptionCode();
385 }
386 _SEH2_END;
387
388 Status = Irp->IoStatus.Status;
389 }
390 else
391 {
392 PMDL Mdl;
393
394 Mdl = Irp->MdlAddress;
395 ok(Mdl != NULL, "Null pointer for MDL!\n");
396 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
397 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
398 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
399
400 Status = STATUS_SUCCESS;
401 }
402
403 if (NT_SUCCESS(Status))
404 {
405 if (Length + Offset.QuadPart > Fcb->Header.FileSize.QuadPart)
406 {
407 Fcb->Header.AllocationSize.QuadPart = Length + Offset.QuadPart;
408 Fcb->Header.FileSize.QuadPart = Length + Offset.QuadPart;
409 Fcb->Header.ValidDataLength.QuadPart = Length + Offset.QuadPart;
410
411 if (CcIsFileCached(IoStack->FileObject))
412 {
413 CcSetFileSizes(IoStack->FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
414 }
415 }
416 }
417 }
418 }
419 else if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
420 {
421 Fcb = IoStack->FileObject->FsContext;
422 ok(Fcb != NULL, "Null pointer!\n");
423 if (IoStack->FileObject->SectionObjectPointer != NULL &&
424 IoStack->FileObject->SectionObjectPointer->SharedCacheMap != NULL)
425 {
426 CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
427 CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);
428 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
429 CcUninitializeCacheMap(IoStack->FileObject, NULL, &CacheUninitEvent);
430 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
431 }
432 ExFreePoolWithTag(Fcb, 'FwrI');
433 IoStack->FileObject->FsContext = NULL;
434 Status = STATUS_SUCCESS;
435 }
436 else if (IoStack->MajorFunction == IRP_MJ_QUERY_INFORMATION)
437 {
438 Fcb = IoStack->FileObject->FsContext;
439
440 ok_eq_pointer(DeviceObject, TestDeviceObject);
441 ok_eq_pointer(IoStack->FileObject, TestFileObject);
442 ok_eq_ulong(IoStack->Parameters.QueryFile.FileInformationClass, FileStandardInformation);
443
444 if (IoStack->Parameters.QueryFile.FileInformationClass == FileStandardInformation)
445 {
446 PFILE_STANDARD_INFORMATION StandardInfo = Irp->AssociatedIrp.SystemBuffer;
447 ULONG BufferLength = IoStack->Parameters.QueryFile.Length;
448
449 if (BufferLength < sizeof(FILE_STANDARD_INFORMATION))
450 {
451 Status = STATUS_BUFFER_OVERFLOW;
452 }
453 else
454 {
455 ok(StandardInfo != NULL, "Null pointer!\n");
456 ok(Fcb != NULL, "Null pointer!\n");
457
458 StandardInfo->AllocationSize = Fcb->Header.AllocationSize;
459 StandardInfo->EndOfFile = Fcb->Header.FileSize;
460 StandardInfo->Directory = FALSE;
461 StandardInfo->NumberOfLinks = 1;
462 StandardInfo->DeletePending = FALSE;
463
464 Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
465 Status = STATUS_SUCCESS;
466 }
467 }
468 else
469 {
470 Status = STATUS_NOT_IMPLEMENTED;
471 }
472 }
473 else if (IoStack->MajorFunction == IRP_MJ_SET_INFORMATION)
474 {
475 Fcb = IoStack->FileObject->FsContext;
476
477 ok_eq_pointer(DeviceObject, TestDeviceObject);
478 ok_eq_pointer(IoStack->FileObject, TestFileObject);
479 ok_eq_ulong(IoStack->Parameters.SetFile.FileInformationClass, FileEndOfFileInformation);
480
481 if (IoStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation)
482 {
483 PFILE_END_OF_FILE_INFORMATION EOFInfo = Irp->AssociatedIrp.SystemBuffer;
484 ULONG BufferLength = IoStack->Parameters.SetFile.Length;
485
486 if (BufferLength < sizeof(FILE_END_OF_FILE_INFORMATION))
487 {
488 Status = STATUS_BUFFER_OVERFLOW;
489 }
490 else
491 {
492 ULONG TestSize = 0;
493
494 ok(EOFInfo != NULL, "Null pointer!\n");
495 ok(Fcb != NULL, "Null pointer!\n");
496 ok_bool_false(IoStack->Parameters.SetFile.AdvanceOnly, "AdvanceOnly set!\n");
497 ok(EOFInfo->EndOfFile.QuadPart > Fcb->Header.AllocationSize.QuadPart, "New size smaller\n");
498
499 if (Fcb->Header.AllocationSize.QuadPart != 0)
500 {
501 TestSize = 512;
502 }
503
504 Fcb->Header.AllocationSize.QuadPart = EOFInfo->EndOfFile.QuadPart;
505 ok_eq_ulong(Fcb->Header.FileSize.QuadPart, TestSize);
506 ok_eq_ulong(Fcb->Header.ValidDataLength.QuadPart, TestSize);
507
508 if (CcIsFileCached(IoStack->FileObject))
509 {
510 CcSetFileSizes(IoStack->FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
511 }
512
513 ok_eq_ulong(Fcb->Header.FileSize.QuadPart, TestSize);
514 ok_eq_ulong(Fcb->Header.ValidDataLength.QuadPart, TestSize);
515
516 Status = STATUS_SUCCESS;
517 }
518 }
519 else
520 {
521 Status = STATUS_NOT_IMPLEMENTED;
522 }
523 }
524
525 if (Status == STATUS_PENDING)
526 {
527 IoMarkIrpPending(Irp);
528 IoCompleteRequest(Irp, IO_NO_INCREMENT);
529 Status = STATUS_PENDING;
530 }
531 else
532 {
533 Irp->IoStatus.Status = Status;
534 IoCompleteRequest(Irp, IO_NO_INCREMENT);
535 }
536
537 return Status;
538 }