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>
13 typedef struct _TEST_FCB
15 FSRTL_ADVANCED_FCB_HEADER Header
;
16 SECTION_OBJECT_POINTERS SectionObjectPointers
;
17 FAST_MUTEX HeaderMutex
;
18 } TEST_FCB
, *PTEST_FCB
;
20 static PFILE_OBJECT TestFileObject
;
21 static PDEVICE_OBJECT TestDeviceObject
;
22 static KMT_IRP_HANDLER TestIrpHandler
;
23 static FAST_IO_DISPATCH TestFastIoDispatch
;
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");
33 _In_ PFILE_OBJECT FileObject
,
34 _In_ PLARGE_INTEGER FileOffset
,
39 _Out_ PIO_STATUS_BLOCK IoStatus
,
40 _In_ PDEVICE_OBJECT DeviceObject
)
42 IoStatus
->Status
= STATUS_NOT_SUPPORTED
;
50 _In_ PFILE_OBJECT FileObject
,
51 _In_ PLARGE_INTEGER FileOffset
,
56 _Out_ PIO_STATUS_BLOCK IoStatus
,
57 _In_ PDEVICE_OBJECT DeviceObject
)
59 IoStatus
->Status
= STATUS_NOT_SUPPORTED
;
66 FastIoQueryStandardInfo(
67 _In_ PFILE_OBJECT FileObject
,
69 _Out_ PFILE_STANDARD_INFORMATION Buffer
,
70 _Out_ PIO_STATUS_BLOCK IoStatus
,
71 _In_ PDEVICE_OBJECT DeviceObject
)
73 IoStatus
->Status
= STATUS_NOT_SUPPORTED
;
79 _In_ PDRIVER_OBJECT DriverObject
,
80 _In_ PCUNICODE_STRING RegistryPath
,
81 _Out_ PCWSTR
*DeviceName
,
84 NTSTATUS Status
= STATUS_SUCCESS
;
88 UNREFERENCED_PARAMETER(RegistryPath
);
90 *DeviceName
= L
"NtCreateSection";
91 *Flags
= TESTENTRY_NO_EXCLUSIVE_DEVICE
|
92 TESTENTRY_BUFFERED_IO_DEVICE
|
93 TESTENTRY_NO_READONLY_DEVICE
;
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
);
102 TestFastIoDispatch
.FastIoRead
= FastIoRead
;
103 TestFastIoDispatch
.FastIoWrite
= FastIoWrite
;
104 TestFastIoDispatch
.FastIoQueryStandardInfo
= FastIoQueryStandardInfo
;
105 DriverObject
->FastIoDispatch
= &TestFastIoDispatch
;
113 _In_ PDRIVER_OBJECT DriverObject
)
129 ReleaseFromLazyWrite(
146 ReleaseFromReadAhead(
152 static CACHE_MANAGER_CALLBACKS Callbacks
= {
154 ReleaseFromLazyWrite
,
156 ReleaseFromReadAhead
,
161 MapAndLockUserBuffer(
163 _In_ ULONG BufferLength
)
167 if (Irp
->MdlAddress
== NULL
)
169 Mdl
= IoAllocateMdl(Irp
->UserBuffer
, BufferLength
, FALSE
, FALSE
, Irp
);
177 MmProbeAndLockPages(Mdl
, Irp
->RequestorMode
, IoWriteAccess
);
179 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
182 Irp
->MdlAddress
= NULL
;
183 _SEH2_YIELD(return NULL
);
188 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
195 _In_ PDEVICE_OBJECT DeviceObject
,
197 _In_ PIO_STACK_LOCATION IoStack
)
201 CACHE_UNINITIALIZE_EVENT CacheUninitEvent
;
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
);
213 Status
= STATUS_NOT_SUPPORTED
;
214 Irp
->IoStatus
.Information
= 0;
216 if (IoStack
->MajorFunction
== IRP_MJ_CREATE
)
218 ULONG RequestedDisposition
= ((IoStack
->Parameters
.Create
.Options
>> 24) & 0xff);
219 ok(RequestedDisposition
== FILE_CREATE
|| RequestedDisposition
== FILE_OPEN
, "Invalid disposition: %lu\n", RequestedDisposition
);
221 if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
))
223 TestDeviceObject
= DeviceObject
;
224 TestFileObject
= IoStack
->FileObject
;
226 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*Fcb
), 'FwrI');
227 RtlZeroMemory(Fcb
, sizeof(*Fcb
));
228 ExInitializeFastMutex(&Fcb
->HeaderMutex
);
229 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->HeaderMutex
);
231 /* Consider file/dir doesn't exist */
232 if (RequestedDisposition
== FILE_CREATE
)
234 Fcb
->Header
.AllocationSize
.QuadPart
= 0;
235 Fcb
->Header
.FileSize
.QuadPart
= 0;
236 Fcb
->Header
.ValidDataLength
.QuadPart
= 0;
240 Fcb
->Header
.AllocationSize
.QuadPart
= 512;
241 Fcb
->Header
.FileSize
.QuadPart
= 512;
242 Fcb
->Header
.ValidDataLength
.QuadPart
= 512;
244 Fcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
246 DPRINT1("File: %wZ\n", &IoStack
->FileObject
->FileName
);
248 IoStack
->FileObject
->FsContext
= Fcb
;
249 if (RtlCompareUnicodeString(&IoStack
->FileObject
->FileName
, &InvalidInit
, FALSE
) != 0)
251 IoStack
->FileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
254 if (IoStack
->FileObject
->FileName
.Length
== 0 ||
255 RtlCompareUnicodeString(&IoStack
->FileObject
->FileName
, &InitOnCreate
, FALSE
) == 0)
259 CcInitializeCacheMap(IoStack
->FileObject
,
260 (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
261 FALSE
, &Callbacks
, NULL
);
264 Irp
->IoStatus
.Information
= (RequestedDisposition
== FILE_CREATE
) ? FILE_CREATED
: FILE_OPENED
;
265 Status
= STATUS_SUCCESS
;
267 else if (IoStack
->MajorFunction
== IRP_MJ_READ
)
272 LARGE_INTEGER Offset
;
274 Offset
= IoStack
->Parameters
.Read
.ByteOffset
;
275 Length
= IoStack
->Parameters
.Read
.Length
;
276 Fcb
= IoStack
->FileObject
->FsContext
;
278 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
279 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
281 if (Offset
.QuadPart
+ Length
> Fcb
->Header
.FileSize
.QuadPart
)
283 Status
= STATUS_END_OF_FILE
;
285 else if (Length
== 0)
287 Status
= STATUS_SUCCESS
;
291 if (!FlagOn(Irp
->Flags
, IRP_NOCACHE
))
293 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
294 ok(Buffer
!= NULL
, "Null pointer!\n");
298 if (IoStack
->FileObject
->PrivateCacheMap
== NULL
)
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
);
307 Ret
= CcCopyRead(IoStack
->FileObject
, &Offset
, Length
, TRUE
, Buffer
,
309 ok_bool_true(Ret
, "CcCopyRead");
311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
313 Irp
->IoStatus
.Status
= _SEH2_GetExceptionCode();
317 Status
= Irp
->IoStatus
.Status
;
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);
326 Status
= STATUS_SUCCESS
;
330 if (NT_SUCCESS(Status
))
332 Irp
->IoStatus
.Information
= Length
;
333 IoStack
->FileObject
->CurrentByteOffset
.QuadPart
= Offset
.QuadPart
+ Length
;
336 else if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
341 LARGE_INTEGER Offset
;
343 Offset
= IoStack
->Parameters
.Write
.ByteOffset
;
344 Length
= IoStack
->Parameters
.Write
.Length
;
345 Fcb
= IoStack
->FileObject
->FsContext
;
347 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
348 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
352 Status
= STATUS_SUCCESS
;
356 if (!FlagOn(Irp
->Flags
, IRP_NOCACHE
))
358 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
359 ok(Buffer
!= NULL
, "Null pointer!\n");
363 if (IoStack
->FileObject
->PrivateCacheMap
== NULL
)
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
);
371 Ret
= CcCopyWrite(IoStack
->FileObject
, &Offset
, Length
, TRUE
, Buffer
);
372 ok_bool_true(Ret
, "CcCopyWrite");
374 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
376 Irp
->IoStatus
.Status
= _SEH2_GetExceptionCode();
380 Status
= Irp
->IoStatus
.Status
;
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((Irp
->Flags
& IRP_PAGING_IO
) != 0, "Non paging IO\n");
392 Status
= STATUS_SUCCESS
;
395 if (NT_SUCCESS(Status
))
397 if (Length
+ Offset
.QuadPart
> Fcb
->Header
.FileSize
.QuadPart
)
399 Fcb
->Header
.AllocationSize
.QuadPart
= Length
+ Offset
.QuadPart
;
400 Fcb
->Header
.FileSize
.QuadPart
= Length
+ Offset
.QuadPart
;
401 Fcb
->Header
.ValidDataLength
.QuadPart
= Length
+ Offset
.QuadPart
;
403 if (CcIsFileCached(IoStack
->FileObject
))
405 CcSetFileSizes(IoStack
->FileObject
, (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
411 else if (IoStack
->MajorFunction
== IRP_MJ_CLEANUP
)
413 Fcb
= IoStack
->FileObject
->FsContext
;
414 ok(Fcb
!= NULL
, "Null pointer!\n");
415 if (IoStack
->FileObject
->SectionObjectPointer
!= NULL
&&
416 IoStack
->FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
418 CcFlushCache(&Fcb
->SectionObjectPointers
, NULL
, 0, NULL
);
419 CcPurgeCacheSection(&Fcb
->SectionObjectPointers
, NULL
, 0, FALSE
);
420 KeInitializeEvent(&CacheUninitEvent
.Event
, NotificationEvent
, FALSE
);
421 CcUninitializeCacheMap(IoStack
->FileObject
, NULL
, &CacheUninitEvent
);
422 KeWaitForSingleObject(&CacheUninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
424 ExFreePoolWithTag(Fcb
, 'FwrI');
425 IoStack
->FileObject
->FsContext
= NULL
;
426 Status
= STATUS_SUCCESS
;
428 else if (IoStack
->MajorFunction
== IRP_MJ_QUERY_INFORMATION
)
430 Fcb
= IoStack
->FileObject
->FsContext
;
432 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
433 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
434 ok_eq_ulong(IoStack
->Parameters
.QueryFile
.FileInformationClass
, FileStandardInformation
);
436 if (IoStack
->Parameters
.QueryFile
.FileInformationClass
== FileStandardInformation
)
438 PFILE_STANDARD_INFORMATION StandardInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
439 ULONG BufferLength
= IoStack
->Parameters
.QueryFile
.Length
;
441 if (BufferLength
< sizeof(FILE_STANDARD_INFORMATION
))
443 Status
= STATUS_BUFFER_OVERFLOW
;
447 ok(StandardInfo
!= NULL
, "Null pointer!\n");
448 ok(Fcb
!= NULL
, "Null pointer!\n");
450 StandardInfo
->AllocationSize
= Fcb
->Header
.AllocationSize
;
451 StandardInfo
->EndOfFile
= Fcb
->Header
.FileSize
;
452 StandardInfo
->Directory
= FALSE
;
453 StandardInfo
->NumberOfLinks
= 1;
454 StandardInfo
->DeletePending
= FALSE
;
456 Irp
->IoStatus
.Information
= sizeof(FILE_STANDARD_INFORMATION
);
457 Status
= STATUS_SUCCESS
;
462 Status
= STATUS_NOT_IMPLEMENTED
;
465 else if (IoStack
->MajorFunction
== IRP_MJ_SET_INFORMATION
)
467 Fcb
= IoStack
->FileObject
->FsContext
;
469 ok_eq_pointer(DeviceObject
, TestDeviceObject
);
470 ok_eq_pointer(IoStack
->FileObject
, TestFileObject
);
471 ok_eq_ulong(IoStack
->Parameters
.SetFile
.FileInformationClass
, FileEndOfFileInformation
);
473 if (IoStack
->Parameters
.SetFile
.FileInformationClass
== FileEndOfFileInformation
)
475 PFILE_END_OF_FILE_INFORMATION EOFInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
476 ULONG BufferLength
= IoStack
->Parameters
.SetFile
.Length
;
478 if (BufferLength
< sizeof(FILE_END_OF_FILE_INFORMATION
))
480 Status
= STATUS_BUFFER_OVERFLOW
;
486 ok(EOFInfo
!= NULL
, "Null pointer!\n");
487 ok(Fcb
!= NULL
, "Null pointer!\n");
488 ok_bool_false(IoStack
->Parameters
.SetFile
.AdvanceOnly
, "AdvanceOnly set!\n");
489 ok(EOFInfo
->EndOfFile
.QuadPart
> Fcb
->Header
.AllocationSize
.QuadPart
, "New size smaller\n");
491 if (Fcb
->Header
.AllocationSize
.QuadPart
!= 0)
496 Fcb
->Header
.AllocationSize
.QuadPart
= EOFInfo
->EndOfFile
.QuadPart
;
497 ok_eq_ulong(Fcb
->Header
.FileSize
.QuadPart
, TestSize
);
498 ok_eq_ulong(Fcb
->Header
.ValidDataLength
.QuadPart
, TestSize
);
500 if (CcIsFileCached(IoStack
->FileObject
))
502 CcSetFileSizes(IoStack
->FileObject
, (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
505 ok_eq_ulong(Fcb
->Header
.FileSize
.QuadPart
, TestSize
);
506 ok_eq_ulong(Fcb
->Header
.ValidDataLength
.QuadPart
, TestSize
);
508 Status
= STATUS_SUCCESS
;
513 Status
= STATUS_NOT_IMPLEMENTED
;
517 if (Status
== STATUS_PENDING
)
519 IoMarkIrpPending(Irp
);
520 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
521 Status
= STATUS_PENDING
;
525 Irp
->IoStatus
.Status
= Status
;
526 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);