From 57dd4b34c78f8ad8b16cecae2bff78e8da0233cb Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Thu, 12 Nov 2015 13:13:54 +0000 Subject: [PATCH 1/1] [KMTESTS:IO] - Add a test trying assorted path variations to open files CORE-10483 svn path=/trunk/; revision=69878 --- rostests/kmtests/ntos_io/IoFilesystem.c | 270 ++++++++++++++++++++++++ 1 file changed, 270 insertions(+) diff --git a/rostests/kmtests/ntos_io/IoFilesystem.c b/rostests/kmtests/ntos_io/IoFilesystem.c index 9537c6ca5a2..bcfc5219f90 100644 --- a/rostests/kmtests/ntos_io/IoFilesystem.c +++ b/rostests/kmtests/ntos_io/IoFilesystem.c @@ -9,6 +9,275 @@ /* FIXME: Test this stuff on non-FAT volumes */ +static +VOID +Substitute( + _Out_writes_bytes_(BufferSize) PWCHAR Buffer, + _In_ ULONG BufferSize, + _In_ PCWSTR Template, + _In_ PCWSTR SystemDriveName, + _In_ PCWSTR SystemRootName) +{ + UNICODE_STRING SystemDriveTemplate = RTL_CONSTANT_STRING(L"C:"); + UNICODE_STRING SystemRootTemplate = RTL_CONSTANT_STRING(L"ReactOS"); + ULONG SystemDriveLength; + ULONG SystemRootLength; + PWCHAR Dest = Buffer; + UNICODE_STRING String; + + SystemDriveLength = wcslen(SystemDriveName) * sizeof(WCHAR); + SystemRootLength = wcslen(SystemRootName) * sizeof(WCHAR); + + RtlInitUnicodeString(&String, Template); + ASSERT(String.Length % sizeof(WCHAR) == 0); + while (String.Length) + { + if (RtlPrefixUnicodeString(&SystemDriveTemplate, &String, TRUE)) + { + ASSERT((Dest - Buffer) * sizeof(WCHAR) + SystemDriveLength < BufferSize); + RtlCopyMemory(Dest, + SystemDriveName, + SystemDriveLength); + Dest += SystemDriveLength / sizeof(WCHAR); + + String.Buffer += SystemDriveTemplate.Length / sizeof(WCHAR); + String.Length -= SystemDriveTemplate.Length; + String.MaximumLength -= SystemDriveTemplate.Length; + continue; + } + + if (RtlPrefixUnicodeString(&SystemRootTemplate, &String, TRUE)) + { + ASSERT((Dest - Buffer) * sizeof(WCHAR) + SystemRootLength < BufferSize); + RtlCopyMemory(Dest, + SystemRootName, + SystemRootLength); + Dest += SystemRootLength / sizeof(WCHAR); + + String.Buffer += SystemRootTemplate.Length / sizeof(WCHAR); + String.Length -= SystemRootTemplate.Length; + String.MaximumLength -= SystemRootTemplate.Length; + continue; + } + + ASSERT(Dest - Buffer < BufferSize / sizeof(WCHAR)); + *Dest++ = String.Buffer[0]; + + String.Buffer++; + String.Length -= sizeof(WCHAR); + String.MaximumLength -= sizeof(WCHAR); + } + ASSERT(Dest - Buffer < BufferSize / sizeof(WCHAR)); + *Dest = UNICODE_NULL; +} + +static +VOID +TestRelativeNames(VOID) +{ + NTSTATUS Status; + struct + { + PCWSTR ParentPathTemplate; + PCWSTR RelativePathTemplate; + BOOLEAN IsDirectory; + NTSTATUS Status; + } Tests[] = + { + { NULL, L"C:\\", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\\\", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\\\\\", TRUE, STATUS_OBJECT_NAME_INVALID }, + { NULL, L"C:\\ReactOS", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\ReactOS\\", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\ReactOS\\\\", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\ReactOS\\\\\\", TRUE, STATUS_OBJECT_NAME_INVALID }, + { NULL, L"C:\\\\ReactOS", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\\\ReactOS\\", TRUE, STATUS_SUCCESS }, + { NULL, L"C:\\ReactOS\\explorer.exe", FALSE, STATUS_SUCCESS }, + { NULL, L"C:\\ReactOS\\\\explorer.exe", FALSE, STATUS_OBJECT_NAME_INVALID }, + { NULL, L"C:\\ReactOS\\explorer.exe\\", FALSE, STATUS_OBJECT_NAME_INVALID }, + { NULL, L"C:\\ReactOS\\explorer.exe\\\\", FALSE, STATUS_OBJECT_NAME_INVALID }, + /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */ + { NULL, L"C:\\ReactOS\\explorer.exe\\\\\\", TRUE, STATUS_OBJECT_NAME_INVALID }, + { L"C:\\", L"", TRUE, STATUS_SUCCESS }, + { L"C:\\", L"\\", TRUE, STATUS_OBJECT_NAME_INVALID }, + { L"C:\\", L"ReactOS", TRUE, STATUS_SUCCESS }, + { L"C:\\", L"\\ReactOS", TRUE, STATUS_OBJECT_NAME_INVALID }, + { L"C:\\", L"ReactOS\\", TRUE, STATUS_SUCCESS }, + { L"C:\\", L"\\ReactOS\\", TRUE, STATUS_OBJECT_NAME_INVALID }, + { L"C:\\ReactOS", L"", TRUE, STATUS_SUCCESS }, + { L"C:\\ReactOS", L"explorer.exe", FALSE, STATUS_SUCCESS }, + { L"C:\\ReactOS\\explorer.exe", L"", FALSE, STATUS_SUCCESS }, + /* Let's try some nonexistent things */ + { NULL, L"C:\\ReactOS\\IDoNotExist", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\IDoNotExist\\file", FALSE, STATUS_OBJECT_PATH_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\IDoNotExist\\file?", FALSE, STATUS_OBJECT_PATH_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE,STATUS_OBJECT_PATH_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE,STATUS_OBJECT_PATH_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\AmIInvalid?", FALSE, STATUS_OBJECT_NAME_INVALID }, + { NULL, L"C:\\ReactOS\\.", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\..", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { NULL, L"C:\\ReactOS\\...", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\", L".", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\", L"..", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\", L"...", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\ReactOS", L".", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\ReactOS", L"..", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + { L"C:\\ReactOS", L"...", FALSE, STATUS_OBJECT_NAME_NOT_FOUND }, + }; + ULONG i; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + UNICODE_STRING ParentPath; + UNICODE_STRING RelativePath; + HANDLE ParentHandle; + HANDLE FileHandle; + UNICODE_STRING SystemRoot = RTL_CONSTANT_STRING(L"\\SystemRoot"); + HANDLE SymbolicLinkHandle = NULL; + WCHAR LinkNameBuffer[128]; + UNICODE_STRING SymbolicLinkName; + PWSTR SystemDriveName; + PWSTR SystemRootName; + PWCHAR Buffer = NULL; + BOOLEAN TrailingBackslash; + + /* Query \SystemRoot */ + InitializeObjectAttributes(&ObjectAttributes, + &SystemRoot, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenSymbolicLinkObject(&SymbolicLinkHandle, + GENERIC_READ, + &ObjectAttributes); + if (skip(NT_SUCCESS(Status), "Failed to open SystemRoot, %lx\n", Status)) + return; + + RtlInitEmptyUnicodeString(&SymbolicLinkName, + LinkNameBuffer, + sizeof(LinkNameBuffer)); + Status = ZwQuerySymbolicLinkObject(SymbolicLinkHandle, + &SymbolicLinkName, + NULL); + ObCloseHandle(SymbolicLinkHandle, KernelMode); + if (skip(NT_SUCCESS(Status), "Failed to query SystemRoot, %lx\n", Status)) + return; + + /* Split SymbolicLinkName into drive and path */ + SystemDriveName = SymbolicLinkName.Buffer; + SystemRootName = SymbolicLinkName.Buffer + SymbolicLinkName.Length / sizeof(WCHAR); + *SystemRootName-- = UNICODE_NULL; + while (*SystemRootName != L'\\') + { + ASSERT(SystemRootName > SymbolicLinkName.Buffer); + SystemRootName--; + } + *SystemRootName++ = UNICODE_NULL; + trace("System Drive: '%ls'\n", SystemDriveName); + trace("System Root: '%ls'\n", SystemRootName); + + /* Allocate path buffer */ + Buffer = ExAllocatePoolWithTag(PagedPool, MAXUSHORT, 'sFmK'); + if (skip(Buffer != NULL, "No buffer\n")) + return; + + /* Finally run some tests! */ + for (i = 0; i < RTL_NUMBER_OF(Tests); i++) + { + /* Open parent directory first */ + ParentHandle = NULL; + if (Tests[i].ParentPathTemplate) + { + Substitute(Buffer, + MAXUSHORT, + Tests[i].ParentPathTemplate, + SystemDriveName, + SystemRootName); + RtlInitUnicodeString(&ParentPath, Buffer); + InitializeObjectAttributes(&ObjectAttributes, + &ParentPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&ParentHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok(Status == STATUS_SUCCESS, + "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i, Status); + if (skip(NT_SUCCESS(Status), "No parent handle %lu\n", i)) + continue; + } + + /* Now open the relative file: */ + Substitute(Buffer, + MAXUSHORT, + Tests[i].RelativePathTemplate, + SystemDriveName, + SystemRootName); + RtlInitUnicodeString(&RelativePath, Buffer); + InitializeObjectAttributes(&ObjectAttributes, + &RelativePath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + ParentHandle, + NULL); + TrailingBackslash = FALSE; + if (wcslen(Buffer) && Buffer[wcslen(Buffer) - 1] == L'\\') + TrailingBackslash = TRUE; + + /* (1) No flags */ + Status = ZwOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok(Status == Tests[i].Status, + "[%lu] Status = %lx, expected %lx\n", i, Status, Tests[i].Status); + if (NT_SUCCESS(Status)) + ObCloseHandle(FileHandle, KernelMode); + + /* (2) Directory File */ + Status = ZwOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE); + if (Tests[i].IsDirectory || (!TrailingBackslash && !NT_SUCCESS(Tests[i].Status))) + ok(Status == Tests[i].Status, + "[%lu] Status = %lx, expected %lx\n", i, Status, Tests[i].Status); + else + ok(Status == STATUS_NOT_A_DIRECTORY, + "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i, Status); + if (NT_SUCCESS(Status)) + ObCloseHandle(FileHandle, KernelMode); + + /* (3) Non-Directory File */ + Status = ZwOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_NON_DIRECTORY_FILE); + if (Tests[i].IsDirectory && NT_SUCCESS(Tests[i].Status)) + ok(Status == STATUS_FILE_IS_A_DIRECTORY, + "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i, Status); + else + ok(Status == Tests[i].Status, + "[%lu] Status = %lx, expected %lx\n", i, Status, Tests[i].Status); + if (NT_SUCCESS(Status)) + ObCloseHandle(FileHandle, KernelMode); + + /* And close */ + ObCloseHandle(ParentHandle, KernelMode); + } + + ExFreePoolWithTag(Buffer, 'sFmK'); +} + static VOID TestSharedCacheMap(VOID) @@ -174,5 +443,6 @@ Cleanup: START_TEST(IoFilesystem) { + TestRelativeNames(); TestSharedCacheMap(); } -- 2.17.1