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

1500 lines
45 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1996-2000 Microsoft Corporation
  3. Module Name :
  4. async.c
  5. Abstract :
  6. This file contains the ndr async implementation.
  7. Author :
  8. Ryszard K. Kott (ryszardk) Nov 1996
  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 "hndl.h"
  17. #include "interp.h"
  18. #include "interp2.h"
  19. #include "pipendr.h"
  20. #include "mulsyntx.h"
  21. #include "asyncndr.h"
  22. #include "attack.h"
  23. #include <stdarg.h>
  24. #pragma code_seg(".orpc")
  25. #ifdef _PPC_
  26. #error PPC code has been removed
  27. #endif
  28. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  29. NdrAsyncClientCall(
  30. PMIDL_STUB_DESC pStubDescriptor,
  31. PFORMAT_STRING pFormat,
  32. ...
  33. )
  34. /*
  35. This entry is used for raw rpc only.
  36. No support for OLE [async] attribute anymore.
  37. */
  38. {
  39. va_list ArgList;
  40. unsigned char * StartofStack;
  41. CLIENT_CALL_RETURN Ret;
  42. //
  43. // Get address of argument to this function following pFormat. This
  44. // is the address of the address of the first argument of the function
  45. // calling this function.
  46. // Then get the address of the stack where the parameters are.
  47. //
  48. RPC_ASYNC_HANDLE AsyncHandle;
  49. PNDR_ASYNC_MESSAGE pAsyncMsg;
  50. RPC_MESSAGE * pRpcMsg;
  51. MIDL_STUB_MESSAGE * pStubMsg;
  52. ulong ProcNum, RpcFlags;
  53. handle_t Handle;
  54. uchar HandleType;
  55. INTERPRETER_FLAGS OldOiFlags;
  56. INTERPRETER_OPT_FLAGS NewOiFlags;
  57. PPARAM_DESCRIPTION Params;
  58. RPC_STATUS Status;
  59. NDR_PROC_CONTEXT *pContext;
  60. Ret.Simple = 0;
  61. INIT_ARG( ArgList, pFormat);
  62. GET_FIRST_IN_ARG(ArgList);
  63. StartofStack = (uchar *) GET_STACK_START(ArgList);
  64. pAsyncMsg = (NDR_ASYNC_MESSAGE*) I_RpcBCacheAllocate( sizeof( NDR_ASYNC_MESSAGE) );
  65. if ( ! pAsyncMsg )
  66. Status = RPC_S_OUT_OF_MEMORY;
  67. else
  68. {
  69. memset( pAsyncMsg, 0, sizeof( NDR_ASYNC_MESSAGE ) );
  70. ProcNum = MulNdrpInitializeContextFromProc(
  71. XFER_SYNTAX_DCE,
  72. pFormat,
  73. &pAsyncMsg->ProcContext,
  74. NULL ); // server StartofStack
  75. Status = NdrpInitializeAsyncMsg(
  76. StartofStack,
  77. pAsyncMsg );
  78. }
  79. if ( Status )
  80. {
  81. // if something is wrong during setup, we need to cleanup
  82. // immediately. We have to process format string here explicitly
  83. NDR_PROC_CONTEXT TempContext;
  84. MIDL_STUB_MESSAGE StubMsgTemp;
  85. ProcNum = MulNdrpInitializeContextFromProc(
  86. XFER_SYNTAX_DCE,
  87. pFormat,
  88. &TempContext,
  89. NULL ); // server StartofStack
  90. OldOiFlags = TempContext.NdrInfo.InterpreterFlags;
  91. if ( OldOiFlags.HasCommOrFault )
  92. {
  93. // It's easier to map the error here than to go through the error
  94. // recovery and normal cleanup without valid handle etc.
  95. StubMsgTemp.StubDesc = pStubDescriptor;
  96. StubMsgTemp.StackTop = StartofStack;
  97. NdrClientMapCommFault( & StubMsgTemp,
  98. ProcNum,
  99. Status,
  100. (ULONG_PTR*) &Ret.Simple );
  101. return Ret;
  102. }
  103. else
  104. RpcRaiseException( Status );
  105. }
  106. pContext = &pAsyncMsg->ProcContext;
  107. HandleType = pContext->HandleType;
  108. NewOiFlags = pContext->NdrInfo.pProcDesc->Oi2Flags;
  109. OldOiFlags = pContext->NdrInfo.InterpreterFlags;
  110. Params = (PARAM_DESCRIPTION *)pContext->Params;
  111. // We need to switch to our copy of the stack everywhere, including pStubMsg.
  112. StartofStack = pAsyncMsg->ProcContext.StartofStack;
  113. // We abstract the level of indirection here.
  114. AsyncHandle = pAsyncMsg->AsyncHandle;
  115. pRpcMsg = & pAsyncMsg->RpcMsg;
  116. pStubMsg = & pAsyncMsg->StubMsg;
  117. //
  118. // Set Params and NumberParams before a call to initialization.
  119. //
  120. // Wrap everything in a try-finally pair. The finally clause does the
  121. // required freeing of resources (RpcBuffer and Full ptr package).
  122. //
  123. RpcTryFinally
  124. {
  125. // Use a nested try-except pair to support [comm_status][fault_status].
  126. //
  127. RpcTryExcept
  128. {
  129. BOOL fRaiseExcFlag;
  130. NdrClientInitializeNew( pRpcMsg,
  131. pStubMsg,
  132. pStubDescriptor,
  133. (uint) ProcNum );
  134. if ( HandleType )
  135. {
  136. //
  137. // We have an implicit handle.
  138. //
  139. Handle = ImplicitBindHandleMgr( pStubDescriptor,
  140. HandleType,
  141. &pContext->SavedGenericHandle);
  142. }
  143. else
  144. {
  145. Handle = ExplicitBindHandleMgr( pStubDescriptor,
  146. StartofStack,
  147. (PFORMAT_STRING)pContext->pHandleFormatSave,
  148. &pContext->SavedGenericHandle );
  149. }
  150. pStubMsg->pAsyncMsg = pAsyncMsg;
  151. NdrpClientInit( pStubMsg,
  152. NULL ); // return value
  153. //
  154. // Skip buffer size pass if possible.
  155. //
  156. if ( NewOiFlags.ClientMustSize )
  157. {
  158. NdrpSizing( pStubMsg,
  159. TRUE ); // isclient
  160. }
  161. pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  162. if ( NewOiFlags.HasPipes )
  163. NdrGetPipeBuffer( pStubMsg,
  164. pStubMsg->BufferLength,
  165. Handle );
  166. else
  167. NdrGetBuffer( pStubMsg,
  168. pStubMsg->BufferLength,
  169. Handle );
  170. NDR_ASSERT( pStubMsg->fBufferValid, "Invalid buffer" );
  171. // Let runtime associate async handle with the call.
  172. NdrpRegisterAsyncHandle( pStubMsg, AsyncHandle );
  173. pAsyncMsg->StubPhase = NDR_ASYNC_SET_PHASE;
  174. //
  175. // ----------------------------------------------------------
  176. // Marshall Pass.
  177. // ----------------------------------------------------------
  178. //
  179. NdrpClientMarshal( pStubMsg,
  180. FALSE ); // IsObject
  181. pAsyncMsg->StubPhase = NDR_ASYNC_CALL_PHASE;
  182. NdrAsyncSend( pStubMsg,
  183. NewOiFlags.HasPipes && pContext->pPipeDesc->InPipes );
  184. pAsyncMsg->Flags.ValidCallPending = 1;
  185. }
  186. RpcExcept( OldOiFlags.HasCommOrFault )
  187. {
  188. RPC_STATUS ExceptionCode = RpcExceptionCode();
  189. // Actually dismantle the call.
  190. // This is a request call and there is nothing left at the runtime.
  191. pAsyncMsg->StubPhase = NDR_ASYNC_ERROR_PHASE;
  192. NdrClientMapCommFault( pStubMsg,
  193. ProcNum,
  194. ExceptionCode,
  195. (ULONG_PTR*) &Ret.Simple );
  196. }
  197. RpcEndExcept
  198. }
  199. RpcFinally
  200. {
  201. if ( pAsyncMsg->Flags.ValidCallPending )
  202. {
  203. if ( NewOiFlags.HasPipes )
  204. {
  205. NdrMarkNextActivePipe( pContext->pPipeDesc );
  206. pContext->pPipeDesc->Flags.NoBufferCallPending = 1;
  207. }
  208. }
  209. else
  210. {
  211. // Cleanup everything but the user's handle.
  212. NdrpFreeAsyncMsg( pAsyncMsg );
  213. AsyncHandle->StubInfo = 0;
  214. }
  215. InterlockedDecrement( & AsyncHandle->Lock );
  216. }
  217. RpcEndFinally
  218. return Ret;
  219. }
  220. RPC_STATUS
  221. NdrpCompleteAsyncClientCall(
  222. RPC_ASYNC_HANDLE AsyncHandle,
  223. PNDR_ASYNC_MESSAGE pAsyncMsg,
  224. void * pReturnValue
  225. )
  226. {
  227. RPC_MESSAGE * pRpcMsg = & pAsyncMsg->RpcMsg;
  228. MIDL_STUB_MESSAGE * pStubMsg = & pAsyncMsg->StubMsg;
  229. PFORMAT_STRING pFormatParam;
  230. NDR_PROC_CONTEXT * pContext = &pAsyncMsg->ProcContext;
  231. NDR_PROC_INFO * pNdrInfo = &pContext->NdrInfo;
  232. INTERPRETER_FLAGS OldOiFlags = pNdrInfo->InterpreterFlags;
  233. INTERPRETER_OPT_FLAGS NewOiFlags = pNdrInfo->pProcDesc->Oi2Flags;
  234. PPARAM_DESCRIPTION Params = (PPARAM_DESCRIPTION )pContext->Params;
  235. uchar * StartofStack = pContext->StartofStack ;
  236. PMIDL_STUB_DESC pStubDescriptor = pStubMsg->StubDesc;
  237. ulong RpcFlags = pRpcMsg->RpcFlags;
  238. ULONG_PTR RetVal = 0;
  239. long NumberParams = pContext->NumberParams;
  240. long n;
  241. NDR_ASYNC_CALL_FLAGS CallFlags = pAsyncMsg->Flags;
  242. RpcTryFinally
  243. {
  244. // Use a nested try-except pair to support [comm_status][fault_status].
  245. //
  246. RpcTryExcept
  247. {
  248. if ( ! CallFlags.ValidCallPending )
  249. RpcRaiseException( RPC_S_INVALID_ASYNC_HANDLE );
  250. CallFlags.ValidCallPending = 0;
  251. // Non-pipe case or after pipe args case.
  252. if ( NewOiFlags.HasPipes )
  253. NdrIsAppDoneWithPipes( pContext->pPipeDesc );
  254. NdrLastAsyncReceive( pStubMsg );
  255. //
  256. // ----------------------------------------------------------
  257. // Unmarshall Pass.
  258. // ----------------------------------------------------------
  259. //
  260. NdrpClientUnMarshal( pStubMsg,
  261. (CLIENT_CALL_RETURN *)pReturnValue );
  262. }
  263. RpcExcept( OldOiFlags.HasCommOrFault )
  264. {
  265. RPC_STATUS ExceptionCode = RpcExceptionCode();
  266. CallFlags.ValidCallPending = ExceptionCode == RPC_S_ASYNC_CALL_PENDING;
  267. NdrClientMapCommFault( pStubMsg,
  268. pRpcMsg->ProcNum,
  269. ExceptionCode,
  270. &RetVal );
  271. if ( ExceptionCode == RPC_S_ASYNC_CALL_PENDING )
  272. {
  273. // If the call is just pending, force the pending error code
  274. // to show up in the return value of RpcAsyncCallComplete.
  275. RetVal = RPC_S_ASYNC_CALL_PENDING;
  276. }
  277. }
  278. RpcEndExcept
  279. }
  280. RpcFinally
  281. {
  282. // There is only one way a valid call may be pending at this stage:
  283. // that is the receive call returned with RPC_S_CALL_PENDING.
  284. if ( ! CallFlags.ValidCallPending )
  285. {
  286. // Cleanup everything. However, don't free user's handle.
  287. NdrpFreeAsyncMsg( pAsyncMsg );
  288. AsyncHandle->StubInfo = 0;
  289. }
  290. InterlockedDecrement( & AsyncHandle->Lock );
  291. }
  292. RpcEndFinally
  293. return (RPC_STATUS)RetVal;
  294. }
  295. void RPC_ENTRY
  296. NdrAsyncServerCall(
  297. PRPC_MESSAGE pRpcMsg
  298. )
  299. /*++
  300. Routine Description :
  301. The server side entry point for regular asynchronous RPC procs.
  302. Arguments :
  303. pRpcMsg - The RPC message.
  304. Return :
  305. None.
  306. --*/
  307. {
  308. RPC_ASYNC_HANDLE AsyncHandle = 0;
  309. PNDR_ASYNC_MESSAGE pAsyncMsg;
  310. PRPC_SERVER_INTERFACE pServerIfInfo;
  311. PMIDL_SERVER_INFO pServerInfo;
  312. PMIDL_STUB_DESC pStubDesc;
  313. const SERVER_ROUTINE * DispatchTable;
  314. ushort ProcNum;
  315. ushort FormatOffset;
  316. PFORMAT_STRING pFormat;
  317. PFORMAT_STRING pFormatParam;
  318. PMIDL_STUB_MESSAGE pStubMsg;
  319. uchar * pArgBuffer;
  320. uchar ** ppArg;
  321. PPARAM_DESCRIPTION Params;
  322. INTERPRETER_FLAGS OldOiFlags;
  323. INTERPRETER_OPT_FLAGS NewOiFlags;
  324. long NumberParams;
  325. ushort ClientBufferSize;
  326. BOOL HasExplicitHandle;
  327. long n;
  328. NDR_PROC_CONTEXT * pContext;
  329. RPC_STATUS Status = RPC_S_OK;
  330. //
  331. // In the case of a context handle, the server side manager function has
  332. // to be called with NDRSContextValue(ctxthandle). But then we may need to
  333. // marshall the handle, so NDRSContextValue(ctxthandle) is put in the
  334. // argument buffer and the handle itself is stored in the following array.
  335. // When marshalling a context handle, we marshall from this array.
  336. //
  337. // The handle table is part of the async handle.
  338. ProcNum = (ushort) pRpcMsg->ProcNum;
  339. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  340. "marshaling buffer misaligned at server" );
  341. pServerIfInfo = (PRPC_SERVER_INTERFACE)pRpcMsg->RpcInterfaceInformation;
  342. pServerInfo = (PMIDL_SERVER_INFO)pServerIfInfo->InterpreterInfo;
  343. DispatchTable = pServerInfo->DispatchTable;
  344. pStubDesc = pServerInfo->pStubDesc;
  345. FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
  346. pFormat = &((pServerInfo->ProcString)[FormatOffset]);
  347. AsyncHandle = 0;
  348. pAsyncMsg = (NDR_ASYNC_MESSAGE*) I_RpcBCacheAllocate( sizeof( NDR_ASYNC_MESSAGE) );
  349. if ( ! pAsyncMsg )
  350. Status = RPC_S_OUT_OF_MEMORY;
  351. else
  352. {
  353. memset( pAsyncMsg, 0, sizeof( NDR_ASYNC_MESSAGE ) );
  354. MulNdrpInitializeContextFromProc(
  355. XFER_SYNTAX_DCE,
  356. pFormat,
  357. &pAsyncMsg->ProcContext,
  358. NULL ); // server StartofStack
  359. Status = NdrpInitializeAsyncMsg( 0, // StartofStack, server
  360. pAsyncMsg
  361. );
  362. }
  363. if ( Status )
  364. RpcRaiseException( Status );
  365. pAsyncMsg->StubPhase = STUB_UNMARSHAL;
  366. pStubMsg = & pAsyncMsg->StubMsg;
  367. // from Kamen:
  368. // we don't need to copy RpcMsg : it's provided by runtime in server side
  369. pContext = &pAsyncMsg->ProcContext;
  370. // setup the type format string in old code.
  371. pContext->DceTypeFormatString = pStubDesc->pFormatTypes;
  372. pStubMsg->RpcMsg = pRpcMsg;
  373. pStubMsg->SavedContextHandles = pAsyncMsg->CtxtHndl;
  374. // The arg buffer is zeroed out already.
  375. pArgBuffer = pAsyncMsg->ProcContext.StartofStack;
  376. OldOiFlags = pContext->NdrInfo.InterpreterFlags;
  377. NewOiFlags = pContext->NdrInfo.pProcDesc->Oi2Flags;
  378. NumberParams = pContext->NumberParams;
  379. Params = ( PPARAM_DESCRIPTION ) pContext->Params;
  380. //
  381. // Wrap the unmarshalling and the invoke call in the try block of
  382. // a try-finally. Put the free phase in the associated finally block.
  383. //
  384. BOOL fManagerCodeInvoked = FALSE;
  385. BOOL fErrorInInvoke = FALSE;
  386. RPC_STATUS ExceptionCode = 0;
  387. // We abstract the level of indirection here.
  388. AsyncHandle = pAsyncMsg->AsyncHandle;
  389. RpcTryFinally
  390. {
  391. RpcTryExcept
  392. {
  393. // Put the async handle on stack.
  394. ((void **)pArgBuffer)[0] = AsyncHandle;
  395. NdrpServerInit( pStubMsg,
  396. pRpcMsg,
  397. pStubDesc,
  398. NULL, // pThis
  399. NULL, // pChannel
  400. pAsyncMsg );
  401. // Let runtime associate async handle with the call.
  402. NdrpRegisterAsyncHandle( pStubMsg, AsyncHandle );
  403. pAsyncMsg->StubPhase = NDR_ASYNC_SET_PHASE;
  404. NdrpServerUnMarshal( pStubMsg );
  405. if ( pRpcMsg->BufferLength <
  406. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  407. {
  408. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  409. }
  410. }
  411. RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
  412. {
  413. ExceptionCode = RpcExceptionCode();
  414. if( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  415. {
  416. ExceptionCode = RPC_X_BAD_STUB_DATA;
  417. }
  418. // we always free the memory list if exception happened
  419. // during unmarshalling. Exception code will tell if this
  420. // is really RPC_X_BAD_STUB_DATA;
  421. NdrpFreeMemoryList( pStubMsg );
  422. pAsyncMsg->Flags.BadStubData = 1;
  423. pAsyncMsg->ErrorCode = ExceptionCode;
  424. RpcRaiseException( ExceptionCode );
  425. }
  426. RpcEndExcept
  427. // Two separate blocks because the filters are different.
  428. // We need to catch exception in the manager code separately
  429. // as the model implies that there will be no other call from
  430. // the server app to clean up.
  431. RpcTryExcept
  432. {
  433. //
  434. // Do [out] initialization before the invoke.
  435. //
  436. NdrpServerOutInit( pStubMsg );
  437. //
  438. // Unblock the first pipe; this needs to be after unmarshalling
  439. // because the buffer may need to be changed to the secondary one.
  440. // In the out only pipes case this happens immediately.
  441. //
  442. if ( NewOiFlags.HasPipes )
  443. NdrMarkNextActivePipe( pContext->pPipeDesc );
  444. pAsyncMsg->StubPhase = STUB_CALL_SERVER;
  445. //
  446. // Check for a thunk. Compiler does all the setup for us.
  447. //
  448. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  449. {
  450. pAsyncMsg->Flags.ValidCallPending = 1;
  451. InterlockedDecrement( & AsyncHandle->Lock );
  452. fManagerCodeInvoked = TRUE;
  453. fErrorInInvoke = TRUE;
  454. pServerInfo->ThunkTable[ProcNum]( pStubMsg );
  455. }
  456. else
  457. {
  458. //
  459. // Note that this ArgNum is not the number of arguments declared
  460. // in the function we called, but really the number of
  461. // REGISTER_TYPEs occupied by the arguments to a function.
  462. //
  463. long ArgNum;
  464. MANAGER_FUNCTION pFunc;
  465. REGISTER_TYPE returnValue;
  466. if ( pRpcMsg->ManagerEpv )
  467. pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
  468. else
  469. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  470. ArgNum = (long) pContext->StackSize / sizeof(REGISTER_TYPE);
  471. //
  472. // The StackSize includes the size of the return. If we want
  473. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  474. // by 1 when there is a return value AND the current ArgNum count
  475. // is greater than 0.
  476. //
  477. if ( ArgNum && NewOiFlags.HasReturn )
  478. ArgNum--;
  479. // Being here means that we can expect results. Note that the user
  480. // can call RpcCompleteCall from inside of the manager code.
  481. pAsyncMsg->Flags.ValidCallPending = 1;
  482. // Unlock the handle - the app is allowed to call RpCAsyncManager
  483. // or RpcAsyncAbort from the manager code.
  484. InterlockedDecrement( & AsyncHandle->Lock );
  485. fManagerCodeInvoked = TRUE;
  486. fErrorInInvoke = TRUE;
  487. returnValue = Invoke( pFunc,
  488. (REGISTER_TYPE *)pArgBuffer,
  489. #if defined(_IA64_)
  490. NewOiFlags.HasExtensions ? ((PNDR_PROC_HEADER_EXTS64)&pContext->NdrInfo.pProcDesc->NdrExts)->FloatArgMask
  491. : 0,
  492. #endif
  493. ArgNum);
  494. // We are discarding the return value as it is not the real one.
  495. // The real return value is passed in the complete call.
  496. }
  497. fErrorInInvoke = FALSE;
  498. }
  499. RpcExcept( 1 )
  500. {
  501. ExceptionCode = RpcExceptionCode();
  502. if ( ExceptionCode == 0 )
  503. ExceptionCode = ERROR_INVALID_PARAMETER;
  504. // We may not have the async message around anymore.
  505. RpcRaiseException( ExceptionCode );
  506. }
  507. RpcEndExcept
  508. }
  509. RpcFinally
  510. {
  511. if ( fManagerCodeInvoked && !fErrorInInvoke )
  512. {
  513. // Success. Just skip everything if the manager code was invoked
  514. // and returned successfully.
  515. // Note that manager code could have called Complete or Abort by now
  516. // and so the async handle may not be valid anymore.
  517. }
  518. else
  519. {
  520. // See if we can clean up;
  521. Status = RPC_S_OK;
  522. if ( fErrorInInvoke )
  523. {
  524. // After an exception in invoking, let's see if we can get a hold
  525. // of the handle. If so, we will be able to clean up.
  526. // If not, there may be a leak there that we can do nothing about.
  527. // The rule is: after an exception the app cannot call Abort or
  528. // Complete. So, we need to force complete if we can.
  529. Status = NdrValidateBothAndLockAsyncHandle( AsyncHandle );
  530. }
  531. if ( Status == RPC_S_OK )
  532. {
  533. // Something went wrong but we are able to do the cleanup.
  534. // Cleanup parameters and async message/handle.
  535. // propagate the exception.
  536. NdrpCleanupServerContextHandles( pStubMsg,
  537. pArgBuffer,
  538. TRUE ); // die in manager routine
  539. if (!pAsyncMsg->Flags.BadStubData)
  540. {
  541. NdrpFreeParams( pStubMsg,
  542. NumberParams,
  543. Params,
  544. pArgBuffer );
  545. }
  546. NdrpFreeAsyncHandleAndMessage( AsyncHandle );
  547. }
  548. // else manager code invoked and we could not recover.
  549. // Exception will be raised by the EndFinally below.
  550. }
  551. }
  552. RpcEndFinally
  553. }
  554. RPC_STATUS
  555. NdrpCompleteAsyncServerCall(
  556. RPC_ASYNC_HANDLE AsyncHandle,
  557. PNDR_ASYNC_MESSAGE pAsyncMsg,
  558. void * pReturnValue
  559. )
  560. /*++
  561. Routine Description :
  562. Complete an async call on the server side. If an exception occurs, the
  563. asynchronous rpc call is aborted with the exception code and the server side
  564. caller is returned S_OK.
  565. Arguments :
  566. AsyncHandle - validated asynchronous handle,
  567. pAsyncMsg - pointer to async msg structure,
  568. pReturnValue - pointer to the return value to be passed to the client.
  569. Return :
  570. Status of S_OK.
  571. --*/
  572. {
  573. // in the server side, we don't use pAsyncMsg->RpcMsg. for Kamen
  574. MIDL_STUB_MESSAGE * pStubMsg = & pAsyncMsg->StubMsg;
  575. RPC_MESSAGE * pRpcMsg = pStubMsg->RpcMsg;
  576. PFORMAT_STRING pFormatParam;
  577. NDR_PROC_CONTEXT * pContext = & pAsyncMsg->ProcContext;
  578. INTERPRETER_FLAGS OldOiFlags = pContext->NdrInfo.InterpreterFlags;
  579. INTERPRETER_OPT_FLAGS NewOiFlags = pContext->NdrInfo.pProcDesc->Oi2Flags;
  580. PPARAM_DESCRIPTION Params = ( PPARAM_DESCRIPTION )pContext->Params;
  581. uchar * pArgBuffer = pContext->StartofStack;
  582. unsigned long StackSize = pContext->StackSize;
  583. PMIDL_STUB_DESC pStubDesc = pStubMsg->StubDesc;
  584. long NumberParams = pContext->NumberParams;
  585. long n;
  586. boolean fParamsFreed = FALSE;
  587. //
  588. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  589. // a try-except. Put the call to abort in the except clause.
  590. //
  591. RpcTryExcept
  592. {
  593. // At this point, this is a valid RPC call since the asynchronous handle
  594. // is owned by NDR on the server side and NDR passes the handle
  595. // to the server during the invoke call. During invoke
  596. // the parameters have already been unmarshalled.
  597. pAsyncMsg->StubPhase = STUB_MARSHAL;
  598. if( NewOiFlags.HasReturn )
  599. {
  600. // Put user's return value on the stack as usual.
  601. // See the invoke for comments on folding return into the arg satck.
  602. NDR_ASSERT( !pContext->HasComplexReturn, "complex return is not supported in async" );
  603. long ArgNum = (long) StackSize / sizeof(REGISTER_TYPE);
  604. if ( ArgNum )
  605. ArgNum--;
  606. if ( ! pReturnValue )
  607. RpcRaiseException( RPC_S_INVALID_ARG );
  608. // We don't support return value larger than register_type,
  609. // and memcpy avoid alignment issue.
  610. if ( Params[NumberParams-1].ParamAttr.IsBasetype )
  611. memcpy( &((REGISTER_TYPE *)pArgBuffer)[ArgNum],
  612. pReturnValue,
  613. (size_t)SIMPLE_TYPE_MEMSIZE( Params[NumberParams-1].SimpleType.Type ) );
  614. else
  615. ((REGISTER_TYPE *)pArgBuffer)[ArgNum] = *(REGISTER_TYPE*)pReturnValue;
  616. }
  617. //
  618. // Buffer size pass.
  619. //
  620. ushort ConstantBufferSize = pContext->NdrInfo.pProcDesc->ServerBufferSize;
  621. if ( NewOiFlags.HasPipes )
  622. {
  623. NdrIsAppDoneWithPipes( pContext->pPipeDesc );
  624. pStubMsg->BufferLength += ConstantBufferSize;
  625. }
  626. else
  627. pStubMsg->BufferLength = ConstantBufferSize;
  628. if ( NewOiFlags.ServerMustSize )
  629. {
  630. NdrpSizing( pStubMsg,
  631. FALSE ); // this is server
  632. }
  633. // Get buffer.
  634. if ( NewOiFlags.HasPipes && pContext->pPipeDesc->OutPipes )
  635. {
  636. NdrGetPartialBuffer( pStubMsg );
  637. pStubMsg->RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
  638. }
  639. else
  640. {
  641. NdrGetBuffer( pStubMsg,
  642. pStubMsg->BufferLength,
  643. 0 );
  644. }
  645. //
  646. // Marshall pass.
  647. //
  648. NdrpServerMarshal( pStubMsg,
  649. FALSE ); // IsObject
  650. pRpcMsg->BufferLength = (ulong)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer);
  651. // We don't drop to the runtime like for synchronous calls,
  652. // we send the last buffer explicitly.
  653. // set the freed flag.
  654. fParamsFreed = TRUE;
  655. /*
  656. we have to do release twice here:
  657. After the last piece of data is sent via NdrAsyncSend, dispatch buffer
  658. will be freed by runtime. We'll have problem calling ndr free routines to
  659. free unique pointers (where both pointer and pointee are in the buffer). So
  660. we call ndr free routines BEFORE the send, because it won't free anything
  661. inside dispatch buffer, and runtime send only cares about dispatch buffer.
  662. We still have to call ndr free routines in RpcFinally for exception cleanup. we
  663. check the flag to avoid calling free twice.
  664. */
  665. NdrpFreeParams( pStubMsg,
  666. NumberParams,
  667. Params,
  668. pArgBuffer );
  669. NdrAsyncSend( pStubMsg,
  670. FALSE ); // the last call is always non-partial
  671. }
  672. RpcExcept(1)
  673. {
  674. // Abort the call which will result in the exception being propagated to
  675. // the client.
  676. NdrpAsyncAbortCall( AsyncHandle,
  677. pAsyncMsg,
  678. RpcExceptionCode(),
  679. !fParamsFreed ); // Do not free if second attempt.
  680. return S_OK;
  681. }
  682. RpcEndExcept
  683. NdrpFreeAsyncHandleAndMessage( AsyncHandle );
  684. return S_OK;
  685. }
  686. RPC_STATUS
  687. NdrpInitializeAsyncMsg(
  688. void * StartofStack,
  689. PNDR_ASYNC_MESSAGE pAsyncMsg )
  690. /*
  691. This method creates and initializes async msg.
  692. Additionally, it creates the handle itself in object case.
  693. pHandleArg - pointer to the proc's async handle argument.
  694. Note the handle arg semantics on the client:
  695. *pHandleArg is
  696. raw: a handle (arg is a *)
  697. - the handle cannot be 0
  698. obj: a pHandle (arg is a **)
  699. pHandle ==0 means a "don't care" call
  700. *pHandle ==0 means "create handle while calling"
  701. *pHandle !=0 means a handle created by the app.
  702. StartofStack - side marker as well:
  703. != 0 - client
  704. == 0 - server
  705. */
  706. {
  707. RPC_STATUS Status = 0;
  708. BOOL fIsClient = StartofStack != 0;
  709. BOOL fHandleCreated = FALSE;
  710. RPC_ASYNC_HANDLE AsyncHandle = 0;
  711. RPC_ASYNC_HANDLE * pHandleArg = (RPC_ASYNC_HANDLE *)StartofStack;
  712. // Do this first to simplify error conditions.
  713. ulong StackSize = pAsyncMsg->ProcContext.StackSize;
  714. if ( fIsClient )
  715. {
  716. // Client always supplies a handle.
  717. if ( *pHandleArg )
  718. {
  719. AsyncHandle = *pHandleArg;
  720. Status = NdrpValidateAndLockAsyncHandle( AsyncHandle );
  721. }
  722. else
  723. Status = RPC_S_INVALID_ASYNC_HANDLE;
  724. }
  725. else
  726. {
  727. // Server - the stub creates the handle.
  728. AsyncHandle = (RPC_ASYNC_STATE *)I_RpcAllocate( sizeof(RPC_ASYNC_STATE) );
  729. if ( ! AsyncHandle )
  730. Status = RPC_S_OUT_OF_MEMORY;
  731. else
  732. {
  733. MIDL_memset( AsyncHandle, 0x0, sizeof( RPC_ASYNC_STATE) );
  734. RpcAsyncInitializeHandle( AsyncHandle, RPC_ASYNC_VERSION_1_0 );
  735. AsyncHandle->Lock = 1;
  736. fHandleCreated = TRUE;
  737. }
  738. }
  739. if ( Status )
  740. {
  741. I_RpcBCacheFree( pAsyncMsg );
  742. return Status;
  743. }
  744. // Initialize the async message properly
  745. pAsyncMsg->Signature = NDR_ASYNC_SIGNATURE;
  746. pAsyncMsg->Version = NDR_ASYNC_VERSION;
  747. pAsyncMsg->StubMsg.pContext = & pAsyncMsg->ProcContext;
  748. pAsyncMsg->ProcContext.StartofStack = (uchar *) NdrpAlloca(
  749. & pAsyncMsg->ProcContext.AllocateContext,
  750. StackSize );
  751. // Must do this before the sizing pass!
  752. pAsyncMsg->StubMsg.StackTop = (uchar *)StartofStack;
  753. pAsyncMsg->StubPhase = NDR_ASYNC_PREP_PHASE;
  754. if ( fIsClient )
  755. {
  756. // Client: copy stack from the app's request call.
  757. RpcpMemoryCopy( pAsyncMsg->ProcContext.StartofStack, StartofStack, StackSize );
  758. }
  759. else
  760. {
  761. // Server: zero out stack for allocs.
  762. MIDL_memset( pAsyncMsg->ProcContext.StartofStack, 0x0, StackSize );
  763. }
  764. MIDL_memset( pAsyncMsg->AsyncGuard,
  765. 0x71,
  766. NDR_ASYNC_GUARD_SIZE );
  767. AsyncHandle->StubInfo = pAsyncMsg;
  768. pAsyncMsg->AsyncHandle = AsyncHandle;
  769. return RPC_S_OK;
  770. }
  771. void
  772. NdrpFreeAsyncMsg(
  773. PNDR_ASYNC_MESSAGE pAsyncMsg )
  774. /*
  775. This routine would free the AsyncMsg but not the AsyncHandle, as on the server
  776. the user may need it and on the client it is user's to begin with.
  777. */
  778. {
  779. NDR_PROC_CONTEXT * pContext = & pAsyncMsg->ProcContext;
  780. if ( pAsyncMsg )
  781. {
  782. PMIDL_STUB_MESSAGE pStubMsg = & pAsyncMsg->StubMsg;
  783. NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
  784. NdrCorrelationFree( pStubMsg );
  785. // Free the RPC buffer.
  786. if ( pStubMsg->IsClient )
  787. {
  788. if ( ! pAsyncMsg->Flags.RuntimeCleanedUp )
  789. NdrFreeBuffer( pStubMsg );
  790. }
  791. RPC_STATUS Status = 0;
  792. if ( pStubMsg->IsClient )
  793. {
  794. if ( pContext->SavedGenericHandle )
  795. {
  796. // Note that we cannot unbind after freeing the handle as the stack would be gone.
  797. RpcTryExcept
  798. {
  799. GenericHandleUnbind( pStubMsg->StubDesc,
  800. pContext->StartofStack,
  801. pContext->pHandleFormatSave,
  802. (pContext->HandleType) ? IMPLICIT_MASK : 0,
  803. & pContext->SavedGenericHandle );
  804. }
  805. RpcExcept(1)
  806. {
  807. Status = RpcExceptionCode();
  808. }
  809. RpcEndExcept;
  810. }
  811. }
  812. NdrpAllocaDestroy( &pContext->AllocateContext );
  813. // Prevent reusing of a handle that has been freed;
  814. pAsyncMsg->Signature = NDR_FREED_ASYNC_SIGNATURE;
  815. I_RpcBCacheFree( pAsyncMsg );
  816. if ( Status )
  817. RpcRaiseException( Status );
  818. }
  819. }
  820. VOID
  821. NdrpFreeAsyncHandleAndMessage(
  822. PRPC_ASYNC_STATE AsyncHandle)
  823. /*++
  824. Routine Description:
  825. Frees an async handle and its associated async message.
  826. Arguments:
  827. AsyncHandle - Supplies the async handle to be freed.
  828. Return Value:
  829. None.
  830. --*/
  831. {
  832. PNDR_ASYNC_MESSAGE pAsyncMsg = (PNDR_ASYNC_MESSAGE)AsyncHandle->StubInfo;
  833. NdrpFreeAsyncMsg( pAsyncMsg );
  834. AsyncHandle->StubInfo = 0;
  835. AsyncHandle->Signature = RPC_FREED_ASYNC_SIGNATURE;
  836. I_RpcFree( AsyncHandle );
  837. }
  838. void
  839. NdrAsyncSend(
  840. PMIDL_STUB_MESSAGE pStubMsg,
  841. BOOL fPartialSend )
  842. {
  843. pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  844. if ( fPartialSend )
  845. NdrPartialSend( pStubMsg->pContext->pPipeDesc,
  846. pStubMsg );
  847. else
  848. {
  849. NdrSend( 0, // not used
  850. pStubMsg,
  851. FALSE ); // not partial
  852. }
  853. }
  854. void
  855. NdrLastAsyncReceive(
  856. PMIDL_STUB_MESSAGE pStubMsg )
  857. {
  858. pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
  859. // A complete call.
  860. // We may have a complete buffer already when pipes are involved.
  861. if ( pStubMsg->pContext->pPipeDesc )
  862. {
  863. if ( pStubMsg->RpcMsg->RpcFlags & RPC_BUFFER_COMPLETE )
  864. return;
  865. if ( pStubMsg->pContext->pPipeDesc->OutPipes )
  866. {
  867. pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_EXTRA;
  868. }
  869. else
  870. {
  871. pStubMsg->RpcMsg->RpcFlags &= ~RPC_BUFFER_EXTRA;
  872. }
  873. }
  874. NdrReceive( pStubMsg->pContext->pPipeDesc,
  875. pStubMsg,
  876. 0, // size, ignored for complete calls
  877. FALSE ); // complete buffer
  878. }
  879. void
  880. NdrpRegisterAsyncHandle(
  881. PMIDL_STUB_MESSAGE pStubMsg,
  882. void * AsyncHandle )
  883. {
  884. RPC_STATUS Status;
  885. Status = I_RpcAsyncSetHandle( pStubMsg->RpcMsg,
  886. (RPC_ASYNC_STATE *)AsyncHandle );
  887. if ( Status )
  888. RpcRaiseException( Status );
  889. }
  890. RPC_STATUS
  891. NdrpValidateAsyncMsg(
  892. PNDR_ASYNC_MESSAGE pAsyncMsg )
  893. {
  894. if ( ! pAsyncMsg )
  895. return RPC_S_INVALID_ASYNC_HANDLE;
  896. if ( 0 != IsBadWritePtr( pAsyncMsg, sizeof(NDR_ASYNC_MESSAGE)) )
  897. return RPC_S_INVALID_ASYNC_HANDLE;
  898. if ( pAsyncMsg->Signature != NDR_ASYNC_SIGNATURE ||
  899. pAsyncMsg->Version != NDR_ASYNC_VERSION )
  900. return RPC_S_INVALID_ASYNC_HANDLE;
  901. return RPC_S_OK;
  902. }
  903. RPC_STATUS
  904. NdrpValidateAndLockAsyncHandle(
  905. IN PRPC_ASYNC_STATE AsyncHandle )
  906. {
  907. if ( 0 != IsBadWritePtr( AsyncHandle, sizeof(RPC_ASYNC_STATE)) )
  908. return RPC_S_INVALID_ASYNC_HANDLE;
  909. // Prevent multiple simultanous abort and complete calls.
  910. if ( 0 != InterlockedCompareExchange( & AsyncHandle->Lock, 1, 0 ) )
  911. {
  912. return RPC_S_INVALID_ASYNC_CALL;
  913. }
  914. else
  915. {
  916. if ( AsyncHandle->Signature != RPC_ASYNC_SIGNATURE ||
  917. AsyncHandle->Size != RPC_ASYNC_VERSION_1_0 )
  918. {
  919. InterlockedDecrement( & AsyncHandle->Lock );
  920. return RPC_S_INVALID_ASYNC_HANDLE;
  921. }
  922. }
  923. return RPC_S_OK;
  924. }
  925. RPC_STATUS
  926. NdrValidateBothAndLockAsyncHandle(
  927. IN PRPC_ASYNC_STATE AsyncHandle )
  928. {
  929. RPC_STATUS Status = NdrpValidateAndLockAsyncHandle( AsyncHandle );
  930. if ( Status != RPC_S_OK )
  931. return Status;
  932. Status = NdrpValidateAsyncMsg( (PNDR_ASYNC_MESSAGE) AsyncHandle->StubInfo );
  933. if ( Status != RPC_S_OK )
  934. InterlockedDecrement( & AsyncHandle->Lock );
  935. return Status;
  936. }
  937. RPC_STATUS
  938. NdrpAsyncAbortCall (
  939. PRPC_ASYNC_STATE AsyncHandle,
  940. PNDR_ASYNC_MESSAGE pAsyncMsg,
  941. unsigned long ExceptionCode,
  942. BOOL bFreeParams
  943. )
  944. /*++
  945. Routine Description:
  946. Aborts the asynchronous RPC call indicated by AsyncHandle on the server and
  947. frees memory allocated for the parameters, message, and handle.
  948. Arguments:
  949. AsyncHandle - supplies the async handle for the call
  950. AsyncMessage - supplies the async message for the call
  951. ExceptionCode - supplies the exception code to send to the client.
  952. bFreeParams - TRUE if the parameters should be freed.
  953. Return Value:
  954. NONE.
  955. --*/
  956. {
  957. RPC_STATUS Status = RPC_S_OK;
  958. // If the async call is aborted, see if context handles are fine.
  959. // We know there is no manager routine exception.
  960. NdrpCleanupServerContextHandles( &pAsyncMsg->StubMsg,
  961. pAsyncMsg->ProcContext.StartofStack,
  962. FALSE );
  963. if (bFreeParams)
  964. {
  965. NdrpFreeParams( & pAsyncMsg->StubMsg,
  966. pAsyncMsg->ProcContext.NumberParams, //Number of parameters
  967. ( PPARAM_DESCRIPTION )pAsyncMsg->ProcContext.Params,
  968. pAsyncMsg->ProcContext.StartofStack );
  969. }
  970. if ( ! pAsyncMsg->Flags.RuntimeCleanedUp )
  971. Status = I_RpcAsyncAbortCall( AsyncHandle, ExceptionCode);
  972. NdrpFreeAsyncHandleAndMessage( AsyncHandle );
  973. return Status;
  974. }
  975. RPC_STATUS
  976. Ndr64pCompleteAsyncClientCall(
  977. RPC_ASYNC_HANDLE AsyncHandle,
  978. IN PNDR_ASYNC_MESSAGE pAsyncMsg,
  979. void * pReturnValue
  980. );
  981. RPC_STATUS
  982. Ndr64pCompleteAsyncServerCall(
  983. RPC_ASYNC_HANDLE AsyncHandle,
  984. PNDR_ASYNC_MESSAGE pAsyncMsg,
  985. void * pReturnValue
  986. );
  987. RPC_STATUS
  988. Ndr64pAsyncAbortCall(
  989. PRPC_ASYNC_STATE AsyncHandle,
  990. PNDR_ASYNC_MESSAGE pAsyncMsg,
  991. unsigned long ExceptionCode,
  992. BOOL bFreeParams
  993. );
  994. //////////////////////////////////////////////////////////////////////////////
  995. //
  996. // Runtime APIs
  997. //
  998. //////////////////////////////////////////////////////////////////////////////
  999. RPC_STATUS RPC_ENTRY
  1000. RpcAsyncInitializeHandle (
  1001. IN PRPC_ASYNC_STATE AsyncHandle,
  1002. IN unsigned int Size
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Initializes an async handle.
  1007. Arguments:
  1008. AsyncHandle - the async handle directing the call
  1009. Return Value:
  1010. RPC_S_OK - the call succeeded.
  1011. RPC_S_INVALID_HANDLE - the handle was bad.
  1012. --*/
  1013. {
  1014. if ( ! AsyncHandle ||
  1015. Size < RPC_ASYNC_VERSION_1_0 || Size > RPC_ASYNC_CURRENT_VERSION )
  1016. return RPC_S_INVALID_ARG;
  1017. if ( 0 != IsBadWritePtr( AsyncHandle, sizeof(RPC_ASYNC_STATE)) )
  1018. return RPC_S_INVALID_ASYNC_HANDLE;
  1019. AsyncHandle->Size = RPC_ASYNC_CURRENT_VERSION;
  1020. AsyncHandle->Signature = RPC_ASYNC_SIGNATURE;
  1021. AsyncHandle->Flags = 0;
  1022. AsyncHandle->Lock = 0;
  1023. AsyncHandle->StubInfo = 0;
  1024. AsyncHandle->RuntimeInfo = 0;
  1025. AsyncHandle->Reserved[0] = 0;
  1026. AsyncHandle->Reserved[1] = 0;
  1027. AsyncHandle->Reserved[2] = 0;
  1028. AsyncHandle->Reserved[3] = 0;
  1029. return RPC_S_OK;
  1030. }
  1031. RPC_STATUS RPC_ENTRY
  1032. RpcAsyncAbortCall (
  1033. IN PRPC_ASYNC_STATE AsyncHandle,
  1034. IN unsigned long ExceptionCode
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. This API is valid only on the server side and is a request to abort
  1039. the call. The asynchronous handle is deleted and no additional API calls
  1040. on that handle are permitted.
  1041. Note that RpcCancelAsyncCall is a different API that is used on the client
  1042. side only.
  1043. Arguments:
  1044. AsyncHandle - the async handle directing the call
  1045. Return Value:
  1046. RPC_S_OK - the call succeeded.
  1047. RPC_S_INVALID_HANDLE - the handle was bad.
  1048. RPC_S_INVALID_ASYNC_CALL - May not be called on the client.
  1049. Other errors from the RPC runtime layer.
  1050. Note: This API cannot be called on the client side.
  1051. --*/
  1052. {
  1053. RPC_STATUS Status;
  1054. PNDR_ASYNC_MESSAGE pAsyncMsg;
  1055. Status = NdrValidateBothAndLockAsyncHandle( AsyncHandle );
  1056. if (RPC_S_OK != Status)
  1057. {
  1058. return Status;
  1059. }
  1060. pAsyncMsg = (PNDR_ASYNC_MESSAGE)AsyncHandle->StubInfo;
  1061. if ( pAsyncMsg->StubMsg.IsClient )
  1062. {
  1063. // Abort is not valid on the client.
  1064. InterlockedDecrement( & AsyncHandle->Lock );
  1065. return RPC_S_INVALID_ASYNC_CALL;
  1066. }
  1067. #if defined(BUILD_NDR64)
  1068. if ( pAsyncMsg->ProcContext.CurrentSyntaxType == XFER_SYNTAX_DCE )
  1069. return NdrpAsyncAbortCall( AsyncHandle,
  1070. pAsyncMsg,
  1071. ExceptionCode,
  1072. TRUE ); // Free parameters
  1073. else
  1074. return Ndr64pAsyncAbortCall( AsyncHandle,
  1075. pAsyncMsg,
  1076. ExceptionCode,
  1077. TRUE ); // Free parameters
  1078. #else
  1079. return NdrpAsyncAbortCall( AsyncHandle,
  1080. pAsyncMsg,
  1081. ExceptionCode,
  1082. TRUE ); // Free parameters
  1083. #endif
  1084. }
  1085. RPC_STATUS
  1086. Ndr64pCompleteAsyncCall (
  1087. IN PRPC_ASYNC_STATE AsyncHandle,
  1088. IN PNDR_ASYNC_MESSAGE pAsyncMsg,
  1089. IN void * pReply
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Completes the virtual async call on server or client side.
  1094. Arguments:
  1095. AsyncHandle - the async handle controlling the call
  1096. Reply - return value:
  1097. on server - passed in
  1098. on client - returned out
  1099. Return Value:
  1100. RPC_S_OK - Function succeeded
  1101. RPC_S_OUT_OF_MEMORY - we ran out of memory
  1102. --*/
  1103. {
  1104. RPC_STATUS Status;
  1105. RpcTryExcept
  1106. {
  1107. if ( pAsyncMsg->StubMsg.IsClient )
  1108. {
  1109. #if defined(BUILD_NDR64)
  1110. if ( pAsyncMsg->ProcContext.CurrentSyntaxType == XFER_SYNTAX_DCE )
  1111. Status = NdrpCompleteAsyncClientCall( AsyncHandle, pAsyncMsg, pReply );
  1112. else
  1113. Status = Ndr64pCompleteAsyncClientCall( AsyncHandle, pAsyncMsg, pReply );
  1114. #else
  1115. NDR_ASSERT( pAsyncMsg->ProcContext.CurrentSyntaxType == XFER_SYNTAX_DCE,
  1116. "Invalid transfer syntax" );
  1117. Status = NdrpCompleteAsyncClientCall( AsyncHandle, pAsyncMsg, pReply );
  1118. #endif
  1119. }
  1120. else
  1121. {
  1122. #if defined(BUILD_NDR64)
  1123. if ( pAsyncMsg->ProcContext.CurrentSyntaxType == XFER_SYNTAX_DCE )
  1124. Status = NdrpCompleteAsyncServerCall ( AsyncHandle, pAsyncMsg, pReply );
  1125. else
  1126. Status = Ndr64pCompleteAsyncServerCall( AsyncHandle, pAsyncMsg, pReply );
  1127. #else
  1128. NDR_ASSERT( pAsyncMsg->ProcContext.CurrentSyntaxType == XFER_SYNTAX_DCE,
  1129. "Invalid transfer Syntax" );
  1130. Status = NdrpCompleteAsyncServerCall ( AsyncHandle, pAsyncMsg, pReply );
  1131. #endif
  1132. }
  1133. }
  1134. RpcExcept( !(RPC_BAD_STUB_DATA_EXCEPTION_FILTER) )
  1135. {
  1136. Status = RpcExceptionCode();
  1137. }
  1138. RpcEndExcept
  1139. return Status;
  1140. }
  1141. RPC_STATUS RPC_ENTRY
  1142. RpcAsyncCompleteCall (
  1143. IN PRPC_ASYNC_STATE AsyncHandle,
  1144. IN void * pReply
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. Completes the virtual async call on server or client side.
  1149. Arguments:
  1150. AsyncHandle - the async handle controlling the call
  1151. Reply - return value:
  1152. on server - passed in
  1153. on client - returned out
  1154. Return Value:
  1155. RPC_S_OK - Function succeeded
  1156. RPC_S_OUT_OF_MEMORY - we ran out of memory
  1157. --*/
  1158. {
  1159. RPC_STATUS Status = NdrValidateBothAndLockAsyncHandle( AsyncHandle );
  1160. if ( Status == RPC_S_OK )
  1161. {
  1162. Status = Ndr64pCompleteAsyncCall( AsyncHandle,
  1163. (PNDR_ASYNC_MESSAGE) AsyncHandle->StubInfo,
  1164. pReply );
  1165. }
  1166. return Status;
  1167. }