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.

1062 lines
34 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. cltcall.c
  5. Abstract :
  6. This file contains the single call Ndr routine for the client side.
  7. Author :
  8. David Kays dkays October 1993.
  9. Revision History :
  10. brucemc 11/15/93 Added struct by value support, corrected
  11. varargs use.
  12. brucemc 12/20/93 Binding handle support
  13. ryszardk 3/12/94 handle optimization and fixes
  14. ---------------------------------------------------------------------*/
  15. #define USE_STUBLESS_PROXY
  16. #define CINTERFACE
  17. #include <stdarg.h>
  18. #include "ndrp.h"
  19. #include "hndl.h"
  20. #include "interp2.h"
  21. #include "pipendr.h"
  22. #include "attack.h"
  23. #include "ndrole.h"
  24. #include "rpcproxy.h"
  25. #pragma code_seg(".orpc")
  26. #if defined ( DEBUG_142065 )
  27. #define _STUB_CALCSIZE 0x1
  28. #define _STUB_GETBUFFER 0x2
  29. #define _STUB_MARSHAL 0x4
  30. #define _STUB_SENDRECEIVE 0x8
  31. #define _STUB_UNMARSHAL 0x10
  32. #define _STUB_EXCEPTION 0x20
  33. #define _STUB_AFTER_EXCEPTION 0x40
  34. #define _STUB_FREE 0x80
  35. typedef struct _STUB_TRACKING_INFO
  36. {
  37. PMIDL_STUB_MESSAGE pStubMsg;
  38. RPC_MESSAGE RpcMsg;
  39. ulong StubPhase;
  40. ulong ExceptionCode;
  41. } STUB_TRACKING_INFO;
  42. #endif
  43. CLIENT_CALL_RETURN RPC_ENTRY
  44. NdrpClientCall2(
  45. PMIDL_STUB_DESC pStubDescriptor,
  46. PFORMAT_STRING pFormat,
  47. uchar * StartofStack
  48. );
  49. #if ! defined(__RPC_WIN64__)
  50. // The old interpreter is not supported on 64b platforms.
  51. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  52. NdrClientCall(
  53. PMIDL_STUB_DESC pStubDescriptor,
  54. PFORMAT_STRING pFormat,
  55. ...
  56. )
  57. {
  58. RPC_MESSAGE RpcMsg;
  59. MIDL_STUB_MESSAGE StubMsg;
  60. PFORMAT_STRING pFormatParam, pFormatParamSaved;
  61. PFORMAT_STRING pHandleFormatSave;
  62. ulong ProcNum;
  63. ulong RpcFlags;
  64. long StackSize;
  65. long TotalStackSize;
  66. CLIENT_CALL_RETURN ReturnValue;
  67. va_list ArgList;
  68. void * pArg;
  69. void ** ppArg;
  70. uchar * StartofStack;
  71. handle_t Handle;
  72. handle_t SavedGenericHandle = NULL;
  73. uchar HandleType;
  74. void * pThis;
  75. INTERPRETER_FLAGS InterpreterFlags;
  76. ARG_QUEUE ArgQueue;
  77. ARG_QUEUE_ELEM QueueElements[QUEUE_LENGTH];
  78. PARG_QUEUE_ELEM pQueue;
  79. long Length;
  80. ArgQueue.Length = 0;
  81. ArgQueue.Queue = QueueElements;
  82. HandleType = *pFormat++;
  83. InterpreterFlags = *((PINTERPRETER_FLAGS)pFormat++);
  84. StubMsg.FullPtrXlatTables = 0;
  85. if ( InterpreterFlags.HasRpcFlags )
  86. RpcFlags = *((ulong UNALIGNED *&)pFormat)++;
  87. else
  88. RpcFlags = 0;
  89. ProcNum = *((ushort *&)pFormat)++;
  90. TotalStackSize = *((ushort *&)pFormat)++;
  91. if ( (TotalStackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH )
  92. {
  93. ArgQueue.Queue = (PARG_QUEUE_ELEM)
  94. I_RpcAllocate( (unsigned int)
  95. (((TotalStackSize / sizeof(REGISTER_TYPE)) + 1) *
  96. sizeof(ARG_QUEUE_ELEM) ) );
  97. }
  98. ReturnValue.Pointer = 0;
  99. //
  100. // Get address of argument to this function following pFormat. This
  101. // is the address of the address of the first argument of the function
  102. // calling this function.
  103. //
  104. INIT_ARG( ArgList, pFormat);
  105. //
  106. // Get the address of the first argument of the function calling this
  107. // function. Save this in a local variable and in the main data structure.
  108. //
  109. GET_FIRST_IN_ARG(ArgList);
  110. StartofStack = (uchar*)GET_STACK_START(ArgList);
  111. //
  112. // Wrap everything in a try-finally pair. The finally clause does the
  113. // required freeing of resources (RpcBuffer and Full ptr package).
  114. //
  115. RpcTryFinally
  116. {
  117. //
  118. // Use a nested try-except pair to support OLE. In OLE case, test the
  119. // exception and map it if required, then set the return value. In
  120. // nonOLE case, just reraise the exception.
  121. //
  122. RpcTryExcept
  123. {
  124. //
  125. // Stash away the place in the format string describing the handle.
  126. //
  127. pHandleFormatSave = pFormat;
  128. // Bind the client to the server. Check for an implicit or
  129. // explicit generic handle.
  130. //
  131. if ( InterpreterFlags.ObjectProc )
  132. {
  133. pThis = *(void **)StartofStack;
  134. NdrProxyInitialize( pThis,
  135. &RpcMsg,
  136. &StubMsg,
  137. pStubDescriptor,
  138. ProcNum );
  139. }
  140. else
  141. {
  142. if ( InterpreterFlags.UseNewInitRoutines )
  143. {
  144. NdrClientInitializeNew( &RpcMsg,
  145. &StubMsg,
  146. pStubDescriptor,
  147. (uint) ProcNum );
  148. }
  149. else
  150. {
  151. NdrClientInitialize( &RpcMsg,
  152. &StubMsg,
  153. pStubDescriptor,
  154. (uint) ProcNum );
  155. }
  156. if ( HandleType )
  157. {
  158. //
  159. // We have an implicit handle.
  160. //
  161. Handle = ImplicitBindHandleMgr( pStubDescriptor,
  162. HandleType,
  163. &SavedGenericHandle);
  164. }
  165. else
  166. {
  167. Handle = ExplicitBindHandleMgr( pStubDescriptor,
  168. StartofStack,
  169. pFormat,
  170. &SavedGenericHandle );
  171. pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
  172. }
  173. }
  174. if ( InterpreterFlags.RpcSsAllocUsed )
  175. NdrRpcSmSetClientToOsf( &StubMsg );
  176. // Set Rpc flags after the call to client initialize.
  177. StubMsg.RpcMsg->RpcFlags = RpcFlags;
  178. // Must do this before the sizing pass!
  179. StubMsg.StackTop = StartofStack;
  180. //
  181. // Make ArgQueue check after all setup/binding is finished.
  182. //
  183. if ( ! ArgQueue.Queue )
  184. RpcRaiseException( RPC_S_OUT_OF_MEMORY );
  185. if ( InterpreterFlags.FullPtrUsed )
  186. StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_CLIENT );
  187. // Save beginning of param description.
  188. pFormatParamSaved = pFormat;
  189. //
  190. // ----------------------------------------------------------------
  191. // Sizing Pass.
  192. // ----------------------------------------------------------------
  193. //
  194. //
  195. // If it's an OLE interface, then the this pointer will occupy
  196. // the first dword on the stack. For each loop hereafter, skip
  197. // the first dword.
  198. //
  199. if ( InterpreterFlags.ObjectProc )
  200. {
  201. GET_NEXT_C_ARG(ArgList,long);
  202. GET_STACK_POINTER(ArgList,long);
  203. }
  204. for ( pQueue = ArgQueue.Queue; ; ArgQueue.Length++, pQueue++ )
  205. {
  206. //
  207. // Clear out flags IsReturn, IsBasetype, IsIn, IsOut,
  208. // IsOutOnly, IsDeferredFree, IsDontCallFreeInst.
  209. //
  210. *((long *)(((char *)pQueue) + 0xc)) = 0;
  211. switch ( *pFormat )
  212. {
  213. case FC_IN_PARAM_BASETYPE :
  214. pQueue->IsIn = TRUE;
  215. pQueue->IsBasetype = TRUE;
  216. SIMPLE_TYPE_BUF_INCREMENT(StubMsg.BufferLength,
  217. pFormat[1]);
  218. //
  219. // Increment arg list pointer correctly.
  220. //
  221. switch ( pFormat[1] )
  222. {
  223. case FC_HYPER :
  224. pArg = GET_STACK_POINTER(ArgList,hyper);
  225. GET_NEXT_C_ARG(ArgList,hyper);
  226. break;
  227. case FC_LONG:
  228. pArg = GET_STACK_POINTER(ArgList,long);
  229. GET_NEXT_C_ARG(ArgList,long);
  230. break;
  231. default :
  232. pArg = GET_STACK_POINTER(ArgList,int);
  233. GET_NEXT_C_ARG(ArgList,int);
  234. break;
  235. }
  236. pQueue->pFormat = &pFormat[1];
  237. pQueue->pArg = (uchar*)pArg;
  238. pFormat += 2;
  239. continue;
  240. case FC_IN_PARAM :
  241. case FC_IN_PARAM_NO_FREE_INST :
  242. pQueue->IsIn = TRUE;
  243. break;
  244. case FC_IN_OUT_PARAM :
  245. pQueue->IsIn = TRUE;
  246. pQueue->IsOut = TRUE;
  247. break;
  248. case FC_OUT_PARAM :
  249. pQueue->IsOut = TRUE;
  250. pQueue->IsOutOnly = TRUE;
  251. //
  252. // An [out] param ALWAYS eats up at 4 bytes of stack
  253. // space on x86, MIPS and PPC and 8 bytes on axp
  254. // because it must be a pointer or an array.
  255. //
  256. ppArg = (void **) GET_STACK_POINTER(ArgList,long);
  257. GET_NEXT_C_ARG(ArgList,long);
  258. pFormat += 2;
  259. pFormatParam = pStubDescriptor->pFormatTypes +
  260. *((short *)pFormat);
  261. pFormat += 2;
  262. pQueue->pFormat = pFormatParam;
  263. pQueue->ppArg = (uchar **)ppArg;
  264. if ( InterpreterFlags.ObjectProc )
  265. {
  266. NdrClientZeroOut( &StubMsg,
  267. pFormatParam,
  268. (uchar*)*ppArg );
  269. }
  270. continue;
  271. case FC_RETURN_PARAM_BASETYPE :
  272. pQueue->IsOut = TRUE;
  273. pQueue->IsBasetype = TRUE;
  274. pQueue->pFormat = &pFormat[1];
  275. pQueue->pArg = (uchar *)&ReturnValue;
  276. ArgQueue.Length++;
  277. goto SizeLoopExit;
  278. case FC_RETURN_PARAM :
  279. pQueue->IsOut = TRUE;
  280. pFormat += 2;
  281. pFormatParam = pStubDescriptor->pFormatTypes +
  282. *((short *)pFormat);
  283. pQueue->pFormat = pFormatParam;
  284. if ( IS_BY_VALUE(*pFormatParam) )
  285. {
  286. pQueue->pArg = (uchar *)&ReturnValue;
  287. pQueue->ppArg = &(pQueue->pArg);
  288. }
  289. else
  290. {
  291. pQueue->ppArg = (uchar **)&ReturnValue;
  292. }
  293. ArgQueue.Length++;
  294. goto SizeLoopExit;
  295. default :
  296. goto SizeLoopExit;
  297. }
  298. //
  299. // Get the paramter's format string description.
  300. //
  301. pFormat += 2;
  302. pFormatParam = pStubDescriptor->pFormatTypes +
  303. *((short *)pFormat);
  304. pQueue->pFormat = pFormatParam;
  305. // Increment main format string past offset field.
  306. pFormat += 2;
  307. pArg = (uchar *) GET_STACK_POINTER(ArgList, int);
  308. GET_NEXT_C_ARG(ArgList, int);
  309. if ( IS_BY_VALUE( *pFormatParam ) )
  310. {
  311. pQueue->pArg = (uchar*)pArg;
  312. // Only transmit as will ever need this.
  313. pQueue->ppArg = &pQueue->pArg;
  314. }
  315. else
  316. {
  317. pQueue->pArg = *((uchar **)pArg);
  318. pQueue->ppArg = (uchar**)pArg;
  319. pArg = *((uchar **)pArg);
  320. }
  321. //
  322. // The second byte of a param's description gives the number of
  323. // ints occupied by the param on the stack.
  324. //
  325. StackSize = pFormat[-3] * sizeof(int);
  326. if ( StackSize > sizeof(REGISTER_TYPE) )
  327. {
  328. StackSize -= sizeof(REGISTER_TYPE);
  329. SKIP_STRUCT_ON_STACK(ArgList, StackSize);
  330. }
  331. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormatParam)])
  332. ( &StubMsg,
  333. (uchar*)pArg,
  334. pFormatParam );
  335. } // for(;;) sizing pass
  336. SizeLoopExit:
  337. //
  338. // Make the new GetBuffer call.
  339. //
  340. if ( (HandleType == FC_AUTO_HANDLE) &&
  341. (! InterpreterFlags.ObjectProc) )
  342. {
  343. NdrNsGetBuffer( &StubMsg,
  344. StubMsg.BufferLength,
  345. Handle );
  346. }
  347. else
  348. {
  349. if ( InterpreterFlags.ObjectProc )
  350. NdrProxyGetBuffer( pThis,
  351. &StubMsg );
  352. else
  353. NdrGetBuffer( &StubMsg,
  354. StubMsg.BufferLength,
  355. Handle );
  356. }
  357. NDR_ASSERT( StubMsg.fBufferValid, "Invalid buffer" );
  358. //
  359. // ----------------------------------------------------------
  360. // Marshall Pass.
  361. // ----------------------------------------------------------
  362. //
  363. for ( Length = ArgQueue.Length, pQueue = ArgQueue.Queue;
  364. Length--;
  365. pQueue++ )
  366. {
  367. if ( pQueue->IsIn )
  368. {
  369. if ( pQueue->IsBasetype )
  370. {
  371. NdrSimpleTypeMarshall( &StubMsg,
  372. pQueue->pArg,
  373. *(pQueue->pFormat) );
  374. }
  375. else
  376. {
  377. pFormatParam = pQueue->pFormat;
  378. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
  379. ( &StubMsg,
  380. pQueue->pArg,
  381. pFormatParam );
  382. }
  383. }
  384. }
  385. //
  386. // Make the RPC call.
  387. //
  388. if ( (HandleType == FC_AUTO_HANDLE) &&
  389. (!InterpreterFlags.ObjectProc) )
  390. {
  391. NdrNsSendReceive( &StubMsg,
  392. StubMsg.Buffer,
  393. (RPC_BINDING_HANDLE *) pStubDescriptor->
  394. IMPLICIT_HANDLE_INFO.pAutoHandle );
  395. }
  396. else
  397. {
  398. if ( InterpreterFlags.ObjectProc )
  399. NdrProxySendReceive( pThis, &StubMsg );
  400. else
  401. NdrSendReceive( &StubMsg, StubMsg.Buffer );
  402. }
  403. //
  404. // Do endian/floating point conversions.
  405. //
  406. if ( (RpcMsg.DataRepresentation & 0X0000FFFFUL) !=
  407. NDR_LOCAL_DATA_REPRESENTATION )
  408. NdrConvert( &StubMsg, pFormatParamSaved );
  409. //
  410. // ----------------------------------------------------------
  411. // Unmarshall Pass.
  412. // ----------------------------------------------------------
  413. //
  414. for ( Length = ArgQueue.Length, pQueue = ArgQueue.Queue;
  415. Length--;
  416. pQueue++ )
  417. {
  418. if ( pQueue->IsOut )
  419. {
  420. if ( pQueue->IsBasetype )
  421. {
  422. NdrSimpleTypeUnmarshall( &StubMsg,
  423. pQueue->pArg,
  424. *(pQueue->pFormat) );
  425. }
  426. else
  427. {
  428. pFormatParam = pQueue->pFormat;
  429. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
  430. ( &StubMsg,
  431. pQueue->ppArg,
  432. pFormatParam,
  433. FALSE );
  434. }
  435. }
  436. }
  437. }
  438. RpcExcept( EXCEPTION_FLAG )
  439. {
  440. RPC_STATUS ExceptionCode = RpcExceptionCode();
  441. //
  442. // In OLE, since they don't know about error_status_t and wanted to
  443. // reinvent the wheel, check to see if we need to map the exception.
  444. // In either case, set the return value and then try to free the
  445. // [out] params, if required.
  446. //
  447. if ( InterpreterFlags.ObjectProc )
  448. {
  449. ReturnValue.Simple = NdrProxyErrorHandler(ExceptionCode);
  450. //
  451. // Set the Buffer endpoints so the NdrFree routines work.
  452. //
  453. StubMsg.BufferStart = 0;
  454. StubMsg.BufferEnd = 0;
  455. for ( Length = ArgQueue.Length, pQueue = ArgQueue.Queue;
  456. Length--;
  457. pQueue++ )
  458. {
  459. if ( pQueue->IsOutOnly )
  460. {
  461. NdrClearOutParameters( &StubMsg,
  462. pQueue->pFormat,
  463. *(pQueue->ppArg) );
  464. }
  465. }
  466. }
  467. else
  468. {
  469. if ( InterpreterFlags.HasCommOrFault )
  470. {
  471. NdrClientMapCommFault( &StubMsg,
  472. ProcNum,
  473. ExceptionCode,
  474. (ulong*)&ReturnValue.Simple );
  475. }
  476. else
  477. {
  478. RpcRaiseException(ExceptionCode);
  479. }
  480. }
  481. }
  482. RpcEndExcept
  483. }
  484. RpcFinally
  485. {
  486. NdrFullPointerXlatFree(StubMsg.FullPtrXlatTables);
  487. //
  488. // Free the RPC buffer.
  489. //
  490. if ( InterpreterFlags.ObjectProc )
  491. {
  492. NdrProxyFreeBuffer( pThis, &StubMsg );
  493. }
  494. else
  495. NdrFreeBuffer( &StubMsg );
  496. //
  497. // Unbind if generic handle used. We do this last so that if the
  498. // the user's unbind routine faults, then all of our internal stuff
  499. // will already have been freed.
  500. //
  501. if ( SavedGenericHandle )
  502. {
  503. GenericHandleUnbind( pStubDescriptor,
  504. StartofStack,
  505. pHandleFormatSave,
  506. (HandleType) ? IMPLICIT_MASK : 0,
  507. &SavedGenericHandle );
  508. }
  509. if ( ((TotalStackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH) &&
  510. ArgQueue.Queue )
  511. {
  512. I_RpcFree( ArgQueue.Queue );
  513. }
  514. }
  515. RpcEndFinally
  516. return ReturnValue;
  517. }
  518. #endif // ! defined(__RPC_WIN64__)
  519. void
  520. NdrClientZeroOut(
  521. PMIDL_STUB_MESSAGE pStubMsg,
  522. PFORMAT_STRING pFormat,
  523. uchar * pArg
  524. )
  525. {
  526. LONG_PTR Size;
  527. //
  528. // In an object proc, we must zero all [out] unique and interface
  529. // pointers which occur as the referent of a ref pointer or embedded in a
  530. // structure or union.
  531. //
  532. // Let's not die on a null ref pointer.
  533. if ( !pArg )
  534. return;
  535. //
  536. // The only top level [out] type allowed is a ref pointer or an array.
  537. //
  538. if ( *pFormat == FC_RP )
  539. {
  540. // Double pointer.
  541. if ( POINTER_DEREF(pFormat[1]) )
  542. {
  543. *((void **)pArg) = 0;
  544. return;
  545. }
  546. // we need to zero out basetype because it might be conformant/
  547. // varying descriptor.
  548. if ( SIMPLE_POINTER(pFormat[1]) )
  549. {
  550. MIDL_memset( pArg, 0, (uint) SIMPLE_TYPE_MEMSIZE(pFormat[2]) );
  551. return;
  552. }
  553. // Pointer to struct, union, or array.
  554. pFormat += 2;
  555. pFormat += *((short *)pFormat);
  556. }
  557. Size = (LONG_PTR)NdrpMemoryIncrement( pStubMsg,
  558. 0,
  559. pFormat );
  560. MIDL_memset( pArg, 0, (size_t)Size );
  561. }
  562. void RPC_ENTRY
  563. NdrClearOutParameters(
  564. PMIDL_STUB_MESSAGE pStubMsg,
  565. PFORMAT_STRING pFormat,
  566. void * pArgVoid
  567. )
  568. /*++
  569. Routine Description :
  570. Free and clear an [out] parameter in case of exceptions for object
  571. interfaces.
  572. Arguments :
  573. pStubMsg - pointer to stub message structure
  574. pFormat - The format string offset
  575. pArg - The [out] pointer to clear.
  576. Return :
  577. NA
  578. Notes:
  579. --*/
  580. {
  581. uchar * pArgSaved;
  582. ULONG_PTR Size;
  583. uchar * pArg = (uchar*)pArgVoid;
  584. if( pStubMsg->dwStubPhase != PROXY_UNMARSHAL)
  585. return;
  586. // Let's not die on a null ref pointer.
  587. if ( !pArg )
  588. return;
  589. Size = 0;
  590. pArgSaved = pArg;
  591. //
  592. // Look for a non-Interface pointer.
  593. //
  594. if ( IS_BASIC_POINTER(*pFormat) )
  595. {
  596. // Pointer to a basetype.
  597. if ( SIMPLE_POINTER(pFormat[1]) )
  598. {
  599. //
  600. // It seems wierd to zero an [out] pointer to a basetypes, but this
  601. // is what we did in NT 3.5x and I wouldn't be surprised if
  602. // something broke if we changed this behavior.
  603. //
  604. Size = SIMPLE_TYPE_MEMSIZE(pFormat[2]);
  605. goto DoZero;
  606. }
  607. // Pointer to a pointer.
  608. if ( POINTER_DEREF(pFormat[1]) )
  609. {
  610. Size = PTR_MEM_SIZE;
  611. pArg = *((uchar **)pArg);
  612. }
  613. pFormat += 2;
  614. pFormat += *((short *)pFormat);
  615. if ( *pFormat == FC_BIND_CONTEXT )
  616. {
  617. *((NDR_CCONTEXT *)pArg) = (NDR_CCONTEXT) 0;
  618. return;
  619. }
  620. }
  621. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormat)])
  622. ( pStubMsg,
  623. pArg,
  624. pFormat );
  625. if ( ! Size )
  626. {
  627. Size = (ULONG_PTR)NdrpMemoryIncrement( pStubMsg,
  628. 0,
  629. pFormat );
  630. }
  631. DoZero:
  632. MIDL_memset( pArgSaved, 0, (size_t)Size );
  633. }
  634. void
  635. NdrClientMapCommFault(
  636. PMIDL_STUB_MESSAGE pStubMsg,
  637. long ProcNum,
  638. RPC_STATUS ExceptionCode,
  639. ULONG_PTR * pReturnValue
  640. )
  641. /*
  642. This routine will map exception code to the related placeholder in the app.
  643. The mapping is based on the information generated by the compiler into
  644. the CommFaultOffset table.
  645. The table may have the following entries in the comm and fault cells:
  646. -2 - not mapped
  647. -1 - mapped to the returned value
  648. 0<= - mapped to an out parameter, the value is the param stack offset.
  649. Mapping to a parameter is not allowed in the handle-less asynchronous calls.
  650. For handle-less async calls, the exception doesn't come from the server,
  651. it is just a way for the client stub to signal if the dispatch was succesful.
  652. Note for 64b platforms. error_status_t has a size of a long and so that is
  653. why we leave pReturnValue as well as pComm and pFault as long pointers.
  654. */
  655. {
  656. PMIDL_STUB_DESC pStubDescriptor;
  657. RPC_STATUS Status;
  658. uchar * StartofStack;
  659. void ** ppArg;
  660. const COMM_FAULT_OFFSETS * Offsets;
  661. ulong * pComm;
  662. ulong * pFault;
  663. pStubDescriptor = pStubMsg->StubDesc;
  664. StartofStack = pStubMsg->StackTop;
  665. Offsets = pStubDescriptor->CommFaultOffsets;
  666. switch ( Offsets[ProcNum].CommOffset )
  667. {
  668. case -2 :
  669. pComm = 0;
  670. break;
  671. case -1 :
  672. pComm = (ulong*)pReturnValue;
  673. break;
  674. default :
  675. ppArg = (void **)(StartofStack + Offsets[ProcNum].CommOffset);
  676. pComm = (ulong *) *ppArg;
  677. break;
  678. }
  679. switch ( Offsets[ProcNum].FaultOffset )
  680. {
  681. case -2 :
  682. pFault = 0;
  683. break;
  684. case -1 :
  685. pFault = (ulong*)pReturnValue;
  686. break;
  687. default :
  688. ppArg = (void **)(StartofStack + Offsets[ProcNum].FaultOffset);
  689. pFault = (ulong *) *ppArg;
  690. break;
  691. }
  692. Status = NdrMapCommAndFaultStatus(
  693. pStubMsg,
  694. pComm,
  695. pFault,
  696. ExceptionCode
  697. );
  698. if ( Status )
  699. RpcRaiseException(Status);
  700. }
  701. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  702. NdrClientCall2(
  703. PMIDL_STUB_DESC pStubDescriptor,
  704. PFORMAT_STRING pFormat,
  705. ...
  706. )
  707. /*
  708. This routine is called from the object stubless proxy dispatcher.
  709. */
  710. {
  711. va_list ArgList;
  712. #if defined(_WIN64)
  713. // Get address of the virtual stack as forced on the ia64 C compiler.
  714. // On ia64 the call takes the actual args, not the address to args as usual,
  715. // so we split the code path with NdrpClientCall2. That is needed for calls
  716. // from the stubless proxy codepath. This routine is used for call_as.
  717. //
  718. INIT_ARG( ArgList, pFormat);
  719. GET_FIRST_IN_ARG(ArgList);
  720. uchar *StartofStack = (uchar*)GET_STACK_START(ArgList);
  721. return NdrpClientCall2( pStubDescriptor, pFormat, StartofStack );
  722. }
  723. CLIENT_CALL_RETURN RPC_ENTRY
  724. NdrpClientCall2(
  725. PMIDL_STUB_DESC pStubDescriptor,
  726. PFORMAT_STRING pFormat,
  727. uchar * StartofStack
  728. )
  729. {
  730. #endif // _WIN64
  731. RPC_MESSAGE RpcMsg;
  732. MIDL_STUB_MESSAGE StubMsg;
  733. CLIENT_CALL_RETURN ReturnValue;
  734. ulong ProcNum, RpcFlags;
  735. uchar * pArg;
  736. void * pThis = NULL;
  737. handle_t Handle;
  738. NDR_PROC_CONTEXT ProcContext;
  739. ReturnValue.Pointer = 0;
  740. #if !defined(_WIN64)
  741. //
  742. // Get address of argument to this function following pFormat. This
  743. // is the address of the address of the first argument of the function
  744. // calling this function.
  745. //
  746. INIT_ARG( ArgList, pFormat);
  747. //
  748. // Get the address of the stack where the parameters are.
  749. //
  750. GET_FIRST_IN_ARG(ArgList);
  751. uchar *StartofStack = (uchar*)GET_STACK_START(ArgList);
  752. #endif
  753. // StartofStack points to the virtual stack at this point.
  754. ProcNum = MulNdrpInitializeContextFromProc( XFER_SYNTAX_DCE,
  755. pFormat,
  756. &ProcContext,
  757. StartofStack );
  758. //
  759. // Wrap everything in a try-finally pair. The finally clause does the
  760. // required freeing of resources (RpcBuffer and Full ptr package).
  761. //
  762. RpcTryFinally
  763. {
  764. //
  765. // Use a nested try-except pair to support OLE. In OLE case, test the
  766. // exception and map it if required, then set the return value. In
  767. // nonOLE case, just reraise the exception.
  768. //
  769. RpcTryExcept
  770. {
  771. // Do this for the sake of the -Os client stubs.
  772. StubMsg.FullPtrXlatTables = 0;
  773. StubMsg.pContext = &ProcContext;
  774. StubMsg.StackTop = ProcContext.StartofStack;
  775. if ( ProcContext.IsObject )
  776. {
  777. pThis = *(void **)StartofStack;
  778. NdrProxyInitialize( pThis,
  779. &RpcMsg,
  780. &StubMsg,
  781. pStubDescriptor,
  782. ProcNum );
  783. }
  784. else
  785. {
  786. NdrClientInitializeNew( &RpcMsg,
  787. &StubMsg,
  788. pStubDescriptor,
  789. (uint) ProcNum );
  790. if ( ProcContext.HandleType )
  791. {
  792. //
  793. // We have an implicit handle.
  794. //
  795. Handle = ImplicitBindHandleMgr( pStubDescriptor,
  796. ProcContext.HandleType,
  797. &ProcContext.SavedGenericHandle);
  798. }
  799. else
  800. {
  801. Handle = ExplicitBindHandleMgr( pStubDescriptor,
  802. StartofStack,
  803. ProcContext.pHandleFormatSave,
  804. &ProcContext.SavedGenericHandle );
  805. }
  806. }
  807. NdrpClientInit( &StubMsg, &ReturnValue );
  808. //
  809. // Skip buffer size pass if possible.
  810. //
  811. if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.ClientMustSize )
  812. {
  813. NdrpSizing( &StubMsg, TRUE ); // IsClient
  814. }
  815. // Compiler prevents variable size non-pipe args for NT v.4.0.
  816. //
  817. // Do the GetBuffer.
  818. //
  819. if ( ProcContext.HasPipe )
  820. NdrGetPipeBuffer( &StubMsg,
  821. StubMsg.BufferLength,
  822. Handle );
  823. else
  824. {
  825. if ( ProcContext.IsObject )
  826. NdrProxyGetBuffer( pThis,
  827. &StubMsg );
  828. else
  829. {
  830. if ( ProcContext.HandleType != FC_AUTO_HANDLE )
  831. {
  832. NdrGetBuffer( &StubMsg,
  833. StubMsg.BufferLength,
  834. Handle );
  835. }
  836. else
  837. NdrNsGetBuffer( &StubMsg,
  838. StubMsg.BufferLength,
  839. Handle );
  840. }
  841. }
  842. NdrRpcSetNDRSlot( &StubMsg );
  843. NDR_ASSERT( StubMsg.fBufferValid, "Invalid buffer" );
  844. //
  845. // ----------------------------------------------------------
  846. // Marshall Pass.
  847. // ----------------------------------------------------------
  848. //
  849. NdrpClientMarshal( &StubMsg, ProcContext.IsObject );
  850. //
  851. // Make the RPC call.
  852. //
  853. if ( ProcContext.HasPipe )
  854. NdrPipeSendReceive( & StubMsg, ProcContext.pPipeDesc );
  855. else
  856. {
  857. if ( ProcContext.IsObject )
  858. NdrProxySendReceive( pThis, &StubMsg );
  859. else
  860. if ( ProcContext.HandleType != FC_AUTO_HANDLE )
  861. NdrSendReceive( &StubMsg, StubMsg.Buffer );
  862. else
  863. NdrNsSendReceive( &StubMsg,
  864. StubMsg.Buffer,
  865. (RPC_BINDING_HANDLE*) pStubDescriptor
  866. ->IMPLICIT_HANDLE_INFO.pAutoHandle );
  867. }
  868. NdrpClientUnMarshal( &StubMsg, &ReturnValue );
  869. }
  870. RpcExcept( ProcContext.ExceptionFlag )
  871. {
  872. if ( ProcContext.IsObject )
  873. NdrpDcomClientExceptionHandling( &StubMsg, ProcNum, RpcExceptionCode(), &ReturnValue);
  874. else
  875. NdrpClientExceptionHandling( &StubMsg, ProcNum, RpcExceptionCode(), &ReturnValue );
  876. }
  877. RpcEndExcept
  878. }
  879. RpcFinally
  880. {
  881. NdrpClientFinally( &StubMsg, pThis );
  882. }
  883. RpcEndFinally
  884. return ReturnValue;
  885. }