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.

1616 lines
48 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. srvcall.c
  5. Abstract :
  6. This file contains the single call Ndr 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. #define USE_STUBLESS_PROXY
  17. #define CINTERFACE
  18. #include "ndrp.h"
  19. #include "ndrole.h"
  20. #include "rpcproxy.h"
  21. #include "hndl.h"
  22. #include "interp2.h"
  23. #include "pipendr.h"
  24. #include "attack.h"
  25. #include <stdarg.h>
  26. #if defined(DEBUG_WALKIP)
  27. HRESULT NdrpReleaseMarshalBuffer(
  28. RPC_MESSAGE *pRpcMsg,
  29. PFORMAT_STRING pFormat,
  30. PMIDL_STUB_DESC pStubDesc,
  31. DWORD dwFlags,
  32. BOOLEAN fServer);
  33. #endif
  34. #pragma code_seg(".orpc")
  35. #if !defined(__RPC_WIN64__)
  36. // No support for the old interpreter on 64b platforms.
  37. void RPC_ENTRY
  38. NdrServerCall(
  39. PRPC_MESSAGE pRpcMsg
  40. )
  41. /*++
  42. Routine Description :
  43. Older Server Interpreter entry point for regular RPC procs.
  44. Arguments :
  45. pRpcMsg - The RPC message.
  46. Return :
  47. None.
  48. --*/
  49. {
  50. ulong dwStubPhase = STUB_UNMARSHAL;
  51. NdrStubCall( 0,
  52. 0,
  53. pRpcMsg,
  54. &dwStubPhase );
  55. }
  56. long RPC_ENTRY
  57. NdrStubCall(
  58. struct IRpcStubBuffer * pThis,
  59. struct IRpcChannelBuffer * pChannel,
  60. PRPC_MESSAGE pRpcMsg,
  61. ulong * pdwStubPhase
  62. )
  63. /*++
  64. Routine Description :
  65. Older Server Interpreter entry point for object RPC procs. Also called by
  66. NdrServerCall, the entry point for regular RPC procs.
  67. Arguments :
  68. pThis - Object proc's 'this' pointer, 0 for non-object procs.
  69. pChannel - Object proc's Channel Buffer, 0 for non-object procs.
  70. pRpcMsg - The RPC message.
  71. pdwStubPhase - Used to track the current interpreter's activity.
  72. Return :
  73. Status of S_OK.
  74. --*/
  75. {
  76. PRPC_SERVER_INTERFACE pServerIfInfo;
  77. PMIDL_SERVER_INFO pServerInfo;
  78. PMIDL_STUB_DESC pStubDesc;
  79. const SERVER_ROUTINE * DispatchTable;
  80. unsigned int ProcNum;
  81. ushort FormatOffset;
  82. PFORMAT_STRING pFormat;
  83. ushort StackSize;
  84. MIDL_STUB_MESSAGE StubMsg;
  85. double ArgBuffer[ARGUMENT_COUNT_THRESHOLD];
  86. REGISTER_TYPE * pArg;
  87. ARG_QUEUE_ELEM QueueElements[QUEUE_LENGTH];
  88. ARG_QUEUE ArgQueue;
  89. int ArgNumModifier;
  90. BOOL fUsesSsAlloc;
  91. //
  92. // In the case of a context handle, the server side manager function has
  93. // to be called with NDRSContextValue(ctxthandle). But then we may need to
  94. // marshall the handle, so NDRSContextValue(ctxthandle) is put in the
  95. // argument buffer and the handle itself is stored in the following array.
  96. // When marshalling a context handle, we marshall from this array.
  97. //
  98. NDR_SCONTEXT CtxtHndl[MAX_CONTEXT_HNDL_NUMBER];
  99. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  100. "marshaling buffer misaligned at server" );
  101. //
  102. // Initialize the argument queue which is used by NdrServerUnmarshall,
  103. // NdrServerMarshall, and NdrServerFree.
  104. //
  105. ArgQueue.Length = 0;
  106. ArgQueue.Queue = QueueElements;
  107. StubMsg.pArgQueue = &ArgQueue;
  108. ProcNum = pRpcMsg->ProcNum;
  109. //
  110. // If OLE, Get a pointer to the stub vtbl and pServerInfo. Else
  111. // just get the pServerInfo the usual way.
  112. //
  113. if ( pThis )
  114. {
  115. //
  116. // pThis is (in unison now!) a pointer to a pointer to a vtable.
  117. // We want some information in this header, so dereference pThis
  118. // and assign that to a pointer to a vtable. Then use the result
  119. // of that assignment to get at the information in the header.
  120. //
  121. IUnknown * pSrvObj;
  122. CInterfaceStubVtbl * pStubVTable;
  123. pSrvObj = (IUnknown * )((CStdStubBuffer *)pThis)->pvServerObject;
  124. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  125. pStubVTable = (CInterfaceStubVtbl *)
  126. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  127. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  128. }
  129. else
  130. {
  131. pServerIfInfo = (PRPC_SERVER_INTERFACE)pRpcMsg->RpcInterfaceInformation;
  132. pServerInfo = (PMIDL_SERVER_INFO)pServerIfInfo->InterpreterInfo;
  133. DispatchTable = pServerInfo->DispatchTable;
  134. }
  135. pStubDesc = pServerInfo->pStubDesc;
  136. FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
  137. pFormat = &((pServerInfo->ProcString)[FormatOffset]);
  138. StackSize = HAS_RPCFLAGS(pFormat[1]) ?
  139. *(ushort *)&pFormat[8] :
  140. *(ushort *)&pFormat[4];
  141. fUsesSsAlloc = pFormat[1] & Oi_RPCSS_ALLOC_USED;
  142. //
  143. // Set up for context handle management.
  144. //
  145. StubMsg.SavedContextHandles = CtxtHndl;
  146. memset( CtxtHndl, 0, sizeof(CtxtHndl) );
  147. pArg = (REGISTER_TYPE *) ArgBuffer;
  148. if ( (StackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH )
  149. {
  150. ArgQueue.Queue =
  151. (ARG_QUEUE_ELEM *)I_RpcAllocate( ((StackSize / sizeof(REGISTER_TYPE)) + 1) *
  152. sizeof(ARG_QUEUE_ELEM) );
  153. }
  154. if ( StackSize > MAX_STACK_SIZE )
  155. {
  156. pArg = (int*)I_RpcAllocate( StackSize );
  157. }
  158. //
  159. // Zero this in case one of the above allocations fail and we raise an exception
  160. // and head to the freeing code.
  161. //
  162. StubMsg.FullPtrXlatTables = 0;
  163. //
  164. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  165. // a try-finally. Put the free phase in the associated finally block.
  166. //
  167. RpcTryFinally
  168. {
  169. if ( ! ArgQueue.Queue || ! pArg )
  170. RpcRaiseException( RPC_S_OUT_OF_MEMORY );
  171. //
  172. // Zero out the arg buffer. We must do this so that parameters
  173. // are properly zeroed before we start unmarshalling. If we catch
  174. // an exception before finishing the unmarshalling we can not leave
  175. // parameters in an unitialized state since we have to do a freeing
  176. // pass.
  177. //
  178. MIDL_memset( pArg,
  179. 0,
  180. StackSize );
  181. //
  182. // If OLE, put pThis in first dword of stack.
  183. //
  184. if (pThis != 0)
  185. pArg[0] = (REGISTER_TYPE)((CStdStubBuffer *)pThis)->pvServerObject;
  186. StubMsg.fHasReturn = FALSE;
  187. //
  188. // Unmarshall all of our parameters.
  189. //
  190. ArgNumModifier = NdrServerUnmarshall( pChannel,
  191. pRpcMsg,
  192. &StubMsg,
  193. pStubDesc,
  194. pFormat,
  195. pArg );
  196. //
  197. // OLE interfaces use pdwStubPhase in the exception filter.
  198. // See CStdStubBuffer_Invoke in rpcproxy.c.
  199. //
  200. if( pFormat[1] & Oi_IGNORE_OBJECT_EXCEPTION_HANDLING )
  201. *pdwStubPhase = STUB_CALL_SERVER_NO_HRESULT;
  202. else
  203. *pdwStubPhase = STUB_CALL_SERVER;
  204. //
  205. // Check for a thunk. Compiler does all the setup for us.
  206. //
  207. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  208. {
  209. pServerInfo->ThunkTable[ProcNum]( &StubMsg );
  210. }
  211. else
  212. {
  213. //
  214. // Note that this ArgNum is not the number of arguments declared
  215. // in the function we called, but really the number of
  216. // REGISTER_TYPEs occupied by the arguments to a function.
  217. //
  218. long ArgNum;
  219. MANAGER_FUNCTION pFunc;
  220. if ( pRpcMsg->ManagerEpv )
  221. pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
  222. else
  223. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  224. ArgNum = (long) StackSize / sizeof(REGISTER_TYPE);
  225. //
  226. // The StackSize includes the size of the return. If we want
  227. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  228. // by 1 when there is a return value AND the current ArgNum count
  229. // is greater than 0. It may also be increased in some cases
  230. // to cover backward compatability with older stubs which sometimes
  231. // had wrong stack sizes.
  232. //
  233. if ( ArgNum )
  234. ArgNum += ArgNumModifier;
  235. NdrCallServerManager( pFunc,
  236. (double *)pArg,
  237. ArgNum,
  238. StubMsg.fHasReturn );
  239. }
  240. *pdwStubPhase = STUB_MARSHAL;
  241. NdrServerMarshall( pThis,
  242. pChannel,
  243. &StubMsg,
  244. pFormat );
  245. }
  246. RpcFinally
  247. {
  248. //
  249. // Skip procedure stuff and the per proc binding information.
  250. //
  251. pFormat += HAS_RPCFLAGS(pFormat[1]) ? 10 : 6;
  252. if ( IS_HANDLE(*pFormat) )
  253. pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
  254. NdrServerFree( &StubMsg,
  255. pFormat,
  256. pThis );
  257. //
  258. // Disable rpcss allocate package if needed.
  259. //
  260. if ( fUsesSsAlloc )
  261. NdrRpcSsDisableAllocate( &StubMsg );
  262. if ( ((StackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH) &&
  263. ArgQueue.Queue )
  264. {
  265. I_RpcFree( ArgQueue.Queue );
  266. }
  267. if ( (StackSize > MAX_STACK_SIZE) && pArg )
  268. {
  269. I_RpcFree( pArg );
  270. }
  271. }
  272. RpcEndFinally
  273. return S_OK;
  274. }
  275. #pragma code_seg()
  276. int RPC_ENTRY
  277. NdrServerUnmarshall(
  278. struct IRpcChannelBuffer * pChannel,
  279. PRPC_MESSAGE pRpcMsg,
  280. PMIDL_STUB_MESSAGE pStubMsg,
  281. PMIDL_STUB_DESC pStubDescriptor,
  282. PFORMAT_STRING pFormat,
  283. void * pParamList
  284. )
  285. {
  286. PFORMAT_STRING pFormatParam;
  287. long StackSize;
  288. void * pArg;
  289. void ** ppArg;
  290. uchar * ArgList;
  291. PARG_QUEUE pArgQueue;
  292. PARG_QUEUE_ELEM pQueue;
  293. long Length;
  294. int ArgNumModifier;
  295. BOOL fIsOleInterface;
  296. BOOL fXlatInit;
  297. BOOL fInitRpcSs;
  298. BOOL fUsesNewInitRoutine;
  299. RpcTryExcept
  300. {
  301. ArgNumModifier = 0;
  302. fIsOleInterface = IS_OLE_INTERFACE( pFormat[1] );
  303. fXlatInit = pFormat[1] & Oi_FULL_PTR_USED;
  304. fInitRpcSs = pFormat[1] & Oi_RPCSS_ALLOC_USED;
  305. fUsesNewInitRoutine = pFormat[1] & Oi_USE_NEW_INIT_ROUTINES;
  306. // Skip to the explicit handle description, if any.
  307. pFormat += HAS_RPCFLAGS(pFormat[1]) ? 10 : 6;
  308. //
  309. // For a handle_t parameter we must pass the handle field of
  310. // the RPC message to the server manager.
  311. //
  312. if ( *pFormat == FC_BIND_PRIMITIVE )
  313. {
  314. pArg = (char *)pParamList + *((ushort *)&pFormat[2]);
  315. if ( IS_HANDLE_PTR(pFormat[1]) )
  316. pArg = *((void **)pArg);
  317. *((handle_t *)pArg) = pRpcMsg->Handle;
  318. }
  319. // Skip to the param format string descriptions.
  320. if ( IS_HANDLE(*pFormat) )
  321. pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
  322. //
  323. // Set ArgList pointing at the address of the first argument.
  324. // This will be the address of the first element of the structure
  325. // holding the arguments in the caller stack.
  326. //
  327. ArgList = (uchar*)pParamList;
  328. //
  329. // If it's an OLE interface, skip the first long on stack, since in this
  330. // case NdrStubCall put pThis in the first long on stack.
  331. //
  332. if ( fIsOleInterface )
  333. GET_NEXT_S_ARG(ArgList, REGISTER_TYPE);
  334. // Initialize the Stub message.
  335. //
  336. if ( ! pChannel )
  337. {
  338. if ( fUsesNewInitRoutine )
  339. {
  340. NdrServerInitializeNew( pRpcMsg,
  341. pStubMsg,
  342. pStubDescriptor );
  343. }
  344. else
  345. {
  346. NdrServerInitialize( pRpcMsg,
  347. pStubMsg,
  348. pStubDescriptor );
  349. }
  350. }
  351. else
  352. {
  353. NdrStubInitialize( pRpcMsg,
  354. pStubMsg,
  355. pStubDescriptor,
  356. pChannel );
  357. }
  358. // Call this after initializing the stub.
  359. if ( fXlatInit )
  360. pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
  361. //
  362. // Set StackTop AFTER the initialize call, since it zeros the field
  363. // out.
  364. //
  365. pStubMsg->StackTop = (uchar*)pParamList;
  366. //
  367. // We must make this check AFTER the call to ServerInitialize,
  368. // since that routine puts the stub descriptor alloc/dealloc routines
  369. // into the stub message.
  370. //
  371. if ( fInitRpcSs )
  372. NdrRpcSsEnableAllocate( pStubMsg );
  373. //
  374. // Do endian/floating point conversions if needed.
  375. //
  376. if ( (pRpcMsg->DataRepresentation & 0X0000FFFFUL) !=
  377. NDR_LOCAL_DATA_REPRESENTATION )
  378. NdrConvert( pStubMsg, pFormat );
  379. pArgQueue = (PARG_QUEUE) pStubMsg->pArgQueue;
  380. //
  381. // --------------------------------------------------------------------
  382. // Unmarshall Pass.
  383. // --------------------------------------------------------------------
  384. //
  385. pStubMsg->ParamNumber = 0;
  386. for ( pQueue = pArgQueue->Queue;
  387. ;
  388. pStubMsg->ParamNumber++, pArgQueue->Length++, pQueue++ )
  389. {
  390. //
  391. // Clear out flags IsReturn, IsBasetype, IsIn, IsOut,
  392. // IsOutOnly, IsDeferredFree, IsDontCallFreeInst.
  393. //
  394. *((long *)(((char *)pQueue) + 0xc)) = 0;
  395. //
  396. // Zero this so that if we catch an exception before finishing the
  397. // unmarshalling and [out] init passes we won't try to free a
  398. // garbage pointer.
  399. //
  400. pQueue->pArg = 0;
  401. //
  402. // Context handles need the parameter number.
  403. //
  404. pQueue->ParamNum = (short) pStubMsg->ParamNumber;
  405. switch ( *pFormat )
  406. {
  407. case FC_IN_PARAM_BASETYPE :
  408. pQueue->IsBasetype = TRUE;
  409. //
  410. // We have to inline the simple type unmarshall so that on
  411. // Alpha, negative longs get properly sign extended.
  412. //
  413. switch ( pFormat[1] )
  414. {
  415. case FC_CHAR :
  416. case FC_BYTE :
  417. case FC_SMALL :
  418. *((REGISTER_TYPE *)ArgList) =
  419. (REGISTER_TYPE) *(pStubMsg->Buffer)++;
  420. break;
  421. case FC_ENUM16 :
  422. case FC_WCHAR :
  423. case FC_SHORT :
  424. ALIGN(pStubMsg->Buffer,1);
  425. *((REGISTER_TYPE *)ArgList) =
  426. (REGISTER_TYPE) *((ushort *&)pStubMsg->Buffer)++;
  427. break;
  428. // case FC_FLOAT : not supported on -Oi
  429. case FC_LONG :
  430. case FC_ENUM32 :
  431. case FC_ERROR_STATUS_T:
  432. ALIGN(pStubMsg->Buffer,3);
  433. *((REGISTER_TYPE *)ArgList) =
  434. (REGISTER_TYPE) *((long *&)pStubMsg->Buffer)++;
  435. break;
  436. // case FC_DOUBLE : not supported on -Oi
  437. case FC_HYPER :
  438. ALIGN(pStubMsg->Buffer,7);
  439. // Let's stay away from casts to doubles.
  440. //
  441. *((ulong *)ArgList) =
  442. *((ulong *&)pStubMsg->Buffer)++;
  443. *((ulong *)(ArgList+4)) =
  444. *((ulong *&)pStubMsg->Buffer)++;
  445. break;
  446. case FC_IGNORE :
  447. break;
  448. default :
  449. NDR_ASSERT(0,"NdrServerUnmarshall : bad format char");
  450. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  451. return 0;
  452. } // switch ( pFormat[1] )
  453. pQueue->pFormat = &pFormat[1];
  454. pQueue->pArg = ArgList;
  455. GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
  456. if ( pFormat[1] == FC_HYPER )
  457. GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
  458. pFormat += 2;
  459. continue;
  460. case FC_IN_PARAM_NO_FREE_INST :
  461. pQueue->IsDontCallFreeInst = TRUE;
  462. // Fall through...
  463. case FC_IN_PARAM :
  464. //
  465. // Here, we break out of the switch statement to the
  466. // unmarshalling code below.
  467. //
  468. break;
  469. case FC_IN_OUT_PARAM :
  470. pQueue->IsOut = TRUE;
  471. //
  472. // Here, we break out of the switch statement to the
  473. // unmarshalling code below.
  474. //
  475. break;
  476. case FC_OUT_PARAM :
  477. pQueue->IsOut = TRUE;
  478. pQueue->IsOutOnly = TRUE;
  479. pFormat += 2;
  480. pFormatParam = pStubDescriptor->pFormatTypes +
  481. *((short *)pFormat);
  482. pFormat += 2;
  483. pQueue->pFormat = pFormatParam;
  484. pQueue->ppArg = (uchar **)ArgList;
  485. //
  486. // An [out] param ALWAYS eats up 4 bytes of stack space.
  487. //
  488. GET_NEXT_S_ARG(ArgList, REGISTER_TYPE);
  489. continue;
  490. case FC_RETURN_PARAM :
  491. pQueue->IsOut = TRUE;
  492. pQueue->IsReturn = TRUE;
  493. pFormatParam = pStubDescriptor->pFormatTypes +
  494. *((short *)(pFormat + 2));
  495. pQueue->pFormat = pFormatParam;
  496. if ( IS_BY_VALUE(*pFormatParam) )
  497. {
  498. pQueue->pArg = (uchar *) ArgList;
  499. pQueue->ppArg = &(pQueue->pArg);
  500. }
  501. else
  502. pQueue->ppArg = (uchar **) ArgList;
  503. //
  504. // Context handle returned by value is the only reason for
  505. // this case here as a context handle has to be initialized.
  506. // A context handle cannot be returned by a pointer.
  507. //
  508. if ( *pFormatParam == FC_BIND_CONTEXT )
  509. {
  510. pStubMsg->SavedContextHandles[pStubMsg->ParamNumber] =
  511. NdrContextHandleInitialize(
  512. pStubMsg,
  513. pFormatParam);
  514. }
  515. //
  516. // The return variable is used in modifying the stacksize
  517. // given us by midl, in order to compute how many
  518. // REGISTER_SIZE items to pass into the manager function.
  519. //
  520. ArgNumModifier--;
  521. pStubMsg->fHasReturn = TRUE;
  522. pArgQueue->Length++;
  523. goto UnmarshallLoopExit;
  524. case FC_RETURN_PARAM_BASETYPE :
  525. pQueue->IsOut = TRUE;
  526. pQueue->IsReturn = TRUE;
  527. pQueue->IsBasetype = TRUE;
  528. pQueue->pFormat = &pFormat[1];
  529. pQueue->pArg = ArgList;
  530. //
  531. // The return variable is used in modifying the stacksize
  532. // given us by midl, in order to compute how many
  533. // REGISTER_SIZE items to pass into the manager function.
  534. //
  535. ArgNumModifier--;
  536. pStubMsg->fHasReturn = TRUE;
  537. pArgQueue->Length++;
  538. goto UnmarshallLoopExit;
  539. default :
  540. goto UnmarshallLoopExit;
  541. } // end of unmarshall pass switch
  542. //
  543. // Now get what ArgList points at and increment over it.
  544. // In the current implementation, what we want is not on the stack
  545. // of the manager function, but is a local in the manager function.
  546. // Thus the code for ppArg below.
  547. //
  548. ppArg = (void **)ArgList;
  549. GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
  550. //
  551. // Get the parameter's format string description.
  552. //
  553. pFormat += 2;
  554. pFormatParam = pStubDescriptor->pFormatTypes + *((short *)pFormat);
  555. //
  556. // Increment main format string past offset field.
  557. //
  558. pFormat += 2;
  559. //
  560. // We must get a double pointer to structs, unions and xmit/rep as.
  561. //
  562. // On MIPS and PPC, an 8 byte aligned structure is passed at an 8 byte
  563. // boundary on the stack. On PowerPC 4 bytes aligned structures which
  564. // are 8 bytes or larger in size are also passed at an 8 byte boundary.
  565. // We check for these cases here and increment our ArgList pointer
  566. // an additional 'int' if necessary to get to the structure.
  567. //
  568. if ( IS_BY_VALUE(*pFormatParam) )
  569. {
  570. pArg = ppArg;
  571. ppArg = &pArg;
  572. }
  573. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
  574. ( pStubMsg,
  575. (uchar **)ppArg,
  576. pFormatParam,
  577. FALSE );
  578. pQueue->pFormat = pFormatParam;
  579. pQueue->pArg = (uchar*)*ppArg;
  580. //
  581. // The second byte of a param's description gives the number of
  582. // ints occupied by the param on the stack.
  583. //
  584. StackSize = pFormat[-3] * sizeof(int);
  585. if ( StackSize > sizeof(REGISTER_TYPE) )
  586. {
  587. StackSize -= sizeof(REGISTER_TYPE);
  588. ArgList += StackSize;
  589. }
  590. } // Unmarshalling loop.
  591. UnmarshallLoopExit:
  592. for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
  593. Length--;
  594. pQueue++ )
  595. {
  596. if ( pQueue->IsOutOnly )
  597. {
  598. pStubMsg->ParamNumber = pQueue->ParamNum;
  599. NdrOutInit( pStubMsg,
  600. pQueue->pFormat,
  601. pQueue->ppArg );
  602. pQueue->pArg = *(pQueue->ppArg);
  603. }
  604. }
  605. }
  606. RpcExcept( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  607. {
  608. // Filter set in rpcndr.h to catch one of the following
  609. // STATUS_ACCESS_VIOLATION
  610. // STATUS_DATATYPE_MISALIGNMENT
  611. // RPC_X_BAD_STUB_DATA
  612. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  613. }
  614. RpcEndExcept
  615. if ( pRpcMsg->BufferLength <
  616. (uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
  617. {
  618. NDR_ASSERT( 0, "NdrStubCall unmarshal: buffer overflow!" );
  619. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  620. }
  621. return ArgNumModifier;
  622. }
  623. void RPC_ENTRY
  624. NdrServerMarshall(
  625. struct IRpcStubBuffer * pThis,
  626. struct IRpcChannelBuffer * pChannel,
  627. PMIDL_STUB_MESSAGE pStubMsg,
  628. PFORMAT_STRING pFormat )
  629. {
  630. PFORMAT_STRING pFormatParam;
  631. PARG_QUEUE pArgQueue;
  632. PARG_QUEUE_ELEM pQueue;
  633. long Length;
  634. pArgQueue = (PARG_QUEUE)pStubMsg->pArgQueue;
  635. //
  636. // Remove?
  637. //
  638. pStubMsg->Memory = 0;
  639. //
  640. // -------------------------------------------------------------------
  641. // Sizing Pass.
  642. // -------------------------------------------------------------------
  643. //
  644. for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
  645. Length--;
  646. pQueue++ )
  647. {
  648. if ( pQueue->IsOut )
  649. {
  650. //
  651. // Must do some special handling for return values.
  652. //
  653. if ( pQueue->IsReturn )
  654. {
  655. if ( pQueue->IsBasetype )
  656. {
  657. //
  658. // Add worse case size of 16 for a simple type return.
  659. //
  660. pStubMsg->BufferLength += 16;
  661. continue;
  662. }
  663. //
  664. // Get the value returned by the server.
  665. //
  666. pQueue->pArg = *(pQueue->ppArg);
  667. //
  668. // We have to do an extra special step for context handles
  669. // which are function return values.
  670. //
  671. // In the unmarshalling phase, we unmarshalled the context
  672. // handle for the return case. But the function we called put
  673. // the user context in the arglist buffer. Before we marshall
  674. // the context handle, we have to put the user context in it.
  675. //
  676. if ( pQueue->pFormat[0] == FC_BIND_CONTEXT )
  677. {
  678. NDR_SCONTEXT SContext;
  679. long ParamNum;
  680. ParamNum = pQueue->ParamNum;
  681. SContext = pStubMsg->SavedContextHandles[ParamNum];
  682. *((uchar **)NDRSContextValue(SContext)) = pQueue->pArg;
  683. }
  684. }
  685. pFormatParam = pQueue->pFormat;
  686. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormatParam)])
  687. ( pStubMsg,
  688. pQueue->pArg,
  689. pFormatParam );
  690. }
  691. }
  692. if ( ! pChannel )
  693. NdrGetBuffer( pStubMsg,
  694. pStubMsg->BufferLength,
  695. 0 );
  696. else
  697. NdrStubGetBuffer( pThis,
  698. pChannel,
  699. pStubMsg );
  700. //
  701. // -------------------------------------------------------------------
  702. // Marshall Pass.
  703. // -------------------------------------------------------------------
  704. //
  705. for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
  706. Length--;
  707. pQueue++ )
  708. {
  709. if ( pQueue->IsOut )
  710. {
  711. if ( pQueue->IsBasetype )
  712. {
  713. //
  714. // Only possible as a return value.
  715. //
  716. NdrSimpleTypeMarshall( pStubMsg,
  717. pQueue->pArg,
  718. pQueue->pFormat[0] );
  719. }
  720. else
  721. {
  722. pFormatParam = pQueue->pFormat;
  723. //
  724. // We need this if we're marshalling a context handle.
  725. //
  726. pStubMsg->ParamNumber = pQueue->ParamNum;
  727. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
  728. ( pStubMsg,
  729. pQueue->pArg,
  730. pFormatParam );
  731. }
  732. }
  733. }
  734. if ( pStubMsg->RpcMsg->BufferLength <
  735. (uint)(pStubMsg->Buffer - (uchar *)pStubMsg->RpcMsg->Buffer) )
  736. {
  737. NDR_ASSERT( 0, "NdrStubCall marshal: buffer overflow!" );
  738. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  739. }
  740. pStubMsg->RpcMsg->BufferLength =
  741. pStubMsg->Buffer - (uchar *) pStubMsg->RpcMsg->Buffer;
  742. }
  743. void
  744. NdrServerFree(
  745. PMIDL_STUB_MESSAGE pStubMsg,
  746. PFORMAT_STRING pFormat,
  747. void * pThis
  748. )
  749. {
  750. PARG_QUEUE pArgQueue;
  751. PARG_QUEUE_ELEM pQueue;
  752. long Length;
  753. PFORMAT_STRING pFormatParam;
  754. uchar * pArg;
  755. pArgQueue = (PARG_QUEUE)pStubMsg->pArgQueue;
  756. for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
  757. Length--;
  758. pQueue++ )
  759. {
  760. if ( pQueue->IsBasetype )
  761. continue;
  762. pFormatParam = pQueue->pFormat;
  763. //
  764. // We have to defer the freeing of pointers to base types in case
  765. // the parameter is [in,out] or [out] and is the size, length, or
  766. // switch specifier for an array, a pointer, or a union. This is
  767. // because we can't free the pointer to base type before we free
  768. // the data structure which uses the pointer to determine it's size.
  769. //
  770. // Note that to make the check as simple as possible [in] only
  771. // pointers to base types will be included, as will string pointers
  772. // of any direction.
  773. //
  774. if ( IS_BASIC_POINTER(*pFormatParam) &&
  775. SIMPLE_POINTER(pFormatParam[1]) )
  776. {
  777. pQueue->IsDeferredFree = TRUE;
  778. continue;
  779. }
  780. pStubMsg->fDontCallFreeInst =
  781. pQueue->IsDontCallFreeInst;
  782. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)])
  783. ( pStubMsg,
  784. pQueue->pArg,
  785. pFormatParam );
  786. //
  787. // Have to explicitly free arrays and strings. But make sure it's
  788. // non-null and not sitting in the buffer.
  789. //
  790. if ( IS_ARRAY_OR_STRING(*pFormatParam) )
  791. {
  792. pArg = pQueue->pArg;
  793. //
  794. // We have to make sure the array/string is non-null in case we
  795. // get an exception before finishing our unmarshalling.
  796. //
  797. if ( pArg &&
  798. ( (pArg < pStubMsg->BufferStart) ||
  799. (pArg > pStubMsg->BufferEnd) ) )
  800. (*pStubMsg->pfnFree)( pArg );
  801. }
  802. }
  803. for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
  804. Length--;
  805. pQueue++ )
  806. {
  807. if ( pQueue->IsDeferredFree )
  808. {
  809. NDR_ASSERT( IS_BASIC_POINTER(*(pQueue->pFormat)),
  810. "NdrServerFree : bad defer logic" );
  811. NdrPointerFree( pStubMsg,
  812. pQueue->pArg,
  813. pQueue->pFormat );
  814. }
  815. }
  816. //
  817. // Free any full pointer resources.
  818. //
  819. if ( pStubMsg->FullPtrXlatTables )
  820. NdrFullPointerXlatFree( pStubMsg->FullPtrXlatTables );
  821. }
  822. #endif // !defined(__RPC_WIN64__)
  823. #pragma code_seg(".orpc")
  824. void
  825. NdrUnmarshallBasetypeInline(
  826. PMIDL_STUB_MESSAGE pStubMsg,
  827. uchar * pArg,
  828. uchar Format
  829. )
  830. {
  831. switch ( Format )
  832. {
  833. case FC_CHAR :
  834. case FC_BYTE :
  835. case FC_SMALL :
  836. case FC_USMALL :
  837. *((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
  838. *(pStubMsg->Buffer)++;
  839. break;
  840. case FC_ENUM16 :
  841. case FC_WCHAR :
  842. case FC_SHORT :
  843. case FC_USHORT :
  844. ALIGN(pStubMsg->Buffer,1);
  845. *((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
  846. *((ushort *&)pStubMsg->Buffer)++;
  847. break;
  848. case FC_FLOAT :
  849. case FC_LONG :
  850. case FC_ULONG :
  851. case FC_ENUM32 :
  852. case FC_ERROR_STATUS_T:
  853. ALIGN(pStubMsg->Buffer,3);
  854. *((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
  855. *((long *&)pStubMsg->Buffer)++;
  856. break;
  857. #if defined(__RPC_WIN64__)
  858. case FC_INT3264:
  859. ALIGN(pStubMsg->Buffer,3);
  860. *((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
  861. *((long *&)pStubMsg->Buffer)++;
  862. break;
  863. case FC_UINT3264:
  864. // REGISTER_TYPE is a signed integral.
  865. ALIGN(pStubMsg->Buffer,3);
  866. *((UINT64 *)pArg) = (UINT64) *((ulong * &)pStubMsg->Buffer)++;
  867. break;
  868. #endif
  869. case FC_DOUBLE :
  870. case FC_HYPER :
  871. ALIGN(pStubMsg->Buffer,7);
  872. *((ulong *)pArg) = *((ulong *&)pStubMsg->Buffer)++;
  873. *((ulong *)(pArg+4)) = *((ulong *&)pStubMsg->Buffer)++;
  874. break;
  875. default :
  876. NDR_ASSERT(0,"NdrUnmarshallBasetypeInline : bad format char");
  877. break;
  878. }
  879. }
  880. #if !defined(__RPC_WIN64__)
  881. void
  882. NdrCallServerManager(
  883. MANAGER_FUNCTION pFtn,
  884. double * pArgs,
  885. ulong NumRegisterArgs,
  886. BOOL fHasReturn )
  887. {
  888. REGISTER_TYPE returnValue;
  889. REGISTER_TYPE * pArg;
  890. pArg = (REGISTER_TYPE *)pArgs;
  891. //
  892. // If we don't have a return value, make sure we don't write past
  893. // the end of our argument buffer!
  894. //
  895. returnValue = Invoke(pFtn,
  896. (REGISTER_TYPE *) pArgs,
  897. NumRegisterArgs);
  898. if ( fHasReturn )
  899. pArg[NumRegisterArgs] = returnValue;
  900. }
  901. #endif // !defined(__RPC_WIN64__)
  902. void RPC_ENTRY
  903. NdrServerCall2(
  904. PRPC_MESSAGE pRpcMsg
  905. )
  906. /*++
  907. Routine Description :
  908. Server Interpreter entry point for regular RPC procs.
  909. Arguments :
  910. pRpcMsg - The RPC message.
  911. Return :
  912. None.
  913. --*/
  914. {
  915. ulong dwStubPhase = STUB_UNMARSHAL;
  916. NdrStubCall2( 0,
  917. 0,
  918. pRpcMsg,
  919. &dwStubPhase );
  920. }
  921. long RPC_ENTRY
  922. NdrStubCall2(
  923. struct IRpcStubBuffer * pThis,
  924. struct IRpcChannelBuffer * pChannel,
  925. PRPC_MESSAGE pRpcMsg,
  926. ulong * pdwStubPhase
  927. )
  928. /*++
  929. Routine Description :
  930. Server Interpreter entry point for object RPC procs. Also called by
  931. NdrServerCall, the entry point for regular RPC procs.
  932. Arguments :
  933. pThis - Object proc's 'this' pointer, 0 for non-object procs.
  934. pChannel - Object proc's Channel Buffer, 0 for non-object procs.
  935. pRpcMsg - The RPC message.
  936. pdwStubPhase - Used to track the current interpreter's activity.
  937. Return :
  938. Status of S_OK.
  939. --*/
  940. {
  941. PRPC_SERVER_INTERFACE pServerIfInfo;
  942. PMIDL_SERVER_INFO pServerInfo;
  943. PMIDL_STUB_DESC pStubDesc;
  944. const SERVER_ROUTINE * DispatchTable;
  945. ushort ProcNum;
  946. ushort FormatOffset;
  947. PFORMAT_STRING pFormat;
  948. MIDL_STUB_MESSAGE StubMsg;
  949. uchar * pArgBuffer;
  950. uchar * pArg;
  951. #if defined(_M_IX86) && (_MSC_FULL_VER <= 13008982)
  952. volatile BOOL fBadStubDataException = FALSE;
  953. #else
  954. BOOL fBadStubDataException = FALSE;
  955. #endif
  956. ulong n;
  957. PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
  958. boolean NotifyAppInvoked = FALSE;
  959. NDR_PROC_CONTEXT ProcContext;
  960. //
  961. // In the case of a context handle, the server side manager function has
  962. // to be called with NDRSContextValue(ctxthandle). But then we may need to
  963. // marshall the handle, so NDRSContextValue(ctxthandle) is put in the
  964. // argument buffer and the handle itself is stored in the following array.
  965. // When marshalling a context handle, we marshall from this array.
  966. //
  967. NDR_SCONTEXT CtxtHndl[MAX_CONTEXT_HNDL_NUMBER];
  968. ProcNum = (ushort) pRpcMsg->ProcNum;
  969. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  970. "marshaling buffer misaligned at server" );
  971. //
  972. // If OLE, Get a pointer to the stub vtbl and pServerInfo. Else
  973. // just get the pServerInfo the usual way.
  974. //
  975. if ( pThis )
  976. {
  977. //
  978. // pThis is (in unison now!) a pointer to a pointer to a vtable.
  979. // We want some information in this header, so dereference pThis
  980. // and assign that to a pointer to a vtable. Then use the result
  981. // of that assignment to get at the information in the header.
  982. //
  983. IUnknown * pSrvObj;
  984. CInterfaceStubVtbl * pStubVTable;
  985. pSrvObj = (IUnknown * )((CStdStubBuffer *)pThis)->pvServerObject;
  986. DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
  987. pStubVTable = (CInterfaceStubVtbl *)
  988. (*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
  989. pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
  990. }
  991. else
  992. {
  993. pServerIfInfo = (PRPC_SERVER_INTERFACE)pRpcMsg->RpcInterfaceInformation;
  994. pServerInfo = (PMIDL_SERVER_INFO)pServerIfInfo->InterpreterInfo;
  995. DispatchTable = pServerInfo->DispatchTable;
  996. }
  997. pStubDesc = pServerInfo->pStubDesc;
  998. FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
  999. pFormat = &((pServerInfo->ProcString)[FormatOffset]);
  1000. MulNdrpInitializeContextFromProc( XFER_SYNTAX_DCE, pFormat, &ProcContext, NULL );
  1001. //
  1002. // Yes, do this here outside of our RpcTryFinally block. If we
  1003. // can't allocate the arg buffer there's nothing more to do, so
  1004. // raise an exception and return control to the RPC runtime.
  1005. //
  1006. // Alloca throws an exception on an error.
  1007. pArgBuffer = (uchar*)alloca(ProcContext.StackSize);
  1008. //
  1009. // Zero out the arg buffer. We must do this so that parameters
  1010. // are properly zeroed before we start unmarshalling. If we catch
  1011. // an exception before finishing the unmarshalling we can not leave
  1012. // parameters in an unitialized state since we have to do a freeing
  1013. // pass.
  1014. //
  1015. MIDL_memset( pArgBuffer,
  1016. 0,
  1017. ProcContext.StackSize );
  1018. // we have to setup this again because we don't know the size when
  1019. // initializing the proc context.
  1020. ProcContext.StartofStack = pArgBuffer;
  1021. StubMsg.pContext = &ProcContext;
  1022. // We need to setup stack AFTER proc header is read so we can
  1023. // know how big the virtual stack is.
  1024. //
  1025. // Set up for context handle management.
  1026. //
  1027. StubMsg.SavedContextHandles = CtxtHndl;
  1028. memset( CtxtHndl, 0, sizeof(CtxtHndl) );
  1029. if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasExtensions )
  1030. pHeaderExts = &ProcContext.NdrInfo.pProcDesc->NdrExts;
  1031. //
  1032. // Wrap the unmarshalling, mgr call and marshalling in the try block of
  1033. // a try-finally. Put the free phase in the associated finally block.
  1034. //
  1035. RpcTryFinally
  1036. {
  1037. // General server initializaiton (NULL async message)
  1038. NdrpServerInit( &StubMsg, pRpcMsg, pStubDesc, pThis, pChannel, NULL );
  1039. // Raise exceptions after initializing the stub.
  1040. RpcTryExcept
  1041. {
  1042. // --------------------------------
  1043. // Unmarshall all of our parameters.
  1044. // --------------------------------
  1045. NdrpServerUnMarshal( &StubMsg );
  1046. if ( pRpcMsg->BufferLength <
  1047. (uint)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
  1048. {
  1049. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  1050. }
  1051. }
  1052. RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
  1053. {
  1054. // Filter set in rpcndr.h to catch one of the following
  1055. // STATUS_ACCESS_VIOLATION
  1056. // STATUS_DATATYPE_MISALIGNMENT
  1057. // RPC_X_BAD_STUB_DATA
  1058. NdrpFreeMemoryList( &StubMsg );
  1059. fBadStubDataException = TRUE;
  1060. if ( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
  1061. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  1062. else
  1063. RpcRaiseException( RpcExceptionCode() );
  1064. }
  1065. RpcEndExcept
  1066. NdrpServerOutInit( &StubMsg );
  1067. //
  1068. // Do [out] initialization.
  1069. //
  1070. //
  1071. // Unblock the first pipe; this needs to be after unmarshalling
  1072. // because the buffer may need to be changed to the secondary one.
  1073. // In the out only pipes case this happens immediately.
  1074. //
  1075. if ( ProcContext.HasPipe )
  1076. NdrMarkNextActivePipe( ProcContext.pPipeDesc );
  1077. //
  1078. // OLE interfaces use pdwStubPhase in the exception filter.
  1079. // See CStdStubBuffer_Invoke in rpcproxy.c.
  1080. //
  1081. if( pFormat[1] & Oi_IGNORE_OBJECT_EXCEPTION_HANDLING )
  1082. *pdwStubPhase = STUB_CALL_SERVER_NO_HRESULT;
  1083. else
  1084. *pdwStubPhase = STUB_CALL_SERVER;
  1085. NotifyAppInvoked = TRUE;
  1086. //
  1087. // Check for a thunk. Compiler does all the setup for us.
  1088. //
  1089. if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
  1090. {
  1091. pServerInfo->ThunkTable[ProcNum]( &StubMsg );
  1092. }
  1093. else
  1094. {
  1095. //
  1096. // Note that this ArgNum is not the number of arguments declared
  1097. // in the function we called, but really the number of
  1098. // REGISTER_TYPEs occupied by the arguments to a function.
  1099. //
  1100. long ArgNum;
  1101. MANAGER_FUNCTION pFunc;
  1102. REGISTER_TYPE returnValue;
  1103. if ( pRpcMsg->ManagerEpv )
  1104. pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
  1105. else
  1106. pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
  1107. ArgNum = (long) ProcContext.StackSize / sizeof(REGISTER_TYPE);
  1108. //
  1109. // The StackSize includes the size of the return. If we want
  1110. // just the number of REGISTER_TYPES, then ArgNum must be reduced
  1111. // by 1 when there is a return value AND the current ArgNum count
  1112. // is greater than 0.
  1113. //
  1114. if ( ArgNum &&
  1115. ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasReturn &&
  1116. !ProcContext.HasComplexReturn )
  1117. ArgNum--;
  1118. returnValue = Invoke( pFunc,
  1119. (REGISTER_TYPE *)pArgBuffer,
  1120. #if defined(_IA64_)
  1121. pHeaderExts != NULL ? ((PNDR_PROC_HEADER_EXTS64)pHeaderExts)->FloatArgMask
  1122. : 0,
  1123. #endif
  1124. ArgNum);
  1125. if( ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasReturn)
  1126. {
  1127. if ( !ProcContext.HasComplexReturn )
  1128. ((REGISTER_TYPE *)pArgBuffer)[ArgNum] = returnValue;
  1129. // Pass the app's return value to OLE channel
  1130. if ( pThis )
  1131. (*pfnDcomChannelSetHResult)( pRpcMsg,
  1132. NULL, // reserved
  1133. (HRESULT) returnValue );
  1134. }
  1135. }
  1136. // Important for context handle cleanup.
  1137. *pdwStubPhase = STUB_MARSHAL;
  1138. if ( ProcContext.HasPipe )
  1139. {
  1140. NdrIsAppDoneWithPipes( ProcContext.pPipeDesc );
  1141. StubMsg.BufferLength += ProcContext.NdrInfo.pProcDesc->ServerBufferSize;
  1142. }
  1143. else
  1144. StubMsg.BufferLength = ProcContext.NdrInfo.pProcDesc->ServerBufferSize;
  1145. if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.ServerMustSize )
  1146. {
  1147. //
  1148. // Buffer size pass.
  1149. //
  1150. NdrpSizing( &StubMsg,
  1151. FALSE ); // is server
  1152. }
  1153. if ( ProcContext.HasPipe && ProcContext.pPipeDesc->OutPipes )
  1154. {
  1155. NdrGetPartialBuffer( & StubMsg );
  1156. StubMsg.RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
  1157. }
  1158. else
  1159. {
  1160. if ( ! pChannel )
  1161. {
  1162. NdrGetBuffer( &StubMsg,
  1163. StubMsg.BufferLength,
  1164. 0 );
  1165. }
  1166. else
  1167. NdrStubGetBuffer( pThis,
  1168. pChannel,
  1169. &StubMsg );
  1170. }
  1171. //
  1172. // Marshall pass.
  1173. //
  1174. NdrpServerMarshal( &StubMsg,
  1175. ( pThis != NULL ) );
  1176. pRpcMsg->BufferLength = (ulong) ( StubMsg.Buffer - (uchar *) pRpcMsg->Buffer );
  1177. #if defined(DEBUG_WALKIP)
  1178. if ( pChannel )
  1179. {
  1180. NdrpReleaseMarshalBuffer(
  1181. StubMsg.RpcMsg,
  1182. pFormat,
  1183. StubMsg.StubDesc,
  1184. 1, //BUFFER_OUT
  1185. true );
  1186. }
  1187. #endif
  1188. }
  1189. RpcFinally
  1190. {
  1191. // clean up context handles if exception is thrown in either marshalling or
  1192. // manager routine.
  1193. if ( RpcAbnormalTermination() && ! pChannel )
  1194. {
  1195. NdrpCleanupServerContextHandles( &StubMsg,
  1196. pArgBuffer,
  1197. STUB_MARSHAL != *pdwStubPhase);
  1198. }
  1199. // If we died because of bad stub data, don't free the params here since they
  1200. // were freed using a linked list of memory in the exception handler above.
  1201. if ( ! fBadStubDataException )
  1202. {
  1203. NdrpFreeParams( &StubMsg,
  1204. ProcContext.NumberParams,
  1205. ( PARAM_DESCRIPTION * )ProcContext.Params,
  1206. pArgBuffer );
  1207. }
  1208. //
  1209. // Deferred frees. Actually, this should only be necessary if you
  1210. // had a pointer to enum16 in a *_is expression.
  1211. //
  1212. //
  1213. // Free any full pointer resources.
  1214. //
  1215. NdrFullPointerXlatFree( StubMsg.FullPtrXlatTables );
  1216. //
  1217. // Disable rpcss allocate package if needed.
  1218. //
  1219. if ( ProcContext.NdrInfo.InterpreterFlags.RpcSsAllocUsed )
  1220. NdrRpcSsDisableAllocate( &StubMsg );
  1221. //
  1222. // Clean up pipe objects
  1223. //
  1224. NdrCorrelationFree( &StubMsg );
  1225. NdrpAllocaDestroy( &ProcContext.AllocateContext );
  1226. if ( pHeaderExts != 0
  1227. && ( pHeaderExts->Flags2.HasNotify
  1228. || pHeaderExts->Flags2.HasNotify2 ) )
  1229. {
  1230. NDR_NOTIFY_ROUTINE pfnNotify;
  1231. pfnNotify = StubMsg.StubDesc->NotifyRoutineTable[ pHeaderExts->NotifyIndex ];
  1232. if ( pHeaderExts->Flags2.HasNotify2 )
  1233. {
  1234. ((NDR_NOTIFY2_ROUTINE)pfnNotify)(NotifyAppInvoked);
  1235. }
  1236. else
  1237. pfnNotify();
  1238. }
  1239. }
  1240. RpcEndFinally
  1241. return S_OK;
  1242. }
  1243. void
  1244. NdrpFreeParams(
  1245. MIDL_STUB_MESSAGE * pStubMsg,
  1246. long NumberParams,
  1247. PPARAM_DESCRIPTION Params,
  1248. uchar * pArgBuffer
  1249. )
  1250. /*++
  1251. Routine Description :
  1252. Frees the memory associated with function parameters as required.
  1253. Arguments :
  1254. pStubMsg - Supplies a pointer to the stub message.
  1255. NumberParams - Supplies the number of parameters for this procedure.
  1256. Params - Supplies a pointer to the parameter list for this function.
  1257. pArgBuffer - Supplies a pointer to the virtual stack.
  1258. pParamFilter - Supplies a filter that is used to determine which functions
  1259. are to be considered. This function should return TRUE if
  1260. the parameter should be considered. If pParamFilter is NULL,
  1261. the default filter is used which is all parameters that have
  1262. MustFree set.
  1263. Return :
  1264. None.
  1265. --*/
  1266. {
  1267. long n;
  1268. PMIDL_STUB_DESC pStubDesc = pStubMsg->StubDesc;
  1269. PFORMAT_STRING pFormatParam;
  1270. uchar * pArg;
  1271. for ( n = 0; n < NumberParams; n++ )
  1272. {
  1273. if ( ! Params[n].ParamAttr.MustFree )
  1274. continue;
  1275. pArg = pArgBuffer + Params[n].StackOffset;
  1276. if ( ! Params[n].ParamAttr.IsByValue )
  1277. pArg = *((uchar **)pArg);
  1278. pFormatParam = pStubDesc->pFormatTypes +
  1279. Params[n].TypeOffset;
  1280. if ( pArg )
  1281. {
  1282. pStubMsg->fDontCallFreeInst =
  1283. Params[n].ParamAttr.IsDontCallFreeInst;
  1284. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)])
  1285. ( pStubMsg,
  1286. pArg,
  1287. pFormatParam );
  1288. }
  1289. //
  1290. // We have to check if we need to free any simple ref pointer,
  1291. // since we skipped it's NdrPointerFree call. We also have
  1292. // to explicitly free arrays and strings. But make sure it's
  1293. // non-null and not sitting in the buffer.
  1294. //
  1295. if ( Params[n].ParamAttr.IsSimpleRef ||
  1296. IS_ARRAY_OR_STRING(*pFormatParam) )
  1297. {
  1298. //
  1299. // Don't free [out] params that we're allocated on the
  1300. // interpreter's stack.
  1301. //
  1302. if ( Params[n].ParamAttr.ServerAllocSize != 0 )
  1303. continue;
  1304. //
  1305. // We have to make sure the array/string is non-null in case we
  1306. // get an exception before finishing our unmarshalling.
  1307. //
  1308. if ( pArg &&
  1309. ( (pArg < pStubMsg->BufferStart) ||
  1310. (pArg > pStubMsg->BufferEnd) ) )
  1311. (*pStubMsg->pfnFree)( pArg );
  1312. }
  1313. } // for
  1314. }
  1315. #pragma code_seg()