[KMTESTS:MM] Properly clean up files
[reactos.git] / modules / 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 ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
322 Buffer = MapAndLockUserBuffer(Irp, Length);
323 ok(Buffer != NULL, "Null pointer!\n");
324 RtlFillMemory(Buffer, Length, 0xBA);
325
326 Status = STATUS_SUCCESS;
327 }
328 }
329
330 if (NT_SUCCESS(Status))
331 {
332 Irp->IoStatus.Information = Length;
333 IoStack->FileObject->CurrentByteOffset.QuadPart = Offset.QuadPart + Length;
334 }
335 }
336 else if (IoStack->MajorFunction == IRP_MJ_WRITE)
337 {
338 BOOLEAN Ret;
339 ULONG Length;
340 PVOID Buffer;
341 LARGE_INTEGER Offset;
342
343 Offset = IoStack->Parameters.Write.ByteOffset;
344 Length = IoStack->Parameters.Write.Length;
345 Fcb = IoStack->FileObject->FsContext;
346
347 ok_eq_pointer(DeviceObject, TestDeviceObject);
348 ok_eq_pointer(IoStack->FileObject, TestFileObject);
349
350 if (Length == 0)
351 {
352 Status = STATUS_SUCCESS;
353 }
354 else
355 {
356 if (!FlagOn(Irp->Flags, IRP_NOCACHE))
357 {
358 Buffer = Irp->AssociatedIrp.SystemBuffer;
359 ok(Buffer != NULL, "Null pointer!\n");
360
361 _SEH2_TRY
362 {
363 if (IoStack->FileObject->PrivateCacheMap == NULL)
364 {
365 ok_eq_ulong(RtlCompareUnicodeString(&IoStack->FileObject->FileName, &InitOnRW, FALSE), 0);
366 CcInitializeCacheMap(IoStack->FileObject,
367 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
368 FALSE, &Callbacks, Fcb);
369 }
370
371 Ret = CcCopyWrite(IoStack->FileObject, &Offset, Length, TRUE, Buffer);
372 ok_bool_true(Ret, "CcCopyWrite");
373 }
374 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
375 {
376 Irp->IoStatus.Status = _SEH2_GetExceptionCode();
377 }
378 _SEH2_END;
379
380 Status = Irp->IoStatus.Status;
381 }
382 else
383 {
384 PMDL Mdl;
385
386 Mdl = Irp->MdlAddress;
387 ok(Mdl != NULL, "Null pointer for MDL!\n");
388 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not locked\n");
389 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
390 ok((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0, "Paging IO for reading\n");
391 ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
392
393 Status = STATUS_SUCCESS;
394 }
395
396 if (NT_SUCCESS(Status))
397 {
398 if (Length + Offset.QuadPart > Fcb->Header.FileSize.QuadPart)
399 {
400 Fcb->Header.AllocationSize.QuadPart = Length + Offset.QuadPart;
401 Fcb->Header.FileSize.QuadPart = Length + Offset.QuadPart;
402 Fcb->Header.ValidDataLength.QuadPart = Length + Offset.QuadPart;
403
404 if (CcIsFileCached(IoStack->FileObject))
405 {
406 CcSetFileSizes(IoStack->FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
407 }
408 }
409 }
410 }
411 }
412 else if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
413 {
414 Fcb = IoStack->FileObject->FsContext;
415 ok(Fcb != NULL, "Null pointer!\n");
416 if (IoStack->FileObject->SectionObjectPointer != NULL)
417 {
418 LARGE_INTEGER Zero = RTL_CONSTANT_LARGE_INTEGER(0LL);
419
420 if (CcIsFileCached(IoStack->FileObject))
421 {
422 CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
423 CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);
424 }
425
426 KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
427 CcUninitializeCacheMap(IoStack->FileObject, &Zero, &CacheUninitEvent);
428 KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
429 }
430 ExFreePoolWithTag(Fcb, 'FwrI');
431 IoStack->FileObject->FsContext = NULL;
432 Status = STATUS_SUCCESS;
433 }
434 else if (IoStack->MajorFunction == IRP_MJ_QUERY_INFORMATION)
435 {
436 Fcb = IoStack->FileObject->FsContext;
437
438 ok_eq_pointer(DeviceObject, TestDeviceObject);
439 ok_eq_pointer(IoStack->FileObject, TestFileObject);
440 ok_eq_ulong(IoStack->Parameters.QueryFile.FileInformationClass, FileStandardInformation);
441
442 if (IoStack->Parameters.QueryFile.FileInformationClass == FileStandardInformation)
443 {
444 PFILE_STANDARD_INFORMATION StandardInfo = Irp->AssociatedIrp.SystemBuffer;
445 ULONG BufferLength = IoStack->Parameters.QueryFile.Length;
446
447 if (BufferLength < sizeof(FILE_STANDARD_INFORMATION))
448 {
449 Status = STATUS_BUFFER_OVERFLOW;
450 }
451 else
452 {
453 ok(StandardInfo != NULL, "Null pointer!\n");
454 ok(Fcb != NULL, "Null pointer!\n");
455
456 StandardInfo->AllocationSize = Fcb->Header.AllocationSize;
457 StandardInfo->EndOfFile = Fcb->Header.FileSize;
458 StandardInfo->Directory = FALSE;
459 StandardInfo->NumberOfLinks = 1;
460 StandardInfo->DeletePending = FALSE;
461
462 Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
463 Status = STATUS_SUCCESS;
464 }
465 }
466 else
467 {
468 Status = STATUS_NOT_IMPLEMENTED;
469 }
470 }
471 else if (IoStack->MajorFunction == IRP_MJ_SET_INFORMATION)
472 {
473 Fcb = IoStack->FileObject->FsContext;
474
475 ok_eq_pointer(DeviceObject, TestDeviceObject);
476 ok_eq_pointer(IoStack->FileObject, TestFileObject);
477 ok_eq_ulong(IoStack->Parameters.SetFile.FileInformationClass, FileEndOfFileInformation);
478
479 if (IoStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation)
480 {
481 PFILE_END_OF_FILE_INFORMATION EOFInfo = Irp->AssociatedIrp.SystemBuffer;
482 ULONG BufferLength = IoStack->Parameters.SetFile.Length;
483
484 if (BufferLength < sizeof(FILE_END_OF_FILE_INFORMATION))
485 {
486 Status = STATUS_BUFFER_OVERFLOW;
487 }
488 else
489 {
490 ULONG TestSize = 0;
491
492 ok(EOFInfo != NULL, "Null pointer!\n");
493 ok(Fcb != NULL, "Null pointer!\n");
494 ok_bool_false(IoStack->Parameters.SetFile.AdvanceOnly, "AdvanceOnly set!\n");
495 ok(EOFInfo->EndOfFile.QuadPart > Fcb->Header.AllocationSize.QuadPart, "New size smaller\n");
496
497 if (Fcb->Header.AllocationSize.QuadPart != 0)
498 {
499 TestSize = 512;
500 }
501
502 Fcb->Header.AllocationSize.QuadPart = EOFInfo->EndOfFile.QuadPart;
503 ok_eq_ulong(Fcb->Header.FileSize.QuadPart, TestSize);
504 ok_eq_ulong(Fcb->Header.ValidDataLength.QuadPart, TestSize);
505
506 if (CcIsFileCached(IoStack->FileObject))
507 {
508 CcSetFileSizes(IoStack->FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
509 }
510
511 ok_eq_ulong(Fcb->Header.FileSize.QuadPart, TestSize);
512 ok_eq_ulong(Fcb->Header.ValidDataLength.QuadPart, TestSize);
513
514 Status = STATUS_SUCCESS;
515 }
516 }
517 else
518 {
519 Status = STATUS_NOT_IMPLEMENTED;
520 }
521 }
522
523 if (Status == STATUS_PENDING)
524 {
525 IoMarkIrpPending(Irp);
526 IoCompleteRequest(Irp, IO_NO_INCREMENT);
527 Status = STATUS_PENDING;
528 }
529 else
530 {
531 Irp->IoStatus.Status = Status;
532 IoCompleteRequest(Irp, IO_NO_INCREMENT);
533 }
534
535 return Status;
536 }