Leaked source code of windows server 2003
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.

2255 lines
68 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1996 - 2000 Microsoft Corporation
  3. Module Name :
  4. asyncu.c
  5. Abstract :
  6. This file contains the ndr async uuid implementation.
  7. Author :
  8. Ryszard K. Kott (ryszardk) Oct 1997
  9. Revision History :
  10. ---------------------------------------------------------------------*/
  11. #define USE_STUBLESS_PROXY
  12. #define CINTERFACE
  13. #include "ndrp.h"
  14. #include "ndrole.h"
  15. #include "rpcproxy.h"
  16. #include "mulsyntx.h"
  17. #include "hndl.h"
  18. #include "interp2.h"
  19. #include "asyncu.h"
  20. #include "attack.h"
  21. #include <stddef.h>
  22. #include <stdarg.h>
  23. #pragma code_seg(".orpc")
  24. RPC_STATUS
  25. NdrpBeginDcomAsyncClientCall(
  26. PMIDL_STUB_DESC pStubDescriptor,
  27. PFORMAT_STRING pFormat,
  28. unsigned char * StartofStack
  29. );
  30. RPC_STATUS
  31. NdrpFinishDcomAsyncClientCall(
  32. PMIDL_STUB_DESC pStubDescriptor,
  33. PFORMAT_STRING pFormat,
  34. unsigned char * StartofStack
  35. );
  36. const IID * RPC_ENTRY
  37. NdrGetProxyIID(
  38. const void *pThis);
  39. VOID
  40. NdrpAsyncDCOMFreeParams(
  41. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg )
  42. {
  43. /*++
  44. Routine Description:
  45. Frees the parameters for both the begin and finish calls.
  46. Arguments:
  47. pAsyncMsg - Supplies a pointer to the async message.
  48. Return Value:
  49. None.
  50. --*/
  51. if ( pAsyncMsg->BeginStack )
  52. {
  53. if ( pAsyncMsg->FinishStack )
  54. {
  55. // Clear out the IN OUT parameters on the begin stack
  56. // so that they are not freed twice.
  57. int n;
  58. REGISTER_TYPE *pBeginStack = (REGISTER_TYPE *)pAsyncMsg->BeginStack;
  59. PPARAM_DESCRIPTION BeginParams = (PPARAM_DESCRIPTION)pAsyncMsg->BeginParams;
  60. int BeginNumberParams = (int)pAsyncMsg->nBeginParams;
  61. for( n = 0; n < BeginNumberParams; n++ )
  62. {
  63. if ( BeginParams[n].ParamAttr.IsIn &&
  64. BeginParams[n].ParamAttr.IsOut )
  65. {
  66. pBeginStack[ BeginParams[ n ].StackOffset / sizeof(REGISTER_TYPE) ] = 0;
  67. }
  68. }
  69. }
  70. pAsyncMsg->StubMsg.StackTop = pAsyncMsg->BeginStack;
  71. NdrpFreeParams( & (pAsyncMsg->StubMsg),
  72. pAsyncMsg->nBeginParams,
  73. (PPARAM_DESCRIPTION)pAsyncMsg->BeginParams,
  74. pAsyncMsg->BeginStack );
  75. }
  76. if ( pAsyncMsg->FinishStack )
  77. {
  78. pAsyncMsg->StubMsg.StackTop = pAsyncMsg->FinishStack;
  79. NdrpFreeParams( & (pAsyncMsg->StubMsg),
  80. pAsyncMsg->nFinishParams,
  81. (PPARAM_DESCRIPTION)pAsyncMsg->FinishParams,
  82. pAsyncMsg->FinishStack );
  83. }
  84. }
  85. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  86. NdrDcomAsyncClientCall(
  87. PMIDL_STUB_DESC pStubDescriptor,
  88. PFORMAT_STRING pFormat,
  89. ...
  90. )
  91. /*
  92. This entry is used by the stubless proxy invoker and also by OLE thunks.
  93. Sync stubless proxies would invoke to NdrClientCall2.
  94. On ia64, this entry would be used by -Oic generated code.
  95. Note that signaling on the client happens behind the async proxy's back
  96. as channel effectively signals to the app and the app issues the Finish.
  97. */
  98. {
  99. va_list ArgList;
  100. unsigned char * StartofStack;
  101. CLIENT_CALL_RETURN Ret;
  102. ulong ProcNum;
  103. //
  104. // Get address of argument to this function following pFormat. This
  105. // is the address of the address of the first argument of the function
  106. // calling this function.
  107. // Then get the address of the stack where the parameters are.
  108. //
  109. INIT_ARG( ArgList, pFormat);
  110. GET_FIRST_IN_ARG(ArgList);
  111. StartofStack = (uchar *) GET_STACK_START(ArgList);
  112. // Object proc layout is fixed for anything that can show up here.
  113. ProcNum = *(ushort *)(pFormat+6);
  114. if ( ProcNum & 0x1 )
  115. {
  116. // An odd proc number means a Begin call (0,1,2,Begin,Finish, ...).
  117. Ret.Simple = NdrpBeginDcomAsyncClientCall( pStubDescriptor,
  118. pFormat,
  119. StartofStack );
  120. }
  121. else
  122. {
  123. Ret.Simple = NdrpFinishDcomAsyncClientCall( pStubDescriptor,
  124. pFormat,
  125. StartofStack );
  126. }
  127. return Ret;
  128. }
  129. #if defined(_WIN64)
  130. CLIENT_CALL_RETURN RPC_ENTRY
  131. NdrpDcomAsyncClientCall(
  132. PMIDL_STUB_DESC pStubDescriptor,
  133. PFORMAT_STRING pFormat,
  134. unsigned char * StartofStack
  135. )
  136. /*
  137. Used only on WIN64,
  138. this entry is used by the stubless proxy invoker and also by OLE thunks.
  139. Sync stubless proxies would invoke to NdrpClientCall2.
  140. Note that signaling on the client happens behind the async proxy's back
  141. as channel effectively signals to the app and the app issues the Finish.
  142. */
  143. {
  144. CLIENT_CALL_RETURN Ret;
  145. ulong ProcNum;
  146. // Object proc layout is fixed for anything that can show up here.
  147. ProcNum = *(ushort *)(pFormat+6);
  148. if ( ProcNum & 0x1 )
  149. {
  150. // An odd proc number means a Begin call (0,1,2,Begin,Finish, ...).
  151. Ret.Simple = NdrpBeginDcomAsyncClientCall( pStubDescriptor,
  152. pFormat,
  153. StartofStack );
  154. }
  155. else
  156. {
  157. Ret.Simple = NdrpFinishDcomAsyncClientCall( pStubDescriptor,
  158. pFormat,
  159. StartofStack );
  160. }
  161. return Ret;
  162. }
  163. #endif
  164. HRESULT
  165. NdrpBeginDcomAsyncClientCall(
  166. PMIDL_STUB_DESC pStubDescriptor,
  167. PFORMAT_STRING pFormat,
  168. unsigned char * StartofStack
  169. )
  170. /*
  171. Notes: OLE Refcounting.
  172. The model for async_uuid() is that async proxies or stubs
  173. are created with RefCount==1 and should never ever be
  174. addrefed by the engine.
  175. What the engine does is only the AsyncMsg clean up when done.
  176. The decision to destroy the AsyncPB or AsyncSB object is
  177. up to the client side PM or channel's SM for the server side.
  178. */
  179. {
  180. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  181. RPC_MESSAGE * pRpcMsg;
  182. MIDL_STUB_MESSAGE * pStubMsg;
  183. PFORMAT_STRING pFormatParam;
  184. uchar * pArg;
  185. void * pThis = *(void **)StartofStack;
  186. INTERPRETER_FLAGS OldOiFlags;
  187. INTERPRETER_OPT_FLAGS NewOiFlags;
  188. PPARAM_DESCRIPTION Params;
  189. long NumberParams;
  190. long n;
  191. RPC_STATUS Status;
  192. PNDR_DCOM_OI2_PROC_HEADER pProcHeader = (PNDR_DCOM_OI2_PROC_HEADER)pFormat;
  193. PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
  194. CStdAsyncProxyBuffer * pAsyncPB;
  195. const IID * piid;
  196. HRESULT hr = S_OK;
  197. BOOL fSendCalled = FALSE;
  198. NDR_PROC_CONTEXT * pContext = NULL;
  199. pAsyncPB = (CStdAsyncProxyBuffer*)
  200. ((uchar*)pThis - offsetof(CStdProxyBuffer, pProxyVtbl));
  201. piid = NdrGetProxyIID( pThis );
  202. Status = NdrpSetupBeginClientCall( pAsyncPB,
  203. StartofStack,
  204. pProcHeader->StackSize,
  205. *piid );
  206. if ( !SUCCEEDED(Status) )
  207. return Status;
  208. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE)pAsyncPB->CallState.pAsyncMsg;
  209. // We need to switch to our copy of the stack everywhere, including pStubMsg.
  210. StartofStack = pAsyncMsg->ProcContext.StartofStack;
  211. pRpcMsg = & pAsyncMsg->RpcMsg;
  212. pStubMsg = & pAsyncMsg->StubMsg;
  213. pContext = ( NDR_PROC_CONTEXT * ) &pAsyncMsg->ProcContext;
  214. pStubMsg->pContext = pContext;
  215. pContext->StartofStack = StartofStack;
  216. pStubMsg->FullPtrXlatTables = 0;
  217. OldOiFlags = pProcHeader->OldOiFlags;
  218. NewOiFlags = pProcHeader->Oi2Flags;
  219. NumberParams = pProcHeader->NumberParams;
  220. //
  221. // Parameter descriptions are nicely spit out by MIDL.
  222. //
  223. Params = (PPARAM_DESCRIPTION)(pFormat + sizeof(NDR_DCOM_OI2_PROC_HEADER));
  224. // Proc header extentions, from NDR ver. 5.2, MIDL 5.0.+
  225. // Params must be set correctly here because of exceptions.
  226. if ( NewOiFlags.HasExtensions )
  227. {
  228. pHeaderExts = (NDR_PROC_HEADER_EXTS *)Params;
  229. Params = (PPARAM_DESCRIPTION)((uchar*)Params + pHeaderExts->Size);
  230. }
  231. pAsyncMsg->nBeginParams = pContext->NumberParams = NumberParams;
  232. pAsyncMsg->BeginParams = pContext->Params = Params;
  233. pAsyncMsg->pThis = pThis;
  234. pContext->DceTypeFormatString = pStubDescriptor->pFormatTypes;
  235. // This is OLE only code path - use a single TryExcept.
  236. // After catching it just map it to OLE exception.
  237. RpcTryExcept
  238. {
  239. ulong RpcFlags;
  240. // Note, pProcHeader->ProcNum is the async proc number.
  241. NdrProxyInitialize( pThis,
  242. pRpcMsg,
  243. pStubMsg,
  244. pStubDescriptor,
  245. (pProcHeader->ProcNum + 3)/2 // sync proc number
  246. );
  247. pStubMsg->pAsyncMsg = (struct _NDR_ASYNC_MESSAGE *) pAsyncMsg;
  248. if ( OldOiFlags.FullPtrUsed )
  249. pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_CLIENT );
  250. // Set Rpc flags after the call to client initialize.
  251. RpcFlags= *(ulong UNALIGNED *)(pFormat + 2);
  252. pStubMsg->RpcMsg->RpcFlags = RpcFlags;
  253. // Must do this before the sizing pass!
  254. pStubMsg->StackTop = pContext->StartofStack = StartofStack;
  255. if ( NewOiFlags.HasExtensions )
  256. {
  257. pStubMsg->fHasExtensions = 1;
  258. pStubMsg->fHasNewCorrDesc = pHeaderExts->Flags2.HasNewCorrDesc;
  259. if ( pHeaderExts->Flags2.ClientCorrCheck )
  260. {
  261. void * pCache = NdrpAlloca( &pAsyncMsg->ProcContext.AllocateContext, NDR_DEFAULT_CORR_CACHE_SIZE );
  262. NdrCorrelationInitialize( pStubMsg,
  263. pCache,
  264. NDR_DEFAULT_CORR_CACHE_SIZE,
  265. 0 /* flags */ );
  266. }
  267. }
  268. //
  269. // ----------------------------------------------------------------
  270. // Sizing Pass.
  271. // ----------------------------------------------------------------
  272. //
  273. //
  274. // Get the compile time computed buffer size.
  275. //
  276. pStubMsg->BufferLength = pProcHeader->ClientBufferSize;
  277. //
  278. // Check ref pointers and do object proc [out] zeroing.
  279. //
  280. for ( n = 0; n < NumberParams; n++ )
  281. {
  282. pArg = StartofStack + Params[n].StackOffset;
  283. if ( Params[n].ParamAttr.IsSimpleRef )
  284. {
  285. // We can raise the exception here as there is no out only args.
  286. if ( ! *((uchar **)pArg) )
  287. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  288. }
  289. // [out] only argument on the Begin call.
  290. if ( ! Params[n].ParamAttr.IsIn &&
  291. Params[n].ParamAttr.IsOut &&
  292. ! Params[n].ParamAttr.IsReturn)
  293. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  294. }
  295. //
  296. // Skip buffer size pass if possible.
  297. //
  298. if ( NewOiFlags.ClientMustSize )
  299. {
  300. NdrpSizing( pStubMsg,
  301. TRUE ); // IsObject
  302. }
  303. //
  304. // Do the GetBuffer.
  305. //
  306. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  307. NdrProxyGetBuffer( pThis, pStubMsg );
  308. NDR_ASSERT( pStubMsg->fBufferValid, "Invalid buffer" );
  309. pAsyncMsg->StubPhase = STUB_MARSHAL;
  310. //
  311. // ----------------------------------------------------------
  312. // Marshall Pass.
  313. // ----------------------------------------------------------
  314. //
  315. NdrpClientMarshal ( pStubMsg,
  316. TRUE ); // IsObject
  317. //
  318. // Make the RPC call.
  319. //
  320. pAsyncMsg->StubPhase = NDR_ASYNC_CALL_PHASE;
  321. fSendCalled = NdrpDcomAsyncClientSend( pStubMsg,
  322. pAsyncPB->punkOuter ); // PM's entry
  323. if ( fSendCalled )
  324. hr = S_OK;
  325. }
  326. RpcExcept( 1 )
  327. {
  328. RPC_STATUS ExceptionCode = RpcExceptionCode();
  329. pAsyncPB->CallState.Flags.BeginError = 1;
  330. // Actually dismantle the call.
  331. // This is a request call and there is nothing left at the runtime.
  332. pAsyncMsg->StubPhase = NDR_ASYNC_ERROR_PHASE;
  333. pAsyncMsg->ErrorCode = ExceptionCode;
  334. hr = NdrHrFromWin32Error(ExceptionCode);
  335. pAsyncPB->CallState.Hr = hr;
  336. // Async call in request phase: don't touch [out] params.
  337. }
  338. RpcEndExcept
  339. // "Finally"
  340. // Dont touch anything, the client has to call the Finish method anyway.
  341. pAsyncPB->CallState.Flags.BeginDone = 1;
  342. if ( SUCCEEDED(hr) )
  343. {
  344. NdrpCloneInOnlyCorrArgs( pAsyncMsg, pAsyncMsg->StubMsg.StubDesc->pFormatTypes );
  345. // Channel will prompt signal
  346. }
  347. else
  348. if (!fSendCalled )
  349. NdrpAsyncProxySignal( pAsyncPB );
  350. // No need to release, our refcount should be 1 at this point.
  351. return hr;
  352. }
  353. void
  354. NdrpCloneInOnlyCorrArgs(
  355. NDR_DCOM_ASYNC_MESSAGE * pAsyncMsg,
  356. PFORMAT_STRING pTypeFormat
  357. )
  358. /*
  359. Walk the client stack looking for an in only argument flagged to clone.
  360. For each one, replace the arg with a clone that we control.
  361. Assumption is, we do it before returning to the user from the Begin call
  362. and also we clone walking the copy of the app's stack not the app stack.
  363. The stack modified in this way will be the one to access for the weird
  364. crossreferenced correlated args.
  365. This issue doesn't happen on the server, as we keep the Begin stack around
  366. when the Finish call is processed.
  367. */
  368. {
  369. unsigned char * pBeginStack = pAsyncMsg->BeginStack;
  370. PPARAM_DESCRIPTION Params = (PPARAM_DESCRIPTION)pAsyncMsg->BeginParams;
  371. int NumberParams = (int)pAsyncMsg->nBeginParams;
  372. unsigned char * pArg;
  373. int n;
  374. for ( n = 0; n < NumberParams; n++ )
  375. {
  376. if ( Params[n].ParamAttr.SaveForAsyncFinish )
  377. {
  378. // Note that the arguments that need cloning come from top level size_is,
  379. // length_is etc, switch_is and iid_is attributes.
  380. // Hence, the only types of interest are uuid clones and integral types
  381. // different from hyper.
  382. // On top of it, we deal with stack-slot chunks of memory, so we don't
  383. // have to care about mac issues.
  384. pArg = pBeginStack + Params[n].StackOffset;
  385. if ( Params[n].ParamAttr.IsBasetype )
  386. {
  387. if ( Params[n].ParamAttr.IsSimpleRef )
  388. {
  389. void * pPointee = AsyncAlloca( pAsyncMsg, 8 );
  390. // The assignment needs to follow the type.
  391. RpcpMemoryCopy( pPointee, *(void **)pArg,
  392. SIMPLE_TYPE_MEMSIZE( Params[n].SimpleType.Type ) );
  393. *(void**)pArg = pPointee;
  394. }
  395. // else the stack slot has the simple value already.
  396. }
  397. else
  398. {
  399. // If it's not a base type, then it cannot be by value.
  400. // It has to be a pointer to a simple type or to an iid.
  401. PFORMAT_STRING pParamFormat;
  402. pParamFormat = pTypeFormat +
  403. Params[n].TypeOffset;
  404. if ( IS_BASIC_POINTER(*pParamFormat) ) // not FC_IP
  405. {
  406. if ( SIMPLE_POINTER(pParamFormat[1]) )
  407. {
  408. // Covers things like a unique pointer to a size
  409. // Essentially the same as for the simple ref above.
  410. void * pPointee = AsyncAlloca( pAsyncMsg, 8 );
  411. // The assignment needs to follow the type.
  412. RpcpMemoryCopy( pPointee, *(void **)pArg,
  413. SIMPLE_TYPE_MEMSIZE( pParamFormat[2] ) );
  414. *(void**)pArg = pPointee;
  415. }
  416. else
  417. {
  418. // has to be the riid case.
  419. // REFIID* comes out as FC_?P -> FC_?P -> FC_STRUCT
  420. PFORMAT_STRING pFormat;
  421. pFormat = pParamFormat + *(short *)(pParamFormat + 2);
  422. if ( IS_BASIC_POINTER(*pFormat) &&
  423. ! SIMPLE_POINTER(pParamFormat[1]) )
  424. {
  425. pParamFormat = pFormat + *(short *)(pFormat + 2);
  426. if ( *pParamFormat == FC_STRUCT )
  427. {
  428. // one alloc for REFIID and IID itself.
  429. IID** ppIID =
  430. (IID**)AsyncAlloca( pAsyncMsg,
  431. sizeof(IID *) + sizeof(IID));
  432. IID* pIID = (IID *)(ppIID + 1);
  433. *ppIID = pIID; //set pointer
  434. RpcpMemoryCopy( pIID, **(IID ***)pArg, sizeof(IID));
  435. *(IID ***)pArg = ppIID;
  436. }
  437. else
  438. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  439. }
  440. else
  441. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  442. }
  443. }
  444. else
  445. {
  446. // has to be the riid case.
  447. // REFIID comes out as FC_STRUCT
  448. if ( *pParamFormat == FC_STRUCT )
  449. {
  450. IID *pIID = (IID*)AsyncAlloca( pAsyncMsg, sizeof(IID) );
  451. RpcpMemoryCopy( pIID, *(IID **)pArg, sizeof(IID));
  452. *(IID **)pArg = pIID;
  453. }
  454. else
  455. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  456. }
  457. }
  458. }
  459. }
  460. }
  461. HRESULT
  462. NdrpFinishDcomAsyncClientCall(
  463. PMIDL_STUB_DESC pStubDescriptor,
  464. PFORMAT_STRING pFormat,
  465. unsigned char * StartofStack
  466. )
  467. {
  468. RPC_MESSAGE * pRpcMsg;
  469. MIDL_STUB_MESSAGE * pStubMsg;
  470. PFORMAT_STRING pFormatParam;
  471. uchar * pArg;
  472. void * pThis = *(void **)StartofStack;
  473. CLIENT_CALL_RETURN ReturnValue;
  474. INTERPRETER_FLAGS OldOiFlags; // Finish proc flags
  475. INTERPRETER_OPT_FLAGS NewOiFlags; //
  476. PPARAM_DESCRIPTION Params; //
  477. long NumberParams;
  478. long n;
  479. NDR_ASYNC_CALL_FLAGS CallFlags;
  480. PNDR_DCOM_OI2_PROC_HEADER pProcHeader = (PNDR_DCOM_OI2_PROC_HEADER)pFormat;
  481. PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
  482. CStdAsyncProxyBuffer * pAsyncPB;
  483. const IID * piid;
  484. HRESULT hr = S_OK;
  485. NDR_PROC_CONTEXT * pContext = NULL;
  486. ReturnValue.Simple = 0;
  487. pAsyncPB = (CStdAsyncProxyBuffer*)
  488. ((uchar*)pThis - offsetof(CStdProxyBuffer, pProxyVtbl));
  489. piid = NdrGetProxyIID( pThis );
  490. hr = NdrpSetupFinishClientCall( pAsyncPB,
  491. StartofStack,
  492. pProcHeader->StackSize,
  493. *piid,
  494. pProcHeader->ProcNum );
  495. if ( !SUCCEEDED(hr) )
  496. return hr;
  497. // Note that we cant call to NdrProxyInitialize again.
  498. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg =
  499. (PNDR_DCOM_ASYNC_MESSAGE)pAsyncPB->CallState.pAsyncMsg;
  500. pRpcMsg = & pAsyncMsg->RpcMsg;
  501. pStubMsg = & pAsyncMsg->StubMsg;
  502. pContext = ( NDR_PROC_CONTEXT * )pStubMsg->pContext;
  503. OldOiFlags = pProcHeader->OldOiFlags;
  504. NewOiFlags = pProcHeader->Oi2Flags;
  505. NumberParams = pProcHeader->NumberParams;
  506. //
  507. // Parameter descriptions are nicely spit out by MIDL.
  508. //
  509. Params = (PPARAM_DESCRIPTION)(pFormat + sizeof(NDR_DCOM_OI2_PROC_HEADER));
  510. if ( NewOiFlags.HasExtensions )
  511. {
  512. pHeaderExts = (NDR_PROC_HEADER_EXTS *)Params;
  513. Params = (PPARAM_DESCRIPTION)((uchar*)Params + pHeaderExts->Size);
  514. }
  515. CallFlags = pAsyncMsg->Flags;
  516. // Initialize the stack top in the stub msg to be
  517. // this stack, the stack for the finish call parameters.
  518. pAsyncMsg->nFinishParams = pContext->NumberParams = NumberParams;
  519. pAsyncMsg->FinishParams = pContext->Params = Params;
  520. pStubMsg->StackTop = pContext->StartofStack = StartofStack;
  521. // OLE only code path - single RpcTryExcept.
  522. //
  523. RpcTryExcept
  524. {
  525. BOOL fRaiseExcFlag = FALSE;
  526. if ( CallFlags.ErrorPending )
  527. RpcRaiseException( pAsyncMsg->ErrorCode );
  528. // We need to zero out the [out] parameters and to check
  529. // the ref pointers.
  530. for ( n = 0; n < NumberParams; n++ )
  531. {
  532. pArg = StartofStack + Params[n].StackOffset;
  533. if ( Params[n].ParamAttr.IsSimpleRef )
  534. {
  535. // We cannot raise the exception here,
  536. // as some out args may not be zeroed out yet.
  537. if ( ! *((uchar **)pArg) )
  538. {
  539. fRaiseExcFlag = TRUE;
  540. continue;
  541. }
  542. }
  543. // We do the basetype check to cover the
  544. // [out] simple ref to basetype case.
  545. //
  546. if ( Params[n].ParamAttr.IsPartialIgnore ||
  547. ( ! Params[n].ParamAttr.IsIn &&
  548. ! Params[n].ParamAttr.IsReturn ) )
  549. {
  550. if ( Params[n].ParamAttr.IsBasetype )
  551. {
  552. // [out] only arg can only be ref, we checked that above.
  553. MIDL_memset( *(uchar **)pArg,
  554. 0,
  555. (size_t)SIMPLE_TYPE_MEMSIZE( Params[n].SimpleType.Type ));
  556. }
  557. else
  558. {
  559. pFormatParam = pStubDescriptor->pFormatTypes +
  560. Params[n].TypeOffset;
  561. NdrClientZeroOut(
  562. pStubMsg,
  563. pFormatParam,
  564. *(uchar **)pArg );
  565. }
  566. }
  567. }
  568. if ( fRaiseExcFlag )
  569. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  570. NdrDcomAsyncReceive( pStubMsg );
  571. //
  572. // ----------------------------------------------------------
  573. // Unmarshall Pass.
  574. // ----------------------------------------------------------
  575. //
  576. NdrpClientUnMarshal( pStubMsg,
  577. &ReturnValue );
  578. // DCOM interface must have HRESULT as return value.
  579. hr = (HRESULT) ReturnValue.Simple;
  580. }
  581. RpcExcept( 1 )
  582. {
  583. RPC_STATUS ExceptionCode = RpcExceptionCode();
  584. //
  585. // In OLE, since they don't know about error_status_t and wanted to
  586. // reinvent the wheel, check to see if we need to map the exception.
  587. // In either case, set the return value and then try to free the
  588. // [out] params, if required.
  589. //
  590. hr = NdrHrFromWin32Error(ExceptionCode);
  591. //
  592. // Set the Buffer endpoints so the NdrFree routines work.
  593. //
  594. pStubMsg->BufferStart = 0;
  595. pStubMsg->BufferEnd = 0;
  596. for ( n = 0; n < NumberParams; n++ )
  597. {
  598. //
  599. // Skip everything but [out] only parameters. We make
  600. // the basetype check to cover [out] simple ref pointers
  601. // to basetypes.
  602. //
  603. if ( !Params[n].ParamAttr.IsPartialIgnore )
  604. {
  605. if ( Params[n].ParamAttr.IsIn ||
  606. Params[n].ParamAttr.IsReturn ||
  607. Params[n].ParamAttr.IsBasetype )
  608. continue;
  609. }
  610. pArg = StartofStack + Params[n].StackOffset;
  611. pFormatParam = pStubDescriptor->pFormatTypes +
  612. Params[n].TypeOffset;
  613. NdrClearOutParameters( pStubMsg,
  614. pFormatParam,
  615. *((uchar **)pArg) );
  616. }
  617. }
  618. RpcEndExcept
  619. // Finish
  620. // Cleanup everything. However, don't free pAsyncPB itself.
  621. NdrpAsyncProxyMsgDestructor( pAsyncPB );
  622. // Never addref or release async proxy object, this is app's/PM's job.
  623. return hr;
  624. }
  625. HRESULT RPC_ENTRY
  626. NdrDcomAsyncStubCall(
  627. struct IRpcStubBuffer * pThis,
  628. struct IRpcChannelBuffer * pChannel,
  629. PRPC_MESSAGE pRpcMsg,
  630. ulong * pdwStubPhase
  631. )
  632. /*++
  633. Routine Description :
  634. Server Interpreter entry point for DCOM async procs.
  635. This is the Begin entry for channel (regular dispatch entry from stub.c).
  636. The Finish happen when the channel calls stub's Synchronize::Signal method
  637. on the stub object. The call then comes to NdrpAsyncStubSignal later below.
  638. Arguments :
  639. pThis - Object proc's 'this' pointer.
  640. pChannel - Object proc's Channel Buffer.
  641. pRpcMsg - The RPC message.
  642. pdwStubPhase - Used to track the current interpreter's activity.
  643. Return :
  644. Status of S_OK.
  645. Notes :
  646. The engine never calls a signal on behalf of the user, regardless what kind of
  647. errors happen during begin (cannot setup begin, cannot unmarshal, app dies in invoke).
  648. In each of these cases, the engine simply returns an error code to the channel.
  649. The only time the engine would call FreeBuffer on the server is if the engine died
  650. between a successful GetBuffer and the final Send.
  651. Notes on OLE Refcounting.
  652. The model for async_uuid() is that async proxies or stubs are created
  653. with RefCount==1 and should never ever be addrefed by the engine.
  654. What the engine does is only the AsyncMsg clean up when done.
  655. The decision to destroy the AsyncPB or AsyncSB object is
  656. up to the client side PM or channel's SM for the server side.
  657. */
  658. {
  659. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  660. PMIDL_SERVER_INFO pServerInfo;
  661. PMIDL_STUB_DESC pStubDesc;
  662. const SERVER_ROUTINE * DispatchTable;
  663. unsigned long ProcNum;
  664. ushort FormatOffset;
  665. PFORMAT_STRING pFormat;
  666. PFORMAT_STRING pFormatParam;
  667. PMIDL_STUB_MESSAGE pStubMsg;
  668. uchar * pArgBuffer;
  669. uchar * pArg;
  670. uchar ** ppArg;
  671. PPARAM_DESCRIPTION Params;
  672. INTERPRETER_FLAGS OldOiFlags;
  673. INTERPRETER_OPT_FLAGS NewOiFlags;
  674. long NumberParams;
  675. BOOL fBadStubDataException = FALSE;
  676. BOOL fManagerCodeInvoked = FALSE;
  677. long n;
  678. PNDR_DCOM_OI2_PROC_HEADER pProcHeader;
  679. PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
  680. CStdAsyncStubBuffer * pAsyncSB;
  681. HRESULT hr;
  682. const IID * piid = 0;
  683. BOOL fErrorInInvoke = FALSE;
  684. BOOL fRecoverableErrorInInvoke = FALSE;
  685. IUnknown * pSrvObj;
  686. CInterfaceStubVtbl * pStubVTable;
  687. NDR_PROC_CONTEXT * pContext = NULL ;
  688. RPC_STATUS ExceptionCode = 0;
  689. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  690. "marshaling buffer misaligned at server" );
  691. // The channel dispatches to the engine with the sync proc num.
  692. // We need only async proc num at the engine level.
  693. ProcNum = pRpcMsg->ProcNum;
  694. ProcNum = 2 * ProcNum - 3; // Begin method #
  695. pSrvObj = (IUnknown *)((CStdStubBuffer *)pThis)->pvServerObject;
  696. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  697. pStubVTable = (CInterfaceStubVtbl *)
  698. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  699. piid = pStubVTable->header.piid;
  700. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  701. pStubDesc = pServerInfo->pStubDesc;
  702. FormatOffset = pServerInfo->FmtStringOffset[ ProcNum ];
  703. pFormat = &((pServerInfo->ProcString)[FormatOffset]);
  704. // The proc header has a fixed layout now.
  705. pProcHeader = (PNDR_DCOM_OI2_PROC_HEADER) pFormat;
  706. pAsyncSB = (CStdAsyncStubBuffer *)
  707. ((uchar *)pThis - offsetof(CStdAsyncStubBuffer,lpVtbl));
  708. hr = NdrpSetupBeginStubCall( pAsyncSB,
  709. pProcHeader->StackSize,
  710. *piid );
  711. if ( FAILED(hr) )
  712. return hr;
  713. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE)pAsyncSB->CallState.pAsyncMsg;
  714. pStubMsg = & pAsyncMsg->StubMsg;
  715. pContext = &pAsyncMsg->ProcContext;
  716. // Both rpc runtime and channel require that we use a copy of the rpc message.
  717. RpcpMemoryCopy( & pAsyncMsg->RpcMsg, pRpcMsg, sizeof(RPC_MESSAGE) );
  718. pRpcMsg = & pAsyncMsg->RpcMsg;
  719. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  720. // The arg buffer is zeroed out already.
  721. pArgBuffer = pAsyncMsg->ProcContext.StartofStack;
  722. //
  723. // Get new interpreter info.
  724. //
  725. OldOiFlags = pProcHeader->OldOiFlags;
  726. NewOiFlags = pProcHeader->Oi2Flags;
  727. NumberParams = pProcHeader->NumberParams;
  728. Params = (PPARAM_DESCRIPTION)(pFormat + sizeof(NDR_DCOM_OI2_PROC_HEADER));
  729. if ( NewOiFlags.HasExtensions )
  730. {
  731. pHeaderExts = (NDR_PROC_HEADER_EXTS *)Params;
  732. Params = (PPARAM_DESCRIPTION)((uchar*)Params + pHeaderExts->Size);
  733. }
  734. pAsyncMsg->nBeginParams = pContext->NumberParams = NumberParams;
  735. pAsyncMsg->BeginParams = pContext->Params = Params;
  736. pAsyncMsg->pThis = pThis;
  737. pContext->DceTypeFormatString = pStubDesc->pFormatTypes;
  738. //
  739. // Wrap the unmarshalling and the invoke call in the try block of
  740. // a try-finally. Put the free phase in the associated finally block.
  741. //
  742. // We abstract the level of indirection here.
  743. RpcTryFinally
  744. {
  745. // OLE: put pThis in first dword of stack.
  746. //
  747. ((void **)pArgBuffer)[0] = ((CStdStubBuffer *)pThis)->pvServerObject;
  748. // Initialize the Stub message.
  749. //
  750. NdrStubInitialize( pRpcMsg,
  751. pStubMsg,
  752. pStubDesc,
  753. pChannel );
  754. pStubMsg->pAsyncMsg = (struct _NDR_ASYNC_MESSAGE *) pAsyncMsg;
  755. pAsyncMsg->pdwStubPhase = pdwStubPhase; // the phase is STUB_UNMARSHAL
  756. // Raise exceptions after initializing the stub.
  757. if ( OldOiFlags.FullPtrUsed )
  758. pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
  759. else
  760. pStubMsg->FullPtrXlatTables = 0;
  761. //
  762. // Set StackTop AFTER the initialize call, since it zeros the field
  763. // out.
  764. //
  765. pStubMsg->StackTop = pArgBuffer;
  766. if ( NewOiFlags.HasExtensions )
  767. {
  768. pStubMsg->fHasExtensions = 1;
  769. pStubMsg->fHasNewCorrDesc = pHeaderExts->Flags2.HasNewCorrDesc;
  770. if ( pHeaderExts->Flags2.ServerCorrCheck )
  771. {
  772. void * pCache = NdrpAlloca( &pAsyncMsg->ProcContext.AllocateContext, NDR_DEFAULT_CORR_CACHE_SIZE );
  773. NdrCorrelationInitialize( pStubMsg,
  774. pCache,
  775. NDR_DEFAULT_CORR_CACHE_SIZE,
  776. 0 /* flags */ );
  777. }
  778. }
  779. // StubPhase set up by invoke is STUB_UNMARSHAL
  780. RpcTryExcept
  781. {
  782. // --------------------------------
  783. // Unmarshall all of our parameters.
  784. // --------------------------------
  785. NdrpServerUnMarshal( pStubMsg );
  786. }
  787. // Last ditch checks.
  788. if ( pRpcMsg->BufferLength <
  789. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  790. {
  791. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  792. }
  793. RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
  794. {
  795. ExceptionCode = RpcExceptionCode();
  796. // Filter set in rpcndr.h to catch one of the following
  797. // STATUS_ACCESS_VIOLATION
  798. // STATUS_DATATYPE_MISALIGNMENT
  799. // RPC_X_BAD_STUB_DATA
  800. fBadStubDataException = TRUE;
  801. pAsyncMsg->Flags.BadStubData = 1;
  802. pAsyncMsg->Flags.ErrorPending = 1;
  803. if ( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  804. {
  805. ExceptionCode = RPC_X_BAD_STUB_DATA;
  806. }
  807. pAsyncMsg->ErrorCode = ExceptionCode;
  808. pAsyncSB->CallState.Flags.BeginError = 1;
  809. pAsyncSB->CallState.Hr = NdrHrFromWin32Error( ExceptionCode);
  810. NdrpFreeMemoryList( pStubMsg );
  811. RpcRaiseException( ExceptionCode );
  812. }
  813. RpcEndExcept
  814. //
  815. // Do [out] initialization before the invoke.
  816. //
  817. for ( n = 0; n < NumberParams; n++ )
  818. {
  819. if ( Params[n].ParamAttr.IsIn ||
  820. Params[n].ParamAttr.IsReturn )
  821. continue;
  822. // This is a Begin call, there cannot be any [out] only args.
  823. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  824. }
  825. //
  826. // OLE interfaces use pdwStubPhase in the exception filter.
  827. // See CStdStubBuffer_Invoke in stub.c.
  828. //
  829. *pdwStubPhase = STUB_CALL_SERVER;
  830. // We need to catch exception in the manager code separately
  831. // as the model implies that there will be no other call from
  832. // the server app to clean up.
  833. pAsyncSB->CallState.Flags.BeginDone = 1;
  834. RpcTryExcept
  835. {
  836. //
  837. // Check for a thunk. Compiler does all the setup for us.
  838. //
  839. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ ProcNum ] )
  840. {
  841. fManagerCodeInvoked = TRUE;
  842. pServerInfo->ThunkTable[ ProcNum ]( pStubMsg );
  843. }
  844. else
  845. {
  846. //
  847. // Note that this ArgNum is not the number of arguments declared
  848. // in the function we called, but really the number of
  849. // REGISTER_TYPEs occupied by the arguments to a function.
  850. //
  851. long ArgNum;
  852. MANAGER_FUNCTION pFunc;
  853. REGISTER_TYPE ReturnValue;
  854. pFunc = (MANAGER_FUNCTION) DispatchTable[ ProcNum ];
  855. ArgNum = (long)pProcHeader->StackSize / sizeof(REGISTER_TYPE);
  856. //
  857. // The StackSize includes the size of the return. If we want
  858. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  859. // by 1 when there is a return value AND the current ArgNum count
  860. // is greater than 0.
  861. //
  862. if ( ArgNum && NewOiFlags.HasReturn )
  863. ArgNum--;
  864. // Being here means that we can expect results. Note that the user
  865. // can call RpcCompleteCall from inside of the manager code.
  866. fManagerCodeInvoked = TRUE;
  867. ReturnValue = Invoke( pFunc,
  868. (REGISTER_TYPE *)pArgBuffer,
  869. #if defined(_WIN64)
  870. NewOiFlags.HasExtensions ? ((PNDR_PROC_HEADER_EXTS64)pHeaderExts)->FloatArgMask
  871. : 0,
  872. #endif
  873. ArgNum);
  874. if ( NewOiFlags.HasReturn )
  875. {
  876. // Pass the app's HR from Begin call to the channel.
  877. (*pfnDcomChannelSetHResult)( pRpcMsg,
  878. NULL, // reserved
  879. (HRESULT) ReturnValue);
  880. }
  881. // We are discarding the return value as it is not the real one.
  882. }
  883. }
  884. RpcExcept( 1 )
  885. {
  886. fErrorInInvoke = TRUE;
  887. pAsyncMsg->Flags.ErrorPending = 1;
  888. pAsyncMsg->ErrorCode = RpcExceptionCode();
  889. pAsyncSB->CallState.Flags.BeginError = 1;
  890. pAsyncSB->CallState.Hr = NdrHrFromWin32Error( RpcExceptionCode());
  891. }
  892. RpcEndExcept
  893. // Done with invoking Begin
  894. }
  895. RpcFinally
  896. {
  897. if ( !fManagerCodeInvoked )
  898. {
  899. // Failed without invoking Begin - return an error. Remember the error.
  900. if ( fBadStubDataException )
  901. pAsyncMsg->ErrorCode = RPC_X_BAD_STUB_DATA;
  902. pAsyncSB->CallState.Flags.BeginDone = 1;
  903. hr = pAsyncSB->CallState.Hr;
  904. }
  905. else // fManagerCodeInvoked
  906. {
  907. hr = S_OK;
  908. if ( fErrorInInvoke )
  909. hr = pAsyncSB->CallState.Hr;
  910. }
  911. }
  912. RpcEndFinally
  913. return hr;
  914. }
  915. void
  916. NdrpCloneInOutStubArgs(
  917. NDR_DCOM_ASYNC_MESSAGE * pAsyncMsg )
  918. /*
  919. Walk the second stack looking for an in-out argument.
  920. For each one, find the corresponding in-out atgument from the first stack
  921. and clone it to the second stack.
  922. Note, we need to do it only on the server side where we preserver the first
  923. stack, the dispatch buffer and all the arguments from the first stack.
  924. On the client, this is the app's task to supply meaningful in-out arguments
  925. for the second stack.
  926. */
  927. {
  928. REGISTER_TYPE * pBeginStack = (REGISTER_TYPE *)pAsyncMsg->BeginStack;
  929. REGISTER_TYPE * pFinishStack = (REGISTER_TYPE *)pAsyncMsg->FinishStack;
  930. PPARAM_DESCRIPTION BeginParams = (PPARAM_DESCRIPTION)pAsyncMsg->BeginParams;
  931. int BeginNumberParams = (int)pAsyncMsg->nBeginParams;
  932. PPARAM_DESCRIPTION FinishParams = (PPARAM_DESCRIPTION)pAsyncMsg->FinishParams;
  933. int FinishNumberParams = pAsyncMsg->nFinishParams;
  934. int FirstIO = 0;
  935. int n;
  936. for ( n = 0; n < FinishNumberParams; n++ )
  937. {
  938. // Find in-out arg that needs cloning.
  939. if ( FinishParams[n].ParamAttr.IsIn &&
  940. FinishParams[n].ParamAttr.IsOut )
  941. {
  942. // Find the first IO on the first stack
  943. while ( FirstIO < BeginNumberParams )
  944. {
  945. if ( BeginParams[ FirstIO ].ParamAttr.IsIn &&
  946. BeginParams[ FirstIO ].ParamAttr.IsOut )
  947. {
  948. break;
  949. }
  950. FirstIO++;
  951. }
  952. if ( BeginNumberParams <= FirstIO )
  953. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  954. // Clone it to the second stack
  955. pFinishStack[ FinishParams[n].StackOffset / sizeof(REGISTER_TYPE) ] =
  956. pBeginStack[ BeginParams[ FirstIO ].StackOffset / sizeof(REGISTER_TYPE) ];
  957. FirstIO++;
  958. }
  959. }
  960. }
  961. HRESULT
  962. NdrpCompleteDcomAsyncStubCall(
  963. CStdAsyncStubBuffer * pAsyncSB
  964. )
  965. /*++
  966. Routine Description :
  967. Complete an async call on the server side.
  968. Arguments :
  969. AsyncHandle - raw or object handle (if pointer) as appropriate,
  970. pAsyncMsg - pointer to async msg structure,
  971. pReturnValue - from the user to pass back to caller.
  972. Return :
  973. Status of S_OK.
  974. --*/
  975. {
  976. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  977. PMIDL_SERVER_INFO pServerInfo;
  978. PMIDL_STUB_DESC pStubDesc; // should be the same
  979. const SERVER_ROUTINE * DispatchTable; // should be the same
  980. unsigned long ProcNum; // should be 1+
  981. ushort FormatOffset;
  982. PFORMAT_STRING pFormat;
  983. PFORMAT_STRING pFormatParam;
  984. RPC_MESSAGE * pRpcMsg;
  985. MIDL_STUB_MESSAGE * pStubMsg;
  986. INTERPRETER_FLAGS OldOiFlags; // Finish flags
  987. INTERPRETER_OPT_FLAGS NewOiFlags; // Finish flags
  988. PPARAM_DESCRIPTION Params; // Finish params
  989. uchar * pArgBuffer; // new stack
  990. // MZ, BUG BUG, Fix after ship
  991. // ulong * pdwStubPhase;
  992. uchar * pArg;
  993. long NumberParams;
  994. long n;
  995. PNDR_DCOM_OI2_PROC_HEADER pProcHeader;
  996. PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
  997. IUnknown * pSrvObj;
  998. CInterfaceStubVtbl * pStubVTable;
  999. void * pThis;
  1000. HRESULT hr;
  1001. const IID * piid; // should be the same
  1002. BOOL fManagerCodeInvoked = FALSE;
  1003. BOOL fErrorInInvoke = FALSE;
  1004. RPC_STATUS ExceptionCode = 0;
  1005. boolean fParamsFreed = FALSE;
  1006. NDR_PROC_CONTEXT * pContext = NULL;
  1007. // We validated both the stub and the async context in the signal call.
  1008. // We validated the pAsyncSB in the Signal call.
  1009. // Do additional checks.
  1010. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE)pAsyncSB->CallState.pAsyncMsg;
  1011. pThis = pAsyncMsg->pThis;
  1012. // See if channel calls on the right stub
  1013. if ( & pAsyncSB->lpVtbl != pThis)
  1014. return E_INVALIDARG;
  1015. pRpcMsg = & pAsyncMsg->RpcMsg;
  1016. pStubMsg = & pAsyncMsg->StubMsg;
  1017. // We have preserved the sync proc num that the channel used.
  1018. // We need only async proc num at the engine level.
  1019. //
  1020. ProcNum = pRpcMsg->ProcNum;
  1021. ProcNum = 2 * ProcNum - 3 + 1; // Finish method #
  1022. pSrvObj = (IUnknown *)((CStdStubBuffer *)pThis)->pvServerObject;
  1023. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  1024. pStubVTable = (CInterfaceStubVtbl *)
  1025. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  1026. piid = pStubVTable->header.piid;
  1027. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  1028. pStubDesc = pServerInfo->pStubDesc;
  1029. FormatOffset = pServerInfo->FmtStringOffset[ ProcNum ];
  1030. pFormat = &((pServerInfo->ProcString)[ FormatOffset ]);
  1031. // The proc header has a fixed layout now.
  1032. pProcHeader = (PNDR_DCOM_OI2_PROC_HEADER) pFormat;
  1033. // Validate and setup for finish.
  1034. hr = NdrpSetupFinishStubCall( pAsyncSB,
  1035. pProcHeader->StackSize,
  1036. *piid );
  1037. if ( hr )
  1038. return hr;
  1039. // The arg buffer is zeroed out already. Note, this is the second stack.
  1040. pContext = &pAsyncMsg->ProcContext;
  1041. pArgBuffer = pContext->StartofStack;
  1042. pStubMsg->StackTop = pArgBuffer;
  1043. //
  1044. // Get new interpreter info.
  1045. //
  1046. OldOiFlags = pProcHeader->OldOiFlags;
  1047. NewOiFlags = pProcHeader->Oi2Flags;
  1048. NumberParams = pProcHeader->NumberParams;
  1049. Params = (PPARAM_DESCRIPTION)(pFormat + sizeof(NDR_DCOM_OI2_PROC_HEADER));
  1050. if ( NewOiFlags.HasExtensions )
  1051. {
  1052. pHeaderExts = (NDR_PROC_HEADER_EXTS *)Params;
  1053. Params = (PPARAM_DESCRIPTION)((uchar*)Params + pHeaderExts->Size);
  1054. }
  1055. pAsyncMsg->nFinishParams = pContext->NumberParams = NumberParams;
  1056. pAsyncMsg->FinishParams = pContext->Params = Params;
  1057. pContext->DceTypeFormatString = pStubDesc->pFormatTypes;
  1058. pStubMsg->pContext = pContext;
  1059. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  1060. // a try-finally. Put the free phase in the associated finally block.
  1061. //
  1062. RpcTryFinally
  1063. {
  1064. if ( pAsyncMsg->Flags.ErrorPending )
  1065. RpcRaiseException( pAsyncMsg->ErrorCode );
  1066. // Initialize the args of the new stack.
  1067. // OLE: put pThis in first dword of stack.
  1068. //
  1069. ((void **)pArgBuffer)[0] = ((CStdStubBuffer *)pThis)->pvServerObject;
  1070. //
  1071. // Do [out] initialization before invoking Finish
  1072. //
  1073. NdrpCloneInOutStubArgs( pAsyncMsg );
  1074. NdrpServerOutInit( pStubMsg );
  1075. //
  1076. // OLE interfaces use pdwStubPhase in the exception filter.
  1077. // See CStdStubBuffer_Invoke in stub.c.
  1078. //
  1079. // MZ, BUG BUG, fix after ship
  1080. // *pdwStubPhase = STUB_CALL_SERVER;
  1081. // We need to catch exception in the manager code separately
  1082. // as the model implies that there will be no other call from
  1083. // the server app to clean up.
  1084. RpcTryExcept
  1085. {
  1086. //
  1087. // Check for a thunk. Compiler does all the setup for us.
  1088. //
  1089. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  1090. {
  1091. fManagerCodeInvoked = TRUE;
  1092. pServerInfo->ThunkTable[ProcNum]( pStubMsg );
  1093. }
  1094. else
  1095. {
  1096. //
  1097. // Note that this ArgNum is not the number of arguments declared
  1098. // in the function we called, but really the number of
  1099. // REGISTER_TYPEs occupied by the arguments to a function.
  1100. //
  1101. long ArgNum;
  1102. MANAGER_FUNCTION pFunc;
  1103. REGISTER_TYPE ReturnValue;
  1104. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  1105. ArgNum = (long)pProcHeader->StackSize / sizeof(REGISTER_TYPE);
  1106. //
  1107. // The StackSize includes the size of the return. If we want
  1108. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  1109. // by 1 when there is a return value AND the current ArgNum count
  1110. // is greater than 0.
  1111. //
  1112. if ( ArgNum && NewOiFlags.HasReturn )
  1113. ArgNum--;
  1114. fManagerCodeInvoked = TRUE;
  1115. ReturnValue = Invoke( pFunc,
  1116. (REGISTER_TYPE *)pArgBuffer,
  1117. #if defined(_WIN64)
  1118. NewOiFlags.HasExtensions ? ((PNDR_PROC_HEADER_EXTS64)pHeaderExts)->FloatArgMask
  1119. : 0,
  1120. #endif
  1121. ArgNum);
  1122. // This is the return value that should be marshaled back.
  1123. if ( NewOiFlags.HasReturn )
  1124. {
  1125. ((REGISTER_TYPE *)pArgBuffer)[ArgNum] = ReturnValue;
  1126. // Pass the app's HR to the channel.
  1127. (*pfnDcomChannelSetHResult)( pRpcMsg,
  1128. NULL, // reserved
  1129. (HRESULT) ReturnValue);
  1130. }
  1131. }
  1132. }
  1133. RpcExcept( 1 )
  1134. {
  1135. pAsyncMsg->Flags.ErrorPending = 1;
  1136. pAsyncMsg->ErrorCode = RpcExceptionCode();
  1137. fErrorInInvoke = TRUE;
  1138. }
  1139. RpcEndExcept
  1140. // Done with invoking Finish
  1141. if ( pAsyncMsg->Flags.ErrorPending )
  1142. RpcRaiseException( pAsyncMsg->ErrorCode );
  1143. //
  1144. // Buffer size pass.
  1145. //
  1146. pStubMsg->BufferLength = pProcHeader->ServerBufferSize;
  1147. if ( NewOiFlags.ServerMustSize )
  1148. {
  1149. NdrpSizing( pStubMsg,
  1150. FALSE ); // IsClient
  1151. }
  1152. // Get buffer.
  1153. NdrStubGetBuffer( (IRpcStubBuffer*)pAsyncMsg->pThis,
  1154. pStubMsg->pRpcChannelBuffer,
  1155. pStubMsg );
  1156. //
  1157. // Marshall pass.
  1158. //
  1159. NdrpServerMarshal( pStubMsg,
  1160. TRUE ); // IsObject
  1161. if ( pRpcMsg->BufferLength <
  1162. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  1163. {
  1164. NDR_ASSERT( 0, "NdrStubCall2 marshal: buffer overflow!" );
  1165. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  1166. }
  1167. pRpcMsg->BufferLength = (ulong)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer);
  1168. // We don't drop to the runtime like for synchronous calls,
  1169. // we send the last buffer explicitly.
  1170. fParamsFreed = TRUE;
  1171. // see comment on async.cxx on why we call this twice.
  1172. NdrpAsyncDCOMFreeParams( pAsyncMsg );
  1173. NdrpDcomAsyncSend( pStubMsg,
  1174. 0 ); // server doesn't pass pSynchronize back to channel.
  1175. }
  1176. RpcFinally
  1177. {
  1178. // Don't free parameters if we died because of bad stub data in unmarshaling.
  1179. if ( ! pAsyncMsg->Flags.BadStubData && !fParamsFreed)
  1180. {
  1181. NdrpAsyncDCOMFreeParams( pAsyncMsg );
  1182. }
  1183. if ( pAsyncMsg->Flags.ErrorPending )
  1184. hr = NdrHrFromWin32Error( pAsyncMsg->ErrorCode );
  1185. else
  1186. hr = S_OK;
  1187. // If we are here, error or not, it means that we can (and need to) dispose of
  1188. // the async context information
  1189. NdrpAsyncStubMsgDestructor( pAsyncSB );
  1190. // The engine never addrefs or releases the call object.
  1191. }
  1192. RpcEndFinally
  1193. return hr;
  1194. }
  1195. HRESULT
  1196. NdrpAsyncProxyMsgConstructor(
  1197. CStdAsyncProxyBuffer * pAsyncPB )
  1198. {
  1199. NdrDcomAsyncCallState * pCallState = & pAsyncPB->CallState;
  1200. pCallState->Lock = 0;
  1201. pCallState->Signature = NDR_ASYNC_PROXY_SIGNATURE;
  1202. pCallState->pAsyncMsg = 0;
  1203. *((long*)&pCallState->Flags) = 0;
  1204. pCallState->Hr = 0;
  1205. return S_OK;
  1206. }
  1207. HRESULT
  1208. NdrpAsyncStubMsgConstructor(
  1209. CStdAsyncStubBuffer * pAsyncSB )
  1210. {
  1211. NdrDcomAsyncCallState * pCallState = & pAsyncSB->CallState;
  1212. pCallState->Lock = 0;
  1213. pCallState->Signature = NDR_ASYNC_STUB_SIGNATURE;
  1214. pCallState->pAsyncMsg = 0;
  1215. *((long*)&pCallState->Flags) = 0;
  1216. pCallState->Hr = 0;
  1217. return S_OK;
  1218. }
  1219. HRESULT
  1220. NdrpAsyncProxyMsgDestructor(
  1221. CStdAsyncProxyBuffer * pAsyncPB )
  1222. {
  1223. NdrDcomAsyncCallState * pCallState = & pAsyncPB->CallState;
  1224. if ( pCallState->pAsyncMsg )
  1225. {
  1226. NdrpFreeDcomAsyncMsg( (PNDR_DCOM_ASYNC_MESSAGE)pCallState->pAsyncMsg );
  1227. pCallState->pAsyncMsg = 0;
  1228. }
  1229. *((long*)&pCallState->Flags) = 0;
  1230. pCallState->Hr = 0;
  1231. return S_OK;
  1232. }
  1233. HRESULT
  1234. NdrpAsyncStubMsgDestructor(
  1235. CStdAsyncStubBuffer * pAsyncSB )
  1236. {
  1237. NdrDcomAsyncCallState * pCallState = & pAsyncSB->CallState;
  1238. if ( pCallState->pAsyncMsg )
  1239. {
  1240. NdrpFreeDcomAsyncMsg( (PNDR_DCOM_ASYNC_MESSAGE)pCallState->pAsyncMsg );
  1241. pCallState->pAsyncMsg = 0;
  1242. }
  1243. *((long*)&pCallState->Flags) = 0;
  1244. pCallState->Hr = 0;
  1245. return S_OK;
  1246. }
  1247. HRESULT
  1248. NdrpValidateAsyncProxyCall(
  1249. CStdAsyncProxyBuffer * pAsyncPB
  1250. )
  1251. {
  1252. HRESULT hr = S_OK;
  1253. RpcTryExcept
  1254. {
  1255. NdrDcomAsyncCallState * pCallState = & pAsyncPB->CallState;
  1256. if ( pCallState->Signature != NDR_ASYNC_PROXY_SIGNATURE )
  1257. hr = E_INVALIDARG;
  1258. }
  1259. RpcExcept(1)
  1260. {
  1261. hr = E_INVALIDARG;
  1262. }
  1263. RpcEndExcept;
  1264. return hr;
  1265. }
  1266. HRESULT
  1267. NdrpValidateAsyncStubCall(
  1268. CStdAsyncStubBuffer * pAsyncSB
  1269. )
  1270. {
  1271. HRESULT hr = S_OK;
  1272. RpcTryExcept
  1273. {
  1274. NdrDcomAsyncCallState * pCallState = & pAsyncSB->CallState;
  1275. if ( pCallState->Signature != NDR_ASYNC_STUB_SIGNATURE )
  1276. hr = E_INVALIDARG;
  1277. }
  1278. RpcExcept(1)
  1279. {
  1280. hr = E_INVALIDARG;
  1281. }
  1282. RpcEndExcept;
  1283. return hr;
  1284. }
  1285. HRESULT
  1286. NdrpValidateDcomAsyncMsg(
  1287. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg )
  1288. {
  1289. HRESULT hr = RPC_S_OK;
  1290. RpcTryExcept
  1291. {
  1292. if ( pAsyncMsg->Signature != NDR_DCOM_ASYNC_SIGNATURE ||
  1293. pAsyncMsg->Version != NDR_DCOM_ASYNC_VERSION )
  1294. {
  1295. hr = E_INVALIDARG;
  1296. }
  1297. }
  1298. RpcExcept(1)
  1299. {
  1300. hr = E_INVALIDARG;
  1301. }
  1302. RpcEndExcept;
  1303. return hr;
  1304. }
  1305. HRESULT
  1306. NdrpSetupBeginClientCall(
  1307. CStdAsyncProxyBuffer * pAsyncPB,
  1308. void * StartofStack,
  1309. unsigned short StackSize,
  1310. REFIID riid )
  1311. /*
  1312. This method creates and initializes async msg.
  1313. */
  1314. {
  1315. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1316. HRESULT hr = S_OK;
  1317. hr = NdrpValidateAsyncProxyCall( pAsyncPB );
  1318. if ( ! SUCCEEDED(hr) )
  1319. return hr;
  1320. if ( pAsyncPB->CallState.pAsyncMsg != 0 ||
  1321. pAsyncPB->CallState.Flags.BeginStarted )
  1322. return E_FAIL;
  1323. // Do this first to simplify error conditions.
  1324. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)
  1325. I_RpcBCacheAllocate( sizeof(NDR_DCOM_ASYNC_MESSAGE) +
  1326. StackSize + NDR_ASYNC_GUARD_SIZE );
  1327. if ( ! pAsyncMsg )
  1328. {
  1329. NdrpAsyncProxySignal( pAsyncPB );
  1330. return E_OUTOFMEMORY;
  1331. }
  1332. // Initialize the async message properly
  1333. MIDL_memset( pAsyncMsg, 0x0, sizeof( NDR_DCOM_ASYNC_MESSAGE) );
  1334. pAsyncMsg->Signature = NDR_DCOM_ASYNC_SIGNATURE;
  1335. pAsyncMsg->Version = NDR_DCOM_ASYNC_VERSION;
  1336. pAsyncMsg->SyntaxType = XFER_SYNTAX_DCE;
  1337. pAsyncMsg->ProcContext.StartofStack = (uchar *) & pAsyncMsg->AppStack;
  1338. pAsyncMsg->BeginStack = (uchar *) & pAsyncMsg->AppStack;
  1339. pAsyncMsg->BeginStackSize = StackSize;
  1340. pAsyncMsg->StubPhase = NDR_ASYNC_PREP_PHASE;
  1341. NdrpAllocaInit( &pAsyncMsg->ProcContext.AllocateContext );
  1342. // Client: copy stack from the app's request call.
  1343. RpcpMemoryCopy( & pAsyncMsg->AppStack, StartofStack, StackSize );
  1344. MIDL_memset( ((char *)& pAsyncMsg->AppStack) + StackSize,
  1345. 0x71,
  1346. NDR_ASYNC_GUARD_SIZE );
  1347. pAsyncMsg->pAsyncPB = pAsyncPB;
  1348. pAsyncPB->CallState.Flags.BeginStarted = 1;
  1349. pAsyncPB->CallState.pAsyncMsg = pAsyncMsg;
  1350. return S_OK;
  1351. }
  1352. HRESULT
  1353. NdrpSetupFinishClientCall(
  1354. CStdAsyncProxyBuffer * pAsyncPB,
  1355. void * StartofStack,
  1356. unsigned short StackSize,
  1357. REFIID riid,
  1358. unsigned long FinishProcNum )
  1359. /*
  1360. This method creates and initializes async msg.
  1361. */
  1362. {
  1363. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1364. HRESULT hr = S_OK;
  1365. hr = NdrpValidateAsyncProxyCall( pAsyncPB );
  1366. if ( ! SUCCEEDED(hr) )
  1367. return hr;
  1368. if ( !pAsyncPB->CallState.Flags.BeginStarted ||
  1369. !pAsyncPB->CallState.Flags.BeginDone ||
  1370. pAsyncPB->CallState.Flags.FinishStarted )
  1371. return E_FAIL;
  1372. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE)pAsyncPB->CallState.pAsyncMsg;
  1373. hr = NdrpValidateDcomAsyncMsg( pAsyncMsg );
  1374. if ( ! SUCCEEDED(hr) )
  1375. return hr;
  1376. if ( (FinishProcNum + 3)/2 != (pAsyncMsg->RpcMsg.ProcNum & 0x7fff) )
  1377. return E_FAIL;
  1378. // Initialize the async message properly
  1379. pAsyncMsg->ProcContext.StartofStack = (uchar *) StartofStack;
  1380. pAsyncMsg->FinishStack = (uchar *) StartofStack;
  1381. pAsyncMsg->FinishStackSize = StackSize;
  1382. pAsyncMsg->StubPhase = NDR_ASYNC_PREP_PHASE;
  1383. NdrSetupLowStackMark( &pAsyncMsg->StubMsg );
  1384. // Dont allocate or copy the new stack anywhere.
  1385. pAsyncPB->CallState.Flags.FinishStarted = 1;
  1386. return S_OK;
  1387. }
  1388. HRESULT
  1389. NdrpSetupBeginStubCall(
  1390. CStdAsyncStubBuffer * pAsyncSB,
  1391. unsigned short StackSize,
  1392. REFIID riid )
  1393. /*
  1394. This method creates and initializes async msg.
  1395. */
  1396. {
  1397. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1398. HRESULT hr = S_OK;
  1399. hr = NdrpValidateAsyncStubCall( pAsyncSB );
  1400. if ( ! SUCCEEDED(hr) )
  1401. return hr;
  1402. if ( pAsyncSB->CallState.pAsyncMsg != 0 ||
  1403. pAsyncSB->CallState.Flags.BeginStarted )
  1404. hr = E_FAIL;
  1405. else
  1406. {
  1407. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)
  1408. I_RpcBCacheAllocate( sizeof( NDR_DCOM_ASYNC_MESSAGE) +
  1409. StackSize + NDR_ASYNC_GUARD_SIZE );
  1410. if ( ! pAsyncMsg )
  1411. hr = E_OUTOFMEMORY;
  1412. }
  1413. if ( ! SUCCEEDED(hr) )
  1414. {
  1415. // The stub never signals.
  1416. pAsyncSB->CallState.Flags.BeginError = 1;
  1417. pAsyncSB->CallState.Hr = hr;
  1418. return hr;
  1419. }
  1420. // Initialize the async message properly
  1421. MIDL_memset( pAsyncMsg, 0x0, sizeof( NDR_DCOM_ASYNC_MESSAGE) );
  1422. pAsyncMsg->Signature = NDR_DCOM_ASYNC_SIGNATURE;
  1423. pAsyncMsg->Version = NDR_DCOM_ASYNC_VERSION;
  1424. pAsyncMsg->SyntaxType = XFER_SYNTAX_DCE;
  1425. pAsyncMsg->ProcContext.StartofStack = (uchar *) & pAsyncMsg->AppStack;
  1426. pAsyncMsg->BeginStack = (uchar *) & pAsyncMsg->AppStack;
  1427. pAsyncMsg->BeginStackSize = StackSize;
  1428. pAsyncMsg->StubPhase = STUB_UNMARSHAL;
  1429. pAsyncMsg->StubMsg.pContext = &pAsyncMsg->ProcContext;
  1430. NdrpAllocaInit( &pAsyncMsg->ProcContext.AllocateContext );
  1431. // Server: zero out stack for allocs.
  1432. MIDL_memset( & pAsyncMsg->AppStack, 0x0, StackSize );
  1433. MIDL_memset( ((char *)& pAsyncMsg->AppStack) + StackSize,
  1434. 0x71,
  1435. NDR_ASYNC_GUARD_SIZE );
  1436. pAsyncSB->CallState.pAsyncMsg = pAsyncMsg;
  1437. pAsyncSB->CallState.Flags.BeginStarted = 1;
  1438. pAsyncMsg->pAsyncSB = pAsyncSB;
  1439. return S_OK;
  1440. }
  1441. HRESULT
  1442. NdrpSetupFinishStubCall(
  1443. CStdAsyncStubBuffer * pAsyncSB,
  1444. unsigned short StackSize,
  1445. REFIID riid )
  1446. /*
  1447. This method creates and initializes async msg.
  1448. */
  1449. {
  1450. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1451. uchar * pFinishStack;
  1452. HRESULT hr = S_OK;
  1453. hr = NdrpValidateAsyncStubCall( pAsyncSB );
  1454. if ( ! SUCCEEDED(hr) )
  1455. return hr;
  1456. if ( !pAsyncSB->CallState.Flags.BeginStarted ||
  1457. !pAsyncSB->CallState.Flags.BeginDone ||
  1458. pAsyncSB->CallState.Flags.FinishStarted )
  1459. return E_FAIL;
  1460. if ( pAsyncSB->CallState.Hr != 0 )
  1461. return pAsyncSB->CallState.Hr;
  1462. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE)pAsyncSB->CallState.pAsyncMsg;
  1463. hr = NdrpValidateDcomAsyncMsg( pAsyncMsg );
  1464. if ( ! SUCCEEDED(hr) )
  1465. return hr;
  1466. // We need to create the second stack for the app invoke.
  1467. // Do this first to simplify error conditions.
  1468. RpcTryExcept
  1469. {
  1470. pFinishStack = (uchar*) AsyncAlloca( pAsyncMsg,
  1471. StackSize + NDR_ASYNC_GUARD_SIZE );
  1472. }
  1473. RpcExcept( 1 )
  1474. {
  1475. NdrpAsyncStubMsgDestructor( pAsyncSB );
  1476. return E_OUTOFMEMORY;
  1477. }
  1478. RpcEndExcept
  1479. // Initialize the async message properly
  1480. // the finish stack is quite possibly different from beginning stack. we need to
  1481. // readjust the low stack mark for finish call
  1482. NdrSetupLowStackMark( &pAsyncMsg->StubMsg );
  1483. pAsyncMsg->ProcContext.StartofStack = (uchar *) pFinishStack;
  1484. pAsyncMsg->FinishStack = (uchar *) pFinishStack;
  1485. pAsyncMsg->FinishStackSize = StackSize;
  1486. pAsyncMsg->StubMsg.pContext = &pAsyncMsg->ProcContext;
  1487. // Server: zero out stack for allocs.
  1488. MIDL_memset( pFinishStack, 0x0, StackSize );
  1489. MIDL_memset( (char *)pFinishStack + StackSize,
  1490. 0x72,
  1491. NDR_ASYNC_GUARD_SIZE );
  1492. pAsyncSB->CallState.Flags.FinishStarted = 1;
  1493. return S_OK;
  1494. }
  1495. HRESULT
  1496. NdrpAsyncProxySignal(
  1497. CStdAsyncProxyBuffer * pAsyncPB )
  1498. {
  1499. ISynchronize * pSynchronize;
  1500. HRESULT hr;
  1501. IUnknown * punkOuter = pAsyncPB->punkOuter;
  1502. hr = punkOuter->lpVtbl->QueryInterface( punkOuter,
  1503. IID_ISynchronize,
  1504. (void**)&pSynchronize );
  1505. if ( SUCCEEDED(hr) )
  1506. {
  1507. pSynchronize->lpVtbl->Signal( pSynchronize );
  1508. pSynchronize->lpVtbl->Release( pSynchronize );
  1509. }
  1510. return hr;
  1511. }
  1512. _inline
  1513. HRESULT
  1514. NdrpCallStateLock(
  1515. NdrDcomAsyncCallState * pCallState )
  1516. {
  1517. if ( 0 != InterlockedCompareExchange( (long*)& pCallState->Lock, 1, 0 ) )
  1518. {
  1519. return E_FAIL;
  1520. }
  1521. return RPC_S_OK;
  1522. }
  1523. _inline
  1524. void
  1525. NdrpCallStateUnlock(
  1526. NdrDcomAsyncCallState * pCallState )
  1527. {
  1528. InterlockedDecrement( (long*)& pCallState->Lock );
  1529. return;
  1530. }
  1531. HRESULT
  1532. NdrpAsyncProxyLock(
  1533. CStdAsyncProxyBuffer * pAsyncPB )
  1534. {
  1535. return NdrpCallStateLock( & pAsyncPB->CallState );
  1536. }
  1537. void
  1538. NdrpAsyncProxyUnlock(
  1539. CStdAsyncProxyBuffer * pAsyncPB )
  1540. {
  1541. NdrpCallStateUnlock( & pAsyncPB->CallState );
  1542. }
  1543. HRESULT
  1544. NdrpAsyncStubLock(
  1545. CStdAsyncStubBuffer * pAsyncSB )
  1546. {
  1547. return NdrpCallStateLock( & pAsyncSB->CallState );
  1548. }
  1549. void
  1550. NdrpAsyncStubUnlock(
  1551. CStdAsyncStubBuffer * pAsyncSB )
  1552. {
  1553. NdrpCallStateUnlock( & pAsyncSB->CallState );
  1554. }
  1555. void
  1556. NdrpFreeDcomAsyncMsg(
  1557. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg )
  1558. /*
  1559. This routine would free the AsyncMsg but not the AsyncHandle, as on the server
  1560. the user may need it and on the client it is user's to begin with.
  1561. */
  1562. {
  1563. if ( pAsyncMsg )
  1564. {
  1565. PMIDL_STUB_MESSAGE pStubMsg = & pAsyncMsg->StubMsg;
  1566. NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
  1567. // in NDR64, we are using allocacontext to hold corr info, so we don't
  1568. // want to free it there.
  1569. if ( pAsyncMsg->SyntaxType == XFER_SYNTAX_DCE )
  1570. NdrCorrelationFree( pStubMsg );
  1571. // Free the RPC buffer.
  1572. if ( pStubMsg->IsClient )
  1573. {
  1574. if ( ! pAsyncMsg->Flags.RuntimeCleanedUp )
  1575. {
  1576. void * pThis = *(void **)pAsyncMsg->ProcContext.StartofStack;
  1577. NdrProxyFreeBuffer( pThis, pStubMsg );
  1578. }
  1579. }
  1580. NdrpAllocaDestroy( &pAsyncMsg->ProcContext.AllocateContext );
  1581. // Prevent reusing of a handle that has been freed;
  1582. pAsyncMsg->Signature = NDR_FREED_ASYNC_SIGNATURE;
  1583. I_RpcBCacheFree( pAsyncMsg );
  1584. }
  1585. }
  1586. BOOL
  1587. NdrpDcomAsyncSend(
  1588. PMIDL_STUB_MESSAGE pStubMsg,
  1589. ISynchronize * pSynchronize )
  1590. /*
  1591. Call the channel to send.
  1592. On the client, pass the app's pSynchronize to it, such that channel can signal
  1593. the app.
  1594. On the server, pass NULL instead of a pSynchronize.
  1595. */
  1596. {
  1597. PRPC_MESSAGE pRpcMsg = pStubMsg->RpcMsg;
  1598. HRESULT hr = S_OK;
  1599. RPC_STATUS Status = RPC_S_OK;
  1600. BOOL fSendCalled = FALSE;
  1601. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  1602. if ( pStubMsg->pRpcChannelBuffer )
  1603. {
  1604. IAsyncRpcChannelBuffer * pAsChannel;
  1605. IRpcChannelBuffer * pChannel = (IRpcChannelBuffer *)
  1606. pStubMsg->pRpcChannelBuffer;
  1607. hr = pChannel->lpVtbl->QueryInterface( pChannel,
  1608. IID_IAsyncRpcChannelBuffer,
  1609. (void**)& pAsChannel );
  1610. if ( SUCCEEDED(hr) )
  1611. {
  1612. fSendCalled = TRUE;
  1613. hr = pAsChannel->lpVtbl->Send( pAsChannel,
  1614. (RPCOLEMESSAGE *)pRpcMsg,
  1615. pSynchronize,
  1616. (ulong*)& Status );
  1617. pAsChannel->lpVtbl->Release( pAsChannel );
  1618. // The channel never returns this code now for new async.
  1619. NDR_ASSERT( Status != RPC_S_SEND_INCOMPLETE, "Unexpected channel error" );
  1620. }
  1621. }
  1622. else
  1623. hr = E_NOINTERFACE;
  1624. if ( pSynchronize )
  1625. pSynchronize->lpVtbl->Release(pSynchronize);
  1626. // Alex:
  1627. if ( SUCCEEDED(hr) && Status == RPC_S_OK )
  1628. pStubMsg->fBufferValid = TRUE;
  1629. else
  1630. RpcRaiseException( Status );
  1631. return fSendCalled;
  1632. }
  1633. BOOL
  1634. NdrpDcomAsyncClientSend(
  1635. PMIDL_STUB_MESSAGE pStubMsg,
  1636. IUnknown * punkOuter )
  1637. /*
  1638. Call the channel to send.
  1639. On the client pass app's pSynchronize to it, such that channel can signal
  1640. the app.
  1641. On the server pass NULL instead of a pSynchronize.
  1642. */
  1643. {
  1644. PRPC_MESSAGE pRpcMsg = pStubMsg->RpcMsg;
  1645. HRESULT hr = S_OK;
  1646. BOOL fSendCalled = FALSE;
  1647. ISynchronize * pSynchronize = 0;
  1648. // Channel needs somebody to signal to, this will be the app.
  1649. hr = punkOuter->lpVtbl->QueryInterface( punkOuter,
  1650. IID_ISynchronize,
  1651. (void**) &pSynchronize );
  1652. if ( SUCCEEDED(hr) )
  1653. fSendCalled = NdrpDcomAsyncSend( pStubMsg, pSynchronize );
  1654. return fSendCalled;
  1655. }
  1656. void
  1657. NdrDcomAsyncReceive(
  1658. PMIDL_STUB_MESSAGE pStubMsg )
  1659. {
  1660. PRPC_MESSAGE pRpcMsg = pStubMsg->RpcMsg;
  1661. RPC_STATUS Status = RPC_S_OK;
  1662. HRESULT hr;
  1663. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  1664. pRpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
  1665. // A complete call.
  1666. if ( pStubMsg->pRpcChannelBuffer )
  1667. {
  1668. IAsyncRpcChannelBuffer * pAsyncChannel = (IAsyncRpcChannelBuffer *)
  1669. pStubMsg->pRpcChannelBuffer;
  1670. hr = pAsyncChannel->lpVtbl->Receive( pAsyncChannel,
  1671. (PRPCOLEMESSAGE) pRpcMsg,
  1672. (unsigned long *)&Status );
  1673. }
  1674. if ( Status )
  1675. {
  1676. // No pending, the call would have blocked, real bug happened.
  1677. if ( pStubMsg->pAsyncMsg )
  1678. ((PNDR_DCOM_ASYNC_MESSAGE)pStubMsg->pAsyncMsg)->Flags.RuntimeCleanedUp = 1;
  1679. RpcRaiseException(Status);
  1680. }
  1681. else
  1682. {
  1683. pStubMsg->Buffer = (uchar*) pRpcMsg->Buffer;
  1684. pStubMsg->BufferStart = (uchar*)pRpcMsg->Buffer;
  1685. pStubMsg->BufferEnd = (uchar*)pRpcMsg->Buffer + pRpcMsg->BufferLength;
  1686. pStubMsg->fBufferValid = TRUE;
  1687. }
  1688. }
  1689. HRESULT
  1690. Ndr64pCompleteDcomAsyncStubCall(
  1691. CStdAsyncStubBuffer * pAsyncSB
  1692. );
  1693. HRESULT
  1694. NdrpAsyncStubSignal(
  1695. CStdAsyncStubBuffer * pAsyncSB )
  1696. /*
  1697. Signal on the async stub object:
  1698. The channel signals that the Finish call should be executed.
  1699. See if the stub object is active (or find one that is).
  1700. If the stub object is not active then the call fails.
  1701. */
  1702. {
  1703. HRESULT hr = S_OK;
  1704. BOOL fFoundActiveCall = FALSE;
  1705. while ( SUCCEEDED(hr) && ! fFoundActiveCall )
  1706. {
  1707. hr = NdrpValidateAsyncStubCall( pAsyncSB );
  1708. if ( SUCCEEDED(hr) )
  1709. {
  1710. if ( pAsyncSB->CallState.Flags.BeginStarted )
  1711. {
  1712. fFoundActiveCall = TRUE;
  1713. }
  1714. else
  1715. {
  1716. // Switch to the base interface call object. In case of
  1717. // delegation one of the base interface objects would be active.
  1718. IRpcStubBuffer * pBaseStubBuffer = pAsyncSB->pBaseStubBuffer;
  1719. if ( pBaseStubBuffer )
  1720. {
  1721. pAsyncSB = (CStdAsyncStubBuffer *) ((uchar *)pBaseStubBuffer
  1722. - offsetof(CStdAsyncStubBuffer,lpVtbl));
  1723. }
  1724. else
  1725. {
  1726. // None of the stubs active and a signal came.
  1727. hr = E_FAIL;
  1728. }
  1729. }
  1730. }
  1731. }
  1732. if ( SUCCEEDED(hr) )
  1733. {
  1734. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg =
  1735. (PNDR_DCOM_ASYNC_MESSAGE)pAsyncSB->CallState.pAsyncMsg;
  1736. hr = NdrpValidateDcomAsyncMsg( pAsyncMsg );
  1737. if ( SUCCEEDED(hr) )
  1738. {
  1739. #if defined(BUILD_NDR64)
  1740. if ( pAsyncMsg->SyntaxType == XFER_SYNTAX_DCE )
  1741. hr = NdrpCompleteDcomAsyncStubCall( pAsyncSB );
  1742. else
  1743. hr = Ndr64pCompleteDcomAsyncStubCall( pAsyncSB );
  1744. #else
  1745. hr = NdrpCompleteDcomAsyncStubCall( pAsyncSB );
  1746. #endif
  1747. }
  1748. }
  1749. return hr;
  1750. }