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.

1578 lines
50 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. #include "precomp.hxx"
  12. #define USE_STUBLESS_PROXY
  13. #define CINTERFACE
  14. #include "ndrole.h"
  15. #include "rpcproxy.h"
  16. #include "interp2.h"
  17. #include "asyncu64.h"
  18. #include "expr.h"
  19. #include "ndrtypes.h"
  20. #include "ndr64types.h"
  21. #include <stddef.h>
  22. #include <stdarg.h>
  23. #pragma code_seg(".ndr64")
  24. void
  25. Ndr64pCloneInOnlyCorrArgs(
  26. NDR_DCOM_ASYNC_MESSAGE * pAsyncMsg,
  27. PFORMAT_STRING pFormatType
  28. );
  29. HRESULT
  30. Ndr64pCompleteDcomAsyncStubCall(
  31. CStdAsyncStubBuffer * pAsyncSB
  32. );
  33. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  34. Ndr64DcomAsyncClientCall(
  35. MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
  36. ulong nProcNum,
  37. void *pReturnValue,
  38. ...
  39. )
  40. {
  41. NDR_PROC_CONTEXT ProcContext;
  42. RPC_STATUS status;
  43. CLIENT_CALL_RETURN Ret;
  44. va_list ArgList;
  45. unsigned char * StartofStack;
  46. INIT_ARG( ArgList, pReturnValue);
  47. GET_FIRST_IN_ARG(ArgList);
  48. StartofStack = (uchar *) GET_STACK_START(ArgList);
  49. Ndr64ClientInitializeContext( NdrpGetSyntaxType( pProxyInfo->pTransferSyntax),
  50. pProxyInfo,
  51. nProcNum,
  52. &ProcContext,
  53. StartofStack );
  54. NDR_ASSERT( ProcContext.IsAsync, "invalid async proc" );
  55. if ( nProcNum & 0x1 )
  56. status = MulNdrpBeginDcomAsyncClientCall( pProxyInfo,
  57. nProcNum,
  58. &ProcContext,
  59. StartofStack );
  60. else
  61. status = MulNdrpFinishDcomAsyncClientCall(pProxyInfo,
  62. nProcNum,
  63. &ProcContext,
  64. StartofStack );
  65. Ret.Simple = status;
  66. return Ret;
  67. }
  68. VOID
  69. Ndr64pAsyncDCOMFreeParams(
  70. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg )
  71. {
  72. /*++
  73. Routine Description:
  74. Frees the parameters for both the begin and finish calls.
  75. Arguments:
  76. pAsyncMsg - Supplies a pointer to the async message.
  77. Return Value:
  78. None.
  79. --*/
  80. NDR64_PARAM_FLAGS * pParamFlags;
  81. if ( pAsyncMsg->BeginStack )
  82. {
  83. if ( pAsyncMsg->FinishStack )
  84. {
  85. // Clear out the IN OUT parameters on the begin stack
  86. // so that they are not freed twice.
  87. int n;
  88. REGISTER_TYPE *pBeginStack = (REGISTER_TYPE *)pAsyncMsg->BeginStack;
  89. NDR64_PARAM_FORMAT *BeginParams = (NDR64_PARAM_FORMAT*)pAsyncMsg->BeginParams;
  90. int BeginNumberParams = pAsyncMsg->nBeginParams ;
  91. for( n = 0; n < BeginNumberParams; n++ )
  92. {
  93. pParamFlags = ( NDR64_PARAM_FLAGS * ) & ( BeginParams[n].Attributes );
  94. if ( pParamFlags->IsIn &&
  95. pParamFlags->IsOut )
  96. {
  97. pBeginStack[ BeginParams[ n ].StackOffset / sizeof(REGISTER_TYPE) ] = 0;
  98. }
  99. }
  100. }
  101. pAsyncMsg->StubMsg.StackTop = pAsyncMsg->BeginStack;
  102. Ndr64pFreeParams( & (pAsyncMsg->StubMsg),
  103. pAsyncMsg->nBeginParams,
  104. ( NDR64_PARAM_FORMAT * ) pAsyncMsg->BeginParams,
  105. pAsyncMsg->BeginStack );
  106. }
  107. if ( pAsyncMsg->FinishStack )
  108. {
  109. pAsyncMsg->StubMsg.StackTop = pAsyncMsg->FinishStack;
  110. Ndr64pFreeParams( & (pAsyncMsg->StubMsg),
  111. pAsyncMsg->nFinishParams,
  112. ( NDR64_PARAM_FORMAT * ) pAsyncMsg->FinishParams,
  113. pAsyncMsg->FinishStack );
  114. }
  115. }
  116. HRESULT
  117. MulNdrpBeginDcomAsyncClientCall(
  118. MIDL_STUBLESS_PROXY_INFO * pProxyInfo,
  119. ulong nProcNum,
  120. NDR_PROC_CONTEXT * pContext,
  121. void * StartofStack )
  122. /*
  123. Notes: OLE Refcounting.
  124. The model for async_uuid() is that async proxies or stubs
  125. are created with RefCount==1 and should never ever be
  126. addrefed by the engine.
  127. What the engine does is only the AsyncMsg clean up when done.
  128. The decision to destroy the AsyncPB or AsyncSB object is
  129. up to the client side PM or channel's SM for the server side.
  130. */
  131. {
  132. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  133. RPC_MESSAGE * pRpcMsg;
  134. MIDL_STUB_MESSAGE * pStubMsg;
  135. uchar * pArg;
  136. void * pThis = *(void **)StartofStack;
  137. void * Params;
  138. long NumberParams;
  139. long n;
  140. RPC_STATUS Status;
  141. CStdAsyncProxyBuffer * pAsyncPB;
  142. const IID * piid;
  143. HRESULT hr = S_OK;
  144. BOOL fSendCalled = FALSE;
  145. pAsyncPB = (CStdAsyncProxyBuffer*)
  146. ((uchar*)pThis - offsetof(CStdProxyBuffer, pProxyVtbl));
  147. piid = NdrGetProxyIID( pThis );
  148. Status = MulNdrpSetupBeginClientCall( pAsyncPB,
  149. StartofStack,
  150. pContext,
  151. *piid );
  152. if ( !SUCCEEDED(Status) )
  153. return Status;
  154. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE *)pAsyncPB->CallState.pAsyncMsg;
  155. // We need to switch to our copy of the stack everywhere, including pStubMsg.
  156. StartofStack = pAsyncMsg->ProcContext.StartofStack;
  157. pRpcMsg = & pAsyncMsg->RpcMsg;
  158. pStubMsg = & pAsyncMsg->StubMsg;
  159. pStubMsg->pContext = &pAsyncMsg->ProcContext;
  160. pContext = &pAsyncMsg->ProcContext;
  161. NumberParams = pContext->NumberParams;
  162. // This is OLE only code path - use a single TryExcept.
  163. // After catching it just map it to OLE exception.
  164. RpcTryExcept
  165. {
  166. ulong RpcFlags;
  167. PFORMAT_STRING pFormat;
  168. pContext->RpcFlags |= RPC_BUFFER_ASYNC;
  169. Ndr64pClientSetupTransferSyntax(pThis,
  170. pRpcMsg,
  171. pStubMsg,
  172. pProxyInfo,
  173. pContext,
  174. nProcNum );
  175. pStubMsg->pAsyncMsg = (struct _NDR_ASYNC_MESSAGE *) pAsyncMsg;
  176. //
  177. // Parameter descriptions are nicely spit out by MIDL.
  178. //
  179. Params = (NDR64_PARAM_FORMAT *) ( pContext->Params );
  180. pFormat = NdrpGetProcString( pContext->pSyntaxInfo,
  181. pContext->CurrentSyntaxType,
  182. nProcNum );
  183. pStubMsg->pContext = pContext;
  184. pAsyncMsg->nBeginParams = NumberParams;
  185. pAsyncMsg->BeginParams = (void *)Params;
  186. pAsyncMsg->pThis = pThis;
  187. pAsyncMsg->SyntaxType = pContext->CurrentSyntaxType;
  188. ( * pContext->pfnInit)(pStubMsg,
  189. NULL ); // return value
  190. ( * pContext->pfnSizing) ( pStubMsg,
  191. TRUE ); // isclient
  192. //
  193. // Do the GetBuffer.
  194. //
  195. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  196. NdrProxyGetBuffer( pThis, pStubMsg );
  197. NDR_ASSERT( pStubMsg->fBufferValid, "Invalid buffer" );
  198. pAsyncMsg->StubPhase = STUB_MARSHAL;
  199. //
  200. // ----------------------------------------------------------
  201. // Marshall Pass.
  202. // ----------------------------------------------------------
  203. //
  204. ( * pContext->pfnMarshal ) ( pStubMsg,
  205. TRUE ); // IsObject
  206. //
  207. // Make the RPC call.
  208. //
  209. pAsyncMsg->StubPhase = NDR_ASYNC_CALL_PHASE;
  210. fSendCalled = NdrpDcomAsyncClientSend( pStubMsg,
  211. pAsyncPB->punkOuter ); // PM's entry
  212. if ( fSendCalled )
  213. hr = S_OK;
  214. }
  215. RpcExcept( 1 )
  216. {
  217. RPC_STATUS ExceptionCode = RpcExceptionCode();
  218. pAsyncPB->CallState.Flags.BeginError = 1;
  219. // Actually dismantle the call.
  220. // This is a request call and there is nothing left at the runtime.
  221. pAsyncMsg->StubPhase = NDR_ASYNC_ERROR_PHASE;
  222. pAsyncMsg->ErrorCode = ExceptionCode;
  223. hr = NdrHrFromWin32Error(ExceptionCode);
  224. pAsyncPB->CallState.Hr = hr;
  225. // Async call in request phase: don't touch [out] params.
  226. }
  227. RpcEndExcept
  228. // "Finally"
  229. // Dont touch anything, the client has to call the Finish method anyway.
  230. pAsyncPB->CallState.Flags.BeginDone = 1;
  231. if ( SUCCEEDED(hr) )
  232. {
  233. if ( pContext->CurrentSyntaxType == XFER_SYNTAX_DCE )
  234. NdrpCloneInOnlyCorrArgs( pAsyncMsg,
  235. pContext->pSyntaxInfo->TypeString );
  236. else
  237. Ndr64pCloneInOnlyCorrArgs( pAsyncMsg,
  238. pContext->pSyntaxInfo->TypeString );
  239. // Channel will prompt signal
  240. }
  241. else
  242. if (!fSendCalled )
  243. NdrpAsyncProxySignal( pAsyncPB );
  244. // No need to release, our refcount should be 1 at this point.
  245. return hr;
  246. }
  247. void
  248. Ndr64pCloneInOnlyCorrArgs(
  249. NDR_DCOM_ASYNC_MESSAGE * pAsyncMsg,
  250. PFORMAT_STRING pFormatTypes
  251. )
  252. /*
  253. Walk the client stack looking for an in only argument flagged to clone.
  254. For each one, replace the arg with a clone that we control.
  255. Assumption is, we do it before returning to the user from the Begin call
  256. and also we clone walking the copy of the app's stack not the app stack.
  257. The stack modified in this way will be the one to access for the weird
  258. crossreferenced correlated args.
  259. This issue doesn't happen on the server, as we keep the Begin stack around
  260. when the Finish call is processed.
  261. */
  262. {
  263. unsigned char * pBeginStack = pAsyncMsg->BeginStack;
  264. NDR64_PARAM_FORMAT * Params = ( NDR64_PARAM_FORMAT *)pAsyncMsg->BeginParams;
  265. NDR64_PARAM_FLAGS * pParamFlags;
  266. int NumberParams = pAsyncMsg->nBeginParams;
  267. unsigned char * pArg;
  268. int n;
  269. for ( n = 0; n < NumberParams; n++ )
  270. {
  271. pParamFlags = ( NDR64_PARAM_FLAGS * ) & Params[n].Attributes ;
  272. if ( pParamFlags->SaveForAsyncFinish )
  273. {
  274. // Note that the arguments that need cloning come from top level size_is,
  275. // length_is etc, switch_is and iid_is attributes.
  276. // Hence, the only types of interest are uuid clones and integral types
  277. // different from hyper.
  278. // On top of it, we deal with stack-slot chunks of memory, so we don't
  279. // have to care about mac issues.
  280. pArg = pBeginStack + Params[n].StackOffset;
  281. if ( pParamFlags->IsBasetype )
  282. {
  283. if ( pParamFlags->IsSimpleRef )
  284. {
  285. void * pPointee = AsyncAlloca( pAsyncMsg, 8 );
  286. NDR64_FORMAT_CHAR type = *(PFORMAT_STRING)Params[n].Type;
  287. // The assignment needs to follow the type.
  288. RpcpMemoryCopy( pPointee, *(void **)pArg,
  289. NDR64_SIMPLE_TYPE_MEMSIZE( type ) );
  290. *(void**)pArg = pPointee;
  291. }
  292. // else the stack slot has the simple value already.
  293. }
  294. else
  295. {
  296. // If it's not a base type, then it cannot be by value.
  297. // It has to be a pointer to a simple type or to an iid.
  298. PFORMAT_STRING pParamFormat;
  299. const NDR64_POINTER_FORMAT *pPointerFormat ;
  300. PFORMAT_STRING pPointeeFormat;
  301. pParamFormat = (PFORMAT_STRING)Params[n].Type;
  302. pPointerFormat = (const NDR64_POINTER_FORMAT*)pParamFormat;
  303. pPointeeFormat = (PFORMAT_STRING)pPointerFormat->Pointee;
  304. if ( NDR64_IS_BASIC_POINTER(*pParamFormat) ) // not FC64_IP
  305. {
  306. if ( NDR64_SIMPLE_POINTER( pPointerFormat->Flags ) )
  307. {
  308. // Covers things like a unique pointer to a size
  309. // Essentially the same as for the simple ref above.
  310. void * pPointee = AsyncAlloca( pAsyncMsg, 8 );
  311. NDR64_FORMAT_CHAR type = *pPointeeFormat;
  312. // The assignment needs to follow the type.
  313. RpcpMemoryCopy( pPointee, *(void **)pArg,
  314. NDR64_SIMPLE_TYPE_MEMSIZE( type ) );
  315. *(void**)pArg = pPointee;
  316. }
  317. else
  318. {
  319. // has to be the riid case.
  320. // REFIID* comes out as FC64_?P -> FC64_?P -> FC64_STRUCT
  321. if ( NDR64_IS_BASIC_POINTER(*pPointeeFormat) &&
  322. ! NDR64_SIMPLE_POINTER( pPointerFormat->Flags) )
  323. {
  324. if ( *pPointeeFormat == FC64_STRUCT )
  325. {
  326. // one alloc for REFIID and IID itself.
  327. IID** ppIID = (IID**)AsyncAlloca( pAsyncMsg,
  328. sizeof(IID *) + sizeof(IID));
  329. IID* pIID = (IID *)(ppIID + 1);
  330. *ppIID = pIID; //set pointer
  331. RpcpMemoryCopy( pIID, **(IID ***)pArg, sizeof(IID));
  332. *(IID ***)pArg = ppIID;
  333. }
  334. else
  335. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  336. }
  337. else
  338. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  339. }
  340. }
  341. else
  342. {
  343. // has to be the riid case.
  344. // REFIID comes out as FC64_STRUCT
  345. if ( *pParamFormat == FC64_STRUCT )
  346. {
  347. IID *pIID = (IID*)AsyncAlloca( pAsyncMsg, sizeof(IID) );
  348. RpcpMemoryCopy( pIID, *(IID **)pArg, sizeof(IID));
  349. *(IID **)pArg = pIID;
  350. }
  351. else
  352. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  353. }
  354. }
  355. }
  356. }
  357. }
  358. HRESULT
  359. MulNdrpFinishDcomAsyncClientCall(
  360. MIDL_STUBLESS_PROXY_INFO * pProxyInfo,
  361. ulong nProcNum,
  362. NDR_PROC_CONTEXT * pContext ,
  363. void * StartofStack )
  364. {
  365. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  366. RPC_MESSAGE * pRpcMsg;
  367. MIDL_STUB_MESSAGE * pStubMsg;
  368. uchar * pArg;
  369. void * pThis = *(void **)StartofStack;
  370. CLIENT_CALL_RETURN ReturnValue;
  371. NDR64_PARAM_FORMAT * Params;
  372. long NumberParams;
  373. long n;
  374. NDR_ASYNC_CALL_FLAGS CallFlags;
  375. CStdAsyncProxyBuffer * pAsyncPB;
  376. const IID * piid;
  377. HRESULT hr = S_OK;
  378. NDR64_PARAM_FLAGS * pParamFlags;
  379. ReturnValue.Simple = 0;
  380. pAsyncPB = (CStdAsyncProxyBuffer*)
  381. ((uchar*)pThis - offsetof(CStdProxyBuffer, pProxyVtbl));
  382. piid = NdrGetProxyIID( pThis );
  383. hr = MulNdrpSetupFinishClientCall( pAsyncPB,
  384. StartofStack,
  385. *piid,
  386. nProcNum,
  387. pContext );
  388. if ( !SUCCEEDED(hr) )
  389. return hr;
  390. // Note that we cant call to Ndr64ProxyInitialize again.
  391. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)pAsyncPB->CallState.pAsyncMsg;
  392. pRpcMsg = & pAsyncMsg->RpcMsg;
  393. pStubMsg = & pAsyncMsg->StubMsg;
  394. // begin method negotiate to a different syntax than default
  395. if ( pContext->CurrentSyntaxType != pAsyncMsg->SyntaxType )
  396. {
  397. PFORMAT_STRING pFormat;
  398. pContext->CurrentSyntaxType = pAsyncMsg->SyntaxType;
  399. pContext->pSyntaxInfo = pAsyncMsg->ProcContext.pSyntaxInfo;
  400. pFormat = NdrpGetProcString( pContext->pSyntaxInfo,
  401. pContext->CurrentSyntaxType,
  402. nProcNum );
  403. MulNdrpInitializeContextFromProc( pContext->CurrentSyntaxType,
  404. pFormat,
  405. pContext,
  406. (uchar *)StartofStack );
  407. }
  408. // we can directly call to ndr20 finish routine because there is extra setup cost.
  409. if ( pContext->CurrentSyntaxType == XFER_SYNTAX_DCE )
  410. return NdrpFinishDcomAsyncClientCall( pProxyInfo->pStubDesc,
  411. pContext->pProcFormat,
  412. (uchar*)StartofStack );
  413. memcpy ( & pAsyncMsg->ProcContext, pContext, offsetof( NDR_PROC_CONTEXT, AllocateContext ) );
  414. NumberParams = pContext->NumberParams;
  415. CallFlags = pAsyncMsg->Flags;
  416. // Initialize the stack top in the stub msg to be
  417. // this stack, the stack for the finish call parameters.
  418. pAsyncMsg->nFinishParams = NumberParams;
  419. pAsyncMsg->FinishParams = pContext->Params;
  420. Params = (NDR64_PARAM_FORMAT *) pContext->Params;
  421. pStubMsg->StackTop = (uchar*)StartofStack;
  422. pStubMsg->pContext = &pAsyncMsg->ProcContext;
  423. // OLE only code path - single RpcTryExcept.
  424. //
  425. RpcTryExcept
  426. {
  427. BOOL fRaiseExcFlag = FALSE;
  428. if ( CallFlags.ErrorPending )
  429. RpcRaiseException( pAsyncMsg->ErrorCode );
  430. // We need to zero out the [out] parameters and to check
  431. // the ref pointers.
  432. for ( n = 0; n < NumberParams; n++ )
  433. {
  434. pParamFlags = ( NDR64_PARAM_FLAGS * ) & Params[n].Attributes ;
  435. pArg = (uchar *)StartofStack + Params[n].StackOffset;
  436. if ( pParamFlags->IsSimpleRef )
  437. {
  438. // We cannot raise the exception here,
  439. // as some out args may not be zeroed out yet.
  440. if ( ! *((uchar **)pArg) )
  441. {
  442. fRaiseExcFlag = TRUE;
  443. continue;
  444. }
  445. }
  446. // We do the basetype check to cover the
  447. // [out] simple ref to basetype case.
  448. //
  449. if ( pParamFlags->IsPartialIgnore ||
  450. ( ! pParamFlags->IsIn &&
  451. ! pParamFlags->IsReturn ))
  452. {
  453. if ( pParamFlags->IsBasetype )
  454. {
  455. // [out] only arg can only be ref, we checked that above.
  456. NDR64_FORMAT_CHAR type = *(PFORMAT_STRING)Params[n].Type;
  457. MIDL_memset( *(uchar **)pArg,
  458. 0,
  459. (size_t)NDR64_SIMPLE_TYPE_MEMSIZE( type ));
  460. }
  461. else
  462. {
  463. Ndr64ClientZeroOut(
  464. pStubMsg,
  465. Params[n].Type,
  466. *(uchar **)pArg );
  467. }
  468. }
  469. }
  470. if ( fRaiseExcFlag )
  471. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  472. NdrDcomAsyncReceive( pStubMsg );
  473. Ndr64pClientUnMarshal( pStubMsg,
  474. &ReturnValue );
  475. // Pass the HR from the Finish call, if there was any, to the client.
  476. if ( pArg == (uchar *) &ReturnValue )
  477. hr = (HRESULT) ReturnValue.Simple;
  478. }
  479. RpcExcept( 1 )
  480. {
  481. RPC_STATUS ExceptionCode = RpcExceptionCode();
  482. //
  483. // In OLE, since they don't know about error_status_t and wanted to
  484. // reinvent the wheel, check to see if we need to map the exception.
  485. // In either case, set the return value and then try to free the
  486. // [out] params, if required.
  487. //
  488. hr = NdrHrFromWin32Error(ExceptionCode);
  489. //
  490. // Set the Buffer endpoints so the Ndr64Free routines work.
  491. //
  492. Ndr64pDcomClientExceptionHandling ( pStubMsg,
  493. nProcNum,
  494. hr,
  495. &ReturnValue );
  496. }
  497. RpcEndExcept
  498. // Finish
  499. // Cleanup everything. However, don't free pAsyncPB itself.
  500. NdrpAsyncProxyMsgDestructor( pAsyncPB );
  501. // Never addref or release async proxy object, this is app's/PM's job.
  502. return hr;
  503. }
  504. HRESULT RPC_ENTRY
  505. Ndr64DcomAsyncStubCall(
  506. struct IRpcStubBuffer * pThis,
  507. struct IRpcChannelBuffer * pChannel,
  508. PRPC_MESSAGE pRpcMsg,
  509. ulong * pdwStubPhase
  510. )
  511. /*++
  512. Routine Description :
  513. Server Interpreter entry point for DCOM async procs.
  514. This is the Begin entry for channel (regular dispatch entry from stub.c).
  515. The Finish happen when the channel calls stub's Synchronize::Signal method
  516. on the stub object. The call then comes to NdrpAsyncStubSignal later below.
  517. Arguments :
  518. pThis - Object proc's 'this' pointer.
  519. pChannel - Object proc's Channel Buffer.
  520. pRpcMsg - The RPC message.
  521. pdwStubPhase - Used to track the current interpreter's activity.
  522. Return :
  523. Status of S_OK.
  524. Notes :
  525. The engine never calls a signal on behalf of the user, regardless what kind of
  526. errors happen during begin (cannot setup begin, cannot unmarshal, app dies in invoke).
  527. In each of these cases, the engine simply returns an error code to the channel.
  528. The only time the engine would call FreeBuffer on the server is if the engine died
  529. between a successful GetBuffer and the final Send.
  530. Notes on OLE Refcounting.
  531. The model for async_uuid() is that async proxies or stubs are created
  532. with RefCount==1 and should never ever be addrefed by the engine.
  533. What the engine does is only the AsyncMsg clean up when done.
  534. The decision to destroy the AsyncPB or AsyncSB object is
  535. up to the client side PM or channel's SM for the server side.
  536. */
  537. {
  538. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  539. PMIDL_SERVER_INFO pServerInfo;
  540. PMIDL_STUB_DESC pStubDesc;
  541. const SERVER_ROUTINE * DispatchTable;
  542. unsigned long ProcNum;
  543. ushort FormatOffset;
  544. PFORMAT_STRING pFormat;
  545. PMIDL_STUB_MESSAGE pStubMsg;
  546. uchar * pArgBuffer;
  547. uchar * pArg;
  548. uchar ** ppArg;
  549. NDR64_PARAM_FORMAT * Params;
  550. BOOL fBadStubDataException = FALSE;
  551. BOOL fManagerCodeInvoked = FALSE;
  552. unsigned long n, i;
  553. CStdAsyncStubBuffer * pAsyncSB;
  554. HRESULT hr;
  555. const IID * piid = 0;
  556. BOOL fErrorInInvoke = FALSE;
  557. BOOL fRecoverableErrorInInvoke = FALSE;
  558. IUnknown * pSrvObj;
  559. CInterfaceStubVtbl * pStubVTable;
  560. NDR_PROC_CONTEXT ProcContext, *pContext;
  561. NDR64_PROC_FORMAT * pProcFormat;
  562. NDR64_PROC_FLAGS * pNdr64Flags;
  563. NDR64_PARAM_FLAGS * pParamFlags;
  564. SYNTAX_TYPE SyntaxType;
  565. RPC_STATUS ExceptionCode = 0;
  566. MIDL_SYNTAX_INFO * pSyntaxInfo = NULL;
  567. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  568. "marshaling buffer misaligned at server" );
  569. // The channel dispatches to the engine with the sync proc num.
  570. // We need only async proc num at the engine level.
  571. ProcNum = pRpcMsg->ProcNum;
  572. ProcNum = 2 * ProcNum - 3; // Begin method #
  573. pSrvObj = (IUnknown *)((CStdStubBuffer *)pThis)->pvServerObject;
  574. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  575. pStubVTable = (CInterfaceStubVtbl *)
  576. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  577. piid = pStubVTable->header.piid;
  578. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  579. SyntaxType = NdrpGetSyntaxType( pRpcMsg->TransferSyntax );
  580. if ( SyntaxType == XFER_SYNTAX_DCE )
  581. return NdrDcomAsyncStubCall( pThis, pChannel, pRpcMsg, pdwStubPhase );
  582. pStubDesc = pServerInfo->pStubDesc;
  583. pAsyncSB = (CStdAsyncStubBuffer *)
  584. ((uchar *)pThis - offsetof(CStdAsyncStubBuffer,lpVtbl));
  585. for ( i = 0; i < (ulong)pServerInfo->nCount; i++ )
  586. {
  587. if ( SyntaxType == NdrpGetSyntaxType( &pServerInfo->pSyntaxInfo[i].TransferSyntax ) )
  588. {
  589. pSyntaxInfo = &pServerInfo->pSyntaxInfo[i];
  590. break;
  591. }
  592. }
  593. if ( NULL == pSyntaxInfo )
  594. return HRESULT_FROM_WIN32( RPC_S_UNSUPPORTED_TRANS_SYN );
  595. NdrServerSetupNDR64TransferSyntax( ProcNum, pSyntaxInfo, &ProcContext);
  596. pProcFormat = ProcContext.Ndr64Header;
  597. pNdr64Flags = (NDR64_PROC_FLAGS *)&pProcFormat->Flags;
  598. hr = NdrpValidateAsyncStubCall( pAsyncSB );
  599. if ( ! SUCCEEDED(hr) )
  600. return hr;
  601. hr = Ndr64pSetupBeginStubCall( pAsyncSB, &ProcContext, *piid );
  602. if ( FAILED(hr) )
  603. return hr;
  604. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)pAsyncSB->CallState.pAsyncMsg;
  605. pStubMsg = & pAsyncMsg->StubMsg;
  606. // Both rpc runtime and channel require that we use a copy of the rpc message.
  607. RpcpMemoryCopy( & pAsyncMsg->RpcMsg, pRpcMsg, sizeof(RPC_MESSAGE) );
  608. pRpcMsg = & pAsyncMsg->RpcMsg;
  609. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  610. pStubMsg->RpcMsg = pRpcMsg;
  611. pContext = &pAsyncMsg->ProcContext;
  612. // The arg buffer is zeroed out already.
  613. pArgBuffer = pAsyncMsg->ProcContext.StartofStack;
  614. //
  615. // Get new interpreter info.
  616. //
  617. Params = (NDR64_PARAM_FORMAT *) pContext->Params;
  618. pAsyncMsg->nBeginParams = pContext->NumberParams;
  619. pAsyncMsg->BeginParams = pContext->Params;
  620. pAsyncMsg->pThis = pThis;
  621. pAsyncMsg->SyntaxType = pContext->CurrentSyntaxType;
  622. //
  623. // Wrap the unmarshalling and the invoke call in the try block of
  624. // a try-finally. Put the free phase in the associated finally block.
  625. //
  626. // We abstract the level of indirection here.
  627. RpcTryFinally
  628. {
  629. // OLE: put pThis in first dword of stack.
  630. //
  631. ((void **)pArgBuffer)[0] = ((CStdStubBuffer *)pThis)->pvServerObject;
  632. // Initialize the Stub message.
  633. //
  634. NdrStubInitialize( pRpcMsg,
  635. pStubMsg,
  636. pStubDesc,
  637. pChannel );
  638. pStubMsg->pAsyncMsg = (struct _NDR_ASYNC_MESSAGE *) pAsyncMsg;
  639. pStubMsg->pContext = pContext;
  640. pAsyncMsg->BeginParams = Params;
  641. pAsyncMsg->pdwStubPhase = pdwStubPhase; // the phase is STUB_UNMARSHAL
  642. // Raise exceptions after initializing the stub.
  643. if ( pNdr64Flags->UsesFullPtrPackage )
  644. pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
  645. else
  646. pStubMsg->FullPtrXlatTables = 0;
  647. //
  648. // Set StackTop AFTER the initialize call, since it zeros the field
  649. // out.
  650. //
  651. pStubMsg->StackTop = pArgBuffer;
  652. // StubPhase set up by invoke is STUB_UNMARSHAL
  653. RpcTryExcept
  654. {
  655. NDR_ASSERT( pContext->StartofStack == pArgBuffer, "startofstack is not set" );
  656. Ndr64pServerUnMarshal ( pStubMsg );
  657. // Last ditch checks.
  658. if ( pRpcMsg->BufferLength <
  659. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  660. {
  661. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  662. }
  663. }
  664. RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
  665. {
  666. // Filter set in rpcndr.h to catch one of the following
  667. // STATUS_ACCESS_VIOLATION
  668. // STATUS_DATATYPE_MISALIGNMENT
  669. // RPC_X_BAD_STUB_DATA
  670. ExceptionCode = RpcExceptionCode();
  671. fBadStubDataException = TRUE;
  672. if ( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  673. ExceptionCode = RPC_X_BAD_STUB_DATA;
  674. pAsyncMsg->Flags.ErrorPending = 1;
  675. pAsyncMsg->Flags.BadStubData = 1;
  676. pAsyncMsg->ErrorCode = ExceptionCode;
  677. pAsyncSB->CallState.Flags.BeginError = 1;
  678. pAsyncSB->CallState.Hr = NdrHrFromWin32Error( ExceptionCode);
  679. NdrpFreeMemoryList( pStubMsg );
  680. RpcRaiseException( ExceptionCode );
  681. }
  682. RpcEndExcept
  683. //
  684. // Do [out] initialization before the invoke.
  685. //
  686. for ( n = 0; n < pContext->NumberParams; n++ )
  687. {
  688. pParamFlags = ( NDR64_PARAM_FLAGS * ) & ( Params[n].Attributes );
  689. if ( pParamFlags->IsIn ||
  690. pParamFlags->IsReturn )
  691. continue;
  692. // This is a Begin call, there cannot be any [out] only args.
  693. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  694. }
  695. //
  696. // OLE interfaces use pdwStubPhase in the exception filter.
  697. // See CStdStubBuffer_Invoke in stub.c.
  698. //
  699. *pdwStubPhase = STUB_CALL_SERVER;
  700. // We need to catch exception in the manager code separately
  701. // as the model implies that there will be no other call from
  702. // the server app to clean up.
  703. pAsyncSB->CallState.Flags.BeginDone = 1;
  704. RpcTryExcept
  705. {
  706. //
  707. // Check for a thunk. Compiler does all the setup for us.
  708. //
  709. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ ProcNum ] )
  710. {
  711. fManagerCodeInvoked = TRUE;
  712. pServerInfo->ThunkTable[ ProcNum ]( pStubMsg );
  713. }
  714. else
  715. {
  716. //
  717. // Note that this ArgNum is not the number of arguments declared
  718. // in the function we called, but really the number of
  719. // REGISTER_TYPEs occupied by the arguments to a function.
  720. //
  721. long ArgNum;
  722. MANAGER_FUNCTION pFunc;
  723. REGISTER_TYPE ReturnValue;
  724. pFunc = (MANAGER_FUNCTION) DispatchTable[ ProcNum ];
  725. ArgNum = (long)pProcFormat->StackSize / sizeof(REGISTER_TYPE);
  726. //
  727. // The StackSize includes the size of the return. If we want
  728. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  729. // by 1 when there is a return value AND the current ArgNum count
  730. // is greater than 0.
  731. //
  732. if ( ArgNum && pNdr64Flags->HasReturn )
  733. ArgNum--;
  734. // Being here means that we can expect results. Note that the user
  735. // can call RpcCompleteCall from inside of the manager code.
  736. fManagerCodeInvoked = TRUE;
  737. ReturnValue = Invoke( pFunc,
  738. (REGISTER_TYPE *)pArgBuffer,
  739. #if defined(_WIN64)
  740. pProcFormat->FloatDoubleMask,
  741. #endif
  742. ArgNum);
  743. if ( pNdr64Flags->HasReturn )
  744. {
  745. // Pass the app's HR from Begin call to the channel.
  746. (*pfnDcomChannelSetHResult)( pRpcMsg,
  747. NULL, // reserved
  748. (HRESULT) ReturnValue);
  749. }
  750. // We are discarding the return value as it is not the real one.
  751. }
  752. }
  753. RpcExcept( 1 )
  754. {
  755. fErrorInInvoke = TRUE;
  756. pAsyncMsg->Flags.ErrorPending = 1;
  757. pAsyncMsg->ErrorCode = RpcExceptionCode();
  758. pAsyncSB->CallState.Flags.BeginError = 1;
  759. pAsyncSB->CallState.Hr = NdrHrFromWin32Error( RpcExceptionCode());
  760. }
  761. RpcEndExcept
  762. // Done with invoking Begin
  763. }
  764. RpcFinally
  765. {
  766. if ( !fManagerCodeInvoked )
  767. {
  768. // Failed without invoking Begin - return an error. Remember the error.
  769. if ( fBadStubDataException )
  770. pAsyncMsg->ErrorCode = RPC_X_BAD_STUB_DATA;
  771. pAsyncSB->CallState.Flags.BeginDone = 1;
  772. hr = pAsyncSB->CallState.Hr;
  773. }
  774. else // fManagerCodeInvoked
  775. {
  776. hr = S_OK;
  777. if ( fErrorInInvoke )
  778. hr = pAsyncSB->CallState.Hr;
  779. }
  780. }
  781. RpcEndFinally
  782. return hr;
  783. }
  784. void
  785. Ndr64pCloneInOutStubArgs(
  786. NDR_DCOM_ASYNC_MESSAGE * pAsyncMsg )
  787. /*
  788. Walk the second stack looking for an in-out argument.
  789. For each one, find the corresponding in-out atgument from the first stack
  790. and clone it to the second stack.
  791. Note, we need to do it only on the server side where we preserver the first
  792. stack, the dispatch buffer and all the arguments from the first stack.
  793. On the client, this is the app's task to supply meaningful in-out arguments
  794. for the second stack.
  795. */
  796. {
  797. REGISTER_TYPE * pBeginStack = (REGISTER_TYPE *)pAsyncMsg->BeginStack;
  798. REGISTER_TYPE * pFinishStack = (REGISTER_TYPE *)pAsyncMsg->FinishStack;
  799. NDR64_PARAM_FORMAT * BeginParams = ( NDR64_PARAM_FORMAT *) pAsyncMsg->BeginParams;
  800. int BeginNumberParams = pAsyncMsg->nBeginParams;
  801. NDR64_PARAM_FLAGS * pParamFlags, * pBeginParamFlags;
  802. NDR64_PARAM_FORMAT * FinishParams = ( NDR64_PARAM_FORMAT *) pAsyncMsg->FinishParams;
  803. int FinishNumberParams = pAsyncMsg->nFinishParams;
  804. int FirstIO = 0;
  805. int n;
  806. for ( n = 0; n < FinishNumberParams; n++ )
  807. {
  808. pParamFlags = ( NDR64_PARAM_FLAGS *) & FinishParams[n].Attributes;
  809. // Find in-out arg that needs cloning.
  810. if ( pParamFlags->IsIn &&
  811. pParamFlags->IsOut )
  812. {
  813. // Find the first IO on the first stack
  814. while ( FirstIO < BeginNumberParams )
  815. {
  816. pBeginParamFlags = ( NDR64_PARAM_FLAGS *) & BeginParams[FirstIO].Attributes;
  817. if ( pBeginParamFlags->IsIn &&
  818. pBeginParamFlags->IsOut )
  819. {
  820. break;
  821. }
  822. FirstIO++;
  823. }
  824. if ( BeginNumberParams <= FirstIO )
  825. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  826. // Clone it to the second stack
  827. pFinishStack[ FinishParams[n].StackOffset / sizeof(REGISTER_TYPE) ] =
  828. pBeginStack[ BeginParams[ FirstIO ].StackOffset / sizeof(REGISTER_TYPE) ];
  829. FirstIO++;
  830. }
  831. }
  832. }
  833. HRESULT
  834. Ndr64pCompleteDcomAsyncStubCall(
  835. CStdAsyncStubBuffer * pAsyncSB
  836. )
  837. /*++
  838. Routine Description :
  839. Complete an async call on the server side.
  840. Arguments :
  841. AsyncHandle - raw or object handle (if pointer) as appropriate,
  842. pAsyncMsg - pointer to async msg structure,
  843. pReturnValue - from the user to pass back to caller.
  844. Return :
  845. Status of S_OK.
  846. --*/
  847. {
  848. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  849. PMIDL_SERVER_INFO pServerInfo;
  850. const SERVER_ROUTINE * DispatchTable; // should be the same
  851. unsigned long ProcNum; // should be 1+
  852. RPC_MESSAGE * pRpcMsg;
  853. MIDL_STUB_MESSAGE * pStubMsg;
  854. NDR64_PARAM_FORMAT * Params; // Finish params
  855. uchar * pArgBuffer; // new stack
  856. // MZ, BUG BUG, Fix after ship
  857. // ulong * pdwStubPhase;
  858. uchar * pArg;
  859. long NumberParams;
  860. long n;
  861. NDR64_PROC_FORMAT * pProcHeader;
  862. IUnknown * pSrvObj;
  863. CInterfaceStubVtbl * pStubVTable;
  864. void * pThis;
  865. HRESULT hr;
  866. const IID * piid; // should be the same
  867. BOOL fManagerCodeInvoked = FALSE;
  868. BOOL fErrorInInvoke = FALSE;
  869. RPC_STATUS ExceptionCode = 0;
  870. boolean fParamsFreed = FALSE;
  871. NDR64_PARAM_FLAGS * pParamFlags;
  872. NDR64_PROC_FLAGS * pNdr64Flags;
  873. NDR_PROC_CONTEXT * pContext = NULL;
  874. // We validated both the stub and the async context in the signal call.
  875. // We validated the pAsyncSB in the Signal call.
  876. // Do additional checks.
  877. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)pAsyncSB->CallState.pAsyncMsg;
  878. pThis = pAsyncMsg->pThis;
  879. // See if channel calls on the right stub
  880. if ( & pAsyncSB->lpVtbl != pThis)
  881. return E_INVALIDARG;
  882. pRpcMsg = & pAsyncMsg->RpcMsg;
  883. pStubMsg = & pAsyncMsg->StubMsg;
  884. pContext = (NDR_PROC_CONTEXT *)pStubMsg->pContext ;
  885. // We have preserved the sync proc num that the channel used.
  886. // We need only async proc num at the engine level.
  887. //
  888. ProcNum = pRpcMsg->ProcNum;
  889. ProcNum = 2 * ProcNum - 3 + 1; // Finish method #
  890. pSrvObj = (IUnknown *)((CStdStubBuffer *)pThis)->pvServerObject;
  891. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  892. pStubVTable = (CInterfaceStubVtbl *)
  893. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  894. piid = pStubVTable->header.piid;
  895. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  896. // The proc header has a fixed layout now.
  897. pProcHeader =
  898. (PNDR64_PROC_FORMAT)NdrpGetProcString( pAsyncMsg->ProcContext.pSyntaxInfo,
  899. XFER_SYNTAX_NDR64,
  900. ProcNum );
  901. pNdr64Flags = ( NDR64_PROC_FLAGS * )&pProcHeader->Flags;
  902. // Validate and setup for finish.
  903. hr = NdrpSetupFinishStubCall( pAsyncSB,
  904. (ushort )pProcHeader->StackSize,
  905. *piid );
  906. if ( hr )
  907. return hr;
  908. // The arg buffer is zeroed out already. Note, this is the second stack.
  909. pArgBuffer = pAsyncMsg->ProcContext.StartofStack;
  910. pStubMsg->StackTop = pArgBuffer;
  911. // MZ, BUG BUG, fix after ship
  912. // pdwStubPhase = pAsyncMsg->pdwStubPhase;
  913. //
  914. // Get new interpreter info.
  915. //
  916. NumberParams = pProcHeader->NumberOfParams;
  917. Params = (NDR64_PARAM_FORMAT *)(((PFORMAT_STRING)( pProcHeader + 1 )) + pProcHeader->ExtensionSize );
  918. pAsyncMsg->nFinishParams = pContext->NumberParams = NumberParams;
  919. pAsyncMsg->FinishParams = pContext->Params = Params;
  920. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  921. // a try-finally. Put the free phase in the associated finally block.
  922. //
  923. RpcTryFinally
  924. {
  925. if ( pAsyncMsg->Flags.ErrorPending )
  926. RpcRaiseException( pAsyncMsg->ErrorCode );
  927. // Initialize the args of the new stack.
  928. // OLE: put pThis in first dword of stack.
  929. //
  930. ((void **)pArgBuffer)[0] = ((CStdStubBuffer *)pThis)->pvServerObject;
  931. //
  932. // Do [out] initialization before invoking Finish
  933. //
  934. Ndr64pCloneInOutStubArgs( pAsyncMsg );
  935. Ndr64pServerOutInit( pStubMsg );
  936. //
  937. // OLE interfaces use pdwStubPhase in the exception filter.
  938. // See CStdStubBuffer_Invoke in stub.c.
  939. //
  940. // MZ, BUG BUG, fix after ship
  941. // *pdwStubPhase = STUB_CALL_SERVER;
  942. // We need to catch exception in the manager code separately
  943. // as the model implies that there will be no other call from
  944. // the server app to clean up.
  945. RpcTryExcept
  946. {
  947. //
  948. // Check for a thunk. Compiler does all the setup for us.
  949. //
  950. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  951. {
  952. fManagerCodeInvoked = TRUE;
  953. pServerInfo->ThunkTable[ProcNum]( pStubMsg );
  954. }
  955. else
  956. {
  957. //
  958. // Note that this ArgNum is not the number of arguments declared
  959. // in the function we called, but really the number of
  960. // REGISTER_TYPEs occupied by the arguments to a function.
  961. //
  962. long ArgNum;
  963. MANAGER_FUNCTION pFunc;
  964. REGISTER_TYPE ReturnValue;
  965. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  966. ArgNum = (long)pProcHeader->StackSize / sizeof(REGISTER_TYPE);
  967. //
  968. // The StackSize includes the size of the return. If we want
  969. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  970. // by 1 when there is a return value AND the current ArgNum count
  971. // is greater than 0.
  972. //
  973. if ( ArgNum && pNdr64Flags->HasReturn )
  974. ArgNum--;
  975. fManagerCodeInvoked = TRUE;
  976. ReturnValue = Invoke( pFunc,
  977. (REGISTER_TYPE *)pArgBuffer,
  978. #if defined(_WIN64)
  979. pProcHeader->FloatDoubleMask,
  980. #endif
  981. ArgNum);
  982. // This is the return value that should be marshaled back.
  983. if ( pNdr64Flags->HasReturn )
  984. {
  985. ((REGISTER_TYPE *)pArgBuffer)[ArgNum] = ReturnValue;
  986. // Pass the app's HR to the channel.
  987. (*pfnDcomChannelSetHResult)( pRpcMsg,
  988. NULL, // reserved
  989. (HRESULT) ReturnValue);
  990. }
  991. }
  992. }
  993. RpcExcept( 1 )
  994. {
  995. pAsyncMsg->Flags.ErrorPending = 1;
  996. pAsyncMsg->ErrorCode = RpcExceptionCode();
  997. fErrorInInvoke = TRUE;
  998. }
  999. RpcEndExcept
  1000. // Done with invoking Finish
  1001. if ( pAsyncMsg->Flags.ErrorPending )
  1002. RpcRaiseException( pAsyncMsg->ErrorCode );
  1003. // MZ, BUG BUG, fix after ship
  1004. // *pdwStubPhase = STUB_MARSHAL;
  1005. //
  1006. // Buffer size pass.
  1007. //
  1008. pStubMsg->BufferLength = pProcHeader->ConstantServerBufferSize;
  1009. if ( pNdr64Flags->ServerMustSize )
  1010. {
  1011. Ndr64pSizing( pStubMsg,
  1012. FALSE ); //server
  1013. }
  1014. // Get buffer.
  1015. NdrStubGetBuffer( (IRpcStubBuffer *)pAsyncMsg->pThis,
  1016. pStubMsg->pRpcChannelBuffer,
  1017. pStubMsg );
  1018. // Marshalling pass.
  1019. Ndr64pServerMarshal ( pStubMsg );
  1020. if ( pRpcMsg->BufferLength <
  1021. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  1022. {
  1023. NDR_ASSERT( 0, "Ndr64StubCall2 marshal: buffer overflow!" );
  1024. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  1025. }
  1026. pRpcMsg->BufferLength = (ulong)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer);
  1027. // We don't drop to the runtime like for synchronous calls,
  1028. // we send the last buffer explicitly.
  1029. fParamsFreed = TRUE;
  1030. // see comment on async.cxx on why we call this twice.
  1031. Ndr64pAsyncDCOMFreeParams( pAsyncMsg );
  1032. NdrpDcomAsyncSend( pStubMsg,
  1033. 0 ); // server doesn't pass pSynchronize back to channel.
  1034. }
  1035. RpcFinally
  1036. {
  1037. // Don't free parameters if we died because of bad stub data in unmarshaling.
  1038. if ( ! pAsyncMsg->Flags.BadStubData && !fParamsFreed)
  1039. {
  1040. Ndr64pAsyncDCOMFreeParams( pAsyncMsg );
  1041. }
  1042. if ( pAsyncMsg->Flags.ErrorPending )
  1043. hr = NdrHrFromWin32Error( pAsyncMsg->ErrorCode );
  1044. else
  1045. hr = S_OK;
  1046. // If we are here, error or not, it means that we can (and need to) dispose of
  1047. // the async context information
  1048. NdrpAsyncStubMsgDestructor( pAsyncSB );
  1049. // The engine never addrefs or releases the call object.
  1050. }
  1051. RpcEndFinally
  1052. return hr;
  1053. }
  1054. HRESULT
  1055. Ndr64pSetupBeginStubCall(
  1056. CStdAsyncStubBuffer * pAsyncSB,
  1057. NDR_PROC_CONTEXT * pContext,
  1058. REFIID riid )
  1059. /*
  1060. This method creates and initializes async msg.
  1061. */
  1062. {
  1063. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1064. HRESULT hr = S_OK;
  1065. if ( pAsyncSB->CallState.pAsyncMsg != 0 ||
  1066. pAsyncSB->CallState.Flags.BeginStarted )
  1067. hr = E_FAIL;
  1068. else
  1069. {
  1070. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)
  1071. I_RpcBCacheAllocate( sizeof( NDR_DCOM_ASYNC_MESSAGE) +
  1072. pContext->StackSize + NDR_ASYNC_GUARD_SIZE );
  1073. if ( ! pAsyncMsg )
  1074. hr = E_OUTOFMEMORY;
  1075. }
  1076. if ( ! SUCCEEDED(hr) )
  1077. {
  1078. // The stub never signals.
  1079. pAsyncSB->CallState.Flags.BeginError = 1;
  1080. pAsyncSB->CallState.Hr = hr;
  1081. return hr;
  1082. }
  1083. // Initialize the async message properly
  1084. MIDL_memset( pAsyncMsg, 0x0, sizeof( NDR_DCOM_ASYNC_MESSAGE) );
  1085. pAsyncMsg->Signature = NDR_DCOM_ASYNC_SIGNATURE;
  1086. pAsyncMsg->Version = NDR_DCOM_ASYNC_VERSION;
  1087. pAsyncMsg->SyntaxType = XFER_SYNTAX_NDR64;
  1088. memcpy( &pAsyncMsg->ProcContext, pContext, offsetof( NDR_PROC_CONTEXT, AllocateContext ) );
  1089. NdrpAllocaInit( &pAsyncMsg->ProcContext.AllocateContext );
  1090. pAsyncMsg->ProcContext.StartofStack = (uchar *) & pAsyncMsg->AppStack;
  1091. pAsyncMsg->BeginStack = (uchar *) & pAsyncMsg->AppStack;
  1092. pAsyncMsg->BeginStackSize = pContext->StackSize;
  1093. pAsyncMsg->StubPhase = STUB_UNMARSHAL;
  1094. pAsyncMsg->StubMsg.pContext = &pAsyncMsg->ProcContext;
  1095. // Server: zero out stack for allocs.
  1096. MIDL_memset( & pAsyncMsg->AppStack, 0x0, pContext->StackSize );
  1097. MIDL_memset( ((char *)& pAsyncMsg->AppStack) + pContext->StackSize,
  1098. 0x71,
  1099. NDR_ASYNC_GUARD_SIZE );
  1100. pAsyncSB->CallState.pAsyncMsg = pAsyncMsg;
  1101. pAsyncSB->CallState.Flags.BeginStarted = 1;
  1102. pAsyncMsg->pAsyncSB = pAsyncSB;
  1103. return S_OK;
  1104. }
  1105. HRESULT
  1106. MulNdrpSetupFinishClientCall(
  1107. CStdAsyncProxyBuffer * pAsyncPB,
  1108. void * StartofStack,
  1109. REFIID riid,
  1110. unsigned long FinishProcNum,
  1111. NDR_PROC_CONTEXT * pContext )
  1112. /*
  1113. This method creates and initializes async msg.
  1114. */
  1115. {
  1116. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1117. HRESULT hr = S_OK;
  1118. hr = NdrpValidateAsyncProxyCall( pAsyncPB );
  1119. if ( ! SUCCEEDED(hr) )
  1120. return hr;
  1121. if ( !pAsyncPB->CallState.Flags.BeginStarted ||
  1122. !pAsyncPB->CallState.Flags.BeginDone ||
  1123. pAsyncPB->CallState.Flags.FinishStarted )
  1124. return E_FAIL;
  1125. pAsyncMsg =
  1126. (NDR_DCOM_ASYNC_MESSAGE*)pAsyncPB->CallState.pAsyncMsg;
  1127. hr = NdrpValidateDcomAsyncMsg( pAsyncMsg );
  1128. if ( ! SUCCEEDED(hr) )
  1129. return hr;
  1130. if ( (FinishProcNum + 3)/2 != (pAsyncMsg->RpcMsg.ProcNum & 0x7fff) )
  1131. return E_FAIL;
  1132. // return S_FALSE in SYNTAX_DCE: we'll call into
  1133. // NdrpDcomFinishClientCall
  1134. if ( pAsyncMsg->SyntaxType == XFER_SYNTAX_DCE )
  1135. return S_OK;
  1136. pAsyncMsg->ProcContext.StartofStack = (uchar *) StartofStack;
  1137. pAsyncMsg->FinishStack = (uchar *) StartofStack;
  1138. pAsyncMsg->FinishStackSize = pContext->StackSize;
  1139. pAsyncMsg->StubPhase = NDR_ASYNC_PREP_PHASE;
  1140. // Dont allocate or copy the new stack anywhere.
  1141. pAsyncPB->CallState.Flags.FinishStarted = 1;
  1142. return S_OK;
  1143. }
  1144. HRESULT
  1145. MulNdrpSetupBeginClientCall(
  1146. CStdAsyncProxyBuffer * pAsyncPB,
  1147. void * StartofStack,
  1148. NDR_PROC_CONTEXT * pContext,
  1149. REFIID riid )
  1150. /*
  1151. This method creates and initializes async msg.
  1152. */
  1153. {
  1154. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  1155. HRESULT hr = S_OK;
  1156. hr = NdrpValidateAsyncProxyCall( pAsyncPB );
  1157. if ( ! SUCCEEDED(hr) )
  1158. return hr;
  1159. if ( pAsyncPB->CallState.pAsyncMsg != 0 ||
  1160. pAsyncPB->CallState.Flags.BeginStarted )
  1161. return E_FAIL;
  1162. // Do this first to simplify error conditions.
  1163. pAsyncMsg = (NDR_DCOM_ASYNC_MESSAGE*)
  1164. I_RpcBCacheAllocate( sizeof(NDR_DCOM_ASYNC_MESSAGE) +
  1165. pContext->StackSize + NDR_ASYNC_GUARD_SIZE );
  1166. if ( ! pAsyncMsg )
  1167. {
  1168. NdrpAsyncProxySignal( pAsyncPB );
  1169. return E_OUTOFMEMORY;
  1170. }
  1171. // Initialize the async message properly
  1172. MIDL_memset( pAsyncMsg, 0x0, sizeof( NDR_DCOM_ASYNC_MESSAGE) );
  1173. pAsyncMsg->Signature = NDR_DCOM_ASYNC_SIGNATURE;
  1174. pAsyncMsg->Version = NDR_DCOM_ASYNC_VERSION;
  1175. pAsyncMsg->ProcContext.StartofStack = (uchar *) & pAsyncMsg->AppStack;
  1176. pAsyncMsg->BeginStack = (uchar *) & pAsyncMsg->AppStack;
  1177. pAsyncMsg->BeginStackSize = pContext->StackSize;
  1178. pAsyncMsg->StubPhase = NDR_ASYNC_PREP_PHASE;
  1179. RpcpMemoryCopy( & pAsyncMsg->ProcContext, pContext, offsetof( NDR_PROC_CONTEXT, AllocateContext ) );
  1180. NdrpAllocaInit( &pAsyncMsg->ProcContext.AllocateContext );
  1181. // Client: copy stack from the app's request call.
  1182. RpcpMemoryCopy( & pAsyncMsg->AppStack, StartofStack, pContext->StackSize );
  1183. MIDL_memset( ((char *)& pAsyncMsg->AppStack) + pContext->StackSize,
  1184. 0x71,
  1185. NDR_ASYNC_GUARD_SIZE );
  1186. pAsyncMsg->pAsyncPB = pAsyncPB;
  1187. pAsyncMsg->StubMsg.pContext = &pAsyncMsg->ProcContext;
  1188. pAsyncPB->CallState.Flags.BeginStarted = 1;
  1189. pAsyncPB->CallState.pAsyncMsg = pAsyncMsg;
  1190. return S_OK;
  1191. }