📄 fsctrl.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
FsCtrl.c
Abstract:
This module implements the File System Control routines for Cdfs called
by the Fsd/Fsp dispatch drivers.
--*/
#include "CdProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_FSCTRL)
//
// Local constants
//
BOOLEAN CdDisable = FALSE;
BOOLEAN CdNoJoliet = FALSE;
//
// Local support routines
//
NTSTATUS
CdUserFsctl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
VOID
CdReMountOldVcb(
IN PIRP_CONTEXT IrpContext,
IN PVCB OldVcb,
IN PVCB NewVcb,
IN PDEVICE_OBJECT DeviceObjectWeTalkTo
);
NTSTATUS
CdMountVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdVerifyVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdOplockRequest (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdLockVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdUnlockVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdDismountVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
int
CdIsVolumeDirty (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdIsVolumeMounted (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdIsPathnameValid (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
NTSTATUS
CdInvalidateVolumes (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
VOID
CdScanForDismountedVcb (
IN PIRP_CONTEXT IrpContext
);
BOOLEAN
CdFindPrimaryVd (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PCHAR RawIsoVd,
IN ULONG BlockFactor,
IN BOOLEAN ReturnOnError,
IN BOOLEAN VerifyVolume
);
BOOLEAN
CdIsRemount (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
OUT PVCB *OldVcb
);
VOID
CdFindActiveVolDescriptor (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN OUT PCHAR RawIsoVd,
IN BOOLEAN VerifyVolume
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonFsControl)
#pragma alloc_text(PAGE, CdDismountVolume)
#pragma alloc_text(PAGE, CdFindActiveVolDescriptor)
#pragma alloc_text(PAGE, CdFindPrimaryVd)
#pragma alloc_text(PAGE, CdIsPathnameValid)
#pragma alloc_text(PAGE, CdIsRemount)
#pragma alloc_text(PAGE, CdIsVolumeDirty)
#pragma alloc_text(PAGE, CdIsVolumeMounted)
#pragma alloc_text(PAGE, CdLockVolume)
#pragma alloc_text(PAGE, CdMountVolume)
#pragma alloc_text(PAGE, CdOplockRequest)
#pragma alloc_text(PAGE, CdScanForDismountedVcb)
#pragma alloc_text(PAGE, CdUnlockVolume)
#pragma alloc_text(PAGE, CdUserFsctl)
#pragma alloc_text(PAGE, CdVerifyVolume)
#endif
//
// Local support routine
//
NTSTATUS
CdLockVolumeInternal (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject OPTIONAL
)
/*++
Routine Description:
This routine performs the actual lock volume operation. It will be called
by anyone wishing to try to protect the volume for a long duration. PNP
operations are such a user.
The volume must be held exclusive by the caller.
Arguments:
Vcb - The volume being locked.
FileObject - File corresponding to the handle locking the volume. If this
is not specified, a system lock is assumed.
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
KIRQL SavedIrql;
NTSTATUS FinalStatus = (FileObject? STATUS_ACCESS_DENIED: STATUS_DEVICE_BUSY);
ULONG RemainingUserReferences = (FileObject? 1: 0);
//
// The cleanup count for the volume only reflects the fileobject that
// will lock the volume. Otherwise, we must fail the request.
//
// Since the only cleanup is for the provided fileobject, we will try
// to get rid of all of the other user references. If there is only one
// remaining after the purge then we can allow the volume to be locked.
//
CdPurgeVolume( IrpContext, Vcb, FALSE );
//
// Now back out of our synchronization and wait for the lazy writer
// to finish off any lazy closes that could have been outstanding.
//
// Since we purged, we know that the lazy writer will issue all
// possible lazy closes in the next tick - if we hadn't, an otherwise
// unopened file with a large amount of dirty data could have hung
// around for a while as the data trickled out to the disk.
//
// This is even more important now since we send notification to
// alert other folks that this style of check is about to happen so
// that they can close their handles. We don't want to enter a fast
// race with the lazy writer tearing down his references to the file.
//
CdReleaseVcb( IrpContext, Vcb );
Status = CcWaitForCurrentLazyWriterActivity();
//
// This is intentional. If we were able to get the Vcb before, just
// wait for it and take advantage of knowing that it is OK to leave
// the flag up.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
if (!NT_SUCCESS( Status )) {
return Status;
}
CdFspClose( Vcb );
//
// If the volume is already explicitly locked then fail. We use the
// Vpb locked flag as an 'explicit lock' flag in the same way as Fat.
//
IoAcquireVpbSpinLock( &SavedIrql );
if (!FlagOn( Vcb->Vpb->Flags, VPB_LOCKED ) &&
(Vcb->VcbCleanup == RemainingUserReferences) &&
(Vcb->VcbUserReference == CDFS_RESIDUAL_USER_REFERENCE + RemainingUserReferences)) {
SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
SetFlag( Vcb->Vpb->Flags, VPB_LOCKED);
Vcb->VolumeLockFileObject = FileObject;
FinalStatus = STATUS_SUCCESS;
}
IoReleaseVpbSpinLock( SavedIrql );
return FinalStatus;
}
NTSTATUS
CdUnlockVolumeInternal (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject OPTIONAL
)
/*++
Routine Description:
This routine performs the actual unlock volume operation.
The volume must be held exclusive by the caller.
Arguments:
Vcb - The volume being locked.
FileObject - File corresponding to the handle locking the volume. If this
is not specified, a system lock is assumed.
Return Value:
NTSTATUS - The return status for the operation
Attempting to remove a system lock that did not exist is OK.
--*/
{
NTSTATUS Status = STATUS_NOT_LOCKED;
KIRQL SavedIrql;
//
// Note that we check the VPB_LOCKED flag here rather than the Vcb
// lock flag. The Vpb flag is only set for an explicit lock request, not
// for the implicit lock obtained on a volume open with zero share mode.
//
IoAcquireVpbSpinLock( &SavedIrql );
if (FlagOn(Vcb->Vpb->Flags, VPB_LOCKED) &&
(FileObject == Vcb->VolumeLockFileObject)) {
ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED);
Vcb->VolumeLockFileObject = NULL;
Status = STATUS_SUCCESS;
}
IoReleaseVpbSpinLock( SavedIrql );
return Status;
}
NTSTATUS
CdCommonFsControl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for doing FileSystem control operations called
by both the fsd and fsp threads
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Get a pointer to the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
//
// We know this is a file system control so we'll case on the
// minor function, and call a internal worker routine to complete
// the irp.
//
switch (IrpSp->MinorFunction) {
case IRP_MN_USER_FS_REQUEST:
Status = CdUserFsctl( IrpContext, Irp );
break;
case IRP_MN_MOUNT_VOLUME:
Status = CdMountVolume( IrpContext, Irp );
break;
case IRP_MN_VERIFY_VOLUME:
Status = CdVerifyVolume( IrpContext, Irp );
break;
default:
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return Status;
}
//
// Local support routine
//
NTSTATUS
CdUserFsctl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for implementing the user's requests made
through NtFsControlFile.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
//
// Case on the control code.
//
switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) {
case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
case FSCTL_REQUEST_BATCH_OPLOCK :
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
case FSCTL_OPLOCK_BREAK_NOTIFY :
case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
case FSCTL_REQUEST_FILTER_OPLOCK :
Status = CdOplockRequest( IrpContext, Irp );
break;
case FSCTL_LOCK_VOLUME :
Status = CdLockVolume( IrpContext, Irp );
break;
case FSCTL_UNLOCK_VOLUME :
Status = CdUnlockVolume( IrpContext, Irp );
break;
case FSCTL_DISMOUNT_VOLUME :
Status = CdDismountVolume( IrpContext, Irp );
break;
case FSCTL_IS_VOLUME_DIRTY :
Status = CdIsVolumeDirty( IrpContext, Irp );
break;
case FSCTL_IS_VOLUME_MOUNTED :
Status = CdIsVolumeMounted( IrpContext, Irp );
break;
case FSCTL_IS_PATHNAME_VALID :
Status = CdIsPathnameValid( IrpContext, Irp );
break;
case FSCTL_INVALIDATE_VOLUMES :
Status = CdInvalidateVolumes( IrpContext, Irp );
break;
//
// We don't support any of the known or unknown requests.
//
default:
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return Status;
}
VOID
CdReMountOldVcb(
IN PIRP_CONTEXT IrpContext,
IN PVCB OldVcb,
IN PVCB NewVcb,
IN PDEVICE_OBJECT DeviceObjectWeTalkTo
)
{
KIRQL SavedIrql;
ULONG Index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -