|
|
/*++
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 ); }
|