Author: pschweitzer Date: Tue Sep 22 22:31:08 2015 New Revision: 69322
URL: http://svn.reactos.org/svn/reactos?rev=69322&view=rev Log: [KMTESTS:IO] Extend the IoCreateFile tests with two parts tests. First part properly checks for opening/reparse handling on mount points (and ideally on symlinks, see below). The other part checks for proper handling of the IO_STOP_ON_SYMLINK parameter.
Regarding symlink, I'm clearly not convinced that what I did is correct (hence the failure on both W2K3 & ROS). It seems to me that symlink resolution is up to the FSD and not to IO which only handles mount point traversal. If someone (Alex?) can confirm/infirm and give more insight, that's more than welcome.
Added: trunk/rostests/kmtests/ntos_io/IoCreateFile.h (with props) trunk/rostests/kmtests/ntos_io/IoCreateFile_drv.c (with props) trunk/rostests/kmtests/ntos_io/IoCreateFile_user.c (with props) Modified: trunk/rostests/kmtests/CMakeLists.txt trunk/rostests/kmtests/kmtest/testlist.c trunk/rostests/kmtests/ntos_io/CMakeLists.txt
Modified: trunk/rostests/kmtests/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/CMakeLists.txt?rev... ============================================================================== --- trunk/rostests/kmtests/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/kmtests/CMakeLists.txt [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -111,6 +111,7 @@
example/Example_user.c kernel32/FindFile_user.c + ntos_io/IoCreateFile_user.c ntos_io/IoDeviceObject_user.c ntos_io/IoReadWrite_user.c tcpip/TcpIp_user.c @@ -134,6 +135,7 @@ add_dependencies(kmtest_drivers kmtest_drv example_drv + iocreatefile_drv iodeviceobject_drv iohelper_drv ioreadwrite_drv
Modified: trunk/rostests/kmtests/kmtest/testlist.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/kmtest/testlist.c?... ============================================================================== --- trunk/rostests/kmtests/kmtest/testlist.c [iso-8859-1] (original) +++ trunk/rostests/kmtests/kmtest/testlist.c [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -9,6 +9,7 @@
KMT_TESTFUNC Test_Example; KMT_TESTFUNC Test_FindFile; +KMT_TESTFUNC Test_IoCreateFile; KMT_TESTFUNC Test_IoDeviceObject; KMT_TESTFUNC Test_IoReadWrite; KMT_TESTFUNC Test_RtlAvlTree; @@ -27,6 +28,7 @@ { { "-Example", Test_Example }, { "FindFile", Test_FindFile }, + { "IoCreateFile", Test_IoCreateFile }, { "IoDeviceObject", Test_IoDeviceObject }, { "IoReadWrite", Test_IoReadWrite }, { "RtlAvlTree", Test_RtlAvlTree },
Modified: trunk/rostests/kmtests/ntos_io/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_io/CMakeLists... ============================================================================== --- trunk/rostests/kmtests/ntos_io/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/kmtests/ntos_io/CMakeLists.txt [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -1,5 +1,20 @@
include_directories(../include) + +# +# IoCreateFile +# +list(APPEND IOCREATEFILE_DRV_SOURCE + ../kmtest_drv/kmtest_standalone.c + IoCreateFile_drv.c) + +add_library(iocreatefile_drv SHARED ${IOCREATEFILE_DRV_SOURCE}) +set_module_type(iocreatefile_drv kernelmodedriver) +target_link_libraries(iocreatefile_drv kmtest_printf ${PSEH_LIB}) +add_importlibs(iocreatefile_drv ntoskrnl hal) +add_target_compile_definitions(iocreatefile_drv KMT_STANDALONE_DRIVER) +#add_pch(iocreatefile_drv ../include/kmt_test.h) +add_cd_file(TARGET iocreatefile_drv DESTINATION reactos/bin FOR all)
# # IoDeviceObject
Added: trunk/rostests/kmtests/ntos_io/IoCreateFile.h URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_io/IoCreateFi... ============================================================================== --- trunk/rostests/kmtests/ntos_io/IoCreateFile.h (added) +++ trunk/rostests/kmtests/ntos_io/IoCreateFile.h [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -0,0 +1,14 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: IoCreateFile test declarations + * PROGRAMMER: Pierre Schweitzer pierre@reactos.org + */ + +#ifndef _KMTEST_IOCREATEFILE_H_ +#define _KMTEST_IOCREATEFILE_H_ + +#define IOCTL_CREATE_SYMLINK 1 +#define IOCTL_CREATE_NO_SYMLINK 2 + +#endif /* !defined _KMTEST_IOCREATEFILE_H_ */
Propchange: trunk/rostests/kmtests/ntos_io/IoCreateFile.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rostests/kmtests/ntos_io/IoCreateFile_drv.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_io/IoCreateFi... ============================================================================== --- trunk/rostests/kmtests/ntos_io/IoCreateFile_drv.c (added) +++ trunk/rostests/kmtests/ntos_io/IoCreateFile_drv.c [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -0,0 +1,270 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test driver for reparse point operations + * PROGRAMMER: Pierre Schweitzer pierre@reactos.org + */ + +#include <kmt_test.h> + +#define NDEBUG +#include <debug.h> + +#include "IoCreateFile.h" + +typedef struct _TEST_FCB +{ + FSRTL_ADVANCED_FCB_HEADER Header; + SECTION_OBJECT_POINTERS SectionObjectPointers; + FAST_MUTEX HeaderMutex; +} TEST_FCB, *PTEST_FCB; + +static KMT_IRP_HANDLER TestIrpHandler; +static KMT_MESSAGE_HANDLER TestMessageHandler; + +static PFILE_OBJECT TestFileObject; +static PDEVICE_OBJECT TestDeviceObject; + +NTSTATUS +TestEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PCUNICODE_STRING RegistryPath, + _Out_ PCWSTR *DeviceName, + _Inout_ INT *Flags) +{ + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(RegistryPath); + + *DeviceName = L"IoCreateFile"; + *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | + TESTENTRY_BUFFERED_IO_DEVICE | + TESTENTRY_NO_READONLY_DEVICE; + + KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler); + KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler); + KmtRegisterMessageHandler(0, NULL, TestMessageHandler); + + return Status; +} + +VOID +TestUnload( + _In_ PDRIVER_OBJECT DriverObject) +{ + PAGED_CODE(); +} + +static +NTSTATUS +TestIrpHandler( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp, + _In_ PIO_STACK_LOCATION IoStack) +{ + NTSTATUS Status; + PTEST_FCB Fcb; + CACHE_UNINITIALIZE_EVENT CacheUninitEvent; + + PAGED_CODE(); + + DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction); + ASSERT(IoStack->MajorFunction == IRP_MJ_CREATE || + IoStack->MajorFunction == IRP_MJ_CLEANUP); + + Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + + if (IoStack->MajorFunction == IRP_MJ_CREATE) + { + ok((IoStack->Parameters.Create.Options & FILE_OPEN_REPARSE_POINT) == 0, "FILE_OPEN_REPARSE_POINT set\n"); + ok((IoStack->Flags == 0) || (IoStack->Flags == SL_STOP_ON_SYMLINK), "IoStack->Flags = %lx\n", IoStack->Flags); + + if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR)) + { + TestDeviceObject = DeviceObject; + TestFileObject = IoStack->FileObject; + } + if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) && + IoStack->FileObject->FileName.Buffer[1] == 'M') + { + PREPARSE_DATA_BUFFER Reparse; + + Irp->Tail.Overlay.AuxiliaryBuffer = ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, 'FwrI'); + Reparse = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; + + RtlZeroMemory(Reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + Reparse->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + Reparse->ReparseDataLength = 12 + sizeof(L"\??\C:\Documents and Settings"); + Reparse->MountPointReparseBuffer.SubstituteNameLength = sizeof(L"\??\C:\Documents and Settings") - sizeof(UNICODE_NULL); + Reparse->MountPointReparseBuffer.PrintNameOffset = sizeof(L"\??\C:\Documents and Settings"); + RtlCopyMemory(Reparse->MountPointReparseBuffer.PathBuffer, L"\??\C:\Documents and Settings", sizeof(L"\??\C:\Documents and Settings")); + Irp->IoStatus.Information = IO_REPARSE_TAG_MOUNT_POINT; + Status = STATUS_REPARSE; + } + else if (IoStack->FileObject->FileName.Length >= 2 * sizeof(WCHAR) && + IoStack->FileObject->FileName.Buffer[1] == 'S') + { + if (IoStack->Flags & SL_STOP_ON_SYMLINK) + { + Status = STATUS_STOPPED_ON_SYMLINK; + } + else + { + PREPARSE_DATA_BUFFER Reparse; + + Irp->Tail.Overlay.AuxiliaryBuffer = ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, 'FwrI'); + Reparse = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; + + RtlZeroMemory(Reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK; + Reparse->ReparseDataLength = 12 + sizeof(L"\??\C:\Documents and Settings"); + Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength = sizeof(L"\??\C:\Documents and Settings") - sizeof(UNICODE_NULL); + Reparse->SymbolicLinkReparseBuffer.PrintNameOffset = sizeof(L"\??\C:\Documents and Settings"); + RtlCopyMemory(Reparse->SymbolicLinkReparseBuffer.PathBuffer, L"\??\C:\Documents and Settings", sizeof(L"\??\C:\Documents and Settings")); + Irp->IoStatus.Information = IO_REPARSE_TAG_SYMLINK; + Status = STATUS_REPARSE; + } + } + else + { + Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Fcb), 'FwrI'); + RtlZeroMemory(Fcb, sizeof(*Fcb)); + ExInitializeFastMutex(&Fcb->HeaderMutex); + FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex); + Fcb->Header.AllocationSize.QuadPart = 0; + Fcb->Header.FileSize.QuadPart = 0; + Fcb->Header.ValidDataLength.QuadPart = 0; + IoStack->FileObject->FsContext = Fcb; + IoStack->FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; + + Irp->IoStatus.Information = FILE_OPENED; + Status = STATUS_SUCCESS; + } + } + else if (IoStack->MajorFunction == IRP_MJ_CLEANUP) + { + KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE); + CcUninitializeCacheMap(IoStack->FileObject, NULL, &CacheUninitEvent); + KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL); + Fcb = IoStack->FileObject->FsContext; + ExFreePoolWithTag(Fcb, 'FwrI'); + IoStack->FileObject->FsContext = NULL; + Status = STATUS_SUCCESS; + } + + if (Status == STATUS_PENDING) + { + IoMarkIrpPending(Irp); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + Status = STATUS_PENDING; + } + else + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return Status; +} + +static UNICODE_STRING FileObjectFileName = RTL_CONSTANT_STRING(L"\NonSymlinked"); +static UNICODE_STRING DocumentsAndSettings = RTL_CONSTANT_STRING(L"\Documents and Settings"); + +static +NTSTATUS +TestIoCreateFile( + IN PUNICODE_STRING Path, + IN BOOLEAN NoLinks) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE Handle; + NTSTATUS Status; + PFILE_OBJECT FileObject; + + InitializeObjectAttributes(&ObjectAttributes, + Path, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = IoCreateFile(&Handle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, + NULL, + 0, + CreateFileTypeNone, + NULL, + IO_NO_PARAMETER_CHECKING | (NoLinks ? IO_STOP_ON_SYMLINK : 0)); + if (NT_SUCCESS(Status)) + { + NTSTATUS IntStatus; + + IntStatus = ObReferenceObjectByHandle(Handle, + FILE_READ_DATA, + *IoFileObjectType, + KernelMode, + (PVOID *)&FileObject, + NULL); + ok_eq_hex(IntStatus, STATUS_SUCCESS); + if (NT_SUCCESS(IntStatus)) + { + ok(RtlCompareUnicodeString(&FileObjectFileName, &FileObject->FileName, TRUE) == 0 || + RtlCompareUnicodeString(&DocumentsAndSettings, &FileObject->FileName, TRUE) == 0, + "Expected: %wZ or %wZ. Opened: %wZ\n", &FileObjectFileName, &DocumentsAndSettings, &FileObject->FileName); + ObDereferenceObject(FileObject); + } + NtClose(Handle); + } + + return Status; +} + +static +NTSTATUS +TestMessageHandler( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN PVOID Buffer OPTIONAL, + IN SIZE_T InLength, + IN OUT PSIZE_T OutLength) +{ + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + switch (ControlCode) + { + case IOCTL_CREATE_SYMLINK: + case IOCTL_CREATE_NO_SYMLINK: + { + ANSI_STRING Path; + UNICODE_STRING PathW; + + ok(Buffer != NULL, "Buffer is NULL\n"); + Path.Length = Path.MaximumLength = (USHORT)InLength; + Path.Buffer = Buffer; + + Status = RtlAnsiStringToUnicodeString(&PathW, &Path, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + + Status = TestIoCreateFile(&PathW, (ControlCode == IOCTL_CREATE_NO_SYMLINK)); + + RtlFreeUnicodeString(&PathW); + + break; + } + default: + return STATUS_NOT_SUPPORTED; + } + + return Status; +}
Propchange: trunk/rostests/kmtests/ntos_io/IoCreateFile_drv.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rostests/kmtests/ntos_io/IoCreateFile_user.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_io/IoCreateFi... ============================================================================== --- trunk/rostests/kmtests/ntos_io/IoCreateFile_user.c (added) +++ trunk/rostests/kmtests/ntos_io/IoCreateFile_user.c [iso-8859-1] Tue Sep 22 22:31:08 2015 @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Reparse points test user-mode part + * PROGRAMMER: Pierre Schweitzer pierre@reactos.org + */ + +#include <kmt_test.h> +#include "IoCreateFile.h" + +static CHAR MountedPointFileName[] = "\Device\Kmtest-IoCreateFile\MountedPoint"; +static CHAR SymlinkedFileName[] = "\Device\Kmtest-IoCreateFile\Symlinked"; +static CHAR NonSymlinkedFileName[] = "\Device\Kmtest-IoCreateFile\NonSymlinked"; + +START_TEST(IoCreateFile) +{ + DWORD Error; + + KmtRunKernelTest("IoCreateFile"); + + KmtLoadDriver(L"IoCreateFile", FALSE); + KmtOpenDriver(); + + Error = KmtSendStringToDriver(IOCTL_CREATE_SYMLINK, NonSymlinkedFileName); + ok(Error == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %lx\n", Error); + Error = KmtSendStringToDriver(IOCTL_CREATE_SYMLINK, SymlinkedFileName); + ok(Error == ERROR_CANT_ACCESS_FILE, "Expected ERROR_CANT_ACCESS_FILE, got %lx\n", Error); /* FIXME */ + Error = KmtSendStringToDriver(IOCTL_CREATE_SYMLINK, MountedPointFileName); + ok(Error == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %lx\n", Error); + + Error = KmtSendStringToDriver(IOCTL_CREATE_NO_SYMLINK, NonSymlinkedFileName); + ok(Error == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %lx\n", Error); + Error = KmtSendStringToDriver(IOCTL_CREATE_NO_SYMLINK, SymlinkedFileName); + ok(Error == ERROR_MR_MID_NOT_FOUND, "Expected ERROR_MR_MID_NOT_FOUND, got %lx\n", Error); + Error = KmtSendStringToDriver(IOCTL_CREATE_NO_SYMLINK, MountedPointFileName); + ok(Error == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %lx\n", Error); + + KmtCloseDriver(); + KmtUnloadDriver(); +}
Propchange: trunk/rostests/kmtests/ntos_io/IoCreateFile_user.c ------------------------------------------------------------------------------ svn:eol-style = native