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.

745 lines
23 KiB

  1. /*++ Copyright (c) 1987-1993 Microsoft Corporation
  2. Module Name:
  3. MRxProxyAsyncEng.c
  4. Abstract:
  5. This module defines the types and functions related to the SMB protocol
  6. selection engine: the component that translates minirdr calldowns into
  7. SMBs.
  8. Author:
  9. Joe Linn [JoeLi] -- Implemented Ordinary Exchange
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <dfsfsctl.h>
  15. RXDT_DefineCategory(MRXPROXY_ASYNCENG);
  16. #define Dbg (DEBUG_TRACE_MRXPROXY_ASYNCENG)
  17. #ifdef RX_PRIVATE_BUILD
  18. #undef IoGetTopLevelIrp
  19. #undef IoSetTopLevelIrp
  20. #endif //ifdef RX_PRIVATE_BUILD
  21. typedef struct _MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT {
  22. struct {
  23. LIST_ENTRY ExchangeListEntry;
  24. union {
  25. MRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext;
  26. };
  27. };
  28. // MRXPROXY_ASYNCENG_VESTIGIAL_SMBBUF SmbBuf;
  29. // struct {
  30. // union {
  31. // MDL;
  32. // MDL Mdl;
  33. // };
  34. // ULONG Pages[2];
  35. // } DataPartialMdl;
  36. } MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT, *PMRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT;
  37. BOOLEAN MRxProxyEntryPointIsMustSucceedable[MRXPROXY_ASYNCENG_CTX_FROM_MAXIMUM];
  38. typedef enum {
  39. MRxProxyAsyncEngMustSucceed = 0,
  40. MRxProxyAsyncEngMustSucceedMaximum
  41. };
  42. RX_MUSTSUCCEED_DESCRIPTOR MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceedMaximum];
  43. MRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT MRxProxyAsyncEngMustSucceedAsyncEngineContext[MRxProxyAsyncEngMustSucceedMaximum];
  44. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  45. #if DBG
  46. #define P__ASSERT(exp) { \
  47. if (!(exp)) { \
  48. DbgPrint("NOT %s\n",#exp); \
  49. errors++; \
  50. }}
  51. VOID
  52. __MRxProxyAsyncEngOEAssertConsistentLinkage(
  53. PSZ MsgPrefix,
  54. PSZ File,
  55. unsigned Line,
  56. PRX_CONTEXT RxContext,
  57. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext,
  58. ULONG Flags
  59. )
  60. /*++
  61. Routine Description:
  62. This routine performs a variety of checks to ensure that the linkage between
  63. the RxContext and the AsyncEngineContext is correct and that various fields
  64. have correct values. if anything is bad....print stuff out and brkpoint;
  65. Arguments:
  66. MsgPrefix an identifying msg
  67. RxContext duh
  68. AsyncEngineContext .
  69. Return Value:
  70. none
  71. Notes:
  72. --*/
  73. {
  74. ULONG errors = 0;
  75. PMRXPROXY_RX_CONTEXT pMRxProxyContext;
  76. pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  77. P__ASSERT( AsyncEngineContext->SerialNumber == RxContext->SerialNumber );
  78. P__ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  79. P__ASSERT( NodeType(AsyncEngineContext)==PROXY_NTC_ASYNCENGINE_CONTEXT );
  80. P__ASSERT( AsyncEngineContext->RxContext == RxContext );
  81. P__ASSERT( pMRxProxyContext->AsyncEngineContext == AsyncEngineContext );
  82. if (!FlagOn(Flags,OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK)) {
  83. P__ASSERT( AsyncEngineContext->RxContextCapturedRequestPacket == RxContext->CurrentIrp);
  84. }
  85. if (errors==0) {
  86. return;
  87. }
  88. DbgPrint("%s INCONSISTENT OE STATE: %d errors at %s line %d\n",
  89. MsgPrefix,errors,File,Line);
  90. DbgBreakPoint();
  91. return;
  92. }
  93. ULONG MRxProxyAsyncEngShortStatus(ULONG Status)
  94. {
  95. ULONG ShortStatus;
  96. ShortStatus = Status & 0xc0003fff;
  97. ShortStatus = ShortStatus | (ShortStatus >>16);
  98. return(ShortStatus);
  99. }
  100. VOID MRxProxyAsyncEngUpdateOEHistory(
  101. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext,
  102. ULONG Tag1,
  103. ULONG Tag2
  104. )
  105. {
  106. ULONG MyIndex,Long0,Long1;
  107. MyIndex = InterlockedIncrement(&AsyncEngineContext->History.Next);
  108. MyIndex = (MyIndex-1) & (MRXPROXY_ASYNCENG_OE_HISTORY_SIZE-1);
  109. Long0 = (Tag1<<16) | (Tag2 & 0xffff);
  110. Long1 = (MRxProxyAsyncEngShortStatus(AsyncEngineContext->Status)<<16) | AsyncEngineContext->Flags;
  111. AsyncEngineContext->History.Markers[MyIndex].Longs[0] = Long0;
  112. AsyncEngineContext->History.Markers[MyIndex].Longs[1] = Long1;
  113. }
  114. #else
  115. #endif
  116. #define UPDATE_OE_HISTORY_WITH_STATUS(a) UPDATE_OE_HISTORY_2SHORTS(a,MRxProxyAsyncEngShortStatus(AsyncEngineContext->Status))
  117. NTSTATUS
  118. MRxProxyResumeAsyncEngineContext(
  119. IN OUT PRX_CONTEXT RxContext
  120. )
  121. /*++
  122. Routine Description:
  123. This routine resumes processing on an exchange. This is called when work is
  124. required to finish processing a request that cannot be completed at DPC
  125. level. This happens either because the parse routine needs access to
  126. structures that are not locks OR because the operation if asynchronous and
  127. there maybe more work to be done.
  128. The two cases are regularized by delaying the parse if we know that we're
  129. going to post: this is indicated by the presense of a resume routine.
  130. Arguments:
  131. RxContext - the context of the operation. .
  132. Return Value:
  133. RXSTATUS - The return status for the operation
  134. Notes:
  135. --*/
  136. {
  137. NTSTATUS Status;
  138. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  139. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext =
  140. (PMRXPROXY_ASYNCENGINE_CONTEXT)(pMRxProxyContext->AsyncEngineContext);
  141. RxCaptureFobx;
  142. BOOLEAN PostedResume;
  143. //PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  144. //PMDL SubmitMdl, HeaderFullMdl;
  145. RxDbgTrace(+1, Dbg, ("MRxProxyResumeAsyncEngineContext entering........OE=%08lx\n",AsyncEngineContext));
  146. ClearFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_AWAITING_DISPATCH);
  147. PostedResume = BooleanFlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
  148. ClearFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
  149. MRxProxyAsyncEngOEAssertConsistentLinkageFromOE("MRxProxyAsyncEngContinueAsyncEngineContext:");
  150. Status = AsyncEngineContext->Status;
  151. UPDATE_OE_HISTORY_WITH_STATUS('0c');
  152. #if 0
  153. __RETRY_FINISH_ROUTINE__:
  154. if ( AsyncEngineContext->FinishRoutine != NULL ) {
  155. if ( Status == (STATUS_MORE_PROCESSING_REQUIRED) ){
  156. AsyncEngineContext->Status = (STATUS_SUCCESS);
  157. }
  158. Status = AsyncEngineContext->FinishRoutine( AsyncEngineContext );
  159. UPDATE_OE_HISTORY_WITH_STATUS('1c');
  160. AsyncEngineContext->Status = Status;
  161. AsyncEngineContext->FinishRoutine = NULL;
  162. } else if ( Status == (STATUS_MORE_PROCESSING_REQUIRED) ) {
  163. NOTHING; //it used to call the receive routine here
  164. // after calling the receive routine again, we may NOW have a finish routine!
  165. if ( AsyncEngineContext->FinishRoutine != NULL ) {
  166. goto __RETRY_FINISH_ROUTINE__;
  167. }
  168. } else {
  169. NOTHING;
  170. }
  171. #endif //0
  172. if (PostedResume) {
  173. Status = AsyncEngineContext->Continuation( MRXPROXY_ASYNCENGINE_ARGUMENTS );
  174. UPDATE_OE_HISTORY_WITH_STATUS('3c');
  175. }
  176. //remove my references, if i'm the last guy then do the putaway...
  177. UPDATE_OE_HISTORY_WITH_STATUS('4c');
  178. MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
  179. RxDbgTrace(-1, Dbg, ("MRxProxyResumeAsyncEngineContext returning %08lx.\n", Status));
  180. return(Status);
  181. } // MRxProxyAsyncEngContinueAsyncEngineContext
  182. NTSTATUS
  183. MRxProxySubmitAsyncEngRequest(
  184. MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE,
  185. IN MRXPROXY_ASYNCENGINE_CONTEXT_TYPE AECTXType
  186. )
  187. /*++
  188. Routine Description:
  189. This routine implements an ordinary exchange as viewed by the protocol
  190. selection routines.
  191. Arguments:
  192. AsyncEngineContext - the exchange to be conducted.
  193. AECTXType - async engine context submit Type
  194. Return Value:
  195. RXSTATUS - The return status for the operation
  196. Notes:
  197. --*/
  198. {
  199. NTSTATUS Status;
  200. RxCaptureFcb;RxCaptureFobx;
  201. PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(RxContext);
  202. //PMRXPROXY_ASYNCENG_CONTINUE_ROUTINE Continuation;
  203. BOOLEAN AsyncOperation = FlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
  204. PIRP TopIrp;
  205. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  206. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  207. RxDbgTrace(+1, Dbg, ("MRxProxyAsyncEngSubmitRequest entering.......OE=%08lx\n",AsyncEngineContext));
  208. MRxProxyAsyncEngOEAssertConsistentLinkageFromOE("MRxProxyAsyncEngSubmitRequest:");
  209. AsyncEngineContext->AECTXType = AECTXType;
  210. KeInitializeEvent( &RxContext->SyncEvent,
  211. NotificationEvent,
  212. FALSE );
  213. MRxProxyReferenceAsyncEngineContext( AsyncEngineContext ); //this one is taken away in Continue
  214. MRxProxyReferenceAsyncEngineContext( AsyncEngineContext ); //this one is taken away below...
  215. //i must NOT finalize before InnerIo returns
  216. IF_DEBUG {
  217. //if ( ((AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_WRITE)
  218. // || (AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_READ)
  219. // || (AsyncEngineContext->AECTXType == MRXPROXY_ASYNCENG_AECTXTYPE_LOCKS))
  220. // && BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)
  221. // ) {
  222. // ASSERT(AsyncOperation);
  223. //}
  224. }
  225. MRxProxyAsyncEngOEAssertConsistentLinkage("just before transceive: ");
  226. UPDATE_OE_HISTORY_2SHORTS('eo',AsyncOperation?'!!':0);
  227. DbgDoit( InterlockedIncrement(&AsyncEngineContext->History.Submits); )
  228. IF_DEBUG {
  229. PIO_STACK_LOCATION IrpSp;
  230. IrpSp = IoGetNextIrpStackLocation( AsyncEngineContext->CalldownIrp ); //ok4ioget
  231. RxLog(("SAsyIrpX %lx %lx %lx %lx %lx %lx %lx",
  232. RxContext,
  233. IrpSp->MajorFunction,
  234. IrpSp->Flags,
  235. IrpSp->Parameters.Others.Argument1,
  236. IrpSp->Parameters.Others.Argument2,
  237. IrpSp->Parameters.Others.Argument3,
  238. IrpSp->Parameters.Others.Argument4));
  239. }
  240. try {
  241. TopIrp = IoGetTopLevelIrp();
  242. IoSetTopLevelIrp(NULL); //tell the underlying guy he's all clear
  243. Status = IoCallDriver(
  244. proxySrvOpen->UnderlyingDeviceObject,
  245. AsyncEngineContext->CalldownIrp
  246. );
  247. } finally {
  248. IoSetTopLevelIrp(TopIrp); //restore my context for unwind
  249. }
  250. RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx(%08lx)\n",Status,RxContext));
  251. if (Status != (STATUS_PENDING)) {
  252. ASSERT(Status == AsyncEngineContext->CalldownIrp->IoStatus.Status);
  253. Status = STATUS_PENDING;
  254. }
  255. MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext); //okay to finalize now that we're back
  256. if ( Status == (STATUS_PENDING) ) {
  257. if ( AsyncOperation ) {
  258. goto FINALLY;
  259. }
  260. UPDATE_OE_HISTORY_WITH_STATUS('1o');
  261. RxWaitSync( RxContext );
  262. } else {
  263. RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx\n",Status));
  264. MRxProxyAsyncEngOEAssertConsistentLinkage("nonpending return from transceive: ");
  265. // if it's an error, remove the references that i placed and get out
  266. if (NT_ERROR(Status)) {
  267. MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
  268. goto FINALLY;
  269. }
  270. }
  271. //at last, call the continuation........
  272. MRxProxyAsyncEngOEAssertConsistentLinkage("just before continueOE: ");
  273. Status = MRxProxyResumeAsyncEngineContext( RxContext );
  274. UPDATE_OE_HISTORY_WITH_STATUS('9o');
  275. FINALLY:
  276. RxDbgTrace(-1, Dbg, ("MRxProxyAsyncEngSubmitRequest returning %08lx.\n", Status));
  277. return(Status);
  278. } // MRxProxyAsyncEngSubmitRequest
  279. //#define MRXSMB_TEST_MUST_SUCCEED
  280. #ifdef MRXSMB_TEST_MUST_SUCCEED
  281. ULONG MRxProxyAllocatedMustSucceedExchange;
  282. ULONG MRxProxyAllocatedMustSucceedSmbBuf;
  283. #define MSFAILPAT ((0x3f)<<2)
  284. #define FAIL_XXX_ALLOCATE() (FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED) \
  285. &&((RxContext->SerialNumber&MSFAILPAT)==MSFAILPAT) \
  286. &&((MRxProxyEntryPointIsMustSucceedable[EntryPoint])) )
  287. #define FAIL_EXCHANGE_ALLOCATE() ( FAIL_XXX_ALLOCATE() && (RxContext->SerialNumber&2) )
  288. #define FAIL_SMBBUF_ALLOCATE() ( FAIL_XXX_ALLOCATE() && (RxContext->SerialNumber&1) )
  289. #define COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED() {MRxProxyAllocatedMustSucceedExchange++;}
  290. #define COUNT_MUST_SUCCEED_SMBBUF_ALLOCATED() {MRxProxyAllocatedMustSucceedSmbBuf++;}
  291. #define MUST_SUCCEED_ASSERT(x) {ASSERT(x);}
  292. #else
  293. #define FAIL_EXCHANGE_ALLOCATE() (FALSE)
  294. #define FAIL_SMBBUF_ALLOCATE() (FALSE)
  295. #define COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED() {NOTHING;}
  296. #define COUNT_MUST_SUCCEED_SMBBUF_ALLOCATED() {NOTHING;}
  297. #define MUST_SUCCEED_ASSERT(x) {NOTHING;}
  298. #endif
  299. PMRXPROXY_ASYNCENGINE_CONTEXT
  300. MRxProxyCreateAsyncEngineContext (
  301. IN PRX_CONTEXT RxContext,
  302. IN MRXPROXY_ASYNCENGINE_CONTEXT_ENTRYPOINTS EntryPoint
  303. )
  304. /*++
  305. Routine Description:
  306. This routine allocates and initializes an SMB header buffer. Currently,
  307. we just allocate them from pool except when must_succeed is specified.
  308. Arguments:
  309. RxContext - the RDBSS context
  310. VNetRoot -
  311. DispatchVector -
  312. Return Value:
  313. A buffer ready to go, OR NULL.
  314. Notes:
  315. --*/
  316. {
  317. PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(RxContext);
  318. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext = NULL;
  319. PMRXPROXY_ASYNCENG_MUST_SUCCEEED_CONTEXT MustSucceedAsyncEngineContext = NULL;
  320. //NTSTATUS Status;
  321. RxCaptureFobx;
  322. RxDbgTrace( +1, Dbg, ("MRxProxyCreateAsyncEngineContext\n") );
  323. //DbgBreakPoint();
  324. if (!FAIL_EXCHANGE_ALLOCATE()) {
  325. AsyncEngineContext = (PMRXPROXY_ASYNCENGINE_CONTEXT)RxAllocatePoolWithTag(
  326. NonPagedPool,
  327. sizeof(MRXPROXY_ASYNCENGINE_CONTEXT),
  328. MRXPROXY_ASYNCENGINECONTEXT_POOLTAG );
  329. }
  330. if ( AsyncEngineContext == NULL ) {
  331. //ASSERT(!"must-succeed");
  332. if (TRUE
  333. || !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED)
  334. || !MRxProxyEntryPointIsMustSucceedable[EntryPoint]) {
  335. RxDbgTrace( 0, Dbg, (" --> Couldn't get the asyncengcontext!\n") );
  336. return NULL;
  337. }
  338. // MustSucceedAsyncEngineContext = RxAcquireMustSucceedStructure(&MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceed]);
  339. // COUNT_MUST_SUCCEED_EXCHANGE_ALLOCATED();
  340. // AsyncEngineContext = (PMRXPROXY_ASYNCENGINE_CONTEXT)SmbMmAllocateExchange(ORDINARY_EXCHANGE,
  341. // &MustSucceedAsyncEngineContext->ExchangeListEntry);
  342. // SetFlag( AsyncEngineContext->Flags, MRXPROXY_ASYNCENG_CTX_FLAG_MUST_SUCCEED_ALLOCATED_OE );
  343. }
  344. ZeroAndInitializeNodeType( AsyncEngineContext,
  345. PROXY_NTC_ASYNCENGINE_CONTEXT,
  346. sizeof(MRXPROXY_ASYNCENGINE_CONTEXT));
  347. InterlockedIncrement( &AsyncEngineContext->NodeReferenceCount );
  348. DbgDoit(AsyncEngineContext->SerialNumber = RxContext->SerialNumber);
  349. //place a reference on the rxcontext until we are finished
  350. InterlockedIncrement( &RxContext->ReferenceCount );
  351. AsyncEngineContext->RxContext = RxContext;
  352. AsyncEngineContext->EntryPoint = EntryPoint;
  353. DbgDoit(AsyncEngineContext->RxContextCapturedRequestPacket = RxContext->CurrentIrp;);
  354. pMRxProxyAsyncEngineContext->AsyncEngineContext = AsyncEngineContext;
  355. RxDbgTrace( -1, Dbg, (" --> exiting w!\n") );
  356. return(AsyncEngineContext);
  357. //UNWIND:
  358. // //RxDbgTraceUnIndent(-1, Dbg);
  359. // RxDbgTrace( -1, Dbg, (" --> exiting w/o!\n") );
  360. // MUST_SUCCEED_ASSERT(!"Finalizing on the way out");
  361. // MRxProxyAsyncEngFinalizeAsyncEngineContext( AsyncEngineContext );
  362. // return(NULL);
  363. }
  364. #if DBG
  365. ULONG MRxProxyFinalizeAECtxTraceLevel = 1200;
  366. #define FINALIZESS_LEVEL MRxProxyFinalizeAECtxTraceLevel
  367. #define FINALIZE_TRACKING_SETUP() \
  368. struct { \
  369. ULONG marker1; \
  370. ULONG finalstate; \
  371. ULONG marker2; \
  372. } Tracking = {'ereh',0,'ereh'};
  373. #define FINALIZE_TRACKING(x) {\
  374. Tracking.finalstate |= x; \
  375. }
  376. #define FINALIZE_TRACE(x) MRxProxyAsyncEngFinalizeAECtxTrace(x,Tracking.finalstate)
  377. VOID
  378. MRxProxyAsyncEngFinalizeAECtxTrace(PSZ text,ULONG finalstate)
  379. {
  380. RxDbgTraceLV(0, Dbg, FINALIZESS_LEVEL,
  381. ("MRxProxyFinalizeAsyncEngineContext --> %s(%08lx)\n",text,finalstate));
  382. }
  383. #else
  384. #define FINALIZE_TRACKING_SETUP()
  385. #define FINALIZE_TRACKING(x)
  386. #define FINALIZE_TRACE(x)
  387. #endif
  388. BOOLEAN
  389. MRxProxyFinalizeAsyncEngineContext (
  390. IN OUT PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext
  391. )
  392. /*++
  393. Routine Description:
  394. This finalizes an OE.
  395. Arguments:
  396. AsyncEngineContext - pointer to the OE to be dismantled.
  397. Return Value:
  398. TRUE if finalization occurs otherwise FALSE.
  399. Notes:
  400. --*/
  401. {
  402. LONG result;
  403. PIRP irp;
  404. ULONG AsyncEngineContextFlags = AsyncEngineContext->Flags;
  405. ULONG ThisIsMustSucceedAllocated =
  406. AsyncEngineContextFlags & (MRXPROXY_ASYNCENG_CTX_FLAG_MUST_SUCCEED_ALLOCATED);
  407. FINALIZE_TRACKING_SETUP()
  408. MRxProxyAsyncEngOEAssertConsistentLinkageFromOEwithFlags("MRxProxyAsyncEngFinalizeAsyncEngineContext:",OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK);
  409. RxDbgTraceLV(+1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext\n"));
  410. result = InterlockedDecrement(&AsyncEngineContext->NodeReferenceCount);
  411. if ( result != 0 ) {
  412. RxDbgTraceLV(-1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext -- returning w/o finalizing (%d)\n",result));
  413. return FALSE;
  414. }
  415. RxLog((">>>OE %lx %lx",
  416. AsyncEngineContext,
  417. AsyncEngineContext->Flags));
  418. FINALIZE_TRACKING( 0x1 );
  419. if ( (irp =AsyncEngineContext->CalldownIrp) != NULL ) {
  420. if (irp->MdlAddress) {
  421. IoFreeMdl(irp->MdlAddress);
  422. }
  423. IoFreeIrp( irp );
  424. FINALIZE_TRACKING( 0x20 );
  425. }
  426. if ( AsyncEngineContext->RxContext != NULL ) {
  427. PMRXPROXY_RX_CONTEXT pMRxProxyAsyncEngineContext = MRxProxyGetMinirdrContext(AsyncEngineContext->RxContext);
  428. ASSERT( pMRxProxyAsyncEngineContext->AsyncEngineContext == AsyncEngineContext );
  429. //get rid of the reference on the RxContext....if i'm the last guy this will finalize
  430. RxDereferenceAndDeleteRxContext( AsyncEngineContext->RxContext );
  431. FINALIZE_TRACKING( 0x600 );
  432. } else {
  433. FINALIZE_TRACKING( 0xf00 );
  434. }
  435. FINALIZE_TRACE("ready to discard exchange");
  436. RxFreePool(AsyncEngineContext);
  437. FINALIZE_TRACKING( 0x3000 );
  438. if (ThisIsMustSucceedAllocated) {
  439. //RxReleaseMustSucceedStructure(&MRxProxyAsyncEngMustSucceedDescriptor[MRxProxyAsyncEngMustSucceed]);
  440. }
  441. FINALIZE_TRACKING( 0x40000 );
  442. RxDbgTraceLV(-1, Dbg, 1000, ("MRxProxyFinalizeAsyncEngineContext --> exit finalstate=%x\n",Tracking.finalstate));
  443. return(TRUE);
  444. } // MRxProxyFinalizeAsyncEngineContext
  445. NTSTATUS
  446. MRxProxyAsyncEngineCalldownIrpCompletion (
  447. IN PDEVICE_OBJECT DeviceObject,
  448. IN PIRP CalldownIrp,
  449. IN PVOID Context
  450. )
  451. /*++
  452. Routine Description:
  453. This routine is called when the calldownirp is completed.
  454. Arguments:
  455. IN PDEVICE_OBJECT DeviceObject,
  456. IN PIRP CalldownIrp,
  457. IN PVOID Context
  458. Return Value:
  459. RXSTATUS - STATUS_MORE_PROCESSING_REQUIRED
  460. --*/
  461. {
  462. PRX_CONTEXT RxContext = Context;
  463. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  464. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext = pMRxProxyContext->AsyncEngineContext;
  465. BOOLEAN AsyncOperation = FlagOn(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
  466. UPDATE_OE_HISTORY_WITH_STATUS('ff');
  467. MRxProxyAsyncEngOEAssertConsistentLinkage("MRxProxyCalldownCompletion: ");
  468. AsyncEngineContext->IoStatusBlock = CalldownIrp->IoStatus;
  469. if (AsyncOperation) {
  470. NTSTATUS PostStatus;
  471. RxDbgTraceLV(0, Dbg, 1000, ("Resume with post-to-async\n"));
  472. SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_AWAITING_DISPATCH);
  473. SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_POSTED_RESUME);
  474. IF_DEBUG {
  475. //fill the workqueue structure with deadbeef....all the better to diagnose
  476. //a failed post
  477. ULONG i;
  478. for (i=0;i+sizeof(ULONG)-1<sizeof(AsyncEngineContext->WorkQueueItem);i+=sizeof(ULONG)) {
  479. //*((PULONG)(((PBYTE)&AsyncEngineContext->WorkQueueItem)+i)) = 0xdeadbeef;
  480. PBYTE BytePtr = ((PBYTE)&AsyncEngineContext->WorkQueueItem)+i;
  481. PULONG UlongPtr = (PULONG)BytePtr;
  482. *UlongPtr = 0xdeadbeef;
  483. }
  484. }
  485. PostStatus = RxPostToWorkerThread(&MRxProxyDeviceObject->RxDeviceObject,
  486. CriticalWorkQueue,
  487. &AsyncEngineContext->WorkQueueItem,
  488. MRxProxyResumeAsyncEngineContext,
  489. RxContext);
  490. ASSERT(PostStatus == STATUS_SUCCESS);
  491. } else {
  492. RxDbgTraceLV(0, Dbg, 1000, ("sync resume\n"));
  493. RxSignalSynchronousWaiter(RxContext);
  494. }
  495. return((STATUS_MORE_PROCESSING_REQUIRED));
  496. }
  497. #if DBG
  498. #define DEBUG_ONLY_CODE(x) x
  499. #else
  500. #define DEBUG_ONLY_CODE(x)
  501. #endif
  502. NTSTATUS
  503. __MRxProxyAsyncEngineOuterWrapper (
  504. IN PRX_CONTEXT RxContext,
  505. IN MRXPROXY_ASYNCENGINE_CONTEXT_ENTRYPOINTS EntryPoint,
  506. IN PMRXPROXY_ASYNCENG_CONTINUE_ROUTINE Continuation
  507. #if DBG
  508. ,IN PSZ RoutineName,
  509. IN BOOLEAN LoudProcessing,
  510. IN BOOLEAN StopOnLoud
  511. #endif
  512. )
  513. /*++
  514. Routine Description:
  515. This routine is common to guys who use the async context engine. it has the
  516. responsibility for getting a context, initing, starting, finalizing but the
  517. internal guts of the procesing is via the continuation routine that is passed in.
  518. Arguments:
  519. RxContext - the RDBSS context
  520. Return Value:
  521. RXSTATUS - The return status for the operation
  522. --*/
  523. {
  524. NTSTATUS Status = STATUS_SUCCESS;
  525. RxCaptureFcb; RxCaptureFobx;
  526. PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext;
  527. PAGED_CODE();
  528. DEBUG_ONLY_CODE(
  529. RxDbgTrace(+1, Dbg, ("Wrapped%s %08lx\n", RoutineName, RxContext ))
  530. );
  531. ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
  532. AsyncEngineContext = MRxProxyCreateAsyncEngineContext(
  533. RxContext,
  534. EntryPoint);
  535. if (AsyncEngineContext==NULL) {
  536. RxDbgTrace(-1, Dbg, ("Couldn't get the AsyncEngineContext!\n"));
  537. return((STATUS_INSUFFICIENT_RESOURCES));
  538. }
  539. AsyncEngineContext->Continuation = Continuation;
  540. Status = Continuation(MRXPROXY_ASYNCENGINE_ARGUMENTS);
  541. if (Status!=(STATUS_PENDING)) {
  542. BOOLEAN FinalizationComplete;
  543. DEBUG_ONLY_CODE(
  544. if (LoudProcessing) {
  545. if ((Status!=STATUS_SUCCESS) && (RxContext->LoudCompletionString)) {
  546. DbgPrint("LoudFailure %08lx on %wZ\n",Status,RxContext->LoudCompletionString);
  547. if (StopOnLoud) {
  548. DbgBreakPoint();
  549. }
  550. }
  551. }
  552. )
  553. FinalizationComplete = MRxProxyFinalizeAsyncEngineContext(AsyncEngineContext);
  554. ASSERT(FinalizationComplete);
  555. } else {
  556. ASSERT(BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION));
  557. }
  558. DEBUG_ONLY_CODE(
  559. RxDbgTrace(+1, Dbg, ("Wrapped%s %08lx exit with status=%08lx\n", RoutineName, RxContext, Status ))
  560. );
  561. return(Status);
  562. } // MRxProxyQueryDir
  563.