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.

752 lines
24 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. srvcall.c
  5. Abstract :
  6. This file contains the single call Ndr64 routine for the server side.
  7. Author :
  8. David Kays dkays October 1993.
  9. Revision History :
  10. brucemc 11/15/93 Added struct by value support, corrected varargs
  11. use.
  12. brucemc 12/20/93 Binding handle support.
  13. brucemc 12/22/93 Reworked argument accessing method.
  14. ryszardk 3/12/94 Handle optimization and fixes.
  15. ---------------------------------------------------------------------*/
  16. #include "precomp.hxx"
  17. #define CINTERFACE
  18. #define USE_STUBLESS_PROXY
  19. #include "ndrole.h"
  20. #include "rpcproxy.h"
  21. #include "hndl.h"
  22. #include "interp2.h"
  23. #include "pipendr.h"
  24. #include <stdarg.h>
  25. #pragma code_seg(".ndr64")
  26. long RPC_ENTRY
  27. Ndr64StubWorker(
  28. IRpcStubBuffer * pThis,
  29. IRpcChannelBuffer * pChannel,
  30. PRPC_MESSAGE pRpcMsg,
  31. MIDL_SERVER_INFO * pServerInfo,
  32. const SERVER_ROUTINE * DispatchTable,
  33. MIDL_SYNTAX_INFO * pSyntaxInfo,
  34. ulong * pdwStubPhase
  35. )
  36. /*++
  37. Routine Description :
  38. Server Interpreter entry point for object RPC procs. Also called by
  39. Ndr64ServerCall, the entry point for regular RPC procs.
  40. Arguments :
  41. pThis - Object proc's 'this' pointer, 0 for non-object procs.
  42. pChannel - Object proc's Channel Buffer, 0 for non-object procs.
  43. pRpcMsg - The RPC message.
  44. pdwStubPhase - Used to track the current interpreter's activity.
  45. Return :
  46. Status of S_OK.
  47. --*/
  48. {
  49. PMIDL_STUB_DESC pStubDesc;
  50. ushort ProcNum;
  51. long FormatOffset;
  52. PFORMAT_STRING pFormat;
  53. PFORMAT_STRING pFormatParam;
  54. ulong StackSize;
  55. MIDL_STUB_MESSAGE StubMsg;
  56. uchar * pArg;
  57. uchar ** ppArg;
  58. NDR64_PROC_FLAGS * pNdr64Flags;
  59. long NumberParams;
  60. BOOL HasExplicitHandle;
  61. BOOL fBadStubDataException = FALSE;
  62. long n;
  63. boolean NotifyAppInvoked = FALSE;
  64. long ret;
  65. NDR_PROC_CONTEXT ProcContext;
  66. NDR64_PROC_FORMAT * pHeader = NULL;
  67. NDR64_PARAM_FLAGS * pParamFlags;
  68. NDR64_BIND_AND_NOTIFY_EXTENSION * pHeaderExts = NULL;
  69. MIDL_STUB_MESSAGE * pStubMsg = &StubMsg;
  70. //
  71. // In the case of a context handle, the server side manager function has
  72. // to be called with NDRSContextValue(ctxthandle). But then we may need to
  73. // marshall the handle, so NDRSContextValue(ctxthandle) is put in the
  74. // argument buffer and the handle itself is stored in the following array.
  75. // When marshalling a context handle, we marshall from this array.
  76. //
  77. NDR_SCONTEXT CtxtHndl[MAX_CONTEXT_HNDL_NUMBER];
  78. ProcNum = (ushort) pRpcMsg->ProcNum;
  79. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  80. "marshaling buffer misaligned at server" );
  81. // setup SyntaxInfo of selected transfer syntax.
  82. NdrServerSetupNDR64TransferSyntax( ProcNum, pSyntaxInfo, &ProcContext );
  83. StubMsg.pContext = &ProcContext;
  84. pStubDesc = pServerInfo->pStubDesc;
  85. pFormat = ProcContext.pProcFormat;
  86. pHeader = (NDR64_PROC_FORMAT *) pFormat;
  87. pNdr64Flags = (NDR64_PROC_FLAGS *) & (pHeader->Flags );
  88. HasExplicitHandle = !NDR64MAPHANDLETYPE( NDR64GETHANDLETYPE ( pNdr64Flags ) );
  89. StackSize = pHeader->StackSize;
  90. //
  91. // Yes, do this here outside of our RpcTryFinally block. If we
  92. // can't allocate the arg buffer there's nothing more to do, so
  93. // raise an exception and return control to the RPC runtime.
  94. //
  95. // Alloca throws an exception on an error.
  96. uchar *pArgBuffer = (uchar*)NdrpAlloca(&ProcContext.AllocateContext, StackSize);
  97. ProcContext.StartofStack = pArgBuffer;
  98. //
  99. // Zero out the arg buffer. We must do this so that parameters
  100. // are properly zeroed before we start unmarshalling. If we catch
  101. // an exception before finishing the unmarshalling we can not leave
  102. // parameters in an unitialized state since we have to do a freeing
  103. // pass.
  104. //
  105. MIDL_memset( pArgBuffer,
  106. 0,
  107. StackSize );
  108. if ( pNdr64Flags->HasOtherExtensions )
  109. pHeaderExts = (NDR64_BIND_AND_NOTIFY_EXTENSION *) (pFormat + sizeof( NDR64_PROC_FORMAT ) );
  110. if ( HasExplicitHandle )
  111. {
  112. //
  113. // For a handle_t parameter we must pass the handle field of
  114. // the RPC message to the server manager.
  115. //
  116. NDR_ASSERT( pHeaderExts, "NULL extension header" );
  117. if ( pHeaderExts->Binding.HandleType == FC64_BIND_PRIMITIVE )
  118. {
  119. pArg = pArgBuffer + pHeaderExts->Binding.StackOffset;
  120. if ( NDR64_IS_HANDLE_PTR( pHeaderExts->Binding.Flags ) )
  121. pArg = *((uchar **)pArg);
  122. *((handle_t *)pArg) = pRpcMsg->Handle;
  123. }
  124. }
  125. //
  126. // Get new interpreter info.
  127. //
  128. NumberParams = pHeader->NumberOfParams;
  129. NDR64_PARAM_FORMAT* Params =
  130. (NDR64_PARAM_FORMAT*)ProcContext.Params;
  131. //
  132. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  133. // a try-finally. Put the free phase in the associated finally block.
  134. //
  135. RpcTryFinally
  136. {
  137. //
  138. // If OLE, put pThis in first dword of stack.
  139. //
  140. if ( pThis )
  141. {
  142. *((void **)pArgBuffer) =
  143. (void *)((CStdStubBuffer *)pThis)->pvServerObject;
  144. }
  145. //
  146. // Initialize the Stub message.
  147. //
  148. if ( ! pChannel )
  149. {
  150. if ( ! pNdr64Flags->UsesPipes )
  151. {
  152. Ndr64ServerInitialize( pRpcMsg,
  153. &StubMsg,
  154. pStubDesc );
  155. }
  156. else
  157. Ndr64ServerInitializePartial( pRpcMsg,
  158. &StubMsg,
  159. pStubDesc,
  160. pHeader->ConstantClientBufferSize );
  161. }
  162. else
  163. {
  164. NDR_ASSERT( ! pNdr64Flags->UsesPipes, "DCOM pipe is not supported" );
  165. NdrStubInitialize( pRpcMsg,
  166. &StubMsg,
  167. pStubDesc,
  168. pChannel );
  169. }
  170. //
  171. // Set up for context handle management.
  172. //
  173. StubMsg.SavedContextHandles = CtxtHndl;
  174. memset( CtxtHndl, 0, sizeof(CtxtHndl) );
  175. pStubMsg->pCorrMemory = pArgBuffer;
  176. if ( pNdr64Flags->UsesFullPtrPackage )
  177. StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
  178. //
  179. // Set StackTop AFTER the initialize call, since it zeros the field
  180. // out.
  181. //
  182. StubMsg.StackTop = pArgBuffer;
  183. if ( pNdr64Flags->UsesPipes )
  184. NdrpPipesInitialize64( & StubMsg,
  185. &ProcContext.AllocateContext,
  186. (PFORMAT_STRING) Params,
  187. (char*)pArgBuffer,
  188. NumberParams );
  189. //
  190. // We must make this check AFTER the call to ServerInitialize,
  191. // since that routine puts the stub descriptor alloc/dealloc routines
  192. // into the stub message.
  193. //
  194. if ( pNdr64Flags->UsesRpcSmPackage )
  195. NdrRpcSsEnableAllocate( &StubMsg );
  196. RpcTryExcept
  197. {
  198. // --------------------------------
  199. // Unmarshall all of our parameters.
  200. // --------------------------------
  201. NDR_ASSERT( ProcContext.StartofStack == pArgBuffer, "startofstack is not set" );
  202. Ndr64pServerUnMarshal( &StubMsg );
  203. if ( pRpcMsg->BufferLength <
  204. (uint)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
  205. {
  206. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  207. }
  208. }
  209. RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
  210. {
  211. // Filter set in rpcndr.h to catch one of the following
  212. // STATUS_ACCESS_VIOLATION
  213. // STATUS_DATATYPE_MISALIGNMENT
  214. // RPC_X_BAD_STUB_DATA
  215. fBadStubDataException = TRUE;
  216. NdrpFreeMemoryList( &StubMsg );
  217. if ( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  218. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  219. else
  220. RpcRaiseException( RpcExceptionCode() );
  221. }
  222. RpcEndExcept
  223. //
  224. // Do [out] initialization.
  225. //
  226. Ndr64pServerOutInit( pStubMsg );
  227. //
  228. // Unblock the first pipe; this needs to be after unmarshalling
  229. // because the buffer may need to be changed to the secondary one.
  230. // In the out only pipes case this happens immediately.
  231. //
  232. if ( pNdr64Flags->UsesPipes )
  233. NdrMarkNextActivePipe( ProcContext.pPipeDesc );
  234. //
  235. // OLE interfaces use pdwStubPhase in the exception filter.
  236. // See CStdStubBuffer_Invoke in rpcproxy.c.
  237. //
  238. *pdwStubPhase = STUB_CALL_SERVER;
  239. NotifyAppInvoked = TRUE;
  240. //
  241. // Check for a thunk. Compiler does all the setup for us.
  242. //
  243. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  244. {
  245. pServerInfo->ThunkTable[ProcNum]( &StubMsg );
  246. }
  247. else
  248. {
  249. //
  250. // Note that this ArgNum is not the number of arguments declared
  251. // in the function we called, but really the number of
  252. // REGISTER_TYPEs occupied by the arguments to a function.
  253. //
  254. long ArgNum;
  255. MANAGER_FUNCTION pFunc;
  256. REGISTER_TYPE returnValue;
  257. if ( pRpcMsg->ManagerEpv )
  258. pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
  259. else
  260. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  261. ArgNum = (long) StackSize / sizeof(REGISTER_TYPE);
  262. //
  263. // The StackSize includes the size of the return. If we want
  264. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  265. // by 1 when there is a return value AND the current ArgNum count
  266. // is greater than 0.
  267. //
  268. if ( ArgNum && pNdr64Flags->HasReturn && !pNdr64Flags->HasComplexReturn )
  269. ArgNum--;
  270. returnValue = Invoke( pFunc,
  271. (REGISTER_TYPE *)pArgBuffer,
  272. #if defined(_WIN64)
  273. pHeader->FloatDoubleMask,
  274. #endif
  275. ArgNum);
  276. if( pNdr64Flags->HasReturn && !pNdr64Flags->HasComplexReturn )
  277. {
  278. ((REGISTER_TYPE *)pArgBuffer)[ArgNum] = returnValue;
  279. // Pass the app's return value to OLE channel
  280. if ( pThis )
  281. (*pfnDcomChannelSetHResult)( pRpcMsg,
  282. NULL, // reserved
  283. (HRESULT) returnValue );
  284. }
  285. }
  286. *pdwStubPhase = STUB_MARSHAL;
  287. if ( pNdr64Flags->UsesPipes )
  288. {
  289. NdrIsAppDoneWithPipes( ProcContext.pPipeDesc );
  290. StubMsg.BufferLength += pHeader->ConstantServerBufferSize;
  291. }
  292. else
  293. StubMsg.BufferLength = pHeader->ConstantServerBufferSize;
  294. if ( pNdr64Flags->ServerMustSize )
  295. {
  296. //
  297. // Buffer size pass.
  298. //
  299. Ndr64pSizing( pStubMsg,
  300. FALSE ); // IsClient
  301. }
  302. if ( pNdr64Flags->UsesPipes && ProcContext.pPipeDesc->OutPipes )
  303. {
  304. NdrGetPartialBuffer( & StubMsg );
  305. StubMsg.RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
  306. }
  307. else
  308. {
  309. if ( ! pChannel )
  310. {
  311. Ndr64GetBuffer( &StubMsg,
  312. StubMsg.BufferLength );
  313. }
  314. else
  315. NdrStubGetBuffer( pThis,
  316. pChannel,
  317. &StubMsg );
  318. }
  319. //
  320. // Marshall pass.
  321. //
  322. Ndr64pServerMarshal ( &StubMsg );
  323. if ( pRpcMsg->BufferLength <
  324. (ulong)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
  325. {
  326. NDR_ASSERT( 0, "Ndr64StubWrok marshal: buffer overflow!" );
  327. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  328. }
  329. pRpcMsg->BufferLength = (ulong) ( StubMsg.Buffer - (uchar *) pRpcMsg->Buffer );
  330. #if defined(DEBUG_WALKIP)
  331. if ( pChannel )
  332. {
  333. Ndr64pReleaseMarshalBuffer(
  334. StubMsg.RpcMsg,
  335. ProcContext.pSyntaxInfo,
  336. StubMsg.RpcMsg->ProcNum,
  337. StubMsg.StubDesc,
  338. 1, //BUFFER_OUT
  339. true );
  340. }
  341. #endif
  342. }
  343. RpcFinally
  344. {
  345. // clean up context handles if exception is thrown in either marshalling or
  346. // manager routine.
  347. if ( RpcAbnormalTermination() && ! pChannel )
  348. {
  349. Ndr64pCleanupServerContextHandles( &StubMsg,
  350. NumberParams,
  351. Params,
  352. pArgBuffer,
  353. STUB_MARSHAL != *pdwStubPhase);
  354. }
  355. // If we died because of bad stub data, don't free the params here since they
  356. // were freed using a linked list of memory in the exception handler above.
  357. if ( ! fBadStubDataException )
  358. {
  359. Ndr64pFreeParams( &StubMsg,
  360. NumberParams,
  361. Params,
  362. pArgBuffer );
  363. }
  364. NdrpAllocaDestroy( &ProcContext.AllocateContext );
  365. //
  366. // Deferred frees. Actually, this should only be necessary if you
  367. // had a pointer to enum16 in a *_is expression.
  368. //
  369. //
  370. // Free any full pointer resources.
  371. //
  372. NdrFullPointerXlatFree( StubMsg.FullPtrXlatTables );
  373. //
  374. // Disable rpcss allocate package if needed.
  375. //
  376. if ( pNdr64Flags->UsesRpcSmPackage )
  377. NdrRpcSsDisableAllocate( &StubMsg );
  378. if ( pNdr64Flags->HasNotify )
  379. {
  380. NDR_NOTIFY_ROUTINE pfnNotify;
  381. // BUGBUG: tests need to be recompiled.
  382. pfnNotify = StubMsg.StubDesc->NotifyRoutineTable[ pHeaderExts->NotifyIndex ];
  383. ((NDR_NOTIFY2_ROUTINE)pfnNotify)(NotifyAppInvoked);
  384. }
  385. }
  386. RpcEndFinally
  387. return S_OK;
  388. }
  389. void
  390. Ndr64pFreeParams(
  391. MIDL_STUB_MESSAGE * pStubMsg,
  392. long NumberParams,
  393. NDR64_PARAM_FORMAT * Params,
  394. uchar * pArgBuffer
  395. )
  396. /*++
  397. Routine Description :
  398. Frees the memory associated with function parameters as required.
  399. Arguments :
  400. pStubMsg - Supplies a pointer to the stub message.
  401. NumberParams - Supplies the number of parameters for this procedure.
  402. Params - Supplies a pointer to the parameter list for this function.
  403. pArgBuffer - Supplies a pointer to the virtual stack.
  404. pParamFilter - Supplies a filter that is used to determine which functions
  405. are to be considered. This function should return TRUE if
  406. the parameter should be considered. If pParamFilter is NULL,
  407. the default filter is used which is all parameters that have
  408. MustFree set.
  409. Return :
  410. None.
  411. --*/
  412. {
  413. for ( long n = 0; n < NumberParams; n++ )
  414. {
  415. NDR64_PARAM_FLAGS *pParamFlags =
  416. ( NDR64_PARAM_FLAGS * ) & ( Params[n].Attributes );
  417. if ( ! pParamFlags->MustFree )
  418. continue;
  419. uchar *pArg = pArgBuffer + Params[n].StackOffset;
  420. if ( ! pParamFlags->IsByValue )
  421. pArg = *((uchar **)pArg);
  422. if ( pArg )
  423. {
  424. pStubMsg->fDontCallFreeInst =
  425. pParamFlags->IsDontCallFreeInst;
  426. Ndr64ToplevelTypeFree( pStubMsg,
  427. pArg,
  428. Params[n].Type );
  429. }
  430. //
  431. // We have to check if we need to free any simple ref pointer,
  432. // since we skipped it's Ndr64PointerFree call. We also have
  433. // to explicitly free arrays and strings. But make sure it's
  434. // non-null and not sitting in the buffer.
  435. //
  436. if ( pParamFlags->IsSimpleRef ||
  437. NDR64_IS_ARRAY_OR_STRING(*(PFORMAT_STRING)Params[n].Type) )
  438. {
  439. //
  440. // Don't free [out] params that we're allocated on the
  441. // interpreter's stack.
  442. //
  443. if ( pParamFlags->UseCache )
  444. continue;
  445. //
  446. // We have to make sure the array/string is non-null in case we
  447. // get an exception before finishing our unmarshalling.
  448. //
  449. if ( pArg &&
  450. ( (pArg < pStubMsg->BufferStart) ||
  451. (pArg > pStubMsg->BufferEnd) ) )
  452. (*pStubMsg->pfnFree)( pArg );
  453. }
  454. } // for
  455. }
  456. void
  457. Ndr64pCleanupServerContextHandles(
  458. MIDL_STUB_MESSAGE * pStubMsg,
  459. long NumberParams,
  460. NDR64_PARAM_FORMAT* Params,
  461. uchar * pArgBuffer,
  462. BOOL fManagerRoutineException
  463. )
  464. /*++
  465. Routine Description :
  466. Cleans up context handles that might have been dropped by the NDR engine between
  467. the return from the manager routine and the end of marshaling.
  468. Arguments :
  469. pStubMsg - Supplies a pointer to the stub message.
  470. NumberParams - Supplies the number of parameters for this procedure.
  471. Params - Supplies a pointer to the parameter list for this function.
  472. pArgBuffer - Supplies a pointer to the virtual stack.
  473. Return :
  474. None.
  475. --*/
  476. {
  477. for ( long n = 0; n < NumberParams; n++ )
  478. {
  479. NDR64_PARAM_FLAGS *pParamFlags =
  480. (NDR64_PARAM_FLAGS *) &( Params[n].Attributes );
  481. if ( ! pParamFlags->IsOut || pParamFlags->IsPipe )
  482. continue;
  483. uchar *pArg = pArgBuffer + Params[n].StackOffset;
  484. if ( ! pParamFlags->IsByValue )
  485. pArg = *((uchar * UNALIGNED *)pArg);
  486. NDR64_FORMAT_CHAR FcType = *(PFORMAT_STRING)Params[n].Type;
  487. if ( FcType == FC64_BIND_CONTEXT )
  488. {
  489. // NDR64_CONTEXT_HANDLE_FORMAT is the same as PNDR_CONTEXT_HANDLE_ARG_DESC.
  490. NdrpEmergencyContextCleanup( pStubMsg,
  491. (PNDR_CONTEXT_HANDLE_ARG_DESC ) Params[n].Type,
  492. pArg,
  493. fManagerRoutineException );
  494. }
  495. } // for
  496. }
  497. void RPC_ENTRY
  498. Ndr64pServerUnMarshal ( MIDL_STUB_MESSAGE * pStubMsg )
  499. {
  500. NDR_PROC_CONTEXT * pContext = ( NDR_PROC_CONTEXT * )pStubMsg->pContext;
  501. // if ( (ULONG_PTR)pStubMsg->Buffer & 15 )
  502. // RpcRaiseException( RPC_X_INVALID_BUFFER );
  503. NDR64_PARAM_FORMAT *Params = (NDR64_PARAM_FORMAT *)pContext->Params;
  504. CORRELATION_CONTEXT CorrCtxt( pStubMsg, pContext->StartofStack );
  505. //
  506. // ----------------------------------------------------------
  507. // Unmarshall Pass.
  508. // ----------------------------------------------------------
  509. //
  510. for ( ulong n = 0; n < pContext->NumberParams; n++ )
  511. {
  512. NDR64_PARAM_FLAGS *pParamFlags =
  513. ( NDR64_PARAM_FLAGS * ) & ( Params[n].Attributes );
  514. if ( ! pParamFlags->IsIn ||
  515. pParamFlags->IsPipe )
  516. continue;
  517. if ( pParamFlags->IsPartialIgnore )
  518. {
  519. uchar *pArg = pContext->StartofStack + Params[n].StackOffset;
  520. ALIGN( pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );
  521. *(void**)pArg = *(NDR64_PTR_WIRE_TYPE*)pStubMsg->Buffer ? (void*)1 : (void*)0;
  522. pStubMsg->Buffer += sizeof(NDR64_PTR_WIRE_TYPE);
  523. continue;
  524. }
  525. uchar *pArg = pContext->StartofStack + Params[n].StackOffset;
  526. //
  527. // This is for returned basetypes and for pointers to
  528. // basetypes.
  529. //
  530. if ( pParamFlags->IsBasetype )
  531. {
  532. NDR64_FORMAT_CHAR type = *(PFORMAT_STRING)Params[n].Type;
  533. //
  534. // Check for a pointer to a basetype. Set the arg pointer
  535. // at the correct buffer location and you're done.
  536. // Except darn int3264.
  537. //
  538. if ( pParamFlags->IsSimpleRef )
  539. {
  540. ALIGN( pStubMsg->Buffer, NDR64_SIMPLE_TYPE_BUFALIGN( type ) );
  541. *((uchar **)pArg) = pStubMsg->Buffer;
  542. pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE( type );
  543. }
  544. else
  545. {
  546. Ndr64SimpleTypeUnmarshall(
  547. pStubMsg,
  548. pArg,
  549. type );
  550. }
  551. continue;
  552. } // IsBasetype
  553. //
  554. // This is an initialization of [in] and [in,out] ref pointers
  555. // to pointers. These can not be initialized to point into the
  556. // rpc buffer and we want to avoid doing a malloc of 4 bytes!
  557. // 32b: a ref pointer to any pointer, we allocate the pointee pointer.
  558. //
  559. if ( pParamFlags->UseCache )
  560. {
  561. *((void **)pArg) = NdrpAlloca( &pContext->AllocateContext, 8);
  562. // Triple indirection - cool!
  563. **((void ***)pArg) = 0;
  564. }
  565. uchar **ppArg = pParamFlags->IsByValue ? &pArg : (uchar **)pArg;
  566. pStubMsg->ReuseBuffer = pParamFlags->IsForceAllocate;
  567. Ndr64TopLevelTypeUnmarshall(pStubMsg,
  568. ppArg,
  569. Params[n].Type,
  570. pParamFlags->IsForceAllocate &&
  571. !pParamFlags->IsByValue );
  572. // force allocate is param attr: reset the flag after each parameter.
  573. pStubMsg->ReuseBuffer = FALSE;
  574. }
  575. if ( pStubMsg->pCorrInfo )
  576. Ndr64CorrelationPass( pStubMsg );
  577. if (CheckVerificationTrailer(pStubMsg->Buffer, pStubMsg->BufferEnd, pStubMsg->RpcMsg) == FALSE)
  578. RpcRaiseException( RPC_S_ACCESS_DENIED );
  579. }
  580. #pragma code_seg()