Index: fcb.c =================================================================== --- drivers/filesystems/fastfat/fcb.c (revision 69845) +++ drivers/filesystems/fastfat/fcb.c (working copy) @@ -143,6 +143,7 @@ } else rcFCB->Attributes = &rcFCB->entry.Fat.Attrib; + ASSERT((*rcFCB->Attributes & _A_VOLID) == 0); rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU); rcFCB->Hash.self = rcFCB; rcFCB->ShortHash.self = rcFCB; @@ -436,7 +437,7 @@ HASHENTRY* entry; DPRINT("'%wZ'\n", PathNameU); - +ASSERT(PathNameU->Length >= sizeof(WCHAR) && PathNameU->Buffer[0] == L'\\'); Hash = vfatNameHash(0, PathNameU); entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize]; @@ -790,182 +791,293 @@ NTSTATUS status; PVFATFCB FCB = NULL; PVFATFCB parentFCB; - UNICODE_STRING NameU; UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\"); UNICODE_STRING FileNameU; WCHAR NameBuffer[260]; - PWCHAR curr, prev, last; - ULONG Length; + UNICODE_STRING Component; + UNICODE_STRING PartialName; + PWCHAR Previous, Current, Last; + //BOOLEAN TrailingBackslash; DPRINT("vfatGetFCBForFile (%p,%p,%p,%wZ)\n", pVCB, pParentFCB, pFCB, pFileNameU); - FileNameU.Buffer = NameBuffer; - FileNameU.MaximumLength = sizeof(NameBuffer); - RtlCopyUnicodeString(&FileNameU, pFileNameU); + RtlInitEmptyUnicodeString(&FileNameU, NameBuffer, sizeof(NameBuffer)); parentFCB = *pParentFCB; + // trailing backslash && !directory -> STATUS_OBJECT_NAME_INVALID + // STATUS_OBJECT_NAME_INVALID if too long if (parentFCB == NULL) { - // Trivial case, open of the root directory on volume - if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE)) - { - DPRINT("returning root FCB\n"); + /* Absolute path must start with a \ */ + ASSERT(pFileNameU->Length >= sizeof(WCHAR) && pFileNameU->Buffer[0] == L'\\'); - FCB = vfatOpenRootFCB(pVCB); - *pFCB = FCB; - *pParentFCB = NULL; + /* Already the full name, just copy it */ + ASSERT(pFileNameU->Length <= FileNameU.MaximumLength); + RtlCopyUnicodeString(&FileNameU, pFileNameU); + } + else + { + /* Starting with a \ is not allowed */ + if (pFileNameU->Length >= sizeof(WCHAR)) + ASSERT(pFileNameU->Buffer[0] != L'\\'); // STATUS_OBJECT_NAME_INVALID if leading backslash - return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Check for an existing FCB */ - FCB = vfatGrabFCBFromTable(pVCB, &FileNameU); - if (FCB) + if (parentFCB->PathNameU.Length == sizeof(WCHAR)) { - *pFCB = FCB; - *pParentFCB = FCB->parentFcb; - vfatGrabFCB(pVCB, *pParentFCB); - return STATUS_SUCCESS; - } + /* Parent is the Root, already has a backslash */ + ASSERT(parentFCB->PathNameU.Buffer[0] == L'\\'); - last = curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; - while (*curr != L'\\' && curr > FileNameU.Buffer) - { - curr--; - } + /* Parent directory */ + ASSERT(parentFCB->PathNameU.Length <= FileNameU.MaximumLength); + RtlCopyUnicodeString(&FileNameU, &parentFCB->PathNameU); - if (curr > FileNameU.Buffer) - { - NameU.Buffer = FileNameU.Buffer; - NameU.MaximumLength = NameU.Length = (curr - FileNameU.Buffer) * sizeof(WCHAR); - FCB = vfatGrabFCBFromTable(pVCB, &NameU); - if (FCB) - { - Length = (curr - FileNameU.Buffer) * sizeof(WCHAR); - if (Length != FCB->PathNameU.Length) - { - if (FileNameU.Length + FCB->PathNameU.Length - Length > FileNameU.MaximumLength) - { - vfatReleaseFCB(pVCB, FCB); - return STATUS_OBJECT_NAME_INVALID; - } - RtlMoveMemory(FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR), - curr, FileNameU.Length - Length); - FileNameU.Length += (USHORT)(FCB->PathNameU.Length - Length); - curr = FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR); - last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; - } - RtlCopyMemory(FileNameU.Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length); - } + /* Relative path */ + ASSERT(parentFCB->PathNameU.Length + pFileNameU->Length <= FileNameU.MaximumLength); + status = RtlAppendUnicodeStringToString(&FileNameU, pFileNameU); + ASSERT(status == STATUS_SUCCESS); } else { - FCB = NULL; - } + /* Parent is not the root, should not end with backslash */ + ASSERT(parentFCB->PathNameU.Length >= sizeof(WCHAR)); + ASSERT(parentFCB->PathNameU.Buffer[parentFCB->PathNameU.Length / sizeof(WCHAR) - 1] != L'\\'); - if (FCB == NULL) - { - FCB = vfatOpenRootFCB(pVCB); - curr = FileNameU.Buffer; + /* Parent directory */ + ASSERT(parentFCB->PathNameU.Length <= FileNameU.MaximumLength); + RtlCopyUnicodeString(&FileNameU, &parentFCB->PathNameU); + + /* Backslash */ + ASSERT(parentFCB->PathNameU.Length + RootNameU.Length <= FileNameU.MaximumLength); + status = RtlAppendUnicodeStringToString(&FileNameU, &RootNameU); + ASSERT(status == STATUS_SUCCESS); + + /* Relative path */ + ASSERT(parentFCB->PathNameU.Length + RootNameU.Length + pFileNameU->Length <= FileNameU.MaximumLength); + status = RtlAppendUnicodeStringToString(&FileNameU, pFileNameU); + ASSERT(status == STATUS_SUCCESS); } + vfatReleaseFCB(pVCB, parentFCB); parentFCB = NULL; - prev = curr; } - else + + /* Now we must have an absolute path */ + ASSERT(FileNameU.Length >= sizeof(WCHAR) && FileNameU.Buffer[0] == L'\\'); + ASSERT(parentFCB == NULL); + + if (FileNameU.Buffer[FileNameU.Length / sizeof(WCHAR) - 1] == L'\\') { - FCB = parentFCB; - parentFCB = NULL; - prev = curr = FileNameU.Buffer - 1; - last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; + //TrailingBackslash = TRUE; + FileNameU.Length -= sizeof(WCHAR); } - while (curr <= last) + /* Keep a pointer to the last character */ + Last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; + + /* PartialName is a substring of the full file name */ + PartialName = FileNameU; + + /* We start off with the root directory */ + FCB = vfatOpenRootFCB(pVCB); + Previous = Current = FileNameU.Buffer + 1; + PartialName.Length = sizeof(WCHAR); + RtlInitEmptyUnicodeString(&Component, + Current, + FileNameU.MaximumLength - sizeof(WCHAR)); + + status = STATUS_SUCCESS; + while (Current <= Last) { + /* FCB will become our parentFCB, we don't need its parent anymore */ if (parentFCB) { vfatReleaseFCB(pVCB, parentFCB); parentFCB = NULL; } - // fail if element in FCB is not a directory + + /* To be a parent, FCB needs to represent a directory */ if (!vfatFCBIsDirectory(FCB)) { - DPRINT ("Element in requested path is not a directory\n"); + DPRINT("Element in requested path is not a directory\n"); vfatReleaseFCB(pVCB, FCB); FCB = NULL; - *pParentFCB = NULL; - *pFCB = NULL; + status = STATUS_OBJECT_PATH_NOT_FOUND; + break; + } - return STATUS_OBJECT_PATH_NOT_FOUND; - } parentFCB = FCB; - if (prev < curr) + + /* Loop entry invariants */ +#if DBG + /* Previous points behind a path separator, Current... somewhere */ + ASSERT(Last == FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1); + ASSERT(Previous > FileNameU.Buffer); + ASSERT(Previous[-1] == L'\\'); + ASSERT(Previous <= Current); + ASSERT(Previous <= Last); + ASSERT(Current <= Last); + + /* PartialName starts at FileNameU and ends at Current */ + ASSERT(PartialName.Buffer == FileNameU.Buffer); + ASSERT(PartialName.Length == (Current - FileNameU.Buffer) * sizeof(WCHAR)); + ASSERT(PartialName.MaximumLength == FileNameU.MaximumLength); + + /* Component starts at Previous and ends at Current */ + ASSERT(Component.Buffer == Previous); + ASSERT(Component.Length == (Current - Previous) * sizeof(WCHAR)); + ASSERT(Component.MaximumLength == FileNameU.MaximumLength - (Previous - FileNameU.Buffer) * sizeof(WCHAR)); +#endif + + /* Fix up the last path component to use the proper cased long name */ + if (Component.Length) { - Length = (curr - prev) * sizeof(WCHAR); - if (Length != parentFCB->LongNameU.Length) + ULONG LengthDifference; + PWCHAR NewCurrent; + + ASSERT(Current > Previous); + ASSERT(parentFCB->LongNameU.Length > 0); + ASSERT(PartialName.Length > sizeof(WCHAR)); + ASSERT(Current == Last + 1 || *Current == L'\\'); + + /* Were we using a short name before and need to move things? */ + if (Component.Length != parentFCB->LongNameU.Length) { - if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength) + /* Does the path still fit if we use the long name? */ + ASSERT(parentFCB->LongNameU.Length > Component.Length); + LengthDifference = parentFCB->LongNameU.Length - Component.Length; + if (FileNameU.Length + LengthDifference > FileNameU.MaximumLength) { vfatReleaseFCB(pVCB, parentFCB); - *pParentFCB = NULL; - *pFCB = NULL; - return STATUS_OBJECT_NAME_INVALID; + parentFCB = NULL; + status = STATUS_OBJECT_NAME_INVALID; + break; } - RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr, - FileNameU.Length - (curr - FileNameU.Buffer) * sizeof(WCHAR)); - FileNameU.Length += (USHORT)(parentFCB->LongNameU.Length - Length); - curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR); - last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; + + /* Move everything starting at Current forward */ + ASSERT(Current == Component.Buffer + Component.Length / sizeof(WCHAR)); + NewCurrent = Component.Buffer + parentFCB->LongNameU.Length / sizeof(WCHAR); + RtlMoveMemory(NewCurrent, + Current, + FileNameU.Length - (Current - FileNameU.Buffer) * sizeof(WCHAR)); + FileNameU.Length += LengthDifference; + PartialName.Length += LengthDifference; + Current = NewCurrent; + Last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; } - RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length); + /* Write the canonical name for the last component */ + RtlCopyUnicodeString(&Component, &parentFCB->LongNameU); } - curr++; - prev = curr; - while (*curr != L'\\' && curr <= last) + else { - curr++; + ASSERT(Current == Previous); + ASSERT(parentFCB->LongNameU.Length == 0); + ASSERT(PartialName.Length == sizeof(WCHAR)); } - NameU.Buffer = FileNameU.Buffer; - NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR); - NameU.MaximumLength = FileNameU.MaximumLength; - DPRINT("%wZ\n", &NameU); - FCB = vfatGrabFCBFromTable(pVCB, &NameU); + + /* Same invariants, plus PartialName is now canonical */ +#if DBG + /* Previous points behind a path separator, Current... somewhere */ + ASSERT(Last == FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1); + ASSERT(Previous > FileNameU.Buffer); + ASSERT(Previous[-1] == L'\\'); + ASSERT(Previous <= Current); + ASSERT(Previous <= Last); + ASSERT(Current <= Last); + + /* PartialName starts at FileNameU and ends at Current */ + ASSERT(PartialName.Buffer == FileNameU.Buffer); + ASSERT(PartialName.Length == (Current - FileNameU.Buffer) * sizeof(WCHAR)); + ASSERT(PartialName.MaximumLength == FileNameU.MaximumLength); + + /* Component starts at Previous and ends at Current */ + ASSERT(Component.Buffer == Previous); + ASSERT(Component.Length == (Current - Previous) * sizeof(WCHAR)); + ASSERT(Component.MaximumLength == FileNameU.MaximumLength - (Previous - FileNameU.Buffer) * sizeof(WCHAR)); + + /* PartialName is the exact name of the new parentFCB */ + FCB = vfatGrabFCBFromTable(pVCB, &PartialName); + ASSERT(FCB); + ASSERT(FCB == parentFCB); + if (FCB) + { + vfatReleaseFCB(pVCB, parentFCB); + } +#endif + + if (Component.Length) + { + ASSERT(*Current = L'\\'); + ASSERT(Current > Previous); + Current++; + } + else + { + ASSERT(Current[-1] == L'\\'); + ASSERT(Current == Previous); + } + + Previous = Current; + while (*Current != L'\\' && Current <= Last) + { + Current++; + } + + Component.Buffer = Previous; + Component.Length = (Current - Previous) * sizeof(WCHAR); + Component.MaximumLength = FileNameU.MaximumLength - (Previous - FileNameU.Buffer) * sizeof(WCHAR); + + if (Component.Length == 0) + { + vfatReleaseFCB(pVCB, parentFCB); + parentFCB = NULL; + status = STATUS_OBJECT_NAME_INVALID; + break; + } + + PartialName.Length = (Current - FileNameU.Buffer) * sizeof(WCHAR); + ASSERT(PartialName.Length <= FileNameU.Length); + + /* See if we have an existing FCB for this partial path */ + FCB = vfatGrabFCBFromTable(pVCB, &PartialName); if (FCB == NULL) { - NameU.Buffer = prev; - NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR); - status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB); - if (status == STATUS_OBJECT_NAME_NOT_FOUND) + /* We don't, so create new FCB for this component */ + ASSERT(parentFCB != NULL); + status = vfatDirFindFile(pVCB, parentFCB, &Component, &FCB); + if (!NT_SUCCESS(status)) { - *pFCB = NULL; - if (curr > last) + ASSERT(FCB == NULL); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - *pParentFCB = parentFCB; - return STATUS_OBJECT_NAME_NOT_FOUND; + if (Current > Last) + { + break; + } + status = STATUS_OBJECT_PATH_NOT_FOUND; } - else - { - vfatReleaseFCB(pVCB, parentFCB); - *pParentFCB = NULL; - return STATUS_OBJECT_PATH_NOT_FOUND; - } + + vfatReleaseFCB(pVCB, parentFCB); + parentFCB = NULL; + break; } - else if (!NT_SUCCESS(status)) + } + + if (*pParentFCB) + { + if (RtlEqualUnicodeString(&(*pParentFCB)->PathNameU, + &PartialName, + TRUE)) { - vfatReleaseFCB(pVCB, parentFCB); - *pParentFCB = NULL; - *pFCB = NULL; - - return status; + ASSERT(FCB == *pParentFCB); } } } + if (!NT_SUCCESS(status)) ASSERT(FCB == NULL); *pParentFCB = parentFCB; *pFCB = FCB; - return STATUS_SUCCESS; + return status; } Index: CMakeLists.txt =================================================================== --- modules/rostests/kmtests/CMakeLists.txt (revision 69845) +++ modules/rostests/kmtests/CMakeLists.txt (working copy) @@ -35,6 +35,7 @@ npfs/NpfsFileInfo.c npfs/NpfsHelpers.c npfs/NpfsReadWrite.c + # npfs/NpfsVolumeInfo.c ntos_cm/CmSecurity.c ntos_ex/ExCallback.c @@ -50,9 +51,11 @@ ntos_fsrtl/FsRtlExpression.c ntos_fsrtl/FsRtlMcb.c ntos_fsrtl/FsRtlTunnel.c + # ntos_io/IoCreateFile.c ntos_io/IoDeviceInterface.c ntos_io/IoEvent.c + ntos_io/IoFilesystem.c ntos_io/IoInterrupt.c ntos_io/IoIrp.c ntos_io/IoMdl.c @@ -60,6 +63,7 @@ ntos_ke/KeDevQueue.c ntos_ke/KeDpc.c ntos_ke/KeEvent.c + # ntos_ke/KeGuardedMutex.c ntos_ke/KeIrql.c ntos_ke/KeMutex.c @@ -87,7 +91,7 @@ add_library(kmtest_drv SHARED ${KMTEST_DRV_SOURCE}) set_module_type(kmtest_drv kernelmodedriver) -target_link_libraries(kmtest_drv kmtest_printf chkstk memcmp ${PSEH_LIB}) +target_link_libraries(kmtest_drv kmtest_printf chkstk wdmguid memcmp ${PSEH_LIB}) add_importlibs(kmtest_drv ntoskrnl hal) add_dependencies(kmtest_drv bugcodes xdk) add_target_compile_definitions(kmtest_drv KMT_KERNEL_MODE NTDDI_VERSION=NTDDI_WS03SP1) Index: kmtest_drv/testlist.c =================================================================== --- modules/rostests/kmtests/kmtest_drv/testlist.c (revision 69845) +++ modules/rostests/kmtests/kmtest_drv/testlist.c (working copy) @@ -23,9 +23,11 @@ KMT_TESTFUNC Test_FsRtlExpression; KMT_TESTFUNC Test_FsRtlMcb; KMT_TESTFUNC Test_FsRtlTunnel; +// KMT_TESTFUNC Test_IoCreateFile; KMT_TESTFUNC Test_IoDeviceInterface; KMT_TESTFUNC Test_IoEvent; +KMT_TESTFUNC Test_IoFilesystem; KMT_TESTFUNC Test_IoInterrupt; KMT_TESTFUNC Test_IoIrp; KMT_TESTFUNC Test_IoMdl; @@ -33,6 +35,7 @@ KMT_TESTFUNC Test_KeDeviceQueue; KMT_TESTFUNC Test_KeDpc; KMT_TESTFUNC Test_KeEvent; +// KMT_TESTFUNC Test_KeGuardedMutex; KMT_TESTFUNC Test_KeIrql; KMT_TESTFUNC Test_KeMutex; @@ -47,6 +50,7 @@ KMT_TESTFUNC Test_NpfsCreate; KMT_TESTFUNC Test_NpfsFileInfo; KMT_TESTFUNC Test_NpfsReadWrite; +// KMT_TESTFUNC Test_NpfsVolumeInfo; KMT_TESTFUNC Test_ObHandle; KMT_TESTFUNC Test_ObReference; @@ -87,9 +91,11 @@ { "FsRtlExpression", Test_FsRtlExpression }, { "FsRtlMcb", Test_FsRtlMcb }, { "FsRtlTunnel", Test_FsRtlTunnel }, + // { "IoCreateFile", Test_IoCreateFile }, { "IoDeviceInterface", Test_IoDeviceInterface }, { "IoEvent", Test_IoEvent }, + { "IoFilesystem", Test_IoFilesystem }, { "IoInterrupt", Test_IoInterrupt }, { "IoIrp", Test_IoIrp }, { "IoMdl", Test_IoMdl }, @@ -97,6 +103,7 @@ { "KeDeviceQueue", Test_KeDeviceQueue }, { "KeDpc", Test_KeDpc }, { "KeEvent", Test_KeEvent }, + // { "KeGuardedMutex", Test_KeGuardedMutex }, { "KeIrql", Test_KeIrql }, { "KeMutex", Test_KeMutex }, @@ -111,6 +118,7 @@ { "NpfsCreate", Test_NpfsCreate }, { "NpfsFileInfo", Test_NpfsFileInfo }, { "NpfsReadWrite", Test_NpfsReadWrite }, + // { "NpfsVolumeInfo", Test_NpfsVolumeInfo }, { "ObHandle", Test_ObHandle }, { "ObReference", Test_ObReference }, Index: ntos_io/IoFilesystem.c =================================================================== --- modules/rostests/kmtests/ntos_io/IoFilesystem.c (revision 0) +++ modules/rostests/kmtests/ntos_io/IoFilesystem.c (working copy) @@ -0,0 +1,445 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test Suite File System test + * PROGRAMMER: Thomas Faber + */ + +#include + +static +VOID +TestBasicInfo(VOID) +{ + NTSTATUS Status; + UNICODE_STRING SystemRoot = RTL_CONSTANT_STRING(L"\\SystemRoot"); + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + HANDLE Handle; + PVOID Object; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + KEVENT Event; + PIRP Irp; + PIO_STACK_LOCATION IoStack; + FILE_BASIC_INFORMATION BasicInfo; + PSECTION_OBJECT_POINTERS SectionObjectPointers; + + InitializeObjectAttributes(&ObjectAttributes, + &SystemRoot, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&Handle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_DIRECTORY_FILE); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No file\n")) + return; + Status = ObReferenceObjectByHandle(Handle, + GENERIC_READ, + *IoFileObjectType, + KernelMode, + &Object, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No file\n")) + { + ObCloseHandle(Handle, KernelMode); + return; + } + FileObject = Object; + SectionObjectPointers = FileObject->SectionObjectPointer; + if (!skip(SectionObjectPointers != NULL, "No section object pointers\n")) + { + trace("DataSectionObject %p\n", SectionObjectPointers->DataSectionObject); + trace("SharedCacheMap %p\n", SectionObjectPointers->SharedCacheMap); + trace("ImageSectionObject %p\n", SectionObjectPointers->ImageSectionObject); + } + Status = ObCloseHandle(Handle, KernelMode); + ok_eq_hex(Status, STATUS_SUCCESS); + DeviceObject = IoGetRelatedDeviceObject(FileObject); + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoAllocateIrp(DeviceObject->StackSize + 1, + FALSE); + if (skip(Irp != NULL, "No IRP\n")) + { + ObDereferenceObject(FileObject); + return; + } + IoSetNextIrpStackLocation(Irp); + IoStack = IoGetCurrentIrpStackLocation(Irp); + IoStack->FileObject = FileObject; + IoStack->MajorFunction = IRP_MJ_QUERY_INFORMATION; + IoStack->Parameters.QueryFile.FileInformationClass = FileBasicInformation; + RtlFillMemory(&BasicInfo, sizeof(BasicInfo), 0x55); + Irp->AssociatedIrp.SystemBuffer = &BasicInfo; + IoStack->Parameters.QueryFile.Length = sizeof(BasicInfo); + if (skip(IoForwardIrpSynchronously(DeviceObject, Irp), "Forward failed\n")) + { + IoFreeIrp(Irp); + ObDereferenceObject(FileObject); + return; + } + ok_eq_hex(Irp->IoStatus.Status, STATUS_SUCCESS); + ok_eq_hex(Irp->IoStatus.Information, sizeof(BasicInfo)); + IoFreeIrp(Irp); + trace("CreationTime: %I64d\n", BasicInfo.CreationTime.QuadPart); + trace("LastAccessTime: %I64d\n", BasicInfo.LastAccessTime.QuadPart); + trace("LastWriteTime: %I64d\n", BasicInfo.LastWriteTime.QuadPart); + trace("ChangeTime: %I64d\n", BasicInfo.ChangeTime.QuadPart); + trace("FileAttributes: 0x%lx\n", BasicInfo.FileAttributes); + ok(BasicInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY, "\n"); + ok_eq_hex(Status, STATUS_SUCCESS); + SectionObjectPointers = FileObject->SectionObjectPointer; + if (!skip(SectionObjectPointers != NULL, "No section object pointers\n")) + { + trace("DataSectionObject %p\n", SectionObjectPointers->DataSectionObject); + trace("SharedCacheMap %p\n", SectionObjectPointers->SharedCacheMap); + trace("ImageSectionObject %p\n", SectionObjectPointers->ImageSectionObject); + } + ObDereferenceObject(FileObject); +} + +static +VOID +TestSharedCacheMap(VOID) +{ + NTSTATUS Status; + UNICODE_STRING SystemRootPath = RTL_CONSTANT_STRING(L"\\SystemRoot"); + UNICODE_STRING System32Path = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32"); + UNICODE_STRING DriversPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\drivers"); + UNICODE_STRING EtcPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\drivers\\etc"); + UNICODE_STRING HostsPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\drivers\\etc\\hosts"); + UNICODE_STRING HostsPathRelSystemRoot = RTL_CONSTANT_STRING(L"system32\\drivers\\etc\\hosts"); + UNICODE_STRING HostsPathRelSystem32 = RTL_CONSTANT_STRING(L"drivers\\etc\\hosts"); + UNICODE_STRING HostsPathRelDrivers = RTL_CONSTANT_STRING(L"etc\\hosts"); + UNICODE_STRING HostsPathRelEtc = RTL_CONSTANT_STRING(L"hosts"); + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + HANDLE SystemRootHandle = NULL; + HANDLE System32Handle = NULL; + HANDLE DriversHandle = NULL; + HANDLE EtcHandle = NULL; + HANDLE HostsHandle1 = NULL; + HANDLE HostsHandle2 = NULL; + HANDLE HostsHandle3 = NULL; + HANDLE HostsHandle4 = NULL; + HANDLE HostsHandle5 = NULL; + PFILE_OBJECT SystemRootObject = NULL; + PFILE_OBJECT HostsObject1 = NULL; + PFILE_OBJECT HostsObject2 = NULL; + PFILE_OBJECT HostsObject3 = NULL; + PFILE_OBJECT HostsObject4 = NULL; + PFILE_OBJECT HostsObject5 = NULL; + UCHAR Buffer[32]; + HANDLE EventHandle; + LARGE_INTEGER FileOffset; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ZwCreateEvent(&EventHandle, + SYNCHRONIZE, + &ObjectAttributes, + NotificationEvent, + FALSE); + if (skip(NT_SUCCESS(Status), "No event\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &SystemRootPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&SystemRootHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No SystemRoot handle\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &System32Path, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&System32Handle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No System32 handle\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &DriversPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&DriversHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No Drivers handle\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &EtcPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&EtcHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No Etc handle\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &HostsPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&HostsHandle1, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts handle 1\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &HostsPathRelSystemRoot, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + SystemRootHandle, + NULL); + Status = ZwOpenFile(&HostsHandle2, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts handle 2\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &HostsPathRelSystem32, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + System32Handle, + NULL); + Status = ZwOpenFile(&HostsHandle3, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts handle 3\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &HostsPathRelDrivers, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + DriversHandle, + NULL); + Status = ZwOpenFile(&HostsHandle4, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts handle 4\n")) + goto Exit; + + InitializeObjectAttributes(&ObjectAttributes, + &HostsPathRelEtc, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + EtcHandle, + NULL); + Status = ZwOpenFile(&HostsHandle5, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts handle 5\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(SystemRootHandle, + GENERIC_READ, + *IoFileObjectType, + KernelMode, + &SystemRootObject, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No SystemRoot object\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(HostsHandle1, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &HostsObject1, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts object 1\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(HostsHandle2, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &HostsObject2, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts object 2\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(HostsHandle3, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &HostsObject3, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts object 3\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(HostsHandle4, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &HostsObject4, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts object 4\n")) + goto Exit; + + Status = ObReferenceObjectByHandle(HostsHandle5, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &HostsObject5, + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No hosts object 5\n")) + goto Exit; + + ok_eq_pointer(SystemRootObject->SectionObjectPointer, NULL); + ok(HostsObject1->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject2->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject3->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject4->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject5->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + if (!skip(HostsObject1->SectionObjectPointer != NULL && + HostsObject2->SectionObjectPointer != NULL && + HostsObject3->SectionObjectPointer != NULL && + HostsObject4->SectionObjectPointer != NULL && + HostsObject5->SectionObjectPointer != NULL, "No section object pointers\n")) + { + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject2->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject3->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject4->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject5->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer->SharedCacheMap, NULL); + } + + FileOffset.QuadPart = 0; + Status = ZwReadFile(HostsHandle1, + EventHandle, + NULL, + NULL, + &IoStatus, + Buffer, + sizeof(Buffer), + &FileOffset, + NULL); + if (Status == STATUS_PENDING) + { + Status = ZwWaitForSingleObject(EventHandle, FALSE, NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = IoStatus.Status; + } + ok_eq_hex(Status, STATUS_SUCCESS); + + ok_eq_pointer(SystemRootObject->SectionObjectPointer, NULL); + ok(HostsObject1->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject2->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject3->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject4->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + ok(HostsObject5->SectionObjectPointer != NULL, "SectionObjectPointer = NULL\n"); + if (!skip(HostsObject1->SectionObjectPointer != NULL && + HostsObject2->SectionObjectPointer != NULL && + HostsObject3->SectionObjectPointer != NULL && + HostsObject4->SectionObjectPointer != NULL && + HostsObject5->SectionObjectPointer != NULL, "No section object pointers\n")) + { + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject2->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject3->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject4->SectionObjectPointer); + ok_eq_pointer(HostsObject1->SectionObjectPointer, HostsObject5->SectionObjectPointer); + ok(HostsObject1->SectionObjectPointer->SharedCacheMap != NULL, "SharedCacheMap is NULL\n"); + } + +Exit: + if (HostsObject5) + ObDereferenceObject(HostsObject5); + if (HostsObject4) + ObDereferenceObject(HostsObject4); + if (HostsObject3) + ObDereferenceObject(HostsObject3); + if (HostsObject2) + ObDereferenceObject(HostsObject2); + if (HostsObject1) + ObDereferenceObject(HostsObject1); + if (SystemRootObject) + ObDereferenceObject(SystemRootObject); + if (HostsHandle5) + ObCloseHandle(HostsHandle5, KernelMode); + if (HostsHandle4) + ObCloseHandle(HostsHandle4, KernelMode); + if (HostsHandle3) + ObCloseHandle(HostsHandle3, KernelMode); + if (HostsHandle2) + ObCloseHandle(HostsHandle2, KernelMode); + if (HostsHandle1) + ObCloseHandle(HostsHandle1, KernelMode); + if (EtcHandle) + ObCloseHandle(EtcHandle, KernelMode); + if (DriversHandle) + ObCloseHandle(DriversHandle, KernelMode); + if (System32Handle) + ObCloseHandle(System32Handle, KernelMode); + if (SystemRootHandle) + ObCloseHandle(SystemRootHandle, KernelMode); + if (EventHandle) + ObCloseHandle(EventHandle, KernelMode); +} + +START_TEST(IoFilesystem) +{ + //TestBasicInfo(); + TestSharedCacheMap(); +}