746 lines
23 KiB
C
746 lines
23 KiB
C
/*++ Copyright (c) 1987-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
MRxProxyAsyncEng.c
|
||
|
||
Abstract:
|
||
|
||
This module defines the types and functions related to the SMB protocol
|
||
selection engine: the component that translates minirdr calldowns into
|
||
SMBs.
|
||
|
||
Author:
|
||
|
||
Joe Linn [JoeLi] -- Implemented Ordinary Exchange
|
||
|
||
Notes:
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include <dfsfsctl.h>
|
||
|
||
RXDT_DefineCategory(MRXPROXY_ASYNCENG);
|
||
#define Dbg (DEBUG_TRACE_MRXPROXY_ASYNCENG)
|
||
|
||
#ifdef RX_PRIVATE_BUILD
|
||
#undef IoGetTopLevelIrp
|
||
#undef IoSetTopLevelIrp
|
||
#endif //ifdef RX_PRIVATE_BUILD
|
||
|
||
typedef struct _MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT {
|
||
struct {
|
||
LIST_ENTRY ExchangeListEntry;
|
||
union {
|
||
MRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext;
|
||
};
|
||
};
|
||
// MRXPROXY_ASYNCENG_VESTIGIAL_SMBBUF SmbBuf;
|
||
// struct {
|
||
// union {
|
||
// MDL;
|
||
// MDL Mdl;
|
||
// };
|
||
// ULONG Pages[2];
|
||
// } DataPartialMdl;
|
||
} MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT, *PMRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT;
|
||
|
||
BOOLEAN MRxProxyEntryPointIsMustSucceedable[MRXPROXY_ASYNCENG_CTX_FROM_MAXIMUM];
|
||
|
||
typedef enum {
|
||
MRxProxyAsyncEngMustSucceed = 0,
|
||
MRxProxyAsyncEngMustSucceedMaximum
|
||
};
|
||
RX_MUSTSUCCEED_DESCRIPTOR MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceedMaximum];
|
||
MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT MRxProxyAsyncEngMustSucceedAsyncEngineContext[MRxProxyAsyncEngMustSucceedMaximum];
|
||
|
||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||
|
||
|
||
#if DBG
|
||
#define P__ASSERT(exp) { \
|
||
if (!(exp)) { \
|
||
DbgPrint("NOT %s\n",#exp); \
|
||
errors++; \
|
||
}}
|
||
VOID
|
||
__MRxProxyAsyncEngOEAssertConsistentLinkage(
|
||
PSZ MsgPrefix,
|
||
PSZ File,
|
||
unsigned Line,
|
||
PRX_CONTEXT RxContext,
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext,
|
||
ULONG Flags
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs a variety of checks to ensure that the linkage between
|
||
the RxContext and the AsyncEngineContext is correct and that various fields
|
||
have correct values. if anything is bad....print stuff out and brkpoint;
|
||
|
||
Arguments:
|
||
|
||
MsgPrefix an identifying msg
|
||
RxContext duh
|
||
AsyncEngineContext .
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
{
|
||
ULONG errors = 0;
|
||
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyContext;
|
||
|
||
pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
|
||
|
||
P__ASSERT( AsyncEngineContext->SerialNumber == RxContext->SerialNumber );
|
||
P__ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
|
||
P__ASSERT( NodeType(AsyncEngineContext)==PROXY_NTC_ASYNCENGINE_CONTEXT );
|
||
P__ASSERT( AsyncEngineContext->RxContext == RxContext );
|
||
P__ASSERT( pMRxProxyContext->AsyncEngineContext == AsyncEngineContext );
|
||
if (!FlagOn(Flags,OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK)) {
|
||
P__ASSERT( AsyncEngineContext->RxContextCapturedRequestPacket == RxContext->CurrentIrp);
|
||
}
|
||
if (errors==0) {
|
||
return;
|
||
}
|
||
DbgPrint("%s INCONSISTENT OE STATE: %d errors at %s line %d\n",
|
||
MsgPrefix,errors,File,Line);
|
||
DbgBreakPoint();
|
||
return;
|
||
}
|
||
|
||
ULONG MRxProxyAsyncEngShortStatus(ULONG Status)
|
||
{
|
||
ULONG ShortStatus;
|
||
|
||
ShortStatus = Status & 0xc0003fff;
|
||
ShortStatus = ShortStatus | (ShortStatus >>16);
|
||
return(ShortStatus);
|
||
}
|
||
|
||
VOID MRxProxyAsyncEngUpdateOEHistory(
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext,
|
||
ULONG Tag1,
|
||
ULONG Tag2
|
||
)
|
||
{
|
||
ULONG MyIndex,Long0,Long1;
|
||
|
||
MyIndex = InterlockedIncrement(&AsyncEngineContext->History.Next);
|
||
MyIndex = (MyIndex-1) & (MRXPROXY_ASYNCENG_OE_HISTORY_SIZE-1);
|
||
Long0 = (Tag1<<16) | (Tag2 & 0xffff);
|
||
Long1 = (MRxProxyAsyncEngShortStatus(AsyncEngineContext->Status)<<16) | AsyncEngineContext->Flags;
|
||
AsyncEngineContext->History.Markers[MyIndex].Longs[0] = Long0;
|
||
AsyncEngineContext->History.Markers[MyIndex].Longs[1] = Long1;
|
||
}
|
||
|
||
#else
|
||
#endif
|
||
|
||
#define UPDATE_OE_HISTORY_WITH_STATUS(a) UPDATE_OE_HISTORY_2SHORTS(a,MRxProxyAsyncEngShortStatus(AsyncEngineContext->Status))
|
||
|
||
NTSTATUS
|
||
MRxProxyResumeAsyncEngineContext(
|
||
IN OUT PRX_CONTEXT RxContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine resumes processing on an exchange. This is called when work is
|
||
required to finish processing a request that cannot be completed at DPC
|
||
level. This happens either because the parse routine needs access to
|
||
structures that are not locks OR because the operation if asynchronous and
|
||
there maybe more work to be done.
|
||
|
||
The two cases are regularized by delaying the parse if we know that we're
|
||
going to post: this is indicated by the presense of a resume routine.
|
||
|
||
Arguments:
|
||
|
||
RxContext - the context of the operation. .
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
|
||
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext =
|
||
(PMRXPROXY_ASYNCENGINE_CONTEXT)(pMRxProxyContext->AsyncEngineContext);
|
||
RxCaptureFobx;
|
||
BOOLEAN PostedResume;
|
||
//PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
||
|
||
//PMDL SubmitMdl, HeaderFullMdl;
|
||
|
||
RxDbgTrace(+1, Dbg, ("MRxProxyResumeAsyncEngineContext entering........OE=%08lx\n",AsyncEngineContext));
|
||
ClearFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_AWAITING_DISPATCH);
|
||
PostedResume = BooleanFlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
|
||
ClearFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
|
||
|
||
MRxProxyAsyncEngOEAssertConsistentLinkageFromOE("MRxProxyAsyncEngContinueAsyncEngineContext:");
|
||
|
||
Status = AsyncEngineContext->Status;
|
||
UPDATE_OE_HISTORY_WITH_STATUS('0c');
|
||
|
||
#if 0
|
||
__RETRY_FINISH_ROUTINE__:
|
||
if ( AsyncEngineContext->FinishRoutine != NULL ) {
|
||
if ( Status == (STATUS_MORE_PROCESSING_REQUIRED) ){
|
||
AsyncEngineContext->Status = (STATUS_SUCCESS);
|
||
}
|
||
Status = AsyncEngineContext->FinishRoutine( AsyncEngineContext );
|
||
UPDATE_OE_HISTORY_WITH_STATUS('1c');
|
||
AsyncEngineContext->Status = Status;
|
||
AsyncEngineContext->FinishRoutine = NULL;
|
||
|
||
} else if ( Status == (STATUS_MORE_PROCESSING_REQUIRED) ) {
|
||
|
||
NOTHING; //it used to call the receive routine here
|
||
|
||
// after calling the receive routine again, we may NOW have a finish routine!
|
||
if ( AsyncEngineContext->FinishRoutine != NULL ) {
|
||
goto __RETRY_FINISH_ROUTINE__;
|
||
}
|
||
} else {
|
||
NOTHING;
|
||
}
|
||
#endif //0
|
||
|
||
if (PostedResume) {
|
||
|
||
Status = AsyncEngineContext->Continuation( MRXPROXY_ASYNCENGINE_ARGUMENTS );
|
||
UPDATE_OE_HISTORY_WITH_STATUS('3c');
|
||
|
||
}
|
||
|
||
//remove my references, if i'm the last guy then do the putaway...
|
||
UPDATE_OE_HISTORY_WITH_STATUS('4c');
|
||
MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
|
||
|
||
RxDbgTrace(-1, Dbg, ("MRxProxyResumeAsyncEngineContext returning %08lx.\n", Status));
|
||
return(Status);
|
||
|
||
} // MRxProxyAsyncEngContinueAsyncEngineContext
|
||
|
||
|
||
|
||
NTSTATUS
|
||
MRxProxySubmitAsyncEngRequest(
|
||
MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
||
IN MRXPROXY_ASYNCENGINE_CONTEXT_TYPE AECTXType
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements an ordinary exchange as viewed by the protocol
|
||
selection routines.
|
||
|
||
Arguments:
|
||
|
||
AsyncEngineContext - the exchange to be conducted.
|
||
AECTXType - async engine context submit Type
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
RxCaptureFcb;RxCaptureFobx;
|
||
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(RxContext);
|
||
//PMRXPROXY_ASYNCENG_CONTINUE_ROUTINE Continuation;
|
||
BOOLEAN AsyncOperation = FlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
|
||
|
||
PIRP TopIrp;
|
||
|
||
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
|
||
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
|
||
|
||
RxDbgTrace(+1, Dbg, ("MRxProxyAsyncEngSubmitRequest entering.......OE=%08lx\n",AsyncEngineContext));
|
||
|
||
MRxProxyAsyncEngOEAssertConsistentLinkageFromOE("MRxProxyAsyncEngSubmitRequest:");
|
||
|
||
AsyncEngineContext->AECTXType = AECTXType;
|
||
KeInitializeEvent( &RxContext->SyncEvent,
|
||
NotificationEvent,
|
||
FALSE );
|
||
|
||
MRxProxyReferenceAsyncEngineContext( AsyncEngineContext ); //this one is taken away in Continue
|
||
MRxProxyReferenceAsyncEngineContext( AsyncEngineContext ); //this one is taken away below...
|
||
//i must NOT finalize before InnerIo returns
|
||
IF_DEBUG {
|
||
//if ( ((AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_WRITE)
|
||
// || (AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_READ)
|
||
// || (AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_LOCKS))
|
||
// && BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)
|
||
// ) {
|
||
// ASSERT(AsyncOperation);
|
||
//}
|
||
}
|
||
|
||
MRxProxyAsyncEngOEAssertConsistentLinkage("just before transceive: ");
|
||
|
||
UPDATE_OE_HISTORY_2SHORTS('eo',AsyncOperation?'!!':0);
|
||
DbgDoit( InterlockedIncrement(&AsyncEngineContext->History.Submits); )
|
||
|
||
IF_DEBUG {
|
||
PIO_STACK_LOCATION IrpSp;
|
||
IrpSp = IoGetNextIrpStackLocation( AsyncEngineContext->CalldownIrp ); //ok4ioget
|
||
RxLog(("SAsyIrpX %lx %lx %lx %lx %lx %lx %lx",
|
||
RxContext,
|
||
IrpSp->MajorFunction,
|
||
IrpSp->Flags,
|
||
IrpSp->Parameters.Others.Argument1,
|
||
IrpSp->Parameters.Others.Argument2,
|
||
IrpSp->Parameters.Others.Argument3,
|
||
IrpSp->Parameters.Others.Argument4));
|
||
}
|
||
|
||
try {
|
||
TopIrp = IoGetTopLevelIrp();
|
||
IoSetTopLevelIrp(NULL); //tell the underlying guy he's all clear
|
||
Status = IoCallDriver(
|
||
proxySrvOpen->UnderlyingDeviceObject,
|
||
AsyncEngineContext->CalldownIrp
|
||
);
|
||
} finally {
|
||
IoSetTopLevelIrp(TopIrp); //restore my context for unwind
|
||
}
|
||
|
||
RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx(%08lx)\n",Status,RxContext));
|
||
|
||
if (Status != (STATUS_PENDING)) {
|
||
ASSERT(Status == AsyncEngineContext->CalldownIrp->IoStatus.Status);
|
||
Status = STATUS_PENDING;
|
||
}
|
||
|
||
|
||
MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext); //okay to finalize now that we're back
|
||
|
||
if ( Status == (STATUS_PENDING) ) {
|
||
if ( AsyncOperation ) {
|
||
goto FINALLY;
|
||
}
|
||
|
||
UPDATE_OE_HISTORY_WITH_STATUS('1o');
|
||
RxWaitSync( RxContext );
|
||
} else {
|
||
RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx\n",Status));
|
||
MRxProxyAsyncEngOEAssertConsistentLinkage("nonpending return from transceive: ");
|
||
// if it's an error, remove the references that i placed and get out
|
||
if (NT_ERROR(Status)) {
|
||
MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
|
||
goto FINALLY;
|
||
}
|
||
}
|
||
|
||
//at last, call the continuation........
|
||
|
||
MRxProxyAsyncEngOEAssertConsistentLinkage("just before continueOE: ");
|
||
Status = MRxProxyResumeAsyncEngineContext( RxContext );
|
||
UPDATE_OE_HISTORY_WITH_STATUS('9o');
|
||
|
||
FINALLY:
|
||
RxDbgTrace(-1, Dbg, ("MRxProxyAsyncEngSubmitRequest returning %08lx.\n", Status));
|
||
return(Status);
|
||
|
||
} // MRxProxyAsyncEngSubmitRequest
|
||
|
||
|
||
|
||
//#define MRXSMB_TEST_MUST_SUCCEED
|
||
#ifdef MRXSMB_TEST_MUST_SUCCEED
|
||
ULONG MRxProxyAllocatedMustSucceedExchange;
|
||
ULONG MRxProxyAllocatedMustSucceedSmbBuf;
|
||
#define MSFAILPAT ((0x3f)<<2)
|
||
#define FAIL_XXX_ALLOCATE() (FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED) \
|
||
&&((RxContext->SerialNumber&MSFAILPAT)==MSFAILPAT) \
|
||
&&((MRxProxyEntryPointIsMustSucceedable[EntryPoint])) )
|
||
#define FAIL_EXCHANGE_ALLOCATE() ( FAIL_XXX_ALLOCATE() && (RxContext->SerialNumber&2) )
|
||
#define FAIL_SMBBUF_ALLOCATE() ( FAIL_XXX_ALLOCATE() && (RxContext->SerialNumber&1) )
|
||
#define COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED() {MRxProxyAllocatedMustSucceedExchange++;}
|
||
#define COUNT_MUST_SUCCEED_SMBBUF_ALLOCATED() {MRxProxyAllocatedMustSucceedSmbBuf++;}
|
||
#define MUST_SUCCEED_ASSERT(x) {ASSERT(x);}
|
||
#else
|
||
#define FAIL_EXCHANGE_ALLOCATE() (FALSE)
|
||
#define FAIL_SMBBUF_ALLOCATE() (FALSE)
|
||
#define COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED() {NOTHING;}
|
||
#define COUNT_MUST_SUCCEED_SMBBUF_ALLOCATED() {NOTHING;}
|
||
#define MUST_SUCCEED_ASSERT(x) {NOTHING;}
|
||
#endif
|
||
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT
|
||
MRxProxyCreateAsyncEngineContext (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN MRXPROXY_ASYNCENGINE_CONTEXT_ENTRYPOINTS EntryPoint
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates and initializes an SMB header buffer. Currently,
|
||
we just allocate them from pool except when must_succeed is specified.
|
||
|
||
Arguments:
|
||
|
||
RxContext - the RDBSS context
|
||
VNetRoot -
|
||
DispatchVector -
|
||
|
||
Return Value:
|
||
|
||
A buffer ready to go, OR NULL.
|
||
|
||
Notes:
|
||
|
||
|
||
|
||
--*/
|
||
{
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(RxContext);
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext = NULL;
|
||
PMRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT MustSucceedAsyncEngineContext = NULL;
|
||
//NTSTATUS Status;
|
||
RxCaptureFobx;
|
||
|
||
|
||
RxDbgTrace( +1, Dbg, ("MRxProxyCreateAsyncEngineContext\n") );
|
||
|
||
//DbgBreakPoint();
|
||
|
||
if (!FAIL_EXCHANGE_ALLOCATE()) {
|
||
AsyncEngineContext = (PMRXPROXY_ASYNCENGINE_CONTEXT)RxAllocatePoolWithTag(
|
||
NonPagedPool,
|
||
sizeof(MRXPROXY_ASYNCENGINE_CONTEXT),
|
||
MRXPROXY_ASYNCENGINECONTEXT_POOLTAG );
|
||
}
|
||
|
||
if ( AsyncEngineContext == NULL ) {
|
||
//ASSERT(!"must-succeed");
|
||
if (TRUE
|
||
|| !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED)
|
||
|| !MRxProxyEntryPointIsMustSucceedable[EntryPoint]) {
|
||
RxDbgTrace( 0, Dbg, (" --> Couldn't get the asyncengcontext!\n") );
|
||
return NULL;
|
||
}
|
||
// MustSucceedAsyncEngineContext = RxAcquireMustSucceedStructure(&MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceed]);
|
||
// COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED();
|
||
// AsyncEngineContext = (PMRXPROXY_ASYNCENGINE_CONTEXT)SmbMmAllocateExchange(ORDINARY_EXCHANGE,
|
||
// &MustSucceedAsyncEngineContext->ExchangeListEntry);
|
||
// SetFlag( AsyncEngineContext->Flags, MRXPROXY_ASYNCENG_CTX_FLAG_MUST_SUCCEED_ALLOCATED_OE );
|
||
}
|
||
|
||
ZeroAndInitializeNodeType( AsyncEngineContext,
|
||
PROXY_NTC_ASYNCENGINE_CONTEXT,
|
||
sizeof(MRXPROXY_ASYNCENGINE_CONTEXT));
|
||
InterlockedIncrement( &AsyncEngineContext->NodeReferenceCount );
|
||
|
||
DbgDoit(AsyncEngineContext->SerialNumber = RxContext->SerialNumber);
|
||
|
||
//place a reference on the rxcontext until we are finished
|
||
InterlockedIncrement( &RxContext->ReferenceCount );
|
||
|
||
AsyncEngineContext->RxContext = RxContext;
|
||
AsyncEngineContext->EntryPoint = EntryPoint;
|
||
|
||
DbgDoit(AsyncEngineContext->RxContextCapturedRequestPacket = RxContext->CurrentIrp;);
|
||
|
||
pMRxProxyAsyncEngineContext->AsyncEngineContext = AsyncEngineContext;
|
||
|
||
|
||
RxDbgTrace( -1, Dbg, (" --> exiting w!\n") );
|
||
return(AsyncEngineContext);
|
||
|
||
|
||
//UNWIND:
|
||
// //RxDbgTraceUnIndent(-1, Dbg);
|
||
// RxDbgTrace( -1, Dbg, (" --> exiting w/o!\n") );
|
||
// MUST_SUCCEED_ASSERT(!"Finalizing on the way out");
|
||
// MRxProxyAsyncEngFinalizeAsyncEngineContext( AsyncEngineContext );
|
||
// return(NULL);
|
||
|
||
}
|
||
|
||
|
||
|
||
#if DBG
|
||
ULONG MRxProxyFinalizeAECtxTraceLevel = 1200;
|
||
#define FINALIZESS_LEVEL MRxProxyFinalizeAECtxTraceLevel
|
||
#define FINALIZE_TRACKING_SETUP() \
|
||
struct { \
|
||
ULONG marker1; \
|
||
ULONG finalstate; \
|
||
ULONG marker2; \
|
||
} Tracking = {'ereh',0,'ereh'};
|
||
#define FINALIZE_TRACKING(x) {\
|
||
Tracking.finalstate |= x; \
|
||
}
|
||
|
||
#define FINALIZE_TRACE(x) MRxProxyAsyncEngFinalizeAECtxTrace(x,Tracking.finalstate)
|
||
VOID
|
||
MRxProxyAsyncEngFinalizeAECtxTrace(PSZ text,ULONG finalstate)
|
||
{
|
||
RxDbgTraceLV(0, Dbg, FINALIZESS_LEVEL,
|
||
("MRxProxyFinalizeAsyncEngineContext --> %s(%08lx)\n",text,finalstate));
|
||
}
|
||
#else
|
||
#define FINALIZE_TRACKING_SETUP()
|
||
#define FINALIZE_TRACKING(x)
|
||
#define FINALIZE_TRACE(x)
|
||
#endif
|
||
|
||
BOOLEAN
|
||
MRxProxyFinalizeAsyncEngineContext (
|
||
IN OUT PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This finalizes an OE.
|
||
|
||
Arguments:
|
||
|
||
AsyncEngineContext - pointer to the OE to be dismantled.
|
||
|
||
Return Value:
|
||
|
||
TRUE if finalization occurs otherwise FALSE.
|
||
|
||
Notes:
|
||
|
||
|
||
|
||
--*/
|
||
{
|
||
LONG result;
|
||
PIRP irp;
|
||
ULONG AsyncEngineContextFlags = AsyncEngineContext->Flags;
|
||
ULONG ThisIsMustSucceedAllocated =
|
||
AsyncEngineContextFlags & (MRXPROXY_ASYNCENG_CTX_FLAG_MUST_SUCCEED_ALLOCATED);
|
||
FINALIZE_TRACKING_SETUP()
|
||
|
||
MRxProxyAsyncEngOEAssertConsistentLinkageFromOEwithFlags("MRxProxyAsyncEngFinalizeAsyncEngineContext:",OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK);
|
||
|
||
RxDbgTraceLV(+1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext\n"));
|
||
|
||
result = InterlockedDecrement(&AsyncEngineContext->NodeReferenceCount);
|
||
if ( result != 0 ) {
|
||
RxDbgTraceLV(-1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext -- returning w/o finalizing (%d)\n",result));
|
||
return FALSE;
|
||
}
|
||
|
||
RxLog((">>>OE %lx %lx",
|
||
AsyncEngineContext,
|
||
AsyncEngineContext->Flags));
|
||
|
||
FINALIZE_TRACKING( 0x1 );
|
||
|
||
if ( (irp =AsyncEngineContext->CalldownIrp) != NULL ) {
|
||
if (irp->MdlAddress) {
|
||
IoFreeMdl(irp->MdlAddress);
|
||
}
|
||
IoFreeIrp( irp );
|
||
FINALIZE_TRACKING( 0x20 );
|
||
}
|
||
|
||
if ( AsyncEngineContext->RxContext != NULL ) {
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(AsyncEngineContext->RxContext);
|
||
ASSERT( pMRxProxyAsyncEngineContext->AsyncEngineContext == AsyncEngineContext );
|
||
|
||
//get rid of the reference on the RxContext....if i'm the last guy this will finalize
|
||
RxDereferenceAndDeleteRxContext( AsyncEngineContext->RxContext );
|
||
FINALIZE_TRACKING( 0x600 );
|
||
} else {
|
||
FINALIZE_TRACKING( 0xf00 );
|
||
}
|
||
|
||
FINALIZE_TRACE("ready to discard exchange");
|
||
RxFreePool(AsyncEngineContext);
|
||
FINALIZE_TRACKING( 0x3000 );
|
||
|
||
if (ThisIsMustSucceedAllocated) {
|
||
//RxReleaseMustSucceedStructure(&MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceed]);
|
||
}
|
||
|
||
|
||
FINALIZE_TRACKING( 0x40000 );
|
||
RxDbgTraceLV(-1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext --> exit finalstate=%x\n",Tracking.finalstate));
|
||
return(TRUE);
|
||
|
||
} // MRxProxyFinalizeAsyncEngineContext
|
||
|
||
|
||
NTSTATUS
|
||
MRxProxyAsyncEngineCalldownIrpCompletion (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP CalldownIrp,
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called when the calldownirp is completed.
|
||
|
||
Arguments:
|
||
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP CalldownIrp,
|
||
IN PVOID Context
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - STATUS_MORE_PROCESSING_REQUIRED
|
||
|
||
--*/
|
||
{
|
||
PRX_CONTEXT RxContext = Context;
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext = pMRxProxyContext->AsyncEngineContext;
|
||
BOOLEAN AsyncOperation = FlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
|
||
|
||
UPDATE_OE_HISTORY_WITH_STATUS('ff');
|
||
MRxProxyAsyncEngOEAssertConsistentLinkage("MRxProxyCalldownCompletion: ");
|
||
|
||
AsyncEngineContext->IoStatusBlock = CalldownIrp->IoStatus;
|
||
|
||
if (AsyncOperation) {
|
||
NTSTATUS PostStatus;
|
||
RxDbgTraceLV(0, Dbg, 1000, ("Resume with post-to-async\n"));
|
||
|
||
SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_AWAITING_DISPATCH);
|
||
SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
|
||
IF_DEBUG {
|
||
//fill the workqueue structure with deadbeef....all the better to diagnose
|
||
//a failed post
|
||
ULONG i;
|
||
for (i=0;i+sizeof(ULONG)-1<sizeof(AsyncEngineContext->WorkQueueItem);i+=sizeof(ULONG)) {
|
||
//*((PULONG)(((PBYTE)&AsyncEngineContext->WorkQueueItem)+i)) = 0xdeadbeef;
|
||
PBYTE BytePtr = ((PBYTE)&AsyncEngineContext->WorkQueueItem)+i;
|
||
PULONG UlongPtr = (PULONG)BytePtr;
|
||
*UlongPtr = 0xdeadbeef;
|
||
}
|
||
}
|
||
PostStatus = RxPostToWorkerThread(&MRxProxyDeviceObject->RxDeviceObject,
|
||
CriticalWorkQueue,
|
||
&AsyncEngineContext->WorkQueueItem,
|
||
MRxProxyResumeAsyncEngineContext,
|
||
RxContext);
|
||
ASSERT(PostStatus == STATUS_SUCCESS);
|
||
} else {
|
||
RxDbgTraceLV(0, Dbg, 1000, ("sync resume\n"));
|
||
RxSignalSynchronousWaiter(RxContext);
|
||
}
|
||
|
||
return((STATUS_MORE_PROCESSING_REQUIRED));
|
||
}
|
||
|
||
#if DBG
|
||
#define DEBUG_ONLY_CODE(x) x
|
||
#else
|
||
#define DEBUG_ONLY_CODE(x)
|
||
#endif
|
||
NTSTATUS
|
||
__MRxProxyAsyncEngineOuterWrapper (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN MRXPROXY_ASYNCENGINE_CONTEXT_ENTRYPOINTS EntryPoint,
|
||
IN PMRXPROXY_ASYNCENG_CONTINUE_ROUTINE Continuation
|
||
#if DBG
|
||
,IN PSZ RoutineName,
|
||
IN BOOLEAN LoudProcessing,
|
||
IN BOOLEAN StopOnLoud
|
||
#endif
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is common to guys who use the async context engine. it has the
|
||
responsibility for getting a context, initing, starting, finalizing but the
|
||
internal guts of the procesing is via the continuation routine that is passed in.
|
||
|
||
Arguments:
|
||
|
||
RxContext - the RDBSS context
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
RxCaptureFcb; RxCaptureFobx;
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext;
|
||
|
||
PAGED_CODE();
|
||
|
||
DEBUG_ONLY_CODE(
|
||
RxDbgTrace(+1, Dbg, ("Wrapped%s %08lx\n", RoutineName, RxContext ))
|
||
);
|
||
|
||
ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
|
||
|
||
AsyncEngineContext = MRxProxyCreateAsyncEngineContext(
|
||
RxContext,
|
||
EntryPoint);
|
||
|
||
if (AsyncEngineContext==NULL) {
|
||
RxDbgTrace(-1, Dbg, ("Couldn't get the AsyncEngineContext!\n"));
|
||
return((STATUS_INSUFFICIENT_RESOURCES));
|
||
}
|
||
|
||
AsyncEngineContext->Continuation = Continuation;
|
||
Status = Continuation(MRXPROXY_ASYNCENGINE_ARGUMENTS);
|
||
|
||
if (Status!=(STATUS_PENDING)) {
|
||
BOOLEAN FinalizationComplete;
|
||
DEBUG_ONLY_CODE(
|
||
if (LoudProcessing) {
|
||
if ((Status!=STATUS_SUCCESS) && (RxContext->LoudCompletionString)) {
|
||
DbgPrint("LoudFailure %08lx on %wZ\n",Status,RxContext->LoudCompletionString);
|
||
if (StopOnLoud) {
|
||
DbgBreakPoint();
|
||
}
|
||
}
|
||
}
|
||
)
|
||
FinalizationComplete = MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
|
||
ASSERT(FinalizationComplete);
|
||
} else {
|
||
ASSERT(BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION));
|
||
}
|
||
|
||
DEBUG_ONLY_CODE(
|
||
RxDbgTrace(+1, Dbg, ("Wrapped%s %08lx exit with status=%08lx\n", RoutineName, RxContext, Status ))
|
||
);
|
||
return(Status);
|
||
|
||
} // MRxProxyQueryDir
|
||
|
||
|
||
|