Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

746 lines
23 KiB

/*++ 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