mirror of https://github.com/lianthony/NT4.0
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.
1878 lines
56 KiB
1878 lines
56 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1993 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
|
|
|
|
#include "ndrp.h"
|
|
#include "ndrole.h"
|
|
#include "rpcproxy.h"
|
|
#include "hndl.h"
|
|
#include "interp.h"
|
|
#include "interp2.h"
|
|
#include "pipendr.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
|
|
REGISTER_TYPE Invoke(
|
|
MANAGER_FUNCTION pFunction,
|
|
REGISTER_TYPE * pArgumentList,
|
|
#ifdef _PPC_
|
|
double * pFloatingPointArgumentList,
|
|
#endif //_PPC_
|
|
ulong cArguments);
|
|
|
|
|
|
|
|
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;
|
|
ushort 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( ! ((unsigned long)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;
|
|
|
|
pArg = (REGISTER_TYPE *) ArgBuffer;
|
|
|
|
if ( (StackSize / sizeof(REGISTER_TYPE)) > QUEUE_LENGTH )
|
|
{
|
|
ArgQueue.Queue =
|
|
I_RpcAllocate( ((StackSize / sizeof(REGISTER_TYPE)) + 1) *
|
|
sizeof(ARG_QUEUE_ELEM) );
|
|
}
|
|
|
|
if ( StackSize > MAX_STACK_SIZE )
|
|
{
|
|
pArg = 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 = 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 = 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 :
|
|
#if defined(_MIPS_) || defined(_PPC_)
|
|
if ( pFormat[1] == FC_HYPER )
|
|
ALIGN(ArgList, 0x7);
|
|
#endif
|
|
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);
|
|
|
|
#ifndef _ALPHA_
|
|
if ( pFormat[1] == FC_HYPER )
|
|
GET_NEXT_S_ARG( ArgList, REGISTER_TYPE);
|
|
#endif
|
|
|
|
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] =
|
|
NDRSContextUnmarshall(
|
|
0,
|
|
pStubMsg->RpcMsg->DataRepresentation );
|
|
}
|
|
|
|
//
|
|
// 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) )
|
|
{
|
|
#if defined(_MIPS_) || defined(_PPC_)
|
|
|
|
if ( IS_STRUCT(*pFormatParam) && (pFormatParam[1] > 3) )
|
|
goto CheckStack;
|
|
|
|
#if defined(_PPC_)
|
|
if ( IS_STRUCT(*pFormatParam) &&
|
|
(pFormatParam[1] == 3) &&
|
|
(*((ushort *)(&pFormatParam[2])) >= 8) )
|
|
goto CheckStack;
|
|
#endif
|
|
|
|
if ( IS_XMIT_AS(*pFormatParam) &&
|
|
(pFormatParam[1] & PRESENTED_TYPE_ALIGN_8) )
|
|
goto CheckStack;
|
|
|
|
#if defined(_PPC_)
|
|
if ( IS_XMIT_AS(*pFormatParam) &&
|
|
(pFormatParam[1] & PRESENTED_TYPE_ALIGN_4) &&
|
|
(*((ushort *)(&pFormatParam[4])) >= 8) )
|
|
goto CheckStack;
|
|
#endif
|
|
|
|
goto CheckStackEnd;
|
|
|
|
CheckStack:
|
|
|
|
if ( (ulong)ppArg % 8 )
|
|
{
|
|
ppArg = (void **) ArgList;
|
|
GET_NEXT_S_ARG(ArgList, int);
|
|
|
|
//
|
|
// Stubs on NT 3.5 (MIDL 2.00.72) had an incorrect
|
|
// stack size for MIPS when there was a gap on the
|
|
// stack because of 8 byte aligned structures. We
|
|
// compensate for that here. MIDLVersion was zero until
|
|
// version 2.00.96.
|
|
//
|
|
if ( pStubMsg->StubDesc->MIDLVersion == 0 )
|
|
ArgNumModifier++;
|
|
}
|
|
|
|
CheckStackEnd:
|
|
|
|
#endif
|
|
|
|
pArg = ppArg;
|
|
ppArg = &pArg;
|
|
}
|
|
|
|
(*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( pStubMsg,
|
|
(uchar **)ppArg,
|
|
pFormatParam,
|
|
FALSE );
|
|
|
|
pQueue->pFormat = pFormatParam;
|
|
pQueue->pArg = *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) )
|
|
{
|
|
#ifdef _ALPHA_
|
|
//
|
|
// MIDL now outputs the correct stack sizes for Alpha. This
|
|
// is needed for backward compatability only.
|
|
//
|
|
StackSize += (sizeof(REGISTER_TYPE) - 1);
|
|
StackSize &= ~(sizeof(REGISTER_TYPE) - 1 );
|
|
#endif
|
|
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 = 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 = 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 ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)] )
|
|
{
|
|
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 );
|
|
}
|
|
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
__inline 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;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrCallServerManager(
|
|
MANAGER_FUNCTION pFtn,
|
|
double * pArgs,
|
|
ulong NumRegisterArgs,
|
|
BOOL fHasReturn )
|
|
{
|
|
#ifdef _PPC_
|
|
double aDouble[13];
|
|
#endif //_PPC_
|
|
|
|
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,
|
|
#ifdef _PPC_
|
|
aDouble,
|
|
#endif //_PPC_
|
|
NumRegisterArgs);
|
|
|
|
if ( fHasReturn )
|
|
pArg[NumRegisterArgs] = returnValue;
|
|
}
|
|
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
#ifdef _PPC_
|
|
double aDouble[13];
|
|
long iDouble = 0;
|
|
#endif //_PPC_
|
|
|
|
PRPC_SERVER_INTERFACE pServerIfInfo;
|
|
PMIDL_SERVER_INFO pServerInfo;
|
|
PMIDL_STUB_DESC pStubDesc;
|
|
const SERVER_ROUTINE * DispatchTable;
|
|
ushort ProcNum;
|
|
|
|
ushort FormatOffset;
|
|
PFORMAT_STRING pFormat;
|
|
PFORMAT_STRING pFormatParam;
|
|
|
|
ushort StackSize;
|
|
|
|
MIDL_STUB_MESSAGE StubMsg;
|
|
|
|
uchar * pArgBuffer;
|
|
uchar * pArg;
|
|
uchar ** ppArg;
|
|
|
|
PPARAM_DESCRIPTION Params;
|
|
INTERPRETER_FLAGS InterpreterFlags;
|
|
INTERPRETER_OPT_FLAGS OptFlags;
|
|
long NumberParams;
|
|
|
|
double OutSpace[16];
|
|
double * OutSpaceCurrent = &OutSpace[16];
|
|
|
|
ushort ConstantBufferSize;
|
|
BOOL HasExplicitHandle;
|
|
BOOL fBadStubDataException = FALSE;
|
|
long n;
|
|
|
|
NDR_PIPE_DESC PipeDesc;
|
|
NDR_PIPE_MESSAGE PipeMsg[ PIPE_MESSAGE_MAX ];
|
|
|
|
//
|
|
// 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 = pRpcMsg->ProcNum;
|
|
|
|
NDR_ASSERT( ! ((unsigned long)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]);
|
|
|
|
HasExplicitHandle = ! pFormat[0];
|
|
InterpreterFlags = *((PINTERPRETER_FLAGS)&pFormat[1]);
|
|
pFormat += InterpreterFlags.HasRpcFlags ? 8 : 4;
|
|
StackSize = *((ushort *)pFormat)++;
|
|
|
|
pArgBuffer = alloca(StackSize);
|
|
|
|
StubMsg.FullPtrXlatTables = 0;
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
if ( ! pArgBuffer )
|
|
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( pArgBuffer,
|
|
0,
|
|
StackSize );
|
|
|
|
if ( HasExplicitHandle )
|
|
{
|
|
//
|
|
// 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 = pArgBuffer + *((ushort *)&pFormat[2]);
|
|
|
|
if ( IS_HANDLE_PTR(pFormat[1]) )
|
|
pArg = *((void **)pArg);
|
|
|
|
*((handle_t *)pArg) = pRpcMsg->Handle;
|
|
}
|
|
|
|
pFormat += (*pFormat == FC_BIND_PRIMITIVE) ? 4 : 6;
|
|
}
|
|
|
|
//
|
|
// Get new interpreter info.
|
|
//
|
|
ConstantBufferSize = *((ushort *)&pFormat[2]);
|
|
OptFlags = *((PINTERPRETER_OPT_FLAGS)&pFormat[4]);
|
|
NumberParams = (long) pFormat[5];
|
|
|
|
Params = (PPARAM_DESCRIPTION) &pFormat[6];
|
|
|
|
//
|
|
// Set up for context handle management.
|
|
//
|
|
StubMsg.SavedContextHandles = CtxtHndl;
|
|
|
|
//
|
|
// 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 OLE, put pThis in first dword of stack.
|
|
//
|
|
if ( pThis )
|
|
{
|
|
*((void **)pArgBuffer) =
|
|
(void *)((CStdStubBuffer *)pThis)->pvServerObject;
|
|
}
|
|
|
|
//
|
|
// Initialize the Stub message.
|
|
//
|
|
if ( ! pChannel )
|
|
{
|
|
if ( OptFlags.HasPipes )
|
|
{
|
|
NdrServerInitializePartial( pRpcMsg,
|
|
&StubMsg,
|
|
pStubDesc,
|
|
ConstantBufferSize );
|
|
}
|
|
else
|
|
{
|
|
NdrServerInitializeNew( pRpcMsg,
|
|
&StubMsg,
|
|
pStubDesc );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdrStubInitialize( pRpcMsg,
|
|
&StubMsg,
|
|
pStubDesc,
|
|
pChannel );
|
|
}
|
|
|
|
// Raise exceptions after initializing the stub.
|
|
|
|
if ( InterpreterFlags.FullPtrUsed )
|
|
StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
|
|
|
|
if ( OptFlags.ServerMustSize & OptFlags.HasPipes )
|
|
RpcRaiseException( RPC_X_WRONG_PIPE_VERSION );
|
|
|
|
//
|
|
// Set StackTop AFTER the initialize call, since it zeros the field
|
|
// out.
|
|
//
|
|
StubMsg.StackTop = pArgBuffer;
|
|
|
|
if ( OptFlags.HasPipes )
|
|
NdrPipesInitialize( & StubMsg,
|
|
(PFORMAT_STRING) Params,
|
|
& PipeDesc,
|
|
& PipeMsg[0],
|
|
pArgBuffer,
|
|
NumberParams );
|
|
|
|
//
|
|
// 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 ( InterpreterFlags.RpcSsAllocUsed )
|
|
NdrRpcSsEnableAllocate( &StubMsg );
|
|
|
|
RpcTryExcept
|
|
{
|
|
//
|
|
// Do endian/floating point conversions if needed.
|
|
//
|
|
if ( (pRpcMsg->DataRepresentation & 0X0000FFFFUL) !=
|
|
NDR_LOCAL_DATA_REPRESENTATION )
|
|
{
|
|
NdrConvert2( &StubMsg,
|
|
(PFORMAT_STRING) Params,
|
|
(long) NumberParams );
|
|
}
|
|
|
|
// --------------------------------
|
|
// Unmarshall all of our parameters.
|
|
// --------------------------------
|
|
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( ! Params[n].ParamAttr.IsIn ||
|
|
Params[n].ParamAttr.IsPipe )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
if ( Params[n].ParamAttr.IsBasetype )
|
|
{
|
|
//
|
|
// Check for a pointer to a basetype. Set the arg pointer
|
|
// at the correct buffer location and you're done.
|
|
//
|
|
if ( Params[n].ParamAttr.IsSimpleRef )
|
|
{
|
|
ALIGN( StubMsg.Buffer,
|
|
SIMPLE_TYPE_ALIGNMENT( Params[n].SimpleType.Type ) );
|
|
|
|
*((uchar **)pArg) = StubMsg.Buffer;
|
|
|
|
StubMsg.Buffer +=
|
|
SIMPLE_TYPE_BUFSIZE( Params[n].SimpleType.Type );
|
|
}
|
|
else
|
|
{
|
|
NdrUnmarshallBasetypeInline(
|
|
&StubMsg,
|
|
pArg,
|
|
Params[n].SimpleType.Type );
|
|
#ifdef _ALPHA_
|
|
if((FC_FLOAT == Params[n].SimpleType.Type) &&
|
|
(n < 5))
|
|
{
|
|
//Special case for top-level float on Alpha.
|
|
//Promote float to double.
|
|
*((double *) pArg) = *((float *)(pArg));
|
|
}
|
|
#endif //_ALPHA_
|
|
#ifdef _PPC_
|
|
//PowerPC support for top-level float and double.
|
|
if(FC_FLOAT == Params[n].SimpleType.Type &&
|
|
iDouble < 13)
|
|
{
|
|
aDouble[iDouble] = *((float *) pArg);
|
|
iDouble++;
|
|
}
|
|
else if(FC_DOUBLE == Params[n].SimpleType.Type &&
|
|
iDouble < 13)
|
|
{
|
|
aDouble[iDouble] = *((double *) pArg);
|
|
iDouble++;
|
|
}
|
|
#endif //_PPC_
|
|
}
|
|
|
|
continue;
|
|
} // IsBasetype
|
|
|
|
//
|
|
// This is an initialization of [in] and [in,out] ref pointers
|
|
// to pointers. These can not be initialized to point into the
|
|
// rpc buffer and we want to avoid doing a malloc of 4 bytes!
|
|
//
|
|
if ( Params[n].ParamAttr.ServerAllocSize != 0 )
|
|
{
|
|
if(OutSpaceCurrent - Params[n].ParamAttr.ServerAllocSize >= OutSpace)
|
|
{
|
|
OutSpaceCurrent -= Params[n].ParamAttr.ServerAllocSize;
|
|
*((void **)pArg) = OutSpaceCurrent;
|
|
}
|
|
else
|
|
{
|
|
*((void **)pArg) = alloca(Params[n].ParamAttr.ServerAllocSize * 8);
|
|
}
|
|
|
|
// Triple indirection - cool!
|
|
**((void ***)pArg) = 0;
|
|
}
|
|
|
|
ppArg = Params[n].ParamAttr.IsByValue ? &pArg : (uchar **)pArg;
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes +
|
|
Params[n].TypeOffset;
|
|
|
|
(*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( &StubMsg,
|
|
ppArg,
|
|
pFormatParam,
|
|
FALSE );
|
|
}
|
|
}
|
|
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
|
|
|
|
fBadStubDataException = TRUE;
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
RpcEndExcept
|
|
|
|
//
|
|
// Do [out] initialization.
|
|
//
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( Params[n].ParamAttr.IsIn ||
|
|
Params[n].ParamAttr.IsReturn ||
|
|
Params[n].ParamAttr.IsPipe )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
//
|
|
// Check if we can initialize this parameter using some of our
|
|
// stack.
|
|
//
|
|
if ( Params[n].ParamAttr.ServerAllocSize != 0 )
|
|
{
|
|
if(OutSpaceCurrent - Params[n].ParamAttr.ServerAllocSize >= OutSpace)
|
|
{
|
|
OutSpaceCurrent -= Params[n].ParamAttr.ServerAllocSize;
|
|
*((void **)pArg) = OutSpaceCurrent;
|
|
}
|
|
else
|
|
{
|
|
*((void **)pArg) = alloca(Params[n].ParamAttr.ServerAllocSize * 8);
|
|
}
|
|
|
|
MIDL_memset( *((void **)pArg),
|
|
0,
|
|
Params[n].ParamAttr.ServerAllocSize * 8 );
|
|
continue;
|
|
}
|
|
else if ( Params[n].ParamAttr.IsBasetype )
|
|
{
|
|
*((void **)pArg) = alloca(8);
|
|
continue;
|
|
};
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes + Params[n].TypeOffset;
|
|
|
|
NdrOutInit( &StubMsg,
|
|
pFormatParam,
|
|
(uchar **)pArg );
|
|
}
|
|
|
|
if ( pRpcMsg->BufferLength <
|
|
(uint)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
|
|
{
|
|
NDR_ASSERT( 0, "NdrStubCall2 unmarshal: buffer overflow!" );
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
|
|
//
|
|
// 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 ( OptFlags.HasPipes )
|
|
NdrMarkNextActivePipe( & PipeDesc, NDR_IN_PIPE );
|
|
|
|
//
|
|
// 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;
|
|
REGISTER_TYPE returnValue;
|
|
|
|
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.
|
|
//
|
|
if ( ArgNum && OptFlags.HasReturn )
|
|
ArgNum--;
|
|
|
|
returnValue = Invoke(pFunc,
|
|
(REGISTER_TYPE *)pArgBuffer,
|
|
#ifdef _PPC_
|
|
aDouble,
|
|
#endif //_PPC_
|
|
ArgNum);
|
|
|
|
if(OptFlags.HasReturn)
|
|
((REGISTER_TYPE *)pArgBuffer)[ArgNum] = returnValue;
|
|
}
|
|
|
|
*pdwStubPhase = STUB_MARSHAL;
|
|
|
|
if ( OptFlags.HasPipes )
|
|
{
|
|
NdrIsAppDoneWithPipes( & PipeDesc );
|
|
StubMsg.BufferLength += ConstantBufferSize;
|
|
}
|
|
else
|
|
StubMsg.BufferLength = ConstantBufferSize;
|
|
|
|
if ( ! OptFlags.ServerMustSize )
|
|
goto DoGetBuffer;
|
|
|
|
if ( OptFlags.HasPipes )
|
|
RpcRaiseException( RPC_X_WRONG_PIPE_VERSION );
|
|
|
|
//
|
|
// Buffer size pass.
|
|
//
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( ! Params[n].ParamAttr.IsOut || ! Params[n].ParamAttr.MustSize )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
if ( ! Params[n].ParamAttr.IsByValue )
|
|
pArg = *((void **)pArg);
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes +
|
|
Params[n].TypeOffset;
|
|
|
|
(*pfnSizeRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( &StubMsg,
|
|
pArg,
|
|
pFormatParam );
|
|
}
|
|
|
|
DoGetBuffer :
|
|
|
|
if ( ! pChannel )
|
|
{
|
|
if ( OptFlags.HasPipes && PipeDesc.OutPipes )
|
|
{
|
|
NdrGetPartialBuffer( & StubMsg );
|
|
StubMsg.RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
|
|
}
|
|
else
|
|
NdrGetBuffer( &StubMsg,
|
|
StubMsg.BufferLength,
|
|
0 );
|
|
}
|
|
else
|
|
NdrStubGetBuffer( pThis,
|
|
pChannel,
|
|
&StubMsg );
|
|
|
|
//
|
|
// Marshall pass.
|
|
//
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( ! Params[n].ParamAttr.IsOut ||
|
|
Params[n].ParamAttr.IsPipe )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
if ( Params[n].ParamAttr.IsBasetype )
|
|
{
|
|
//
|
|
// For pointers to basetype, simply deref the arg pointer and
|
|
// continue.
|
|
//
|
|
if ( Params[n].ParamAttr.IsSimpleRef )
|
|
pArg = *((uchar **)pArg);
|
|
|
|
ALIGN( StubMsg.Buffer,
|
|
SIMPLE_TYPE_ALIGNMENT( Params[n].SimpleType.Type ) );
|
|
|
|
RpcpMemoryCopy(
|
|
StubMsg.Buffer,
|
|
pArg,
|
|
(uint)SIMPLE_TYPE_BUFSIZE( Params[n].SimpleType.Type ) );
|
|
|
|
StubMsg.Buffer +=
|
|
SIMPLE_TYPE_BUFSIZE( Params[n].SimpleType.Type );
|
|
|
|
continue;
|
|
}
|
|
|
|
if ( ! Params[n].ParamAttr.IsByValue )
|
|
pArg = *((void **)pArg);
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes +
|
|
Params[n].TypeOffset;
|
|
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( &StubMsg,
|
|
pArg,
|
|
pFormatParam );
|
|
}
|
|
|
|
if ( pRpcMsg->BufferLength <
|
|
(uint)(StubMsg.Buffer - (uchar *)pRpcMsg->Buffer) )
|
|
{
|
|
NDR_ASSERT( 0, "NdrStubCall2 marshal: buffer overflow!" );
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
}
|
|
|
|
pRpcMsg->BufferLength = StubMsg.Buffer - (uchar *) pRpcMsg->Buffer;
|
|
}
|
|
RpcFinally
|
|
{
|
|
// Don't free the params if we died because of bad stub data
|
|
// when unmarshaling.
|
|
|
|
if ( ! (fBadStubDataException && *pdwStubPhase == STUB_UNMARSHAL) )
|
|
{
|
|
//
|
|
// Free pass.
|
|
//
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( ! Params[n].ParamAttr.MustFree )
|
|
continue;
|
|
|
|
pArg = pArgBuffer + Params[n].StackOffset;
|
|
|
|
if ( ! Params[n].ParamAttr.IsByValue )
|
|
pArg = *((void **)pArg);
|
|
|
|
pFormatParam = pStubDesc->pFormatTypes +
|
|
Params[n].TypeOffset;
|
|
|
|
if ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)] && pArg )
|
|
{
|
|
StubMsg.fDontCallFreeInst =
|
|
Params[n].ParamAttr.IsDontCallFreeInst;
|
|
|
|
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormatParam)])
|
|
( &StubMsg,
|
|
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 < StubMsg.BufferStart) ||
|
|
(pArg > StubMsg.BufferEnd) ) )
|
|
(*StubMsg.pfnFree)( pArg );
|
|
}
|
|
} // for
|
|
} // if !fBadStubData
|
|
|
|
//
|
|
// Deferred frees. Actually, this should only be necessary if you
|
|
// had a pointer to enum16 in a *_is expression.
|
|
//
|
|
|
|
//
|
|
// Free any full pointer resources.
|
|
//
|
|
if ( StubMsg.FullPtrXlatTables )
|
|
NdrFullPointerXlatFree( StubMsg.FullPtrXlatTables );
|
|
|
|
//
|
|
// Disable rpcss allocate package if needed.
|
|
//
|
|
if ( InterpreterFlags.RpcSsAllocUsed )
|
|
NdrRpcSsDisableAllocate( &StubMsg );
|
|
|
|
//
|
|
// Clean up pipe objects
|
|
//
|
|
|
|
if ( OptFlags.HasPipes )
|
|
NdrPipesDone( & StubMsg );
|
|
|
|
}
|
|
RpcEndFinally
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
#pragma code_seg()
|
|
|