📄 fsctrl.c
字号:
//
if (Vcb->VcbCondition != VcbMounted) {
Status = STATUS_VOLUME_DISMOUNTED;
} else {
//
// Invalidate the volume right now.
//
// The intent here is to make every subsequent operation
// on the volume fail and grease the rails toward dismount.
// By definition there is no going back from a SURPRISE.
//
CdLockVcb( IrpContext, Vcb );
if (Vcb->VcbCondition != VcbDismountInProgress) {
CdUpdateVcbCondition( Vcb, VcbInvalid);
}
CdUnlockVcb( IrpContext, Vcb );
//
// Set flag to tell the close path that we want to force dismount
// the volume when this handle is closed.
//
SetFlag( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE);
Status = STATUS_SUCCESS;
}
//
// Release all of our resources
//
CdReleaseVcb( IrpContext, Vcb );
CdReleaseCdData( IrpContext);
//
// Complete the request if there haven't been any exceptions.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
int
CdIsVolumeDirty (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine determines if a volume is currently dirty.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
PIO_STACK_LOCATION IrpSp;
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
PULONG VolumeState;
//
// Get the current stack location and extract the output
// buffer information.
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Get a pointer to the output buffer.
//
if (Irp->AssociatedIrp.SystemBuffer != NULL) {
VolumeState = Irp->AssociatedIrp.SystemBuffer;
} else {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_USER_BUFFER );
return STATUS_INVALID_USER_BUFFER;
}
//
// Make sure the output buffer is large enough and then initialize
// the answer to be that the volume isn't dirty.
//
if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
*VolumeState = 0;
//
// Decode the file object
//
TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
if (TypeOfOpen != UserVolumeOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
if (Fcb->Vcb->VcbCondition != VcbMounted) {
CdCompleteRequest( IrpContext, Irp, STATUS_VOLUME_DISMOUNTED );
return STATUS_VOLUME_DISMOUNTED;
}
//
// Now set up to return the clean state. CDs obviously can never be dirty
// but we want to make sure we have enforced the full semantics of this call.
//
Irp->IoStatus.Information = sizeof( ULONG );
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdIsVolumeMounted (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine determines if a volume is currently mounted.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PFCB Fcb;
PCCB Ccb;
PAGED_CODE();
//
// Decode the file object.
//
CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
if (Fcb != NULL) {
//
// Disable PopUps, we want to return any error.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS );
//
// Verify the Vcb. This will raise in the error condition.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
}
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdIsPathnameValid (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine determines if pathname is a valid CDFS pathname.
We always succeed this request.
Arguments:
Irp - Supplies the Irp to process.
Return Value:
None
--*/
{
PAGED_CODE();
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdInvalidateVolumes (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine searches for all the volumes mounted on the same real device
of the current DASD handle, and marks them all bad. The only operation
that can be done on such handles is cleanup and close.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
KIRQL SavedIrql;
BOOLEAN UnlockVcb = FALSE;
LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
HANDLE Handle;
PVCB Vcb;
PLIST_ENTRY Links;
PFILE_OBJECT FileToMarkBad;
PDEVICE_OBJECT DeviceToMarkBad;
//
// We only allow the invalidate call to come in on our file system devices.
//
if (IrpSp->DeviceObject != CdData.FileSystemDeviceObject) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
return STATUS_INVALID_DEVICE_REQUEST;
}
//
// Check for the correct security access.
// The caller must have the SeTcbPrivilege.
//
if (!SeSinglePrivilegeCheck( TcbPrivilege, Irp->RequestorMode )) {
CdCompleteRequest( IrpContext, Irp, STATUS_PRIVILEGE_NOT_HELD );
return STATUS_PRIVILEGE_NOT_HELD;
}
//
// Try to get a pointer to the device object from the handle passed in.
//
#if defined(_WIN64)
if (IoIs32bitProcess( Irp )) {
if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( UINT32 )) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
Handle = (HANDLE) LongToHandle( *((PUINT32) Irp->AssociatedIrp.SystemBuffer) );
} else {
#endif
if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer);
#if defined(_WIN64)
}
#endif
Status = ObReferenceObjectByHandle( Handle,
0,
*IoFileObjectType,
KernelMode,
&FileToMarkBad,
NULL );
if (!NT_SUCCESS(Status)) {
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Grab the DeviceObject from the FileObject.
//
DeviceToMarkBad = FileToMarkBad->DeviceObject;
//
// We only needed the device object involved, not a reference to the file.
//
ObDereferenceObject( FileToMarkBad );
//
// Make sure this request can wait.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
//
// Synchronise with pnp/mount/verify paths.
//
CdAcquireCdData( IrpContext );
//
// Nothing can go wrong now.
//
//
// Now walk through all the mounted Vcb's looking for candidates to
// mark invalid.
//
// On volumes we mark invalid, check for dismount possibility (which is
// why we have to get the next link so early).
//
Links = CdData.VcbQueue.Flink;
while (Links != &CdData.VcbQueue) {
Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks);
Links = Links->Flink;
//
// If we get a match, mark the volume Bad, and also check to
// see if the volume should go away.
//
CdLockVcb( IrpContext, Vcb );
if (Vcb->Vpb->RealDevice == DeviceToMarkBad) {
//
// Take the VPB spinlock, and look to see if this volume is the
// one currently mounted on the actual device. If it is, pull it
// off immediately.
//
IoAcquireVpbSpinLock( &SavedIrql );
if (DeviceToMarkBad->Vpb == Vcb->Vpb) {
PVPB NewVpb = Vcb->SwapVpb;
ASSERT( FlagOn( Vcb->Vpb->Flags, VPB_MOUNTED));
ASSERT( NULL != NewVpb);
RtlZeroMemory( NewVpb, sizeof( VPB ) );
NewVpb->Type = IO_TYPE_VPB;
NewVpb->Size = sizeof( VPB );
NewVpb->RealDevice = DeviceToMarkBad;
NewVpb->Flags = FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING );
DeviceToMarkBad->Vpb = NewVpb;
Vcb->SwapVpb = NULL;
}
IoReleaseVpbSpinLock( SavedIrql );
if (Vcb->VcbCondition != VcbDismountInProgress) {
CdUpdateVcbCondition( Vcb, VcbInvalid);
}
CdUnlockVcb( IrpContext, Vcb );
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE);
CdPurgeVolume( IrpContext, Vcb, FALSE );
UnlockVcb = CdCheckForDismount( IrpContext, Vcb, FALSE );
if (UnlockVcb) {
CdReleaseVcb( IrpContext, Vcb);
}
} else {
CdUnlockVcb( IrpContext, Vcb );
}
}
CdReleaseCdData( IrpContext );
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Local support routine
//
VOID
CdScanForDismountedVcb (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine walks through the list of Vcb's looking for any which may
now be deleted. They may have been left on the list because there were
outstanding references.
Arguments:
Return Value:
None
--*/
{
PVCB Vcb;
PLIST_ENTRY Links;
PAGED_CODE();
//
// Walk through all of the Vcb's attached to the global data.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -