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.

347 lines
10 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. // context handle is not allowed in DCOM interface so I don't think
  80. // we need the check here (for both DCE & NDR64). we can get
  81. // rid of this code in Longhorn. yongqu
  82. if ( *(PFORMAT_STRING)pFormat == FC64_BIND_CONTEXT )
  83. {
  84. *((NDR_CCONTEXT *)pArg) = (NDR_CCONTEXT) 0;
  85. return;
  86. }
  87. pFormat = pPointee;
  88. }
  89. // We have a pointer to complex type.
  90. Ndr64ToplevelTypeFree( pStubMsg,
  91. pArg,
  92. pFormat );
  93. if ( ! Size )
  94. {
  95. Size = Ndr64pMemorySize( pStubMsg,
  96. pFormat,
  97. FALSE );
  98. }
  99. DoZero:
  100. MIDL_memset( pArgSaved, 0, (size_t)Size );
  101. }
  102. __forceinline void
  103. Ndr64pGetBuffer( void * pThis,
  104. MIDL_STUB_MESSAGE * pStubMsg,
  105. NDR_PROC_CONTEXT * pContext )
  106. {
  107. if ( pThis )
  108. NdrProxyGetBuffer( pThis,
  109. pStubMsg );
  110. else
  111. {
  112. if ( pContext->HandleType != FC64_AUTO_HANDLE )
  113. {
  114. Ndr64GetBuffer( pStubMsg,
  115. pStubMsg->BufferLength );
  116. }
  117. else
  118. Ndr64NsGetBuffer( pStubMsg,
  119. pStubMsg->BufferLength );
  120. // We only need to save the stubmsg in sync interfaces.
  121. // In the client side, runtime tls would be available AFTER call
  122. // to runtime, it might be after I_RpcNegotiateTransferSyntax or
  123. // GetBuffer, and we are sure the slot is available now.
  124. }
  125. NdrRpcSetNDRSlot( pStubMsg );
  126. }
  127. __forceinline void
  128. Ndr64pSendReceive( void * pThis,
  129. MIDL_STUB_MESSAGE * pStubMsg,
  130. NDR_PROC_CONTEXT * pContext )
  131. {
  132. if ( pContext->HasPipe )
  133. NdrPipeSendReceive( pStubMsg, pContext->pPipeDesc );
  134. else
  135. {
  136. if ( pThis )
  137. NdrProxySendReceive( pThis, pStubMsg );
  138. else
  139. if ( pContext->HandleType != FC64_AUTO_HANDLE )
  140. NdrSendReceive( pStubMsg, pStubMsg->Buffer );
  141. else
  142. NdrNsSendReceive( pStubMsg,
  143. pStubMsg->Buffer,
  144. (RPC_BINDING_HANDLE*) pStubMsg->StubDesc
  145. ->IMPLICIT_HANDLE_INFO.pAutoHandle );
  146. }
  147. }
  148. CLIENT_CALL_RETURN RPC_VAR_ENTRY
  149. NdrClientCall3(
  150. MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
  151. ulong nProcNum,
  152. void *pReturnValue,
  153. ...
  154. )
  155. /*
  156. This routine is called from the object stubless proxy dispatcher.
  157. */
  158. {
  159. va_list ArgList;
  160. RPC_STATUS res = RPC_S_OK;
  161. NDR_PROC_CONTEXT ProcContext;
  162. INIT_ARG( ArgList, pReturnValue );
  163. GET_FIRST_IN_ARG(ArgList);
  164. uchar * StartofStack = (uchar *)GET_STACK_START(ArgList);
  165. Ndr64ClientInitializeContext( NdrpGetSyntaxType( pProxyInfo->pTransferSyntax),
  166. pProxyInfo,
  167. nProcNum,
  168. &ProcContext,
  169. StartofStack );
  170. // call_as routines in ORPC interface come through here also.
  171. return NdrpClientCall3( ProcContext.IsObject ? *(void **)StartofStack : NULL,
  172. pProxyInfo,
  173. nProcNum,
  174. pReturnValue,
  175. &ProcContext,
  176. StartofStack );
  177. }
  178. CLIENT_CALL_RETURN RPC_ENTRY
  179. NdrpClientCall3(
  180. void * pThis,
  181. MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
  182. ulong nProcNum,
  183. void *pReturnValue,
  184. NDR_PROC_CONTEXT * pContext,
  185. uchar * StartofStack
  186. )
  187. {
  188. RPC_MESSAGE RpcMsg;
  189. MIDL_STUB_MESSAGE StubMsg;
  190. PMIDL_STUB_MESSAGE pStubMsg = &StubMsg;
  191. CLIENT_CALL_RETURN ReturnValue;
  192. ReturnValue.Pointer = 0;
  193. if ( NULL == pReturnValue )
  194. pReturnValue = &ReturnValue;
  195. //
  196. // Wrap everything in a try-finally pair. The finally clause does the
  197. // required freeing of resources (RpcBuffer and Full ptr package).
  198. //
  199. RpcTryFinally
  200. {
  201. //
  202. // Use a nested try-except pair to support OLE. In OLE case, test the
  203. // exception and map it if required, then set the return value. In
  204. // nonOLE case, just reraise the exception.
  205. //
  206. RpcTryExcept
  207. {
  208. // client initialization and syntax negotiation.
  209. Ndr64pClientSetupTransferSyntax(pThis,
  210. &RpcMsg,
  211. pStubMsg,
  212. pProxyInfo,
  213. pContext,
  214. nProcNum );
  215. ( * pContext->pfnInit) ( pStubMsg,
  216. pReturnValue );
  217. ( * pContext->pfnSizing) ( pStubMsg,
  218. TRUE ); // isclient
  219. //
  220. // Do the GetBuffer.
  221. //
  222. Ndr64pGetBuffer( pThis, &StubMsg, pContext );
  223. NDR_ASSERT( StubMsg.fBufferValid, "Invalid buffer" );
  224. (* pContext->pfnMarshal) (&StubMsg,
  225. ( pThis != NULL ) ); // isobject
  226. //
  227. // Make the RPC call.
  228. //
  229. Ndr64pSendReceive( pThis, &StubMsg, pContext ) ;
  230. ( * pContext->pfnUnMarshal )( &StubMsg,
  231. pContext->HasComplexReturn
  232. ? &pReturnValue
  233. : pReturnValue );
  234. }
  235. RpcExcept( EXCEPTION_FLAG )
  236. {
  237. RPC_STATUS ExceptionCode = RpcExceptionCode();
  238. NDR_ASSERT( pContext->NeedsResend == FALSE, "resend flag should be false here" );
  239. // fail after some retries.
  240. if ( ExceptionCode == RPC_P_TRANSFER_SYNTAX_CHANGED &&
  241. ( pContext->ResendCount < NDR_MAX_RESEND_COUNT ) &&
  242. ( pProxyInfo->nCount > 1 ) )
  243. {
  244. // we'll retry only if:
  245. // . runtime returns changed syntax error code
  246. // . client support multiple transfer syntax
  247. // . we retried less than the max retried number
  248. pContext->ResendCount ++;
  249. pContext->NeedsResend = TRUE;
  250. }
  251. else
  252. (pContext->pfnExceptionHandling) ( pStubMsg,
  253. nProcNum,
  254. ExceptionCode,
  255. &ReturnValue );
  256. }
  257. RpcEndExcept
  258. }
  259. RpcFinally
  260. {
  261. (pContext->pfnClientFinally )( pStubMsg,
  262. pThis );
  263. // recurse back if resend is needed. we are very much making a new call again because runtime doesn't
  264. // know which tranfer syntax the new server supports when the previous negotiated transfer syntax failes.
  265. if ( pContext->NeedsResend )
  266. NdrpClientCall3( pThis, pProxyInfo, nProcNum, pReturnValue, pContext, StartofStack );
  267. }
  268. RpcEndFinally
  269. return ReturnValue;
  270. }
  271. #pragma code_seg()