|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993 - 2000 Microsoft Corporation
Module Name :
cltcall.c
Abstract :
This file contains the single call Ndr64 routine for the client side.
Author :
David Kays dkays October 1993.
Revision History :
brucemc 11/15/93 Added struct by value support, corrected varargs use. brucemc 12/20/93 Binding handle support ryszardk 3/12/94 handle optimization and fixes
---------------------------------------------------------------------*/ #include "precomp.hxx"
#define CINTERFACE
#define USE_STUBLESS_PROXY
#include <stdarg.h>
#include "hndl.h"
#include "interp2.h"
#include "pipendr.h"
#include "ndrole.h"
#include "rpcproxy.h"
#pragma code_seg(".ndr64")
#define NDR_MAX_RESEND_COUNT 5
#define WIN32RPC
#include "rpcerrp.h"
void Ndr64ClearOutParameters( PMIDL_STUB_MESSAGE pStubMsg, PNDR64_FORMAT pFormat, uchar * pArg ) /*++
Routine Description :
Free and clear an [out] parameter in case of exceptions for object interfaces.
Arguments :
pStubMsg - pointer to stub message structure pFormat - The format string offset pArg - The [out] pointer to clear.
Return :
NA
Notes:
--*/ { const NDR64_POINTER_FORMAT *pPointerFormat = (const NDR64_POINTER_FORMAT*)pFormat; PFORMAT_STRING pPointee = (PFORMAT_STRING)pPointerFormat->Pointee;
if( pStubMsg->dwStubPhase != PROXY_UNMARSHAL) return;
// Let's not die on a null ref pointer.
if ( !pArg ) return;
NDR64_UINT32 Size = 0; uchar *pArgSaved = pArg;
//
// Look for a non-Interface pointer.
//
if ( NDR64_IS_BASIC_POINTER(*(PFORMAT_STRING)pFormat) ) { // Pointer to a basetype.
if ( NDR64_SIMPLE_POINTER(pPointerFormat->Flags) ) { //
// It seems wierd to zero an [out] pointer to a basetypes, but this
// is what we did in NT 3.5x and I wouldn't be surprised if
// something broke if we changed this behavior.
//
Size = NDR64_SIMPLE_TYPE_MEMSIZE( *pPointee ); goto DoZero; }
// Pointer to a pointer.
if ( NDR64_POINTER_DEREF( pPointerFormat->Flags ) ) { Size = PTR_MEM_SIZE; pArg = *((uchar **)pArg); }
if ( *(PFORMAT_STRING)pFormat == FC64_BIND_CONTEXT ) { *((NDR_CCONTEXT *)pArg) = (NDR_CCONTEXT) 0; return; } }
// We have a pointer to complex type.
Ndr64ToplevelTypeFree( pStubMsg, pArg, pPointee );
if ( ! Size ) { Size = Ndr64pMemorySize( pStubMsg, pPointee, FALSE ); }
DoZero:
MIDL_memset( pArgSaved, 0, (size_t)Size ); }
__forceinline void Ndr64pGetBuffer( void * pThis, MIDL_STUB_MESSAGE * pStubMsg, NDR_PROC_CONTEXT * pContext ) { if ( pThis ) NdrProxyGetBuffer( pThis, pStubMsg ); else { if ( pContext->HandleType != FC64_AUTO_HANDLE ) { Ndr64GetBuffer( pStubMsg, pStubMsg->BufferLength ); } else Ndr64NsGetBuffer( pStubMsg, pStubMsg->BufferLength );
// We only need to save the stubmsg in sync interfaces.
// In the client side, runtime tls would be available AFTER call
// to runtime, it might be after I_RpcNegotiateTransferSyntax or
// GetBuffer, and we are sure the slot is available now.
}
NdrRpcSetNDRSlot( pStubMsg ); }
__forceinline void Ndr64pSendReceive( void * pThis, MIDL_STUB_MESSAGE * pStubMsg, NDR_PROC_CONTEXT * pContext ) { if ( pContext->HasPipe ) NdrPipeSendReceive( pStubMsg, pContext->pPipeDesc ); else { if ( pThis ) NdrProxySendReceive( pThis, pStubMsg ); else if ( pContext->HandleType != FC64_AUTO_HANDLE ) NdrSendReceive( pStubMsg, pStubMsg->Buffer ); else NdrNsSendReceive( pStubMsg, pStubMsg->Buffer, (RPC_BINDING_HANDLE*) pStubMsg->StubDesc ->IMPLICIT_HANDLE_INFO.pAutoHandle ); } }
CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrClientCall3( MIDL_STUBLESS_PROXY_INFO *pProxyInfo, ulong nProcNum, void *pReturnValue, ... ) /*
This routine is called from the object stubless proxy dispatcher. */ { va_list ArgList; RPC_STATUS res = RPC_S_OK; NDR_PROC_CONTEXT ProcContext;
INIT_ARG( ArgList, pReturnValue ); GET_FIRST_IN_ARG(ArgList); uchar * StartofStack = (uchar *)GET_STACK_START(ArgList);
Ndr64ClientInitializeContext( NdrpGetSyntaxType( pProxyInfo->pTransferSyntax), pProxyInfo, nProcNum, &ProcContext, StartofStack );
// call_as routines in ORPC interface come through here also.
return NdrpClientCall3( ProcContext.IsObject ? *(void **)StartofStack : NULL, pProxyInfo, nProcNum, pReturnValue, &ProcContext, StartofStack ); }
CLIENT_CALL_RETURN RPC_ENTRY NdrpClientCall3( void * pThis, MIDL_STUBLESS_PROXY_INFO *pProxyInfo, ulong nProcNum, void *pReturnValue, NDR_PROC_CONTEXT * pContext, uchar * StartofStack ) {
RPC_MESSAGE RpcMsg; MIDL_STUB_MESSAGE StubMsg; PMIDL_STUB_MESSAGE pStubMsg = &StubMsg; CLIENT_CALL_RETURN ReturnValue;
ReturnValue.Pointer = 0;
if ( NULL == pReturnValue ) pReturnValue = &ReturnValue;
//
// Wrap everything in a try-finally pair. The finally clause does the
// required freeing of resources (RpcBuffer and Full ptr package).
//
RpcTryFinally { //
// Use a nested try-except pair to support OLE. In OLE case, test the
// exception and map it if required, then set the return value. In
// nonOLE case, just reraise the exception.
//
RpcTryExcept {
// client initialization and syntax negotiation.
Ndr64pClientSetupTransferSyntax(pThis, &RpcMsg, pStubMsg, pProxyInfo, pContext, nProcNum );
( * pContext->pfnInit) ( pStubMsg, pReturnValue );
( * pContext->pfnSizing) ( pStubMsg, TRUE ); // isclient
//
// Do the GetBuffer.
//
Ndr64pGetBuffer( pThis, &StubMsg, pContext );
NDR_ASSERT( StubMsg.fBufferValid, "Invalid buffer" );
(* pContext->pfnMarshal) (&StubMsg, ( pThis != NULL ) ); // isobject
//
// Make the RPC call.
//
Ndr64pSendReceive( pThis, &StubMsg, pContext ) ;
( * pContext->pfnUnMarshal )( &StubMsg, pContext->HasComplexReturn ? &pReturnValue : pReturnValue ); } RpcExcept( EXCEPTION_FLAG ) {
RPC_STATUS ExceptionCode = RpcExceptionCode(); NDR_ASSERT( pContext->NeedsResend == FALSE, "resend flag should be false here" );
// fail after some retries.
if ( ExceptionCode == RPC_P_TRANSFER_SYNTAX_CHANGED && ( pContext->ResendCount < NDR_MAX_RESEND_COUNT ) && ( pProxyInfo->nCount > 1 ) ) { // we'll retry only if:
// . runtime returns changed syntax error code
// . client support multiple transfer syntax
// . we retried less than the max retried number
pContext->ResendCount ++; pContext->NeedsResend = TRUE; } else (pContext->pfnExceptionHandling) ( pStubMsg, nProcNum, ExceptionCode, &ReturnValue ); } RpcEndExcept } RpcFinally {
(pContext->pfnClientFinally )( pStubMsg, pThis );
// recurse back if resend is needed. we are very much making a new call again because runtime doesn't
// know which tranfer syntax the new server supports when the previous negotiated transfer syntax failes.
if ( pContext->NeedsResend ) NdrpClientCall3( pThis, pProxyInfo, nProcNum, pReturnValue, pContext, StartofStack ); } RpcEndFinally
return ReturnValue; }
#pragma code_seg()
|