Author: ion Date: Fri Jul 7 21:18:52 2006 New Revision: 22903
URL: http://svn.reactos.org/svn/reactos?rev=22903&view=rev Log: - Implement IopCheckVpbMounted and use it in IopParseDevice as documented in NT File System Internals. - Add some missing ref/deref calls for DOs and VPBs.
Modified: trunk/reactos/ntoskrnl/include/internal/io.h trunk/reactos/ntoskrnl/io/iomgr/file.c trunk/reactos/ntoskrnl/io/iomgr/volume.c
Modified: trunk/reactos/ntoskrnl/include/internal/io.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/io.h (original) +++ trunk/reactos/ntoskrnl/include/internal/io.h Fri Jul 7 21:18:52 2006 @@ -574,6 +574,15 @@ 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( @@ -617,6 +626,13 @@ NTAPI IopReferenceDeviceObject( IN PDEVICE_OBJECT DeviceObject +); + +VOID +NTAPI +IopDereferenceDeviceObject( + IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN ForceUnload );
//
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/file.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/file.c Fri Jul 7 21:18:52 2006 @@ -92,6 +92,9 @@ { /* Yes, remember it */ Vpb = OpenPacket->RelatedFileObject->Vpb; + + /* Reference it */ + InterlockedIncrement(&Vpb->ReferenceCount); } } else @@ -102,25 +105,15 @@ /* 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 */
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/volume.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/volume.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/volume.c Fri Jul 7 21:18:52 2006 @@ -52,6 +52,76 @@ ExInitializeResourceLite(&FileSystemListLock); InitializeListHead(&FsChangeNotifyListHead); 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