271 lines
6.1 KiB
C
271 lines
6.1 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
DevCtrl.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the Device Control routines for Ntfs called by
|
|||
|
the dispatch driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 28-May-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "NtfsProc.h"
|
|||
|
#include <ntddsnap.h>
|
|||
|
|
|||
|
//
|
|||
|
// The local debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_DEVCTRL)
|
|||
|
|
|||
|
//
|
|||
|
// Local procedure prototypes
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DeviceControlCompletionRoutine (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PVOID Contxt
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, NtfsCommonDeviceControl)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NtfsCommonDeviceControl (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for Device Control 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 = STATUS_SUCCESS;
|
|||
|
TYPE_OF_OPEN TypeOfOpen;
|
|||
|
PIO_STACK_LOCATION IrpSp;
|
|||
|
NTFS_COMPLETION_CONTEXT Context;
|
|||
|
PNTFS_COMPLETION_CONTEXT CompletionContext = NULL;
|
|||
|
LOGICAL ReleaseResources = FALSE;
|
|||
|
PVCB Vcb;
|
|||
|
PFCB Fcb;
|
|||
|
PSCB Scb;
|
|||
|
PCCB Ccb;
|
|||
|
|
|||
|
ASSERT_IRP_CONTEXT( IrpContext );
|
|||
|
ASSERT_IRP( Irp );
|
|||
|
ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace( +1, Dbg, ("NtfsCommonDeviceControl\n") );
|
|||
|
DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
|
|||
|
DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
|
|||
|
|
|||
|
//
|
|||
|
// Extract and decode the file object
|
|||
|
//
|
|||
|
|
|||
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
TypeOfOpen = NtfsDecodeFileObject( IrpContext,
|
|||
|
IrpSp->FileObject,
|
|||
|
&Vcb,
|
|||
|
&Fcb,
|
|||
|
&Scb,
|
|||
|
&Ccb,
|
|||
|
TRUE );
|
|||
|
|
|||
|
//
|
|||
|
// The only type of opens we accept are user volume opens.
|
|||
|
//
|
|||
|
|
|||
|
if (TypeOfOpen != UserVolumeOpen) {
|
|||
|
|
|||
|
NtfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
|
|||
|
DebugTrace( -1, Dbg, ("NtfsCommonDeviceControl -> %08lx\n", STATUS_INVALID_PARAMETER) );
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// A few IOCTLs actually require some intervention on our part
|
|||
|
//
|
|||
|
|
|||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
|
|||
|
|
|||
|
case IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES:
|
|||
|
|
|||
|
//
|
|||
|
// This is sent by the Volume Snapshot driver (Lovelace).
|
|||
|
// We flush the volume, and hold all file resources
|
|||
|
// to make sure that nothing more gets dirty. Then we wait
|
|||
|
// for the IRP to complete or cancel.
|
|||
|
//
|
|||
|
|
|||
|
Status = NtfsCheckpointForVolumeSnapshot( IrpContext );
|
|||
|
|
|||
|
if (NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
ReleaseResources = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
KeInitializeEvent( &Context.Event, NotificationEvent, FALSE );
|
|||
|
Context.IrpContext = IrpContext;
|
|||
|
CompletionContext = &Context;
|
|||
|
SetFlag( IrpContext->State, IRP_CONTEXT_STATE_WAIT );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case IOCTL_VOLSNAP_RELEASE_WRITES:
|
|||
|
|
|||
|
//
|
|||
|
// No-op for filesystems.
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If error, complete the irp, free the IrpContext
|
|||
|
// and return to the caller.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
NtfsCompleteRequest( NULL, Irp, Status );
|
|||
|
leave;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the next stack location, and copy over the stack parameter
|
|||
|
// information
|
|||
|
//
|
|||
|
|
|||
|
IoCopyCurrentIrpStackLocationToNext( Irp );
|
|||
|
|
|||
|
//
|
|||
|
// Set up the completion routine
|
|||
|
//
|
|||
|
|
|||
|
IoSetCompletionRoutine( Irp,
|
|||
|
DeviceControlCompletionRoutine,
|
|||
|
CompletionContext,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE );
|
|||
|
|
|||
|
//
|
|||
|
// Send the request. And wait.
|
|||
|
//
|
|||
|
|
|||
|
Status = IoCallDriver( Vcb->TargetDeviceObject, Irp );
|
|||
|
|
|||
|
if ((Status == STATUS_PENDING) &&
|
|||
|
(CompletionContext != NULL)) {
|
|||
|
|
|||
|
KeWaitForSingleObject( &CompletionContext->Event,
|
|||
|
Executive,
|
|||
|
KernelMode,
|
|||
|
FALSE,
|
|||
|
NULL );
|
|||
|
}
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
//
|
|||
|
// Release all the resources that we held because of a
|
|||
|
// VOLSNAP_FLUSH_AND_HOLD.
|
|||
|
//
|
|||
|
|
|||
|
if (ReleaseResources && !NtfsIsVolumeReadOnly( IrpContext->Vcb )) {
|
|||
|
|
|||
|
NtfsReleaseAllFiles( IrpContext, IrpContext->Vcb, FALSE );
|
|||
|
NtfsReleaseVcb( IrpContext, Vcb );
|
|||
|
}
|
|||
|
#ifdef SUPW_DBG
|
|||
|
if (AbnormalTermination()) {
|
|||
|
|
|||
|
DbgPrint("CommonDevControl Raised: Status %8lx\n", Status);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
NtfsCleanupIrpContext( IrpContext, TRUE );
|
|||
|
|
|||
|
DebugTrace( -1, Dbg, ("NtfsCommonDeviceControl -> %08lx\n", Status) );
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Local support routine
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DeviceControlCompletionRoutine (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PVOID Contxt
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Add the hack-o-ramma to fix formats.
|
|||
|
//
|
|||
|
|
|||
|
if (Irp->PendingReturned) {
|
|||
|
|
|||
|
IoMarkIrpPending( Irp );
|
|||
|
}
|
|||
|
|
|||
|
if (Contxt) {
|
|||
|
|
|||
|
PNTFS_COMPLETION_CONTEXT CompletionContext = (PNTFS_COMPLETION_CONTEXT)Contxt;
|
|||
|
|
|||
|
KeSetEvent( &CompletionContext->Event, 0, FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Return success always, because we want this IRP to go away for good
|
|||
|
// irrespective of the IRP completion status.
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( DeviceObject );
|
|||
|
}
|