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.

343 lines
9.5 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 - 2000 Microsoft Corporation
  3. Module Name :
  4. cltcall.c
  5. Abstract :
  6. This file contains the single call Ndr64 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. #include "precomp.hxx"
  16. #define CINTERFACE
  17. #define USE_STUBLESS_PROXY
  18. #include <stdarg.h>
  19. #include "hndl.h"
  20. #include "interp2.h"
  21. #include "pipendr.h"
  22. #include "ndrole.h"
  23. #include "rpcproxy.h"
  24. #pragma code_seg(".ndr64")
  25. #define NDR_MAX_RESEND_COUNT 5
  26. #define WIN32RPC
  27. #include "rpcerrp.h"
  28. void
  29. Ndr64ClearOutParameters(
  30. PMIDL_STUB_MESSAGE pStubMsg,
  31. PNDR64_FORMAT pFormat,
  32. uchar * pArg
  33. )
  34. /*++
  35. Routine Description :
  36. Free and clear an [out] parameter in case of exceptions for object
  37. interfaces.
  38. Arguments :
  39. pStubMsg - pointer to stub message structure
  40. pFormat - The format string offset
  41. pArg - The [out] pointer to clear.
  42. Return :
  43. NA
  44. Notes:
  45. --*/
  46. {
  47. const NDR64_POINTER_FORMAT *pPointerFormat =
  48. (const NDR64_POINTER_FORMAT*)pFormat;
  49. PFORMAT_STRING pPointee = (PFORMAT_STRING)pPointerFormat->Pointee;
  50. if( pStubMsg->dwStubPhase != PROXY_UNMARSHAL)
  51. return;
  52. // Let's not die on a null ref pointer.
  53. if ( !pArg )
  54. return;
  55. NDR64_UINT32 Size = 0;
  56. uchar *pArgSaved = pArg;
  57. //
  58. // Look for a non-Interface pointer.
  59. //
  60. if ( NDR64_IS_BASIC_POINTER(*(PFORMAT_STRING)pFormat) )
  61. {
  62. // Pointer to a basetype.
  63. if ( NDR64_SIMPLE_POINTER(pPointerFormat->Flags) )
  64. {
  65. //
  66. // It seems wierd to zero an [out] pointer to a basetypes, but this
  67. // is what we did in NT 3.5x and I wouldn't be surprised if
  68. // something broke if we changed this behavior.
  69. //
  70. Size = NDR64_SIMPLE_TYPE_MEMSIZE( *pPointee );
  71. goto DoZero;
  72. }
  73. // Pointer to a pointer.
  74. if ( NDR64_POINTER_DEREF( pPointerFormat->Flags ) )
  75. {
  76. Size = PTR_MEM_SIZE;
  77. pArg = *((uchar **)pArg);
  78. }
  79. if ( *(PFORMAT_STRING)pFormat == FC64_BIND_CONTEXT )
  80. {
  81. *((NDR_CCONTEXT *)pArg) = (NDR_CCONTEXT) 0;
  82. return;
  83. }
  84. }
  85. // We have a pointer to complex type.
  86. Ndr64ToplevelTypeFree( pStubMsg,
  87. pArg,
  88. pPointee );
  89. if ( ! Size )
  90. {
  91. Size = Ndr64pMemorySize( pStubMsg,
  92. pPointee,
  93. FALSE );
  94. }
  95. DoZero:
  96. MIDL_memset( pArgSaved, 0, (size_t)Size );
  97. }
  98. __forceinline void
  99. Ndr64pGetBuffer( void * pThis,
  100. MIDL_STUB_MESSAGE * pStubMsg,
  101. NDR_PROC_CONTEXT * pContext )
  102. {
  103. if ( pThis )
  104. NdrProxyGetBuffer( pThis,
  105. pStubMsg );
  106. else
  107. {
  108. if ( pContext->HandleType != FC64_AUTO_HANDLE )
  109. {
  110. Ndr64GetBuffer( pStubMsg,
  111. pStubMsg->BufferLength );
  112. }
  113. else
  114. Ndr64NsGetBuffer( pStubMsg,
  115. pStubMsg->BufferLength );
  116. // We only need to save the stubmsg in sync interfaces.
  117. // In the client side, runtime tls would be available AFTER call
  118. // to runtime, it might be after I_RpcNegotiateTransferSyntax or
  119. // GetBuffer, and we are sure the slot is available now.
  120. }
  121. NdrRpcSetNDRSlot( pStubMsg );
  122. }
  123. __forceinline void
  124. Ndr64pSendReceive( void * pThis,
  125. MIDL_STUB_MESSAGE * pStubMsg,
  126. NDR_PROC_CONTEXT * pContext )
  127. {
  128. if ( pContext->HasPipe )
  129. NdrPipeSendReceive( pStubMsg, pContext->pPipeDesc );
  130. else
  131. {
  132. if ( pThis )
  133. NdrProxySendReceive( pThis, pStubMsg );
  134. else
  135. if ( pContext->HandleType != FC64_AUTO_HANDLE )
  136. NdrSendReceive( pStubMsg, pStubMsg->Buffer );
  137. else
  138. NdrNsSendReceive( pStubMsg,
  139. pStubMsg->Buffer,
  140. (RPC_BINDING_HANDLE*) pStubMsg->StubDesc
  141. ->IMPLICIT_HANDLE_INFO.pAutoHandle );
  142. }
  143. }
  144. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  145. NdrClientCall3(
  146. MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
  147. ulong nProcNum,
  148. void *pReturnValue,
  149. ...
  150. )
  151. /*
  152. This routine is called from the object stubless proxy dispatcher.
  153. */
  154. {
  155. va_list ArgList;
  156. RPC_STATUS res = RPC_S_OK;
  157. NDR_PROC_CONTEXT ProcContext;
  158. INIT_ARG( ArgList, pReturnValue );
  159. GET_FIRST_IN_ARG(ArgList);
  160. uchar * StartofStack = (uchar *)GET_STACK_START(ArgList);
  161. Ndr64ClientInitializeContext( NdrpGetSyntaxType( pProxyInfo->pTransferSyntax),
  162. pProxyInfo,
  163. nProcNum,
  164. &ProcContext,
  165. StartofStack );
  166. // call_as routines in ORPC interface come through here also.
  167. return NdrpClientCall3( ProcContext.IsObject ? *(void **)StartofStack : NULL,
  168. pProxyInfo,
  169. nProcNum,
  170. pReturnValue,
  171. &ProcContext,
  172. StartofStack );
  173. }
  174. CLIENT_CALL_RETURN RPC_ENTRY
  175. NdrpClientCall3(
  176. void * pThis,
  177. MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
  178. ulong nProcNum,
  179. void *pReturnValue,
  180. NDR_PROC_CONTEXT * pContext,
  181. uchar * StartofStack
  182. )
  183. {
  184. RPC_MESSAGE RpcMsg;
  185. MIDL_STUB_MESSAGE StubMsg;
  186. PMIDL_STUB_MESSAGE pStubMsg = &StubMsg;
  187. CLIENT_CALL_RETURN ReturnValue;
  188. ReturnValue.Pointer = 0;
  189. if ( NULL == pReturnValue )
  190. pReturnValue = &ReturnValue;
  191. //
  192. // Wrap everything in a try-finally pair. The finally clause does the
  193. // required freeing of resources (RpcBuffer and Full ptr package).
  194. //
  195. RpcTryFinally
  196. {
  197. //
  198. // Use a nested try-except pair to support OLE. In OLE case, test the
  199. // exception and map it if required, then set the return value. In
  200. // nonOLE case, just reraise the exception.
  201. //
  202. RpcTryExcept
  203. {
  204. // client initialization and syntax negotiation.
  205. Ndr64pClientSetupTransferSyntax(pThis,
  206. &RpcMsg,
  207. pStubMsg,
  208. pProxyInfo,
  209. pContext,
  210. nProcNum );
  211. ( * pContext->pfnInit) ( pStubMsg,
  212. pReturnValue );
  213. ( * pContext->pfnSizing) ( pStubMsg,
  214. TRUE ); // isclient
  215. //
  216. // Do the GetBuffer.
  217. //
  218. Ndr64pGetBuffer( pThis, &StubMsg, pContext );
  219. NDR_ASSERT( StubMsg.fBufferValid, "Invalid buffer" );
  220. (* pContext->pfnMarshal) (&StubMsg,
  221. ( pThis != NULL ) ); // isobject
  222. //
  223. // Make the RPC call.
  224. //
  225. Ndr64pSendReceive( pThis, &StubMsg, pContext ) ;
  226. ( * pContext->pfnUnMarshal )( &StubMsg,
  227. pContext->HasComplexReturn
  228. ? &pReturnValue
  229. : pReturnValue );
  230. }
  231. RpcExcept( EXCEPTION_FLAG )
  232. {
  233. RPC_STATUS ExceptionCode = RpcExceptionCode();
  234. NDR_ASSERT( pContext->NeedsResend == FALSE, "resend flag should be false here" );
  235. // fail after some retries.
  236. if ( ExceptionCode == RPC_P_TRANSFER_SYNTAX_CHANGED &&
  237. ( pContext->ResendCount < NDR_MAX_RESEND_COUNT ) &&
  238. ( pProxyInfo->nCount > 1 ) )
  239. {
  240. // we'll retry only if:
  241. // . runtime returns changed syntax error code
  242. // . client support multiple transfer syntax
  243. // . we retried less than the max retried number
  244. pContext->ResendCount ++;
  245. pContext->NeedsResend = TRUE;
  246. }
  247. else
  248. (pContext->pfnExceptionHandling) ( pStubMsg,
  249. nProcNum,
  250. ExceptionCode,
  251. &ReturnValue );
  252. }
  253. RpcEndExcept
  254. }
  255. RpcFinally
  256. {
  257. (pContext->pfnClientFinally )( pStubMsg,
  258. pThis );
  259. // recurse back if resend is needed. we are very much making a new call again because runtime doesn't
  260. // know which tranfer syntax the new server supports when the previous negotiated transfer syntax failes.
  261. if ( pContext->NeedsResend )
  262. NdrpClientCall3( pThis, pProxyInfo, nProcNum, pReturnValue, pContext, StartofStack );
  263. }
  264. RpcEndFinally
  265. return ReturnValue;
  266. }
  267. #pragma code_seg()