mirror of https://github.com/tongzx/nt5src
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
1616 lines
48 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1993-2000 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
srvcall.c
|
|
|
|
Abstract :
|
|
|
|
This file contains the single call Ndr routine for the server 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.
|
|
brucemc 12/22/93 Reworked argument accessing method.
|
|
ryszardk 3/12/94 Handle optimization and fixes.
|
|
|
|
---------------------------------------------------------------------*/
|
|
|
|
#define USE_STUBLESS_PROXY
|
|
#define CINTERFACE
|
|
|
|
#include "ndrp.h"
|
|
#include "ndrole.h"
|
|
#include "rpcproxy.h"
|
|
#include "hndl.h"
|
|
#include "interp2.h"
|
|
#include "pipendr.h"
|
|
#include "attack.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#if defined(DEBUG_WALKIP)
|
|
HRESULT NdrpReleaseMarshalBuffer(
|
|
RPC_MESSAGE *pRpcMsg,
|
|
PFORMAT_STRING pFormat,
|
|
PMIDL_STUB_DESC pStubDesc,
|
|
DWORD dwFlags,
|
|
BOOLEAN fServer);
|
|
#endif
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
#if !defined(__RPC_WIN64__)
|
|
// No support for the old interpreter on 64b platforms.
|
|
|
|
void RPC_ENTRY
|
|
NdrServerCall(
|
|
PRPC_MESSAGE pRpcMsg
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Older Server Interpreter entry point for regular RPC procs.
|
|
|
|
Arguments :
|
|
|
|
pRpcMsg - The RPC message.
|
|
|
|
Return :
|
|
|
|
None.
|
|
--*/
|
|
{
|
|
ulong dwStubPhase = STUB_UNMARSHAL;
|
|
|
|
NdrStubCall( 0,
|
|
0,
|
|
pRpcMsg,
|
|
&dwStubPhase );
|
|
}
|
|
|
|
long RPC_ENTRY
|
|
NdrStubCall(
|
|
struct IRpcStubBuffer * pThis,
|
|
struct IRpcChannelBuffer * pChannel,
|
|
PRPC_MESSAGE pRpcMsg,
|
|
ulong * pdwStubPhase
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Older Server Interpreter entry point for object RPC procs. Also called by
|
|
NdrServerCall, the entry point for regular RPC procs.
|
|
|
|
Arguments :
|
|
|
|
pThis - Object proc's 'this' pointer, 0 for non-object procs.
|
|
pChannel - Object proc's Channel Buffer, 0 for non-object procs.
|
|
pRpcMsg - The RPC message.
|
|
pdwStubPhase - Used to track the current interpreter's activity.
|
|
|
|
Return :
|
|
|
|
Status of S_OK.
|
|
|
|
--*/
|
|
{
|
|
PRPC_SERVER_INTERFACE pServerIfInfo;
|
|
PMIDL_SERVER_INFO pServerInfo;
|
|
PMIDL_STUB_DESC pStubDesc;
|
|
const SERVER_ROUTINE * DispatchTable;
|
|
unsigned int ProcNum;
|
|
|
|
ushort FormatOffset;
|
|
PFORMAT_STRING pFormat;
|
|
|
|
ushort StackSize;
|
|
|
|
MIDL_STUB_MESSAGE StubMsg;
|
|
|
|
double ArgBuffer[ARGUMENT_COUNT_THRESHOLD];
|
|
REGISTER_TYPE * pArg;
|
|
ARG_QUEUE_ELEM QueueElements[QUEUE_LENGTH];
|
|
ARG_QUEUE ArgQueue;
|
|
|
|
int ArgNumModifier;
|
|
BOOL fUsesSsAlloc;
|
|
|
|
//
|
|
// In the case of a context handle, the server side manager function has
|
|
// to be called with NDRSContextValue(ctxthandle). But then we may need to
|
|
// marshall the handle, so NDRSContextValue(ctxthandle) is put in the
|
|
// argument buffer and the handle itself is stored in the following array.
|
|
// When marshalling a context handle, we marshall from this array.
|
|
//
|
|
NDR_SCONTEXT CtxtHndl[MAX_CONTEXT_HNDL_NUMBER];
|
|
|
|
NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
|
|
"marshaling buffer misaligned at server" );
|
|
|
|
//
|
|
// Initialize the argument queue which is used by NdrServerUnmarshall,
|
|
// NdrServerMarshall, and NdrServerFree.
|
|
//
|
|
ArgQueue.Length = 0;
|
|
ArgQueue.Queue = QueueElements;
|
|
|
|
StubMsg.pArgQueue = &ArgQueue;
|
|
|
|
ProcNum = pRpcMsg->ProcNum;
|
|
|
|
//
|
|
// If OLE, Get a pointer to the stub vtbl and pServerInfo. Else
|
|
// just get the pServerInfo the usual way.
|
|
//
|
|
if ( pThis )
|
|
{
|
|
//
|
|
// pThis is (in unison now!) a pointer to a pointer to a vtable.
|
|
// We want some information in this header, so dereference pThis
|
|
// and assign that to a pointer to a vtable. Then use the result
|
|
// of that assignment to get at the information in the header.
|
|
//
|
|
IUnknown * pSrvObj;
|
|
CInterfaceStubVtbl * pStubVTable;
|
|
|
|
pSrvObj = (IUnknown * )((CStdStubBuffer *)pThis)->pvServerObject;
|
|
|
|
DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
|
|
|
|
pStubVTable = (CInterfaceStubVtbl *)
|
|
(*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
|
|
|
|
pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
|
|
}
|
|
else
|
|
{
|
|
pServerIfInfo = (PRPC_SERVER_INTERFACE)pRpcMsg->RpcInterfaceInformation;
|
|
pServerInfo = (PMIDL_SERVER_INFO)pServerIfInfo->InterpreterInfo;
|
|
DispatchTable = pServerInfo->DispatchTable;
|
|
}
|
|
|
|
pStubDesc = pServerInfo->pStubDesc;
|
|
|
|
FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
|
|
pFormat = &((pServerInfo->ProcString)[FormatOffset]);
|
|
|
|
StackSize = HAS_RPCFLAGS(pFormat[1]) ?
|
|
*(ushort *)&pFormat[8] :
|
|
*(ushort *)&pFormat[4];
|
|
|
|
fUsesSsAlloc = pFormat[1] & Oi_RPCSS_ALLOC_USED;
|
|
|
|
//
|
|
// Set up for context handle management.
|
|
//
|
|
StubMsg.SavedContextHandles = CtxtHndl;
|
|
memset( CtxtHndl, 0, sizeof(CtxtHndl) );
|
|
|
|
pArg = (REGISTER_TYPE *) ArgBuffer;
|
|
|
|
if ( (StackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH )
|
|
{
|
|
ArgQueue.Queue =
|
|
(ARG_QUEUE_ELEM *)I_RpcAllocate( ((StackSize / sizeof(REGISTER_TYPE)) + 1) *
|
|
sizeof(ARG_QUEUE_ELEM) );
|
|
}
|
|
|
|
if ( StackSize > MAX_STACK_SIZE )
|
|
{
|
|
pArg = (int*)I_RpcAllocate( StackSize );
|
|
}
|
|
|
|
//
|
|
// Zero this in case one of the above allocations fail and we raise an exception
|
|
// and head to the freeing code.
|
|
//
|
|
StubMsg.FullPtrXlatTables = 0;
|
|
|
|
//
|
|
// Wrap the unmarshalling, mgr call and marshalling in the try block of
|
|
// a try-finally. Put the free phase in the associated finally block.
|
|
//
|
|
RpcTryFinally
|
|
{
|
|
if ( ! ArgQueue.Queue || ! pArg )
|
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|
|
|
//
|
|
// Zero out the arg buffer. We must do this so that parameters
|
|
// are properly zeroed before we start unmarshalling. If we catch
|
|
// an exception before finishing the unmarshalling we can not leave
|
|
// parameters in an unitialized state since we have to do a freeing
|
|
// pass.
|
|
//
|
|
MIDL_memset( pArg,
|
|
0,
|
|
StackSize );
|
|
|
|
//
|
|
// If OLE, put pThis in first dword of stack.
|
|
//
|
|
if (pThis != 0)
|
|
pArg[0] = (REGISTER_TYPE)((CStdStubBuffer *)pThis)->pvServerObject;
|
|
|
|
StubMsg.fHasReturn = FALSE;
|
|
|
|
//
|
|
// Unmarshall all of our parameters.
|
|
//
|
|
|
|
ArgNumModifier = NdrServerUnmarshall( pChannel,
|
|
pRpcMsg,
|
|
&StubMsg,
|
|
pStubDesc,
|
|
pFormat,
|
|
pArg );
|
|
|
|
//
|
|
// OLE interfaces use pdwStubPhase in the exception filter.
|
|
// See CStdStubBuffer_Invoke in rpcproxy.c.
|
|
//
|
|
if( pFormat[1] & Oi_IGNORE_OBJECT_EXCEPTION_HANDLING )
|
|
*pdwStubPhase = STUB_CALL_SERVER_NO_HRESULT;
|
|
else
|
|
*pdwStubPhase = STUB_CALL_SERVER;
|
|
|
|
//
|
|
// Check for a thunk. Compiler does all the setup for us.
|
|
//
|
|
if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
|
|
{
|
|
pServerInfo->ThunkTable[ProcNum]( &StubMsg );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Note that this ArgNum is not the number of arguments declared
|
|
// in the function we called, but really the number of
|
|
// REGISTER_TYPEs occupied by the arguments to a function.
|
|
//
|
|
long ArgNum;
|
|
MANAGER_FUNCTION pFunc;
|
|
|
|
if ( pRpcMsg->ManagerEpv )
|
|
pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
|
|
else
|
|
pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
|
|
|
|
ArgNum = (long) StackSize / sizeof(REGISTER_TYPE);
|
|
|
|
//
|
|
// The StackSize includes the size of the return. If we want
|
|
// just the number of REGISTER_TYPES, then ArgNum must be reduced
|
|
// by 1 when there is a return value AND the current ArgNum count
|
|
// is greater than 0. It may also be increased in some cases
|
|
// to cover backward compatability with older stubs which sometimes
|
|
// had wrong stack sizes.
|
|
//
|
|
if ( ArgNum )
|
|
ArgNum += ArgNumModifier;
|
|
|
|
NdrCallServerManager( pFunc,
|
|
(double *)pArg,
|
|
ArgNum,
|
|
StubMsg.fHasReturn );
|
|
}
|
|
|
|
*pdwStubPhase = STUB_MARSHAL;
|
|
|
|
NdrServerMarshall( pThis,
|
|
pChannel,
|
|
&StubMsg,
|
|
pFormat );
|
|
}
|
|
RpcFinally
|
|
{
|
|
//
|
|
// Skip procedure stuff and the per proc binding information.
|
|
//
|
|
pFormat += HAS_RPCFLAGS(pFormat[1]) ? 10 : 6;
|
|
|
|
if ( IS_HANDLE(*pFormat) )
|
|
pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
|
|
|
|
NdrServerFree( &StubMsg,
|
|
pFormat,
|
|
pThis );
|
|
|
|
//
|
|
// Disable rpcss allocate package if needed.
|
|
//
|
|
if ( fUsesSsAlloc )
|
|
NdrRpcSsDisableAllocate( &StubMsg );
|
|
|
|
if ( ((StackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH) &&
|
|
ArgQueue.Queue )
|
|
{
|
|
I_RpcFree( ArgQueue.Queue );
|
|
}
|
|
|
|
if ( (StackSize > MAX_STACK_SIZE) && pArg )
|
|
{
|
|
I_RpcFree( pArg );
|
|
}
|
|
}
|
|
RpcEndFinally
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#pragma code_seg()
|
|
|
|
int RPC_ENTRY
|
|
NdrServerUnmarshall(
|
|
struct IRpcChannelBuffer * pChannel,
|
|
PRPC_MESSAGE pRpcMsg,
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PMIDL_STUB_DESC pStubDescriptor,
|
|
PFORMAT_STRING pFormat,
|
|
void * pParamList
|
|
)
|
|
{
|
|
PFORMAT_STRING pFormatParam;
|
|
long StackSize;
|
|
void * pArg;
|
|
void ** ppArg;
|
|
uchar * ArgList;
|
|
PARG_QUEUE pArgQueue;
|
|
PARG_QUEUE_ELEM pQueue;
|
|
long Length;
|
|
int ArgNumModifier;
|
|
BOOL fIsOleInterface;
|
|
BOOL fXlatInit;
|
|
BOOL fInitRpcSs;
|
|
BOOL fUsesNewInitRoutine;
|
|
|
|
RpcTryExcept
|
|
{
|
|
ArgNumModifier = 0;
|
|
|
|
fIsOleInterface = IS_OLE_INTERFACE( pFormat[1] );
|
|
fXlatInit = pFormat[1] & Oi_FULL_PTR_USED;
|
|
fInitRpcSs = pFormat[1] & Oi_RPCSS_ALLOC_USED;
|
|
fUsesNewInitRoutine = pFormat[1] & Oi_USE_NEW_INIT_ROUTINES;
|
|
|
|
// Skip to the explicit handle description, if any.
|
|
pFormat += HAS_RPCFLAGS(pFormat[1]) ? 10 : 6;
|
|
|
|
//
|
|
// For a handle_t parameter we must pass the handle field of
|
|
// the RPC message to the server manager.
|
|
//
|
|
if ( *pFormat == FC_BIND_PRIMITIVE )
|
|
{
|
|
pArg = (char *)pParamList + *((ushort *)&pFormat[2]);
|
|
|
|
if ( IS_HANDLE_PTR(pFormat[1]) )
|
|
pArg = *((void **)pArg);
|
|
|
|
*((handle_t *)pArg) = pRpcMsg->Handle;
|
|
}
|
|
|
|
// Skip to the param format string descriptions.
|
|
if ( IS_HANDLE(*pFormat) )
|
|
pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
|
|
|
|
//
|
|
// Set ArgList pointing at the address of the first argument.
|
|
// This will be the address of the first element of the structure
|
|
// holding the arguments in the caller stack.
|
|
//
|
|
ArgList = (uchar*)pParamList;
|
|
|
|
//
|
|
// If it's an OLE interface, skip the first long on stack, since in this
|
|
// case NdrStubCall put pThis in the first long on stack.
|
|
//
|
|
if ( fIsOleInterface )
|
|
GET_NEXT_S_ARG(ArgList, REGISTER_TYPE);
|
|
|
|
// Initialize the Stub message.
|
|
//
|
|
if ( ! pChannel )
|
|
{
|
|
if ( fUsesNewInitRoutine )
|
|
{
|
|
NdrServerInitializeNew( pRpcMsg,
|
|
pStubMsg,
|
|
pStubDescriptor );
|
|
}
|
|
else
|
|
{
|
|
NdrServerInitialize( pRpcMsg,
|
|
pStubMsg,
|
|
pStubDescriptor );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdrStubInitialize( pRpcMsg,
|
|
pStubMsg,
|
|
pStubDescriptor,
|
|
pChannel );
|
|
}
|
|
|
|
// Call this after initializing the stub.
|
|
|
|
if ( fXlatInit )
|
|
pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
|
|
|
|
//
|
|
// Set StackTop AFTER the initialize call, since it zeros the field
|
|
// out.
|
|
//
|
|
pStubMsg->StackTop = (uchar*)pParamList;
|
|
|
|
//
|
|
// We must make this check AFTER the call to ServerInitialize,
|
|
// since that routine puts the stub descriptor alloc/dealloc routines
|
|
// into the stub message.
|
|
//
|
|
if ( fInitRpcSs )
|
|
NdrRpcSsEnableAllocate( pStubMsg );
|
|
|
|
//
|
|
// Do endian/floating point conversions if needed.
|
|
//
|
|
if ( (pRpcMsg->DataRepresentation & 0X0000FFFFUL) !=
|
|
NDR_LOCAL_DATA_REPRESENTATION )
|
|
NdrConvert( pStubMsg, pFormat );
|
|
|
|
pArgQueue = (PARG_QUEUE) pStubMsg->pArgQueue;
|
|
|
|
//
|
|
// --------------------------------------------------------------------
|
|
// Unmarshall Pass.
|
|
// --------------------------------------------------------------------
|
|
//
|
|
pStubMsg->ParamNumber = 0;
|
|
|
|
for ( pQueue = pArgQueue->Queue;
|
|
;
|
|
pStubMsg->ParamNumber++, pArgQueue->Length++, pQueue++ )
|
|
{
|
|
//
|
|
// Clear out flags IsReturn, IsBasetype, IsIn, IsOut,
|
|
// IsOutOnly, IsDeferredFree, IsDontCallFreeInst.
|
|
//
|
|
*((long *)(((char *)pQueue) + 0xc)) = 0;
|
|
|
|
//
|
|
// Zero this so that if we catch an exception before finishing the
|
|
// unmarshalling and [out] init passes we won't try to free a
|
|
// garbage pointer.
|
|
//
|
|
pQueue->pArg = 0;
|
|
|
|
//
|
|
// Context handles need the parameter number.
|
|
//
|
|
pQueue->ParamNum = (short) pStubMsg->ParamNumber;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_IN_PARAM_BASETYPE :
|
|
pQueue->IsBasetype = TRUE;
|
|
|
|
//
|
|
// We have to inline the simple type unmarshall so that on
|
|
// Alpha, negative longs get properly sign extended.
|
|
//
|
|
switch ( pFormat[1] )
|
|
{
|
|
case FC_CHAR :
|
|
case FC_BYTE :
|
|
case FC_SMALL :
|
|
*((REGISTER_TYPE *)ArgList) =
|
|
(REGISTER_TYPE) *(pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
case FC_ENUM16 :
|
|
case FC_WCHAR :
|
|
case FC_SHORT :
|
|
ALIGN(pStubMsg->Buffer,1);
|
|
|
|
*((REGISTER_TYPE *)ArgList) =
|
|
(REGISTER_TYPE) *((ushort *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
// case FC_FLOAT : not supported on -Oi
|
|
case FC_LONG :
|
|
case FC_ENUM32 :
|
|
case FC_ERROR_STATUS_T:
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
*((REGISTER_TYPE *)ArgList) =
|
|
(REGISTER_TYPE) *((long *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
// case FC_DOUBLE : not supported on -Oi
|
|
case FC_HYPER :
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
// Let's stay away from casts to doubles.
|
|
//
|
|
*((ulong *)ArgList) =
|
|
*((ulong *&)pStubMsg->Buffer)++;
|
|
*((ulong *)(ArgList+4)) =
|
|
*((ulong *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
case FC_IGNORE :
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrServerUnmarshall : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
} // switch ( pFormat[1] )
|
|
|
|
pQueue->pFormat = &pFormat[1];
|
|
pQueue->pArg = ArgList;
|
|
|
|
GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
|
|
|
|
if ( pFormat[1] == FC_HYPER )
|
|
GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
|
|
|
|
pFormat += 2;
|
|
continue;
|
|
|
|
case FC_IN_PARAM_NO_FREE_INST :
|
|
pQueue->IsDontCallFreeInst = TRUE;
|
|
// Fall through...
|
|
|
|
case FC_IN_PARAM :
|
|
//
|
|
// Here, we break out of the switch statement to the
|
|
// unmarshalling code below.
|
|
//
|
|
break;
|
|
|
|
case FC_IN_OUT_PARAM :
|
|
pQueue->IsOut = TRUE;
|
|
//
|
|
// Here, we break out of the switch statement to the
|
|
// unmarshalling code below.
|
|
//
|
|
break;
|
|
|
|
case FC_OUT_PARAM :
|
|
pQueue->IsOut = TRUE;
|
|
pQueue->IsOutOnly = TRUE;
|
|
|
|
pFormat += 2;
|
|
pFormatParam = pStubDescriptor->pFormatTypes +
|
|
*((short *)pFormat);
|
|
pFormat += 2;
|
|
|
|
pQueue->pFormat = pFormatParam;
|
|
pQueue->ppArg = (uchar **)ArgList;
|
|
|
|
//
|
|
// An [out] param ALWAYS eats up 4 bytes of stack space.
|
|
//
|
|
GET_NEXT_S_ARG(ArgList, REGISTER_TYPE);
|
|
continue;
|
|
|
|
case FC_RETURN_PARAM :
|
|
pQueue->IsOut = TRUE;
|
|
pQueue->IsReturn = TRUE;
|
|
|
|
pFormatParam = pStubDescriptor->pFormatTypes +
|
|
*((short *)(pFormat + 2));
|
|
|
|
pQueue->pFormat = pFormatParam;
|
|
|
|
if ( IS_BY_VALUE(*pFormatParam) )
|
|
{
|
|
pQueue->pArg = (uchar *) ArgList;
|
|
pQueue->ppArg = &(pQueue->pArg);
|
|
}
|
|
else
|
|
pQueue->ppArg = (uchar **) ArgList;
|
|
|
|
//
|
|
// Context handle returned by value is the only reason for
|
|
// this case here as a context handle has to be initialized.
|
|
// A context handle cannot be returned by a pointer.
|
|
//
|
|
if ( *pFormatParam == FC_BIND_CONTEXT )
|
|
{
|
|
pStubMsg->SavedContextHandles[pStubMsg->ParamNumber] =
|
|
NdrContextHandleInitialize(
|
|
pStubMsg,
|
|
pFormatParam);
|
|
}
|
|
//
|
|
// The return variable is used in modifying the stacksize
|
|
// given us by midl, in order to compute how many
|
|
// REGISTER_SIZE items to pass into the manager function.
|
|
//
|
|
ArgNumModifier--;
|
|
|
|
pStubMsg->fHasReturn = TRUE;
|
|
|
|
pArgQueue->Length++;
|
|
|
|
goto UnmarshallLoopExit;
|
|
|
|
case FC_RETURN_PARAM_BASETYPE :
|
|
pQueue->IsOut = TRUE;
|
|
pQueue->IsReturn = TRUE;
|
|
pQueue->IsBasetype = TRUE;
|
|
|
|
pQueue->pFormat = &pFormat[1];
|
|
pQueue->pArg = ArgList;
|
|
|
|
//
|
|
// The return variable is used in modifying the stacksize
|
|
// given us by midl, in order to compute how many
|
|
// REGISTER_SIZE items to pass into the manager function.
|
|
//
|
|
ArgNumModifier--;
|
|
|
|
pStubMsg->fHasReturn = TRUE;
|
|
|
|
pArgQueue->Length++;
|
|
|
|
goto UnmarshallLoopExit;
|
|
|
|
default :
|
|
goto UnmarshallLoopExit;
|
|
} // end of unmarshall pass switch
|
|
|
|
//
|
|
// Now get what ArgList points at and increment over it.
|
|
// In the current implementation, what we want is not on the stack
|
|
// of the manager function, but is a local in the manager function.
|
|
// Thus the code for ppArg below.
|
|
//
|
|
ppArg = (void **)ArgList;
|
|
GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
|
|
|
|
//
|
|
// Get the parameter's format string description.
|
|
//
|
|
pFormat += 2;
|
|
pFormatParam = pStubDescriptor->pFormatTypes + *((short *)pFormat);
|
|
|
|
//
|
|
// Increment main format string past offset field.
|
|
//
|
|
pFormat += 2;
|
|
|
|
//
|
|
// We must get a double pointer to structs, unions and xmit/rep as.
|
|
//
|
|
// On MIPS and PPC, an 8 byte aligned structure is passed at an 8 byte
|
|
// boundary on the stack. On PowerPC 4 bytes aligned structures which
|
|
// are 8 bytes or larger in size are also passed at an 8 byte boundary.
|
|
// We check for these cases here and increment our ArgList pointer
|
|
// an additional 'int' if necessary to get to the structure.
|
|
//
|
|
if ( IS_BY_VALUE(*pFormatParam) )
|
|
{
|
|
pArg = ppArg;
|
|
ppArg = &pArg;
|
|
}
|
|
|
|
(*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
(uchar **)ppArg,
|
|
pFormatParam,
|
|
FALSE );
|
|
|
|
pQueue->pFormat = pFormatParam;
|
|
pQueue->pArg = (uchar*)*ppArg;
|
|
|
|
//
|
|
// The second byte of a param's description gives the number of
|
|
// ints occupied by the param on the stack.
|
|
//
|
|
StackSize = pFormat[-3] * sizeof(int);
|
|
|
|
if ( StackSize > sizeof(REGISTER_TYPE) )
|
|
{
|
|
StackSize -= sizeof(REGISTER_TYPE);
|
|
ArgList += StackSize;
|
|
}
|
|
} // Unmarshalling loop.
|
|
|
|
UnmarshallLoopExit:
|
|
|
|
for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
|
|
Length--;
|
|
pQueue++ )
|
|
{
|
|
if ( pQueue->IsOutOnly )
|
|
{
|
|
pStubMsg->ParamNumber = pQueue->ParamNum;
|
|
|
|
NdrOutInit( pStubMsg,
|
|
pQueue->pFormat,
|
|
pQueue->ppArg );
|
|
|
|
pQueue->pArg = *(pQueue->ppArg);
|
|
}
|
|
}
|
|
}
|
|
RpcExcept( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
|
|
{
|
|
// Filter set in rpcndr.h to catch one of the following
|
|
// STATUS_ACCESS_VIOLATION
|
|
// STATUS_DATATYPE_MISALIGNMENT
|
|
// RPC_X_BAD_STUB_DATA
|
|
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
RpcEndExcept
|
|
|
|
if ( pRpcMsg->BufferLength <
|
|
(uint)(pStubMsg->Buffer - (uchar *)pRpcMsg->Buffer) )
|
|
{
|
|
NDR_ASSERT( 0, "NdrStubCall unmarshal: buffer overflow!" );
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
|
|
return ArgNumModifier;
|
|
}
|
|
|
|
void RPC_ENTRY
|
|
NdrServerMarshall(
|
|
struct IRpcStubBuffer * pThis,
|
|
struct IRpcChannelBuffer * pChannel,
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
PFORMAT_STRING pFormatParam;
|
|
PARG_QUEUE pArgQueue;
|
|
PARG_QUEUE_ELEM pQueue;
|
|
long Length;
|
|
|
|
pArgQueue = (PARG_QUEUE)pStubMsg->pArgQueue;
|
|
|
|
//
|
|
// Remove?
|
|
//
|
|
pStubMsg->Memory = 0;
|
|
|
|
//
|
|
// -------------------------------------------------------------------
|
|
// Sizing Pass.
|
|
// -------------------------------------------------------------------
|
|
//
|
|
|
|
for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
|
|
Length--;
|
|
pQueue++ )
|
|
{
|
|
if ( pQueue->IsOut )
|
|
{
|
|
//
|
|
// Must do some special handling for return values.
|
|
//
|
|
if ( pQueue->IsReturn )
|
|
{
|
|
if ( pQueue->IsBasetype )
|
|
{
|
|
//
|
|
// Add worse case size of 16 for a simple type return.
|
|
//
|
|
pStubMsg->BufferLength += 16;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Get the value returned by the server.
|
|
//
|
|
pQueue->pArg = *(pQueue->ppArg);
|
|
|
|
//
|
|
// We have to do an extra special step for context handles
|
|
// which are function return values.
|
|
//
|
|
// In the unmarshalling phase, we unmarshalled the context
|
|
// handle for the return case. But the function we called put
|
|
// the user context in the arglist buffer. Before we marshall
|
|
// the context handle, we have to put the user context in it.
|
|
//
|
|
if ( pQueue->pFormat[0] == FC_BIND_CONTEXT )
|
|
{
|
|
NDR_SCONTEXT SContext;
|
|
long ParamNum;
|
|
|
|
ParamNum = pQueue->ParamNum;
|
|
|
|
SContext = pStubMsg->SavedContextHandles[ParamNum];
|
|
|
|
*((uchar **)NDRSContextValue(SContext)) = pQueue->pArg;
|
|
}
|
|
}
|
|
|
|
pFormatParam = pQueue->pFormat;
|
|
|
|
(*pfnSizeRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
pQueue->pArg,
|
|
pFormatParam );
|
|
}
|
|
}
|
|
|
|
if ( ! pChannel )
|
|
NdrGetBuffer( pStubMsg,
|
|
pStubMsg->BufferLength,
|
|
0 );
|
|
else
|
|
NdrStubGetBuffer( pThis,
|
|
pChannel,
|
|
pStubMsg );
|
|
|
|
//
|
|
// -------------------------------------------------------------------
|
|
// Marshall Pass.
|
|
// -------------------------------------------------------------------
|
|
//
|
|
|
|
for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
|
|
Length--;
|
|
pQueue++ )
|
|
{
|
|
if ( pQueue->IsOut )
|
|
{
|
|
if ( pQueue->IsBasetype )
|
|
{
|
|
//
|
|
// Only possible as a return value.
|
|
//
|
|
NdrSimpleTypeMarshall( pStubMsg,
|
|
pQueue->pArg,
|
|
pQueue->pFormat[0] );
|
|
}
|
|
else
|
|
{
|
|
pFormatParam = pQueue->pFormat;
|
|
|
|
//
|
|
// We need this if we're marshalling a context handle.
|
|
//
|
|
pStubMsg->ParamNumber = pQueue->ParamNum;
|
|
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
pQueue->pArg,
|
|
pFormatParam );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pStubMsg->RpcMsg->BufferLength <
|
|
(uint)(pStubMsg->Buffer - (uchar *)pStubMsg->RpcMsg->Buffer) )
|
|
{
|
|
NDR_ASSERT( 0, "NdrStubCall marshal: buffer overflow!" );
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
|
|
pStubMsg->RpcMsg->BufferLength =
|
|
pStubMsg->Buffer - (uchar *) pStubMsg->RpcMsg->Buffer;
|
|
}
|
|
|
|
void
|
|
NdrServerFree(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
void * pThis
|
|
)
|
|
{
|
|
PARG_QUEUE pArgQueue;
|
|
PARG_QUEUE_ELEM pQueue;
|
|
long Length;
|
|
PFORMAT_STRING pFormatParam;
|
|
uchar * pArg;
|
|
|
|
pArgQueue = (PARG_QUEUE)pStubMsg->pArgQueue;
|
|
|
|
for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
|
|
Length--;
|
|
pQueue++ )
|
|
{
|
|
if ( pQueue->IsBasetype )
|
|
continue;
|
|
|
|
pFormatParam = pQueue->pFormat;
|
|
|
|
//
|
|
// We have to defer the freeing of pointers to base types in case
|
|
// the parameter is [in,out] or [out] and is the size, length, or
|
|
// switch specifier for an array, a pointer, or a union. This is
|
|
// because we can't free the pointer to base type before we free
|
|
// the data structure which uses the pointer to determine it's size.
|
|
//
|
|
// Note that to make the check as simple as possible [in] only
|
|
// pointers to base types will be included, as will string pointers
|
|
// of any direction.
|
|
//
|
|
if ( IS_BASIC_POINTER(*pFormatParam) &&
|
|
SIMPLE_POINTER(pFormatParam[1]) )
|
|
{
|
|
pQueue->IsDeferredFree = TRUE;
|
|
continue;
|
|
}
|
|
|
|
pStubMsg->fDontCallFreeInst =
|
|
pQueue->IsDontCallFreeInst;
|
|
|
|
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
pQueue->pArg,
|
|
pFormatParam );
|
|
|
|
//
|
|
// Have to explicitly free arrays and strings. But make sure it's
|
|
// non-null and not sitting in the buffer.
|
|
//
|
|
if ( IS_ARRAY_OR_STRING(*pFormatParam) )
|
|
{
|
|
pArg = pQueue->pArg;
|
|
|
|
//
|
|
// We have to make sure the array/string is non-null in case we
|
|
// get an exception before finishing our unmarshalling.
|
|
//
|
|
if ( pArg &&
|
|
( (pArg < pStubMsg->BufferStart) ||
|
|
(pArg > pStubMsg->BufferEnd) ) )
|
|
(*pStubMsg->pfnFree)( pArg );
|
|
}
|
|
}
|
|
|
|
for ( Length = pArgQueue->Length, pQueue = pArgQueue->Queue;
|
|
Length--;
|
|
pQueue++ )
|
|
{
|
|
if ( pQueue->IsDeferredFree )
|
|
{
|
|
NDR_ASSERT( IS_BASIC_POINTER(*(pQueue->pFormat)),
|
|
"NdrServerFree : bad defer logic" );
|
|
|
|
NdrPointerFree( pStubMsg,
|
|
pQueue->pArg,
|
|
pQueue->pFormat );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free any full pointer resources.
|
|
//
|
|
if ( pStubMsg->FullPtrXlatTables )
|
|
NdrFullPointerXlatFree( pStubMsg->FullPtrXlatTables );
|
|
}
|
|
|
|
#endif // !defined(__RPC_WIN64__)
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
void
|
|
NdrUnmarshallBasetypeInline(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pArg,
|
|
uchar Format
|
|
)
|
|
{
|
|
switch ( Format )
|
|
{
|
|
case FC_CHAR :
|
|
case FC_BYTE :
|
|
case FC_SMALL :
|
|
case FC_USMALL :
|
|
*((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
|
|
*(pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
case FC_ENUM16 :
|
|
case FC_WCHAR :
|
|
case FC_SHORT :
|
|
case FC_USHORT :
|
|
ALIGN(pStubMsg->Buffer,1);
|
|
|
|
*((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
|
|
*((ushort *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
case FC_FLOAT :
|
|
case FC_LONG :
|
|
case FC_ULONG :
|
|
case FC_ENUM32 :
|
|
case FC_ERROR_STATUS_T:
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
*((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
|
|
*((long *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
#if defined(__RPC_WIN64__)
|
|
case FC_INT3264:
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
*((REGISTER_TYPE *)pArg) = (REGISTER_TYPE)
|
|
*((long *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
case FC_UINT3264:
|
|
// REGISTER_TYPE is a signed integral.
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
*((UINT64 *)pArg) = (UINT64) *((ulong * &)pStubMsg->Buffer)++;
|
|
break;
|
|
#endif
|
|
|
|
case FC_DOUBLE :
|
|
case FC_HYPER :
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
*((ulong *)pArg) = *((ulong *&)pStubMsg->Buffer)++;
|
|
*((ulong *)(pArg+4)) = *((ulong *&)pStubMsg->Buffer)++;
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrUnmarshallBasetypeInline : bad format char");
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if !defined(__RPC_WIN64__)
|
|
|
|
void
|
|
NdrCallServerManager(
|
|
MANAGER_FUNCTION pFtn,
|
|
double * pArgs,
|
|
ulong NumRegisterArgs,
|
|
BOOL fHasReturn )
|
|
{
|
|
|
|
REGISTER_TYPE returnValue;
|
|
REGISTER_TYPE * pArg;
|
|
|
|
pArg = (REGISTER_TYPE *)pArgs;
|
|
|
|
//
|
|
// If we don't have a return value, make sure we don't write past
|
|
// the end of our argument buffer!
|
|
//
|
|
returnValue = Invoke(pFtn,
|
|
(REGISTER_TYPE *) pArgs,
|
|
NumRegisterArgs);
|
|
|
|
if ( fHasReturn )
|
|
pArg[NumRegisterArgs] = returnValue;
|
|
|
|
}
|
|
|
|
#endif // !defined(__RPC_WIN64__)
|
|
|
|
void RPC_ENTRY
|
|
NdrServerCall2(
|
|
PRPC_MESSAGE pRpcMsg
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Server Interpreter entry point for regular RPC procs.
|
|
|
|
Arguments :
|
|
|
|
pRpcMsg - The RPC message.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ulong dwStubPhase = STUB_UNMARSHAL;
|
|
|
|
NdrStubCall2( 0,
|
|
0,
|
|
pRpcMsg,
|
|
&dwStubPhase );
|
|
}
|
|
|
|
long RPC_ENTRY
|
|
NdrStubCall2(
|
|
struct IRpcStubBuffer * pThis,
|
|
struct IRpcChannelBuffer * pChannel,
|
|
PRPC_MESSAGE pRpcMsg,
|
|
ulong * pdwStubPhase
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Server Interpreter entry point for object RPC procs. Also called by
|
|
NdrServerCall, the entry point for regular RPC procs.
|
|
|
|
Arguments :
|
|
|
|
pThis - Object proc's 'this' pointer, 0 for non-object procs.
|
|
pChannel - Object proc's Channel Buffer, 0 for non-object procs.
|
|
pRpcMsg - The RPC message.
|
|
pdwStubPhase - Used to track the current interpreter's activity.
|
|
|
|
Return :
|
|
|
|
Status of S_OK.
|
|
|
|
--*/
|
|
{
|
|
PRPC_SERVER_INTERFACE pServerIfInfo;
|
|
PMIDL_SERVER_INFO pServerInfo;
|
|
PMIDL_STUB_DESC pStubDesc;
|
|
const SERVER_ROUTINE * DispatchTable;
|
|
ushort ProcNum;
|
|
|
|
ushort FormatOffset;
|
|
PFORMAT_STRING pFormat;
|
|
|
|
MIDL_STUB_MESSAGE StubMsg;
|
|
|
|
uchar * pArgBuffer;
|
|
uchar * pArg;
|
|
#if defined(_M_IX86) && (_MSC_FULL_VER <= 13008982)
|
|
volatile BOOL fBadStubDataException = FALSE;
|
|
#else
|
|
BOOL fBadStubDataException = FALSE;
|
|
#endif
|
|
ulong n;
|
|
|
|
PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
|
|
boolean NotifyAppInvoked = FALSE;
|
|
NDR_PROC_CONTEXT ProcContext;
|
|
|
|
//
|
|
// In the case of a context handle, the server side manager function has
|
|
// to be called with NDRSContextValue(ctxthandle). But then we may need to
|
|
// marshall the handle, so NDRSContextValue(ctxthandle) is put in the
|
|
// argument buffer and the handle itself is stored in the following array.
|
|
// When marshalling a context handle, we marshall from this array.
|
|
//
|
|
NDR_SCONTEXT CtxtHndl[MAX_CONTEXT_HNDL_NUMBER];
|
|
|
|
ProcNum = (ushort) pRpcMsg->ProcNum;
|
|
|
|
NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
|
|
"marshaling buffer misaligned at server" );
|
|
|
|
//
|
|
// If OLE, Get a pointer to the stub vtbl and pServerInfo. Else
|
|
// just get the pServerInfo the usual way.
|
|
//
|
|
if ( pThis )
|
|
{
|
|
//
|
|
// pThis is (in unison now!) a pointer to a pointer to a vtable.
|
|
// We want some information in this header, so dereference pThis
|
|
// and assign that to a pointer to a vtable. Then use the result
|
|
// of that assignment to get at the information in the header.
|
|
//
|
|
IUnknown * pSrvObj;
|
|
CInterfaceStubVtbl * pStubVTable;
|
|
|
|
pSrvObj = (IUnknown * )((CStdStubBuffer *)pThis)->pvServerObject;
|
|
|
|
DispatchTable = (SERVER_ROUTINE *)pSrvObj->lpVtbl;
|
|
|
|
pStubVTable = (CInterfaceStubVtbl *)
|
|
(*((uchar **)pThis) - sizeof(CInterfaceStubHeader));
|
|
|
|
pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
|
|
}
|
|
else
|
|
{
|
|
pServerIfInfo = (PRPC_SERVER_INTERFACE)pRpcMsg->RpcInterfaceInformation;
|
|
pServerInfo = (PMIDL_SERVER_INFO)pServerIfInfo->InterpreterInfo;
|
|
DispatchTable = pServerInfo->DispatchTable;
|
|
}
|
|
|
|
pStubDesc = pServerInfo->pStubDesc;
|
|
|
|
FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
|
|
pFormat = &((pServerInfo->ProcString)[FormatOffset]);
|
|
|
|
MulNdrpInitializeContextFromProc( XFER_SYNTAX_DCE, pFormat, &ProcContext, NULL );
|
|
|
|
//
|
|
// Yes, do this here outside of our RpcTryFinally block. If we
|
|
// can't allocate the arg buffer there's nothing more to do, so
|
|
// raise an exception and return control to the RPC runtime.
|
|
//
|
|
// Alloca throws an exception on an error.
|
|
|
|
pArgBuffer = (uchar*)alloca(ProcContext.StackSize);
|
|
|
|
//
|
|
// Zero out the arg buffer. We must do this so that parameters
|
|
// are properly zeroed before we start unmarshalling. If we catch
|
|
// an exception before finishing the unmarshalling we can not leave
|
|
// parameters in an unitialized state since we have to do a freeing
|
|
// pass.
|
|
//
|
|
MIDL_memset( pArgBuffer,
|
|
0,
|
|
ProcContext.StackSize );
|
|
|
|
// we have to setup this again because we don't know the size when
|
|
// initializing the proc context.
|
|
ProcContext.StartofStack = pArgBuffer;
|
|
StubMsg.pContext = &ProcContext;
|
|
// We need to setup stack AFTER proc header is read so we can
|
|
// know how big the virtual stack is.
|
|
|
|
|
|
//
|
|
// Set up for context handle management.
|
|
//
|
|
StubMsg.SavedContextHandles = CtxtHndl;
|
|
memset( CtxtHndl, 0, sizeof(CtxtHndl) );
|
|
|
|
if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasExtensions )
|
|
pHeaderExts = &ProcContext.NdrInfo.pProcDesc->NdrExts;
|
|
//
|
|
// Wrap the unmarshalling, mgr call and marshalling in the try block of
|
|
// a try-finally. Put the free phase in the associated finally block.
|
|
//
|
|
RpcTryFinally
|
|
{
|
|
// General server initializaiton (NULL async message)
|
|
NdrpServerInit( &StubMsg, pRpcMsg, pStubDesc, pThis, pChannel, NULL );
|
|
|
|
// Raise exceptions after initializing the stub.
|
|
|
|
RpcTryExcept
|
|
{
|
|
|
|
// --------------------------------
|
|
// Unmarshall all of our parameters.
|
|
// --------------------------------
|
|
|
|
NdrpServerUnMarshal( &StubMsg );
|
|
|
|
if ( pRpcMsg->BufferLength <
|
|
(uint)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
|
|
{
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
|
|
}
|
|
RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) )
|
|
{
|
|
// Filter set in rpcndr.h to catch one of the following
|
|
// STATUS_ACCESS_VIOLATION
|
|
// STATUS_DATATYPE_MISALIGNMENT
|
|
// RPC_X_BAD_STUB_DATA
|
|
|
|
NdrpFreeMemoryList( &StubMsg );
|
|
|
|
fBadStubDataException = TRUE;
|
|
if ( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
else
|
|
RpcRaiseException( RpcExceptionCode() );
|
|
}
|
|
RpcEndExcept
|
|
|
|
NdrpServerOutInit( &StubMsg );
|
|
//
|
|
// Do [out] initialization.
|
|
//
|
|
|
|
//
|
|
// Unblock the first pipe; this needs to be after unmarshalling
|
|
// because the buffer may need to be changed to the secondary one.
|
|
// In the out only pipes case this happens immediately.
|
|
//
|
|
|
|
if ( ProcContext.HasPipe )
|
|
NdrMarkNextActivePipe( ProcContext.pPipeDesc );
|
|
|
|
//
|
|
// OLE interfaces use pdwStubPhase in the exception filter.
|
|
// See CStdStubBuffer_Invoke in rpcproxy.c.
|
|
//
|
|
if( pFormat[1] & Oi_IGNORE_OBJECT_EXCEPTION_HANDLING )
|
|
*pdwStubPhase = STUB_CALL_SERVER_NO_HRESULT;
|
|
else
|
|
*pdwStubPhase = STUB_CALL_SERVER;
|
|
|
|
NotifyAppInvoked = TRUE;
|
|
//
|
|
// Check for a thunk. Compiler does all the setup for us.
|
|
//
|
|
if ( pServerInfo->ThunkTable && pServerInfo->ThunkTable[ProcNum] )
|
|
{
|
|
pServerInfo->ThunkTable[ProcNum]( &StubMsg );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Note that this ArgNum is not the number of arguments declared
|
|
// in the function we called, but really the number of
|
|
// REGISTER_TYPEs occupied by the arguments to a function.
|
|
//
|
|
long ArgNum;
|
|
MANAGER_FUNCTION pFunc;
|
|
REGISTER_TYPE returnValue;
|
|
|
|
if ( pRpcMsg->ManagerEpv )
|
|
pFunc = ((MANAGER_FUNCTION *)pRpcMsg->ManagerEpv)[ProcNum];
|
|
else
|
|
pFunc = (MANAGER_FUNCTION) DispatchTable[ProcNum];
|
|
|
|
ArgNum = (long) ProcContext.StackSize / sizeof(REGISTER_TYPE);
|
|
|
|
//
|
|
// The StackSize includes the size of the return. If we want
|
|
// just the number of REGISTER_TYPES, then ArgNum must be reduced
|
|
// by 1 when there is a return value AND the current ArgNum count
|
|
// is greater than 0.
|
|
//
|
|
if ( ArgNum &&
|
|
ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasReturn &&
|
|
!ProcContext.HasComplexReturn )
|
|
ArgNum--;
|
|
|
|
returnValue = Invoke( pFunc,
|
|
(REGISTER_TYPE *)pArgBuffer,
|
|
#if defined(_IA64_)
|
|
pHeaderExts != NULL ? ((PNDR_PROC_HEADER_EXTS64)pHeaderExts)->FloatArgMask
|
|
: 0,
|
|
#endif
|
|
ArgNum);
|
|
|
|
if( ProcContext.NdrInfo.pProcDesc->Oi2Flags.HasReturn)
|
|
{
|
|
if ( !ProcContext.HasComplexReturn )
|
|
((REGISTER_TYPE *)pArgBuffer)[ArgNum] = returnValue;
|
|
|
|
// Pass the app's return value to OLE channel
|
|
if ( pThis )
|
|
(*pfnDcomChannelSetHResult)( pRpcMsg,
|
|
NULL, // reserved
|
|
(HRESULT) returnValue );
|
|
}
|
|
}
|
|
|
|
// Important for context handle cleanup.
|
|
*pdwStubPhase = STUB_MARSHAL;
|
|
|
|
if ( ProcContext.HasPipe )
|
|
{
|
|
NdrIsAppDoneWithPipes( ProcContext.pPipeDesc );
|
|
StubMsg.BufferLength += ProcContext.NdrInfo.pProcDesc->ServerBufferSize;
|
|
}
|
|
else
|
|
StubMsg.BufferLength = ProcContext.NdrInfo.pProcDesc->ServerBufferSize;
|
|
|
|
if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.ServerMustSize )
|
|
{
|
|
//
|
|
// Buffer size pass.
|
|
//
|
|
NdrpSizing( &StubMsg,
|
|
FALSE ); // is server
|
|
}
|
|
|
|
if ( ProcContext.HasPipe && ProcContext.pPipeDesc->OutPipes )
|
|
{
|
|
NdrGetPartialBuffer( & StubMsg );
|
|
StubMsg.RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
|
|
}
|
|
else
|
|
{
|
|
if ( ! pChannel )
|
|
{
|
|
NdrGetBuffer( &StubMsg,
|
|
StubMsg.BufferLength,
|
|
0 );
|
|
}
|
|
else
|
|
NdrStubGetBuffer( pThis,
|
|
pChannel,
|
|
&StubMsg );
|
|
}
|
|
|
|
//
|
|
// Marshall pass.
|
|
//
|
|
NdrpServerMarshal( &StubMsg,
|
|
( pThis != NULL ) );
|
|
|
|
pRpcMsg->BufferLength = (ulong) ( StubMsg.Buffer - (uchar *) pRpcMsg->Buffer );
|
|
|
|
#if defined(DEBUG_WALKIP)
|
|
if ( pChannel )
|
|
{
|
|
NdrpReleaseMarshalBuffer(
|
|
StubMsg.RpcMsg,
|
|
pFormat,
|
|
StubMsg.StubDesc,
|
|
1, //BUFFER_OUT
|
|
true );
|
|
}
|
|
#endif
|
|
|
|
}
|
|
RpcFinally
|
|
{
|
|
// clean up context handles if exception is thrown in either marshalling or
|
|
// manager routine.
|
|
|
|
if ( RpcAbnormalTermination() && ! pChannel )
|
|
{
|
|
NdrpCleanupServerContextHandles( &StubMsg,
|
|
pArgBuffer,
|
|
STUB_MARSHAL != *pdwStubPhase);
|
|
}
|
|
|
|
// If we died because of bad stub data, don't free the params here since they
|
|
// were freed using a linked list of memory in the exception handler above.
|
|
|
|
if ( ! fBadStubDataException )
|
|
{
|
|
NdrpFreeParams( &StubMsg,
|
|
ProcContext.NumberParams,
|
|
( PARAM_DESCRIPTION * )ProcContext.Params,
|
|
pArgBuffer );
|
|
}
|
|
|
|
//
|
|
// Deferred frees. Actually, this should only be necessary if you
|
|
// had a pointer to enum16 in a *_is expression.
|
|
//
|
|
|
|
//
|
|
// Free any full pointer resources.
|
|
//
|
|
NdrFullPointerXlatFree( StubMsg.FullPtrXlatTables );
|
|
|
|
//
|
|
// Disable rpcss allocate package if needed.
|
|
//
|
|
if ( ProcContext.NdrInfo.InterpreterFlags.RpcSsAllocUsed )
|
|
NdrRpcSsDisableAllocate( &StubMsg );
|
|
|
|
//
|
|
// Clean up pipe objects
|
|
//
|
|
|
|
NdrCorrelationFree( &StubMsg );
|
|
|
|
NdrpAllocaDestroy( &ProcContext.AllocateContext );
|
|
|
|
if ( pHeaderExts != 0
|
|
&& ( pHeaderExts->Flags2.HasNotify
|
|
|| pHeaderExts->Flags2.HasNotify2 ) )
|
|
{
|
|
NDR_NOTIFY_ROUTINE pfnNotify;
|
|
|
|
pfnNotify = StubMsg.StubDesc->NotifyRoutineTable[ pHeaderExts->NotifyIndex ];
|
|
|
|
if ( pHeaderExts->Flags2.HasNotify2 )
|
|
{
|
|
((NDR_NOTIFY2_ROUTINE)pfnNotify)(NotifyAppInvoked);
|
|
}
|
|
else
|
|
pfnNotify();
|
|
}
|
|
}
|
|
RpcEndFinally
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void
|
|
NdrpFreeParams(
|
|
MIDL_STUB_MESSAGE * pStubMsg,
|
|
long NumberParams,
|
|
PPARAM_DESCRIPTION Params,
|
|
uchar * pArgBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Frees the memory associated with function parameters as required.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Supplies a pointer to the stub message.
|
|
NumberParams - Supplies the number of parameters for this procedure.
|
|
Params - Supplies a pointer to the parameter list for this function.
|
|
pArgBuffer - Supplies a pointer to the virtual stack.
|
|
pParamFilter - Supplies a filter that is used to determine which functions
|
|
are to be considered. This function should return TRUE if
|
|
the parameter should be considered. If pParamFilter is NULL,
|
|
the default filter is used which is all parameters that have
|
|
MustFree set.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
long n;
|
|
PMIDL_STUB_DESC pStubDesc = pStubMsg->StubDesc;
|
|
|
|
PFORMAT_STRING pFormatParam;
|
|
uchar * pArg;
|
|
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
|
|
if ( ! Params[n].ParamAttr.MustFree )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
if ( ! Params[n].ParamAttr.IsByValue )
|
|
pArg = *((uchar **)pArg);
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes +
|
|
Params[n].TypeOffset;
|
|
|
|
if ( pArg )
|
|
{
|
|
pStubMsg->fDontCallFreeInst =
|
|
Params[n].ParamAttr.IsDontCallFreeInst;
|
|
|
|
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
pArg,
|
|
pFormatParam );
|
|
}
|
|
|
|
//
|
|
// We have to check if we need to free any simple ref pointer,
|
|
// since we skipped it's NdrPointerFree call. We also have
|
|
// to explicitly free arrays and strings. But make sure it's
|
|
// non-null and not sitting in the buffer.
|
|
//
|
|
if ( Params[n].ParamAttr.IsSimpleRef ||
|
|
IS_ARRAY_OR_STRING(*pFormatParam) )
|
|
{
|
|
//
|
|
// Don't free [out] params that we're allocated on the
|
|
// interpreter's stack.
|
|
//
|
|
|
|
if ( Params[n].ParamAttr.ServerAllocSize != 0 )
|
|
continue;
|
|
|
|
//
|
|
// We have to make sure the array/string is non-null in case we
|
|
// get an exception before finishing our unmarshalling.
|
|
//
|
|
if ( pArg &&
|
|
( (pArg < pStubMsg->BufferStart) ||
|
|
(pArg > pStubMsg->BufferEnd) ) )
|
|
(*pStubMsg->pfnFree)( pArg );
|
|
}
|
|
} // for
|
|
}
|
|
|
|
#pragma code_seg()
|
|
|