📄 fsctrl.c
字号:
CdMarkRealDevVerifyOk( Vpb->RealDevice);
//
// See if we will need to provide notification of the remount. This is the readonly
// filesystem's form of dismount/mount notification.
//
if (FlagOn( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
ClearFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
ObReferenceObject( FileObjectToNotify );
}
try_exit: NOTHING;
//
// Update the media change count to note that we have verified the volume
// at this value - regardless of the outcome.
//
CdUpdateMediaChangeCount( Vcb, MediaChangeCount);
//
// If we got the wrong volume then free any remaining XA sector in
// the current Vcb. Also mark the Vcb as not mounted.
//
if (Status == STATUS_WRONG_VOLUME) {
CdUpdateVcbCondition( Vcb, VcbNotMounted);
if (Vcb->XASector != NULL) {
CdFreePool( &Vcb->XASector );
Vcb->XASector = 0;
Vcb->XADiskOffset = 0;
}
CdFreeDirCache( IrpContext);
//
// Now, if there are no user handles to the volume, try to spark
// teardown by purging the volume.
//
if (Vcb->VcbCleanup == 0) {
if (NT_SUCCESS( CdPurgeVolume( IrpContext, Vcb, FALSE ))) {
ReleaseVcb = CdCheckForDismount( IrpContext, Vcb, FALSE );
}
}
}
}
finally {
//
// Free the TOC buffer if allocated.
//
if (CdromToc != NULL) {
CdFreePool( &CdromToc );
}
if (RawIsoVd != NULL) {
CdFreePool( &RawIsoVd );
}
if (ReleaseVcb) {
CdReleaseVcb( IrpContext, Vcb );
}
CdReleaseCdData( IrpContext );
}
//
// Now send mount notification.
//
if (FileObjectToNotify) {
FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
ObDereferenceObject( FileObjectToNotify );
}
//
// Complete the request if no exception.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
NTSTATUS
CdOplockRequest (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine to handle oplock requests made via the
NtFsControlFile call.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PFCB Fcb;
PCCB Ccb;
ULONG OplockCount = 0;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
//
// We only permit oplock requests on files.
//
if (CdDecodeFileObject( IrpContext,
IrpSp->FileObject,
&Fcb,
&Ccb ) != UserFileOpen ) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Make this a waitable Irpcontext so we don't fail to acquire
// the resources.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
//
// Switch on the function control code. We grab the Fcb exclusively
// for oplock requests, shared for oplock break acknowledgement.
//
switch (IrpSp->Parameters.FileSystemControl.FsControlCode) {
case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
case FSCTL_REQUEST_BATCH_OPLOCK :
case FSCTL_REQUEST_FILTER_OPLOCK :
CdAcquireFcbExclusive( IrpContext, Fcb, FALSE );
if (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
if (Fcb->FileLock != NULL) {
OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks( Fcb->FileLock );
}
} else {
OplockCount = Fcb->FcbCleanup;
}
break;
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
case FSCTL_OPLOCK_BREAK_NOTIFY:
case FSCTL_OPLOCK_BREAK_ACK_NO_2:
CdAcquireFcbShared( IrpContext, Fcb, FALSE );
break;
default:
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Use a try finally to free the Fcb.
//
try {
//
// Verify the Fcb.
//
CdVerifyFcbOperation( IrpContext, Fcb );
//
// Call the FsRtl routine to grant/acknowledge oplock.
//
Status = FsRtlOplockFsctrl( &Fcb->Oplock,
Irp,
OplockCount );
//
// Set the flag indicating if Fast I/O is possible
//
CdLockFcb( IrpContext, Fcb );
Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
CdUnlockFcb( IrpContext, Fcb );
//
// The oplock package will complete the Irp.
//
Irp = NULL;
} finally {
//
// Release all of our resources
//
CdReleaseFcb( IrpContext, Fcb );
}
//
// Complete the request if there was no exception.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
NTSTATUS
CdLockVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine performs the lock volume operation. It is responsible for
either completing of enqueuing the input Irp.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
PAGED_CODE();
//
// Decode the file object, the only type of opens we accept are
// user volume opens.
//
if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Send our notification so that folks that like to hold handles on
// volumes can get out of the way.
//
FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_LOCK );
//
// Acquire exclusive access to the Vcb.
//
Vcb = Fcb->Vcb;
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
try {
//
// Verify the Vcb.
//
CdVerifyVcb( IrpContext, Vcb );
Status = CdLockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
} finally {
//
// Release the Vcb.
//
CdReleaseVcb( IrpContext, Vcb );
if (AbnormalTermination() || !NT_SUCCESS( Status )) {
FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_LOCK_FAILED );
}
}
//
// Complete the request if there haven't been any exceptions.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
NTSTATUS
CdUnlockVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine performs the unlock volume operation. It is responsible for
either completing of enqueuing the input Irp.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
PAGED_CODE();
//
// Decode the file object, the only type of opens we accept are
// user volume opens.
//
if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Acquire exclusive access to the Vcb.
//
Vcb = Fcb->Vcb;
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
//
// We won't check for a valid Vcb for this request. An unlock will always
// succeed on a locked volume.
//
Status = CdUnlockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
//
// Release all of our resources
//
CdReleaseVcb( IrpContext, Vcb );
//
// Send notification that the volume is avaliable.
//
if (NT_SUCCESS( Status )) {
FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_UNLOCK );
}
//
// Complete the request if there haven't been any exceptions.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
NTSTATUS
CdDismountVolume (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine performs the dismount volume operation. It is responsible for
either completing of enqueuing the input Irp. We only dismount a volume which
has been locked. The intent here is that someone has locked the volume (they are the
only remaining handle). We set the verify bit here and the user will close his handle.
We will dismount a volume with no user's handles in the verify path.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
PAGED_CODE();
if (CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
Vcb = Fcb->Vcb;
//
// Make this request waitable.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
//
// Acquire exclusive access to the Vcb, and take the global resource to
// sync. against mounts, verifies etc.
//
CdAcquireCdData( IrpContext );
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
//
// Mark the volume as needs to be verified, but only do it if
// the vcb is locked by this handle and the volume is currently mounted.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -