From d6e384ce39351c552e94a57bbd32289ec506d438 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Fri, 7 Jul 2006 17:18:52 +0000 Subject: [PATCH] - Implement IopCheckVpbMounted and use it in IopParseDevice as documented in NT File System Internals. - Add some missing ref/deref calls for DOs and VPBs. svn path=/trunk/; revision=22903 --- reactos/ntoskrnl/include/internal/io.h | 16 ++++++ reactos/ntoskrnl/io/iomgr/file.c | 27 ++++------ reactos/ntoskrnl/io/iomgr/volume.c | 70 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index b8bbebfe82b..84b64168dec 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -574,6 +574,15 @@ IopStartDevice( IN PDEVICE_NODE DeviceNode ); +PVPB +NTAPI +IopCheckVpbMounted( + IN POPEN_PACKET OpenPacket, + IN PDEVICE_OBJECT DeviceObject, + IN PUNICODE_STRING RemainingName, + OUT PNTSTATUS Status +); + NTSTATUS NTAPI IopMountVolume( @@ -619,6 +628,13 @@ IopReferenceDeviceObject( IN PDEVICE_OBJECT DeviceObject ); +VOID +NTAPI +IopDereferenceDeviceObject( + IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN ForceUnload +); + // // IRP Routines // diff --git a/reactos/ntoskrnl/io/iomgr/file.c b/reactos/ntoskrnl/io/iomgr/file.c index 913bd277c18..2b97d276987 100644 --- a/reactos/ntoskrnl/io/iomgr/file.c +++ b/reactos/ntoskrnl/io/iomgr/file.c @@ -92,6 +92,9 @@ IopParseDevice(IN PVOID ParseObject, { /* Yes, remember it */ Vpb = OpenPacket->RelatedFileObject->Vpb; + + /* Reference it */ + InterlockedIncrement(&Vpb->ReferenceCount); } } else @@ -102,25 +105,15 @@ IopParseDevice(IN PVOID ParseObject, /* Check if it has a VPB */ if ((DeviceObject->Vpb) && !(DirectOpen)) { - /* Check if it's not already mounted */ - if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED)) - { - /* Mount the volume */ - Status = IopMountVolume(DeviceObject, - FALSE, - FALSE, - FALSE, - &Vpb); - if (!NT_SUCCESS(Status)) - { - /* Couldn't mount, fail the lookup */ - ObDereferenceObject(FileObject); - return STATUS_UNSUCCESSFUL; - } - } + /* Check if the VPB is mounted, and mount it */ + Vpb = IopCheckVpbMounted(OpenPacket, + DeviceObject, + RemainingName, + &Status); + if (!Vpb) return Status; /* Get the VPB's device object */ - DeviceObject = DeviceObject->Vpb->DeviceObject; + DeviceObject = Vpb->DeviceObject; } /* Check if there's an attached device */ diff --git a/reactos/ntoskrnl/io/iomgr/volume.c b/reactos/ntoskrnl/io/iomgr/volume.c index 0f1732bf3fe..a958f0c3520 100644 --- a/reactos/ntoskrnl/io/iomgr/volume.c +++ b/reactos/ntoskrnl/io/iomgr/volume.c @@ -54,6 +54,76 @@ IoInitFileSystemImplementation(VOID) KeInitializeGuardedMutex(&FsChangeNotifyListLock); } +PVPB +NTAPI +IopCheckVpbMounted(IN POPEN_PACKET OpenPacket, + IN PDEVICE_OBJECT DeviceObject, + IN PUNICODE_STRING RemainingName, + OUT PNTSTATUS Status) +{ + BOOLEAN Alertable, Raw; + KIRQL OldIrql; + PVPB Vpb = NULL; + + /* Lock the VPBs */ + IoAcquireVpbSpinLock(&OldIrql); + + /* Set VPB mount settings */ + Raw = !RemainingName->Length && !OpenPacket->RelatedFileObject; + Alertable = (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT); + + /* Start looping until the VPB is mounted */ + while (!(DeviceObject->Vpb->Flags & VPB_MOUNTED)) + { + /* Release the lock */ + IoReleaseVpbSpinLock(OldIrql); + + /* Mount the volume */ + *Status = IopMountVolume(DeviceObject, + Raw, + FALSE, + Alertable, + &Vpb); + + /* Check if we failed or if we were alerted */ + if (!(NT_SUCCESS(*Status)) || + (*Status == STATUS_USER_APC) || + (*Status == STATUS_ALERTED)) + { + /* Dereference the device, since IopParseDevice referenced it */ + IopDereferenceDeviceObject(DeviceObject, FALSE); + + /* Check if it was a total failure */ + if (!NT_SUCCESS(Status)) return NULL; + + /* Otherwise we were alerted */ + *Status = STATUS_WRONG_VOLUME; + return NULL; + } + + /* Re-acquire the lock */ + IoAcquireVpbSpinLock(&OldIrql); + } + + /* Make sure the VPB isn't locked */ + Vpb = DeviceObject->Vpb; + if (Vpb->Flags & VPB_LOCKED) + { + /* We're locked, so fail */ + *Status = STATUS_ACCESS_DENIED; + Vpb = NULL; + } + else + { + /* Success! Reference the VPB */ + Vpb->ReferenceCount++; + } + + /* Release the lock and return the VPB */ + IoReleaseVpbSpinLock(OldIrql); + return Vpb; +} + NTSTATUS NTAPI IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)