824 lines
26 KiB
C++
824 lines
26 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
stblsclt.c
|
|
|
|
Abstract :
|
|
|
|
This file contains the routines for support of stubless clients in
|
|
object interfaces.
|
|
|
|
Note:
|
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
IMPORTANT!
|
|
THIS FILE IS PLATFORM SPECIFIC AND DUPLICATE AMONG ALL PLATFORMS. CHANING
|
|
ONE FILE MEANS CHANGE ALL OF THEM!!!
|
|
|
|
Author :
|
|
|
|
David Kays dkays February 1995.
|
|
|
|
Revision History :
|
|
Yong Qu YongQu Oct. 1998 change to platform specific and allow unlimited
|
|
vtbl & delegation vtbl
|
|
|
|
---------------------------------------------------------------------*/
|
|
|
|
#define USE_STUBLESS_PROXY
|
|
#define CINTERFACE
|
|
|
|
#include <stdarg.h>
|
|
#include "ndrp.h"
|
|
#include "hndl.h"
|
|
#include "interp2.h"
|
|
#include "ndrtypes.h"
|
|
|
|
#include "ndrole.h"
|
|
#include "mulsyntx.h"
|
|
#include "rpcproxy.h"
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
|
|
typedef unsigned short ushort;
|
|
|
|
#define NUMBER_OF_BLOCKS_PER_ALLOC 4
|
|
|
|
// for dynamically generated vtbl
|
|
#define NUMBER_OF_METHODS_PER_BLOCK 56
|
|
#define NUMBER_OF_FORWARDING_METHODS_PER_BLOCK 48
|
|
// pointed to array of masm macro. don't need to generate the buffer everytime.
|
|
#define CB_METHOD 4
|
|
// vtbl jmp talble
|
|
const BYTE CASM_GENERATESTUBLESS[] =
|
|
{
|
|
0x33, 0xC9, // xor eax,eax
|
|
0x8A, 0xC8, // move al,cl
|
|
0x81, 0xC1, 00,00,04,00, // method id
|
|
0xFF, 0x25, 00,00,00,00 // long jmp to ObjectStubless@0
|
|
};
|
|
|
|
const BYTE CASM_GENERATEFORWARD[] =
|
|
{
|
|
0x8b, 0x4c, 0x24, 0x04, // mov ecx, [esp+4]
|
|
0x8b, 0x49, 0x10, // mov ecx, [ecx+a]
|
|
0x89, 0x4c, 0x24, 0x4, // mov [esp+4], ecx
|
|
0x8b, 0x09, // mov ecx, [ecx]
|
|
0x66, 0x98, // cbw
|
|
0x98, // cwde
|
|
5, 00, 10, 00, 00, // add eax, 0x1000
|
|
0xc1, 0xe0, 0x02, // shl eax, 0x2
|
|
0x8b, 0x04, 0x01, // mov eax, [eax+ecx]
|
|
0xff, 0xe0 // jmp eax
|
|
};
|
|
|
|
|
|
typedef struct tagStublessProcBuffer
|
|
{
|
|
BYTE pMethodsa[NUMBER_OF_METHODS_PER_BLOCK/2][CB_METHOD];
|
|
struct tagStublessProcBuffer* pNext;
|
|
BYTE pAsm[sizeof(CASM_GENERATESTUBLESS)];
|
|
BYTE pMethodsb[NUMBER_OF_METHODS_PER_BLOCK/2][CB_METHOD];
|
|
} StublessProcBuffer, *PStublessProcBuffer;
|
|
|
|
static StublessProcBuffer * g_pStublessProcBuffer = NULL;
|
|
|
|
typedef struct tagForwardProcBuffer
|
|
{
|
|
BYTE pMethodsa[NUMBER_OF_FORWARDING_METHODS_PER_BLOCK/2][CB_METHOD];
|
|
struct tagForwardProcBuffer* pNext;
|
|
BYTE pAsm[sizeof(CASM_GENERATEFORWARD)];
|
|
BYTE pMethodsb[NUMBER_OF_FORWARDING_METHODS_PER_BLOCK/2][CB_METHOD];
|
|
} ForwardProcBuffer, *PForwardProcBuffer;
|
|
|
|
static ForwardProcBuffer * g_pForwardProcBuffer = NULL;
|
|
extern void ** ProxyForwardVtbl;
|
|
|
|
EXTERN_C void ObjectStubless(void);
|
|
void ReleaseTemplateForwardVtbl(void ** pVtbl);
|
|
void ReleaseTemplateVtbl(void ** pVtbl);
|
|
|
|
static DWORD g_ObjectStubless = (DWORD)ObjectStubless;
|
|
extern ULONG g_dwVtblSize,g_dwForwardVtblSize;
|
|
|
|
extern "C"
|
|
{
|
|
|
|
long
|
|
ObjectStublessClient(
|
|
void * ParamAddress,
|
|
long Method
|
|
);
|
|
|
|
void ObjectStublessClient3(void);
|
|
void ObjectStublessClient4(void);
|
|
void ObjectStublessClient5(void);
|
|
void ObjectStublessClient6(void);
|
|
void ObjectStublessClient7(void);
|
|
|
|
void ObjectStublessClient8(void);
|
|
void ObjectStublessClient9(void);
|
|
void ObjectStublessClient10(void);
|
|
void ObjectStublessClient11(void);
|
|
void ObjectStublessClient12(void);
|
|
void ObjectStublessClient13(void);
|
|
void ObjectStublessClient14(void);
|
|
void ObjectStublessClient15(void);
|
|
void ObjectStublessClient16(void);
|
|
void ObjectStublessClient17(void);
|
|
void ObjectStublessClient18(void);
|
|
void ObjectStublessClient19(void);
|
|
void ObjectStublessClient20(void);
|
|
void ObjectStublessClient21(void);
|
|
void ObjectStublessClient22(void);
|
|
void ObjectStublessClient23(void);
|
|
void ObjectStublessClient24(void);
|
|
void ObjectStublessClient25(void);
|
|
void ObjectStublessClient26(void);
|
|
void ObjectStublessClient27(void);
|
|
void ObjectStublessClient28(void);
|
|
void ObjectStublessClient29(void);
|
|
void ObjectStublessClient30(void);
|
|
void ObjectStublessClient31(void);
|
|
void ObjectStublessClient32(void);
|
|
void ObjectStublessClient33(void);
|
|
void ObjectStublessClient34(void);
|
|
void ObjectStublessClient35(void);
|
|
void ObjectStublessClient36(void);
|
|
void ObjectStublessClient37(void);
|
|
void ObjectStublessClient38(void);
|
|
void ObjectStublessClient39(void);
|
|
void ObjectStublessClient40(void);
|
|
void ObjectStublessClient41(void);
|
|
void ObjectStublessClient42(void);
|
|
void ObjectStublessClient43(void);
|
|
void ObjectStublessClient44(void);
|
|
void ObjectStublessClient45(void);
|
|
void ObjectStublessClient46(void);
|
|
void ObjectStublessClient47(void);
|
|
void ObjectStublessClient48(void);
|
|
void ObjectStublessClient49(void);
|
|
void ObjectStublessClient50(void);
|
|
void ObjectStublessClient51(void);
|
|
void ObjectStublessClient52(void);
|
|
void ObjectStublessClient53(void);
|
|
void ObjectStublessClient54(void);
|
|
void ObjectStublessClient55(void);
|
|
void ObjectStublessClient56(void);
|
|
void ObjectStublessClient57(void);
|
|
void ObjectStublessClient58(void);
|
|
void ObjectStublessClient59(void);
|
|
void ObjectStublessClient60(void);
|
|
void ObjectStublessClient61(void);
|
|
void ObjectStublessClient62(void);
|
|
void ObjectStublessClient63(void);
|
|
void ObjectStublessClient64(void);
|
|
void ObjectStublessClient65(void);
|
|
void ObjectStublessClient66(void);
|
|
void ObjectStublessClient67(void);
|
|
void ObjectStublessClient68(void);
|
|
void ObjectStublessClient69(void);
|
|
void ObjectStublessClient70(void);
|
|
void ObjectStublessClient71(void);
|
|
void ObjectStublessClient72(void);
|
|
void ObjectStublessClient73(void);
|
|
void ObjectStublessClient74(void);
|
|
void ObjectStublessClient75(void);
|
|
void ObjectStublessClient76(void);
|
|
void ObjectStublessClient77(void);
|
|
void ObjectStublessClient78(void);
|
|
void ObjectStublessClient79(void);
|
|
void ObjectStublessClient80(void);
|
|
void ObjectStublessClient81(void);
|
|
void ObjectStublessClient82(void);
|
|
void ObjectStublessClient83(void);
|
|
void ObjectStublessClient84(void);
|
|
void ObjectStublessClient85(void);
|
|
void ObjectStublessClient86(void);
|
|
void ObjectStublessClient87(void);
|
|
void ObjectStublessClient88(void);
|
|
void ObjectStublessClient89(void);
|
|
void ObjectStublessClient90(void);
|
|
void ObjectStublessClient91(void);
|
|
void ObjectStublessClient92(void);
|
|
void ObjectStublessClient93(void);
|
|
void ObjectStublessClient94(void);
|
|
void ObjectStublessClient95(void);
|
|
void ObjectStublessClient96(void);
|
|
void ObjectStublessClient97(void);
|
|
void ObjectStublessClient98(void);
|
|
void ObjectStublessClient99(void);
|
|
void ObjectStublessClient100(void);
|
|
void ObjectStublessClient101(void);
|
|
void ObjectStublessClient102(void);
|
|
void ObjectStublessClient103(void);
|
|
void ObjectStublessClient104(void);
|
|
void ObjectStublessClient105(void);
|
|
void ObjectStublessClient106(void);
|
|
void ObjectStublessClient107(void);
|
|
void ObjectStublessClient108(void);
|
|
void ObjectStublessClient109(void);
|
|
void ObjectStublessClient110(void);
|
|
void ObjectStublessClient111(void);
|
|
void ObjectStublessClient112(void);
|
|
void ObjectStublessClient113(void);
|
|
void ObjectStublessClient114(void);
|
|
void ObjectStublessClient115(void);
|
|
void ObjectStublessClient116(void);
|
|
void ObjectStublessClient117(void);
|
|
void ObjectStublessClient118(void);
|
|
void ObjectStublessClient119(void);
|
|
void ObjectStublessClient120(void);
|
|
void ObjectStublessClient121(void);
|
|
void ObjectStublessClient122(void);
|
|
void ObjectStublessClient123(void);
|
|
void ObjectStublessClient124(void);
|
|
void ObjectStublessClient125(void);
|
|
void ObjectStublessClient126(void);
|
|
void ObjectStublessClient127(void);
|
|
|
|
extern void * const g_StublessClientVtbl[128] =
|
|
{
|
|
IUnknown_QueryInterface_Proxy,
|
|
IUnknown_AddRef_Proxy,
|
|
IUnknown_Release_Proxy,
|
|
ObjectStublessClient3,
|
|
ObjectStublessClient4,
|
|
ObjectStublessClient5,
|
|
ObjectStublessClient6,
|
|
ObjectStublessClient7,
|
|
ObjectStublessClient8,
|
|
ObjectStublessClient9,
|
|
ObjectStublessClient10,
|
|
ObjectStublessClient11,
|
|
ObjectStublessClient12,
|
|
ObjectStublessClient13,
|
|
ObjectStublessClient14,
|
|
ObjectStublessClient15,
|
|
ObjectStublessClient16,
|
|
ObjectStublessClient17,
|
|
ObjectStublessClient18,
|
|
ObjectStublessClient19,
|
|
ObjectStublessClient20,
|
|
ObjectStublessClient21,
|
|
ObjectStublessClient22,
|
|
ObjectStublessClient23,
|
|
ObjectStublessClient24,
|
|
ObjectStublessClient25,
|
|
ObjectStublessClient26,
|
|
ObjectStublessClient27,
|
|
ObjectStublessClient28,
|
|
ObjectStublessClient29,
|
|
ObjectStublessClient30,
|
|
ObjectStublessClient31,
|
|
ObjectStublessClient32,
|
|
ObjectStublessClient33,
|
|
ObjectStublessClient34,
|
|
ObjectStublessClient35,
|
|
ObjectStublessClient36,
|
|
ObjectStublessClient37,
|
|
ObjectStublessClient38,
|
|
ObjectStublessClient39,
|
|
ObjectStublessClient40,
|
|
ObjectStublessClient41,
|
|
ObjectStublessClient42,
|
|
ObjectStublessClient43,
|
|
ObjectStublessClient44,
|
|
ObjectStublessClient45,
|
|
ObjectStublessClient46,
|
|
ObjectStublessClient47,
|
|
ObjectStublessClient48,
|
|
ObjectStublessClient49,
|
|
ObjectStublessClient50,
|
|
ObjectStublessClient51,
|
|
ObjectStublessClient52,
|
|
ObjectStublessClient53,
|
|
ObjectStublessClient54,
|
|
ObjectStublessClient55,
|
|
ObjectStublessClient56,
|
|
ObjectStublessClient57,
|
|
ObjectStublessClient58,
|
|
ObjectStublessClient59,
|
|
ObjectStublessClient60,
|
|
ObjectStublessClient61,
|
|
ObjectStublessClient62,
|
|
ObjectStublessClient63,
|
|
ObjectStublessClient64,
|
|
ObjectStublessClient65,
|
|
ObjectStublessClient66,
|
|
ObjectStublessClient67,
|
|
ObjectStublessClient68,
|
|
ObjectStublessClient69,
|
|
ObjectStublessClient70,
|
|
ObjectStublessClient71,
|
|
ObjectStublessClient72,
|
|
ObjectStublessClient73,
|
|
ObjectStublessClient74,
|
|
ObjectStublessClient75,
|
|
ObjectStublessClient76,
|
|
ObjectStublessClient77,
|
|
ObjectStublessClient78,
|
|
ObjectStublessClient79,
|
|
ObjectStublessClient80,
|
|
ObjectStublessClient81,
|
|
ObjectStublessClient82,
|
|
ObjectStublessClient83,
|
|
ObjectStublessClient84,
|
|
ObjectStublessClient85,
|
|
ObjectStublessClient86,
|
|
ObjectStublessClient87,
|
|
ObjectStublessClient88,
|
|
ObjectStublessClient89,
|
|
ObjectStublessClient90,
|
|
ObjectStublessClient91,
|
|
ObjectStublessClient92,
|
|
ObjectStublessClient93,
|
|
ObjectStublessClient94,
|
|
ObjectStublessClient95,
|
|
ObjectStublessClient96,
|
|
ObjectStublessClient97,
|
|
ObjectStublessClient98,
|
|
ObjectStublessClient99,
|
|
ObjectStublessClient100,
|
|
ObjectStublessClient101,
|
|
ObjectStublessClient102,
|
|
ObjectStublessClient103,
|
|
ObjectStublessClient104,
|
|
ObjectStublessClient105,
|
|
ObjectStublessClient106,
|
|
ObjectStublessClient107,
|
|
ObjectStublessClient108,
|
|
ObjectStublessClient109,
|
|
ObjectStublessClient110,
|
|
ObjectStublessClient111,
|
|
ObjectStublessClient112,
|
|
ObjectStublessClient113,
|
|
ObjectStublessClient114,
|
|
ObjectStublessClient115,
|
|
ObjectStublessClient116,
|
|
ObjectStublessClient117,
|
|
ObjectStublessClient118,
|
|
ObjectStublessClient119,
|
|
ObjectStublessClient120,
|
|
ObjectStublessClient121,
|
|
ObjectStublessClient122,
|
|
ObjectStublessClient123,
|
|
ObjectStublessClient124,
|
|
ObjectStublessClient125,
|
|
ObjectStublessClient126,
|
|
ObjectStublessClient127
|
|
};
|
|
|
|
}
|
|
|
|
void ** StublessClientVtbl = (void **)g_StublessClientVtbl;
|
|
|
|
long
|
|
ObjectStublessClient(
|
|
void * ParamAddress,
|
|
long Method
|
|
)
|
|
{
|
|
PMIDL_STUBLESS_PROXY_INFO ProxyInfo;
|
|
CInterfaceProxyHeader * ProxyHeader;
|
|
PFORMAT_STRING ProcFormat;
|
|
unsigned short ProcFormatOffset;
|
|
CLIENT_CALL_RETURN Return;
|
|
long ParamSize;
|
|
void * This;
|
|
|
|
|
|
This = *((void **)ParamAddress);
|
|
|
|
ProxyHeader = (CInterfaceProxyHeader *)
|
|
(*((char **)This) - sizeof(CInterfaceProxyHeader));
|
|
ProxyInfo = (PMIDL_STUBLESS_PROXY_INFO) ProxyHeader->pStublessProxyInfo;
|
|
|
|
#if defined(BUILD_NDR64)
|
|
|
|
if ( ProxyInfo->pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES )
|
|
{
|
|
|
|
NDR_PROC_CONTEXT ProcContext;
|
|
HRESULT hr;
|
|
|
|
Ndr64ClientInitializeContext(
|
|
NdrpGetSyntaxType( ProxyInfo->pTransferSyntax),
|
|
ProxyInfo,
|
|
Method,
|
|
&ProcContext,
|
|
(uchar*)ParamAddress );
|
|
|
|
if ( ProcContext.IsAsync )
|
|
{
|
|
if ( Method & 0x1 )
|
|
hr = MulNdrpBeginDcomAsyncClientCall( ProxyInfo,
|
|
Method,
|
|
&ProcContext,
|
|
ParamAddress );
|
|
else
|
|
hr = MulNdrpFinishDcomAsyncClientCall(ProxyInfo,
|
|
Method,
|
|
&ProcContext,
|
|
ParamAddress );
|
|
Return.Simple = hr;
|
|
}
|
|
else
|
|
Return = NdrpClientCall3(This,
|
|
ProxyInfo,
|
|
Method,
|
|
NULL, // return value
|
|
&ProcContext,
|
|
(uchar*)ParamAddress);
|
|
|
|
ParamSize = ProcContext.StackSize;
|
|
goto Finish;
|
|
}
|
|
|
|
#endif
|
|
|
|
ProcFormatOffset = ProxyInfo->FormatStringOffset[Method];
|
|
ProcFormat = &ProxyInfo->ProcFormatString[ProcFormatOffset];
|
|
|
|
ParamSize = (long)
|
|
( (ProcFormat[1] & Oi_HAS_RPCFLAGS) ?
|
|
*((ushort *)&ProcFormat[8]) : *((ushort *)&ProcFormat[4]) );
|
|
|
|
if ( MIDL_VERSION_3_0_39 <= ProxyInfo->pStubDesc->MIDLVersion )
|
|
{
|
|
// Since MIDL 3.0.39 we have a proc flag that indicates
|
|
// which interpeter to call. This is because the NDR version
|
|
// may be bigger than 1.1 for other reasons.
|
|
|
|
if ( ProcFormat[1] & Oi_OBJ_USE_V2_INTERPRETER )
|
|
{
|
|
|
|
if ( MIDL_VERSION_5_0_136 <= ProxyInfo->pStubDesc->MIDLVersion
|
|
&&
|
|
((PNDR_DCOM_OI2_PROC_HEADER) ProcFormat)->Oi2Flags.HasAsyncUuid )
|
|
{
|
|
Return = NdrDcomAsyncClientCall( ProxyInfo->pStubDesc,
|
|
ProcFormat,
|
|
ParamAddress );
|
|
}
|
|
else
|
|
{
|
|
Return = NdrClientCall2( ProxyInfo->pStubDesc,
|
|
ProcFormat,
|
|
ParamAddress );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Return = NdrClientCall( ProxyInfo->pStubDesc,
|
|
ProcFormat,
|
|
ParamAddress );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Prior to that, the NDR version (on per file basis)
|
|
// was the only indication of -Oi2.
|
|
|
|
if ( ProxyInfo->pStubDesc->Version <= NDR_VERSION_1_1 )
|
|
{
|
|
Return = NdrClientCall( ProxyInfo->pStubDesc,
|
|
ProcFormat,
|
|
ParamAddress );
|
|
Return.Simple = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
Return = NdrClientCall2( ProxyInfo->pStubDesc,
|
|
ProcFormat,
|
|
ParamAddress );
|
|
}
|
|
}
|
|
|
|
#if defined(BUILD_NDR64)
|
|
Finish:
|
|
#endif
|
|
//
|
|
// Return the size of the parameter stack minus 4 bytes for the HRESULT
|
|
// return in ecx. The ObjectStublessClient* routines need this to pop
|
|
// the stack the correct number of bytes. We don't have to worry about
|
|
// this on RISC platforms since the caller pops any argument stack space
|
|
// needed .
|
|
//
|
|
_asm { mov ecx, ParamSize }
|
|
_asm { sub ecx, 4 }
|
|
|
|
return (long) Return.Simple;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateStublessProcBuffer
|
|
//
|
|
// Synopsis: Create a StublessClientProcBuffer for vtbl to point to. starting from g_dwVtblSize,
|
|
// till the larger of numMethods and maximum vtbls created in the block
|
|
//
|
|
// Arguments: USHORT numMethods // number of methods in this interface
|
|
// StublessProcBuffer **pTail // the last pNext in the allocated block
|
|
//
|
|
// Note: in x86, we are using short move & short jmps such that each method entry is 4 bytes.
|
|
// this force we to have two method table in each block
|
|
// in alpha, each entry has to be 8 bytes (2 instructions) so we can just have one
|
|
// method table in a block.
|
|
//
|
|
// Returns:
|
|
// pointer to ProcBuffer if succeeded;
|
|
// NULL if failed. GetLastError() to retrieve error.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CreateStublessProcBuffer(IN ULONG numMethods,
|
|
OUT void *** lpTempVtbl)
|
|
{
|
|
// pointer to the last "pNext" pointer in vtbl link list: only increase, never release.
|
|
static StublessProcBuffer** pVtblTail = NULL;
|
|
ULONG i,j,k,iBlock = 0;
|
|
ULONG nMethodsToAlloc = numMethods - g_dwVtblSize;
|
|
StublessProcBuffer InitBuffer, *pStart = NULL, **pTail = NULL, *pBuf = NULL;
|
|
DWORD* lpdwTemp, dwStartMethod = g_dwVtblSize ;
|
|
LPBYTE lpByte;
|
|
BYTE lDist;
|
|
ULONG dwNewLength;
|
|
void ** TempVtbl = NULL;
|
|
HRESULT hr;
|
|
|
|
// get number of blocks need to be allocated
|
|
iBlock = nMethodsToAlloc / (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK);
|
|
|
|
if (nMethodsToAlloc % (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK) != 0)
|
|
iBlock++;
|
|
|
|
// size of new vtbl tempplate.
|
|
dwNewLength = g_dwVtblSize + iBlock * (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK);
|
|
|
|
TempVtbl = (void **)I_RpcAllocate(dwNewLength * sizeof(void *) + sizeof(LONG));
|
|
if (NULL == TempVtbl)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*(LONG*)TempVtbl = 1; // ref count
|
|
TempVtbl = (void **)((LPBYTE)TempVtbl + sizeof(LONG));
|
|
memcpy(TempVtbl,StublessClientVtbl,g_dwVtblSize*sizeof(void *));
|
|
|
|
// the template other StublessProcBuffers copy from.
|
|
if (NULL == g_pStublessProcBuffer)
|
|
{
|
|
BYTE nRelativeID = 0;
|
|
memset(&InitBuffer,0,sizeof(StublessProcBuffer));
|
|
memcpy(InitBuffer.pAsm,CASM_GENERATESTUBLESS,sizeof(CASM_GENERATESTUBLESS));
|
|
*((DWORD *)&InitBuffer.pAsm[12]) = (DWORD)&g_ObjectStubless;
|
|
|
|
lpByte = (LPBYTE)InitBuffer.pMethodsa;
|
|
lDist = CB_METHOD * NUMBER_OF_METHODS_PER_BLOCK / 2;
|
|
|
|
for (i = 0; i < NUMBER_OF_METHODS_PER_BLOCK / 2; i++)
|
|
{
|
|
*lpByte++ = 0xB0; // _asm mov al
|
|
*lpByte++ = nRelativeID++;
|
|
*lpByte++ = 0xEB; // _asm jmp
|
|
*lpByte++ = lDist;
|
|
lDist -=CB_METHOD; // goes further and further
|
|
}
|
|
|
|
lpByte = (LPBYTE)InitBuffer.pMethodsb;
|
|
lDist = sizeof(CASM_GENERATESTUBLESS) + CB_METHOD;
|
|
lDist = -lDist;
|
|
for (i = 0; i < NUMBER_OF_METHODS_PER_BLOCK /2 ; i++)
|
|
{
|
|
*lpByte++ = 0xB0; // _asm mov al
|
|
*lpByte++ = nRelativeID++;
|
|
*lpByte++ = 0xEB; // _asm jmp
|
|
*lpByte++ = lDist;
|
|
lDist -=CB_METHOD; // goes further and further
|
|
}
|
|
}
|
|
else
|
|
memcpy(&InitBuffer,g_pStublessProcBuffer,sizeof(StublessProcBuffer));
|
|
|
|
for (i = 0; i < iBlock; i++)
|
|
{
|
|
// we need to create a buffer
|
|
pBuf = (StublessProcBuffer *)I_RpcAllocate(NUMBER_OF_BLOCKS_PER_ALLOC * sizeof(StublessProcBuffer) );
|
|
if (NULL == pBuf)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// remember the starting block of all the block in the call.
|
|
if (NULL == pStart)
|
|
pStart = pBuf;
|
|
|
|
if (pTail)
|
|
*pTail = pBuf; // link up the link list.
|
|
|
|
for (j = 0; j < NUMBER_OF_BLOCKS_PER_ALLOC; j++)
|
|
{
|
|
memcpy(&pBuf[j],&InitBuffer,sizeof(StublessProcBuffer));
|
|
if (j < NUMBER_OF_BLOCKS_PER_ALLOC -1 )
|
|
pBuf[j].pNext = &pBuf[j+1];
|
|
else
|
|
{
|
|
pTail = &(pBuf[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext);
|
|
*pTail = NULL;
|
|
}
|
|
|
|
|
|
// adjust the starting methodid in this block
|
|
lpdwTemp = (DWORD *)& (pBuf[j].pAsm[6]);
|
|
*lpdwTemp = dwStartMethod;
|
|
|
|
for (k = 0; k < NUMBER_OF_METHODS_PER_BLOCK / 2; k++)
|
|
TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsa[k];
|
|
|
|
for (k = 0; k < NUMBER_OF_METHODS_PER_BLOCK / 2; k++)
|
|
TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsb[k];
|
|
|
|
}
|
|
}
|
|
|
|
if (NULL == g_pStublessProcBuffer)
|
|
g_pStublessProcBuffer = pStart;
|
|
else
|
|
*pVtblTail = pStart;
|
|
|
|
*lpTempVtbl = TempVtbl;
|
|
pVtblTail = pTail;
|
|
g_dwVtblSize = dwNewLength;
|
|
return S_OK;
|
|
|
|
Cleanup:
|
|
while (pStart)
|
|
{
|
|
pTail = &pStart[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext;
|
|
I_RpcFree(pStart);
|
|
pStart = *pTail;
|
|
}
|
|
if (TempVtbl)
|
|
I_RpcFree(TempVtbl);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateForwardProcBuffer
|
|
//
|
|
// Synopsis: Create a StublessClientProcBuffer for vtbl to point to. starting from g_dwVtblSize,
|
|
// till the larger of numMethods and maximum vtbls created in the block
|
|
//
|
|
// Arguments: USHORT numMethods // number of methods in this interface
|
|
// StublessProcBuffer **pTail // the last pNext in the allocated block
|
|
//
|
|
// Note: in x86, we are using short move & short jmps such that each method entry is 4 bytes.
|
|
// this force we to have two method table in each block
|
|
// in alpha, each entry has to be 8 bytes (2 instructions) so we can just have one
|
|
// method table in a block.
|
|
//
|
|
// Returns:
|
|
// pointer to ProcBuffer if succeeded;
|
|
// NULL if failed. GetLastError() to retrieve error.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CreateForwardProcBuffer(ULONG numMethods, void ***lpTempVtbl)
|
|
{
|
|
// pointer to the last "pNext" pointer in vtbl link list: only increase, never release.
|
|
static ForwardProcBuffer** pVtblTail = NULL;
|
|
ULONG i,j,k,iBlock = 0;
|
|
ULONG nMethodsToAlloc = numMethods - g_dwForwardVtblSize;
|
|
ForwardProcBuffer InitBuffer, *pStart = NULL, **pTail = NULL, *pBuf = NULL;
|
|
DWORD* lpdwTemp, dwStartMethod = g_dwForwardVtblSize ;
|
|
LPBYTE lpByte;
|
|
BYTE lDist;
|
|
ULONG dwNewLength;
|
|
void ** TempVtbl;
|
|
HRESULT hr;
|
|
|
|
// get number of blocks need to be allocated
|
|
iBlock = nMethodsToAlloc / (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK);
|
|
|
|
if (nMethodsToAlloc % (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK) != 0)
|
|
iBlock++;
|
|
|
|
// size of new vtbl tempplate.
|
|
dwNewLength = g_dwForwardVtblSize + iBlock * (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK);
|
|
|
|
TempVtbl = (void **)I_RpcAllocate(dwNewLength * sizeof(void *) + sizeof(LONG));
|
|
if (NULL == TempVtbl)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*(LONG*)TempVtbl = 1; // ref count
|
|
TempVtbl = (void **)((LPBYTE)TempVtbl + sizeof(LONG));
|
|
memcpy(TempVtbl,ProxyForwardVtbl,g_dwForwardVtblSize*sizeof(void *));
|
|
|
|
// the template other StublessProcBuffers copy from.
|
|
if (NULL == g_pForwardProcBuffer)
|
|
{
|
|
BYTE nRelativeID = 0;
|
|
memset(&InitBuffer,0,sizeof(ForwardProcBuffer));
|
|
memcpy(&InitBuffer.pAsm,CASM_GENERATEFORWARD,sizeof(CASM_GENERATEFORWARD));
|
|
|
|
lpByte = (LPBYTE)InitBuffer.pMethodsa;
|
|
lDist = CB_METHOD * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2;
|
|
|
|
for (i = 0; i < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; i++)
|
|
{
|
|
*lpByte++ = 0xB0; // _asm mov al
|
|
*lpByte++ = nRelativeID++;
|
|
*lpByte++ = 0xEB; // _asm jmp
|
|
*lpByte++ = lDist;
|
|
lDist -=CB_METHOD; // goes further and further
|
|
}
|
|
|
|
lpByte = (LPBYTE)InitBuffer.pMethodsb;
|
|
lDist = sizeof(CASM_GENERATEFORWARD) + CB_METHOD;
|
|
lDist = -lDist;
|
|
for (i = 0; i < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK /2 ; i++)
|
|
{
|
|
*lpByte++ = 0xB0; // _asm mov al
|
|
*lpByte++ = nRelativeID++;
|
|
*lpByte++ = 0xEB; // _asm jmp
|
|
*lpByte++ = lDist;
|
|
lDist -=CB_METHOD; // goes further and further
|
|
}
|
|
}
|
|
else
|
|
memcpy(&InitBuffer,g_pForwardProcBuffer,sizeof(ForwardProcBuffer));
|
|
|
|
for (i = 0; i < iBlock; i++)
|
|
{
|
|
// we need to create a buffer
|
|
pBuf = (ForwardProcBuffer *)I_RpcAllocate(NUMBER_OF_BLOCKS_PER_ALLOC * sizeof(ForwardProcBuffer) );
|
|
if (NULL == pBuf)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// remember the starting block of all the block in the call.
|
|
if (NULL == pStart)
|
|
pStart = pBuf;
|
|
|
|
if (pTail)
|
|
*pTail = pBuf; // link up the link list.
|
|
|
|
for (j = 0; j < NUMBER_OF_BLOCKS_PER_ALLOC; j++)
|
|
{
|
|
memcpy(&pBuf[j],&InitBuffer,sizeof(ForwardProcBuffer));
|
|
if (j < NUMBER_OF_BLOCKS_PER_ALLOC -1 )
|
|
pBuf[j].pNext = &pBuf[j+1];
|
|
else
|
|
{
|
|
pTail = &(pBuf[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext);
|
|
*pTail = NULL;
|
|
}
|
|
|
|
|
|
// adjust the starting methodid in this block
|
|
lpdwTemp = (DWORD *)& (pBuf[j].pAsm[17]);
|
|
*lpdwTemp = dwStartMethod;
|
|
|
|
for (k = 0; k < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; k++)
|
|
TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsa[k];
|
|
|
|
for (k = 0; k < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; k++)
|
|
TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsb[k];
|
|
|
|
}
|
|
}
|
|
|
|
if (NULL == g_pForwardProcBuffer)
|
|
g_pForwardProcBuffer = pStart;
|
|
else
|
|
*pVtblTail = pStart;
|
|
|
|
*lpTempVtbl = TempVtbl;
|
|
pVtblTail = pTail;
|
|
g_dwForwardVtblSize = dwNewLength;
|
|
return S_OK;
|
|
|
|
Cleanup:
|
|
while (pStart)
|
|
{
|
|
pTail = &pStart[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext;
|
|
I_RpcFree(pStart);
|
|
pStart = *pTail;
|
|
}
|
|
if (TempVtbl)
|
|
I_RpcFree(TempVtbl);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|