|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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; }
|