- 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
This commit is contained in:
Alex Ionescu 2006-07-07 17:18:52 +00:00
parent 979b777dd5
commit d6e384ce39
3 changed files with 96 additions and 17 deletions

View file

@ -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
//

View file

@ -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 */

View file

@ -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)