mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 19:26:33 +00:00
[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. svn path=/trunk/; revision=69322
This commit is contained in:
@@ -111,6 +111,7 @@ list(APPEND KMTEST_SOURCE
|
||||
|
||||
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_custom_target(kmtest_drivers)
|
||||
add_dependencies(kmtest_drivers
|
||||
kmtest_drv
|
||||
example_drv
|
||||
iocreatefile_drv
|
||||
iodeviceobject_drv
|
||||
iohelper_drv
|
||||
ioreadwrite_drv
|
||||
|
||||
@@ -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 @@ const KMT_TEST TestList[] =
|
||||
{
|
||||
{ "-Example", Test_Example },
|
||||
{ "FindFile", Test_FindFile },
|
||||
{ "IoCreateFile", Test_IoCreateFile },
|
||||
{ "IoDeviceObject", Test_IoDeviceObject },
|
||||
{ "IoReadWrite", Test_IoReadWrite },
|
||||
{ "RtlAvlTree", Test_RtlAvlTree },
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
@@ -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 <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _KMTEST_IOCREATEFILE_H_
|
||||
#define _KMTEST_IOCREATEFILE_H_
|
||||
|
||||
#define IOCTL_CREATE_SYMLINK 1
|
||||
#define IOCTL_CREATE_NO_SYMLINK 2
|
||||
|
||||
#endif /* !defined _KMTEST_IOCREATEFILE_H_ */
|
||||
@@ -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 <[email protected]>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <[email protected]>
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
Reference in New Issue
Block a user