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.

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