255 lines
7.2 KiB
C
255 lines
7.2 KiB
C
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: FSPDISP.C
|
|
//
|
|
// Contents: This module implements the main dispatch procedure
|
|
// for the Dsfs FSP.
|
|
//
|
|
// Functions: DfsFsdPostRequest - post an IRP request to the FSP
|
|
// DfsFspDispatch - Dispatch IRP requests from FSP thread
|
|
//
|
|
// History: 12 Nov 1991 AlanW Created from CDFS souce.
|
|
// 25 Apr 1993 Alanw Updated to use Ex worker threads
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "dfsprocs.h"
|
|
#include "dnr.h"
|
|
|
|
|
|
//
|
|
// Define our local debug trace level
|
|
//
|
|
|
|
#define Dbg (DEBUG_TRACE_FSP_DISPATCHER)
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, DfsFspDispatch )
|
|
//
|
|
// DfsFsdPostRequest cannot be paged since it is called from
|
|
// DnrCompleteFileOpen
|
|
//
|
|
// DfsFsdPostRequest
|
|
//
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFsdPostRequest, public
|
|
//
|
|
// Synopsis: This routine enqueues the request packet specified by
|
|
// IrpContext to the work queue associated with the
|
|
// FileSysDeviceObject. This is a FSD routine.
|
|
//
|
|
// Arguments: [IrpContext] -- Pointer to the IrpContext to be queued to
|
|
// the Fsp
|
|
// [Irp] -- I/O Request Packet, or NULL if it has already been
|
|
// completed.
|
|
//
|
|
// Returns: STATUS_PENDING
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsFsdPostRequest(
|
|
IN PIRP_CONTEXT IrpContext,
|
|
IN PIRP Irp
|
|
) {
|
|
DfsDbgTrace(0, Dbg, "DfsFsdPostRequest: Irp = %08lx\n", Irp);
|
|
|
|
ASSERT( ARGUMENT_PRESENT(Irp) &&
|
|
IrpContext->OriginatingIrp == Irp );
|
|
|
|
//
|
|
// Verify our assumptions about not needing DfsPrePostIrp processing.
|
|
//
|
|
ASSERT((IrpContext->MajorFunction != IRP_MJ_READ) &&
|
|
(IrpContext->MajorFunction != IRP_MJ_WRITE) &&
|
|
(IrpContext->MajorFunction != IRP_MJ_DIRECTORY_CONTROL) &&
|
|
(IrpContext->MajorFunction != IRP_MJ_QUERY_EA) &&
|
|
(IrpContext->MajorFunction != IRP_MJ_SET_EA));
|
|
|
|
|
|
//
|
|
// Mark that we've already returned pending to the user
|
|
//
|
|
IoMarkIrpPending( Irp );
|
|
|
|
//
|
|
// Send the IRP_CONTEXT off to an Ex worker thread.
|
|
//
|
|
|
|
ExInitializeWorkItem( &IrpContext->WorkQueueItem,
|
|
DfsFspDispatch,
|
|
IrpContext );
|
|
|
|
ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue );
|
|
|
|
//
|
|
// And return to our caller
|
|
//
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFspDispatch, public
|
|
//
|
|
// Synopsis: This is the main FSP thread routine that is executed to receive
|
|
// and dispatch IRP requests. Each FSP requst begins its
|
|
// execution here.
|
|
//
|
|
// Arguments: [Context] -- Supplies a pointer to a DFS IRP context record.
|
|
//
|
|
// Returns: Nonthing
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID
|
|
DfsFspDispatch (
|
|
IN PVOID Context
|
|
) {
|
|
|
|
// PFS_DEVICE_OBJECT FileSysDeviceObject = Context;
|
|
PIRP Irp;
|
|
PIRP_CONTEXT IrpContext = Context;
|
|
|
|
Irp = IrpContext->OriginatingIrp;
|
|
|
|
//
|
|
// Now because we are the Fsp we will force the IrpContext to
|
|
// indicate true on Wait.
|
|
//
|
|
|
|
IrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT;
|
|
IrpContext->Flags &= ~IRP_CONTEXT_FLAG_IN_FSD;
|
|
|
|
//
|
|
// Now we'll loop forever, reading a new IRP request and dispatching
|
|
// on the IRP function
|
|
//
|
|
|
|
while (TRUE) {
|
|
|
|
DfsDbgTrace(0, Dbg, "DfsFspDispatch: Irp = %08lx\n", Irp);
|
|
|
|
ASSERT (Irp != NULL && Irp->IoStatus.Status != STATUS_VERIFY_REQUIRED);
|
|
|
|
|
|
//
|
|
// Now case on the function code. For each major function code,
|
|
// either call the appropriate FSP routine or case on the minor
|
|
// function and then call the FSP routine. The FSP routine that
|
|
// we call is responsible for completing the IRP, and not us.
|
|
// That way the routine can complete the IRP and then continue
|
|
// post processing as required. For example, a read can be
|
|
// satisfied right away and then read-ahead can be done.
|
|
//
|
|
// We'll do all of the work within an exception handler that
|
|
// will be invoked if ever some underlying operation gets into
|
|
// trouble.
|
|
//
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
try {
|
|
switch (IrpContext->MajorFunction) {
|
|
|
|
//
|
|
// For Create/Open operations, we post a workitem only
|
|
// to resume DNR after a call to IoCallDriver.
|
|
//
|
|
//
|
|
|
|
case IRP_MJ_CREATE:
|
|
case IRP_MJ_CREATE_NAMED_PIPE:
|
|
case IRP_MJ_CREATE_MAILSLOT:
|
|
|
|
ASSERT(IrpContext->Context != NULL);
|
|
ASSERT( ((PDNR_CONTEXT)IrpContext->Context)->NodeTypeCode ==
|
|
DSFS_NTC_DNR_CONTEXT );
|
|
DnrNameResolve( (PDNR_CONTEXT)IrpContext->Context );
|
|
PsAssignImpersonationToken(PsGetCurrentThread(),NULL);
|
|
break;
|
|
|
|
//
|
|
// For close operations
|
|
//
|
|
case IRP_MJ_CLOSE:
|
|
DfsFspClose( IrpContext, Irp );
|
|
break;
|
|
|
|
//
|
|
// For Set Information operations,
|
|
//
|
|
|
|
case IRP_MJ_SET_INFORMATION:
|
|
|
|
DfsFspSetInformation( IrpContext, Irp );
|
|
break;
|
|
|
|
//
|
|
// For Query Volume Information operations,
|
|
//
|
|
|
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
|
|
|
DfsFspQueryVolumeInformation( IrpContext, Irp );
|
|
break;
|
|
|
|
//
|
|
// For Set Volume Information operations,
|
|
//
|
|
|
|
case IRP_MJ_SET_VOLUME_INFORMATION:
|
|
|
|
DfsFspSetVolumeInformation( IrpContext, Irp );
|
|
break;
|
|
|
|
//
|
|
// For File System Control operations,
|
|
//
|
|
|
|
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
|
|
|
DfsFspFileSystemControl( IrpContext, Irp );
|
|
break;
|
|
|
|
//
|
|
// For any other major operations, return an invalid
|
|
// request.
|
|
//
|
|
|
|
default:
|
|
DfsDbgTrace(0, Dbg, "DfsFspDispatch: Unhandled request, MajorFunction = %08lx\n", IrpContext->MajorFunction);
|
|
|
|
DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
|
|
break;
|
|
}
|
|
|
|
} except( DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
|
|
|
|
DfsProcessException( IrpContext, Irp, GetExceptionCode() );
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
//
|
|
// NOTE: If we were to process an overflow device queue, we would
|
|
// do it here. Instead, we'll just return to the worker
|
|
// thread.
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
}
|