#include
#include
#include
#include
#include
#include
#include
#include
extern "C"
{
#include "orpc_dbg.h"
}
#include
#include
#include
#include
#include
#include
#pragma code_seg(".orpc")
/***************************************************************************/
#define MAKE_WIN32( status ) \
MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, (status) )
#ifdef _CHICAGO_
#define RETURN_COMM_STATUS( status ) return (status)
#else
#define RETURN_COMM_STATUS( status ) RpcRaiseException( status )
#endif
const int ORPCF_INPUT_SYNC = ORPCF_RESERVED1;
const int ORPCF_ASYNC = ORPCF_RESERVED2;
const int ORPCF_REJECTED = ORPCF_RESERVED1;
const int ORPCF_RETRY_LATER = ORPCF_RESERVED2;
const int INITIAL_NUM_BUCKETS = 20;
/***************************************************************************/
const DWORD CALLCACHE_SIZE = 8;
struct working_call : public CChannelCallInfo
{
working_call( CALLCATEGORY callcat,
RPCOLEMESSAGE *message,
DWORD flags,
REFIPID ipidServer,
DWORD destctx,
CRpcChannelBuffer *channel,
DWORD authn_level );
void *operator new ( size_t );
void operator delete( void * );
static void Cleanup ( void );
static void Initialize ( void );
RPCOLEMESSAGE message;
private:
static void *list[CALLCACHE_SIZE];
static DWORD next;
};
void *working_call::list[CALLCACHE_SIZE] =
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
DWORD working_call::next = 0;
/***************************************************************************/
inline DWORD SIZENEEDED_ORPCTHIS( BOOL local, DWORD debug_size )
{
if (debug_size == 0)
return sizeof(WireThisPart1) + ((local) ? sizeof(LocalThis) : 0);
else
return sizeof(WireThisPart2) + ((local) ? sizeof(LocalThis) : 0) +
debug_size;
}
inline DWORD SIZENEEDED_ORPCTHAT( DWORD debug_size )
{
if (debug_size == 0)
return sizeof(WireThatPart1);
else
return sizeof(WireThatPart2) + debug_size;
}
inline CALLCATEGORY GetCallCat( void *header )
{
WireThis *inb = (WireThis *) header;
if (inb->c.flags & ORPCF_ASYNC)
return CALLCAT_ASYNC;
else if (inb->c.flags & ORPCF_INPUT_SYNC)
return CALLCAT_INPUTSYNC;
else
return CALLCAT_SYNCHRONOUS;
}
/***************************************************************************/
BOOL DoDebuggerHooks = FALSE;
LPORPC_INIT_ARGS DebuggerArg = NULL;
const uuid_t DEBUG_EXTENSION =
{ 0xf1f19680, 0x4d2a, 0x11ce, {0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}};
#if DBG == 1
WCHAR *wszDebugORPCCallPrefixString[4] = { L"--> [BEG]",
L" --> [end]",
L"<-- [BEG]",
L" <-- [end]" };
LONG ulDebugORPCCallNestingLevel[4] = {1, -1, 1, -1};
#endif
SHashChain OIDBuckets[23] = { {&OIDBuckets[0], &OIDBuckets[0]},
{&OIDBuckets[1], &OIDBuckets[1]},
{&OIDBuckets[2], &OIDBuckets[2]},
{&OIDBuckets[3], &OIDBuckets[3]},
{&OIDBuckets[4], &OIDBuckets[4]},
{&OIDBuckets[5], &OIDBuckets[5]},
{&OIDBuckets[6], &OIDBuckets[6]},
{&OIDBuckets[7], &OIDBuckets[7]},
{&OIDBuckets[8], &OIDBuckets[8]},
{&OIDBuckets[9], &OIDBuckets[9]},
{&OIDBuckets[10], &OIDBuckets[10]},
{&OIDBuckets[11], &OIDBuckets[11]},
{&OIDBuckets[12], &OIDBuckets[12]},
{&OIDBuckets[13], &OIDBuckets[13]},
{&OIDBuckets[14], &OIDBuckets[14]},
{&OIDBuckets[15], &OIDBuckets[15]},
{&OIDBuckets[16], &OIDBuckets[16]},
{&OIDBuckets[17], &OIDBuckets[17]},
{&OIDBuckets[18], &OIDBuckets[18]},
{&OIDBuckets[19], &OIDBuckets[19]},
{&OIDBuckets[20], &OIDBuckets[20]},
{&OIDBuckets[21], &OIDBuckets[21]},
{&OIDBuckets[22], &OIDBuckets[22]}
};
CUUIDHashTable gClientRegisteredOIDs;
BOOL gfChannelProcessInitialized = 0;
BOOL gfMTAChannelInitialized = 0;
extern DWORD g_cMTAInits;
CDebugChannelHook gDebugHook;
CErrorChannelHook gErrorHook;
#if DBG==1
LONG GetInterfaceName(REFIID riid, WCHAR *pwszName)
{
CDbgGuidStr dbgsIID(riid);
LONG ulcb=256;
WCHAR szKey[80];
szKey[0] = L'\0';
lstrcatW(szKey, L"Interface\\");
lstrcatW(szKey, dbgsIID._wszGuid);
LONG result = RegQueryValue(
HKEY_CLASSES_ROOT,
szKey,
pwszName,
&ulcb);
Win4Assert( result == 0 );
return result;
}
void DebugPrintORPCCall(DWORD dwFlag, REFIID riid, DWORD iMethod, DWORD Callcat)
{
if (CairoleInfoLevel & DEB_USER15)
{
Win4Assert (dwFlag < 4);
COleTls tls;
tls->cORPCNestingLevel += ulDebugORPCCallNestingLevel[dwFlag];
CHAR szNesting[100];
memset(szNesting, 0x20, 100);
if (tls->cORPCNestingLevel > 99)
szNesting[99] = '\0';
else
szNesting[tls->cORPCNestingLevel] = '\0';
WCHAR *pwszDirection = wszDebugORPCCallPrefixString[dwFlag];
WCHAR wszName[100];
GetInterfaceName(riid, wszName);
ComDebOut((DEB_USER15, "%s%ws [%x] %ws:: %x\n",
szNesting, pwszDirection, Callcat, wszName, iMethod));
}
}
#endif
/***************************************************************************/
void ByteSwapThis( DWORD drep, WireThis *inb )
{
if ((drep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
{
ByteSwapShort( inb->c.version.MajorVersion );
ByteSwapShort( inb->c.version.MinorVersion );
ByteSwapLong( inb->c.flags );
ByteSwapLong( inb->c.cid.Data1 );
ByteSwapShort( inb->c.cid.Data2 );
ByteSwapShort( inb->c.cid.Data3 );
}
}
/***************************************************************************/
void ByteSwapThat( DWORD drep, WireThat *outb )
{
if ((drep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
{
ByteSwapLong( outb->c.flags );
}
}
STDAPI ChannelProcessInitialize()
{
TRACECALL(TRACE_RPC, "ChannelProcessInitialize");
ComDebOut((DEB_COMPOBJ, "ChannelProcessInitialize [IN]\n"));
Win4Assert( (sizeof(WireThisPart1) & 7) == 0 );
Win4Assert( (sizeof(WireThisPart2) & 7) == 0 );
Win4Assert( (sizeof(LocalThis) & 7) == 0 );
Win4Assert( (sizeof(WireThatPart1) & 7) == 0 );
Win4Assert( (sizeof(WireThatPart2) & 7) == 0 );
ASSERT_LOCK_RELEASED
LOCK
HRESULT hr = S_OK;
if (!gfChannelProcessInitialized)
{
gMIDTbl.Initialize();
gOXIDTbl.Initialize();
gRIFTbl.Initialize();
gIPIDTbl.Initialize();
gSRFTbl.Initialize();
gClientRegisteredOIDs.Initialize(OIDBuckets);
hr = CoRegisterChannelHook( DEBUG_EXTENSION, &gDebugHook );
if(SUCCEEDED(hr))
{
hr = CoRegisterChannelHook( ERROR_EXTENSION, &gErrorHook );
}
if (SUCCEEDED(hr))
{
hr = InitializeSecurity();
}
gfChannelProcessInitialized = TRUE;
}
UNLOCK
ASSERT_LOCK_RELEASED
if (FAILED(hr))
{
ChannelProcessUninitialize();
}
ComDebOut((DEB_COMPOBJ, "ChannelProcessInitialize [OUT] hr:%x\n", hr));
return hr;
}
void CleanupRegOIDs(SHashChain *pNode)
{
delete pNode;
}
STDAPI_(void) ChannelProcessUninitialize(void)
{
TRACECALL(TRACE_RPC, "ChannelProcessUninitialize");
ComDebOut((DEB_COMPOBJ, "ChannelProcessUninitialize [IN]\n"));
if (gfChannelProcessInitialized)
{
UnregisterDcomInterfaces();
}
gResolver.ReleaseSCMProxy();
ASSERT_LOCK_RELEASED
LOCK
if (gfChannelProcessInitialized)
{
gRIFTbl.Cleanup();
if (gpLocalMIDEntry)
{
DecMIDRefCnt(gpLocalMIDEntry);
gpLocalMIDEntry = NULL;
}
gOXIDTbl.ReleaseLocalMTAEntry();
if (gpsaCurrentProcess)
{
PrivMemFree(gpsaCurrentProcess);
gpsaCurrentProcess = NULL;
}
gOXIDTbl.FreeExpiredEntries(GetTickCount()+1);
gIPIDTbl.Cleanup();
gOXIDTbl.Cleanup();
gMIDTbl.Cleanup();
gSRFTbl.Cleanup();
gClientRegisteredOIDs.Cleanup(CleanupRegOIDs);
working_call::Cleanup();
gRpcThreadCache.ClearFreeList();
gEventCache.Cleanup();
CleanupChannelHooks();
}
gResolver.Cleanup();
UninitializeSecurity();
gfChannelProcessInitialized = FALSE;
gfMTAChannelInitialized = FALSE;
UNLOCK
ASSERT_LOCK_RELEASED
if (gpStdMarshal)
{
((CStdIdentity *)gpStdMarshal)->UnlockAndRelease();
gpStdMarshal = NULL;
}
ComDebOut((DEB_COMPOBJ, "ChannelProcessUninitialize [OUT]\n"));
return;
}
STDAPI STAChannelInitialize(void)
{
ComDebOut((DEB_COMPOBJ, "STAChannelInitialize [IN]\n"));
Win4Assert(IsSTAThread());
HRESULT hr = S_OK;
if (!gfChannelProcessInitialized)
{
if (FAILED(hr = ChannelProcessInitialize()))
return hr;
}
COleTls tls;
if (tls->pCallCtrl == NULL)
{
hr = E_OUTOFMEMORY;
CAptCallCtrl *pCallCtrl = new CAptCallCtrl();
}
if (tls->pCallCtrl)
{
tls->dwFlags |= OLETLS_CHANNELTHREADINITIALZED;
ASSERT_LOCK_RELEASED
LOCK
OXIDEntry *pOxid;
hr = gOXIDTbl.GetLocalEntry( &pOxid );
UNLOCK
ASSERT_LOCK_RELEASED
if (SUCCEEDED(hr))
{
hr = ThreadStart();
}
if (FAILED(hr))
tls->dwFlags &= ~OLETLS_CHANNELTHREADINITIALZED;
}
ComDebOut((DEB_COMPOBJ, "STAChannelInitialize [OUT] hr:%x\n", hr));
return hr;
}
STDAPI MTAChannelInitialize(void)
{
ComDebOut((DEB_COMPOBJ, "MTAChannelInitialize [IN]\n"));
Win4Assert(IsMTAThread());
HRESULT hr = S_OK;
if (!gfChannelProcessInitialized)
{
if (FAILED(hr = ChannelProcessInitialize()))
return hr;
}
ASSERT_LOCK_RELEASED
LOCK
if (!gfMTAChannelInitialized)
{
OXIDEntry *pOxid;
hr = gOXIDTbl.GetLocalEntry( &pOxid );
if (SUCCEEDED(hr))
{
pOxid->dwFlags &= ~ OXIDF_STOPPED;
gfMTAChannelInitialized = TRUE;
}
}
UNLOCK
ASSERT_LOCK_RELEASED
ComDebOut((DEB_COMPOBJ, "MTAChannelInitialize [OUT] hr:%x\n", hr));
return hr;
}
STDAPI_(void) ChannelThreadUninitialize(void)
{
TRACECALL(TRACE_RPC, "ChannelThreadUninitialize");
ComDebOut((DEB_COMPOBJ, "ChannelThreadUninitialize [IN]\n"));
COleTls tls;
if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
{
ThreadCleanup();
delete tls->pCallCtrl;
tls->pCallCtrl = NULL;
if (tls->pMsgFilter)
{
tls->pMsgFilter->Release();
tls->pMsgFilter = NULL;
}
ASSERT_LOCK_RELEASED
LOCK
gOXIDTbl.ReleaseLocalSTAEntry();
UNLOCK
ASSERT_LOCK_RELEASED
tls->dwFlags &= ~OLETLS_CHANNELTHREADINITIALZED;
}
else
{
gfMTAChannelInitialized = FALSE;
}
ComDebOut((DEB_COMPOBJ, "ChannelThreadUninitialize [OUT]\n"));
}
INTERNAL InitChannelIfNecessary()
{
HRESULT hr;
COleTls tls(hr);
if (FAILED(hr))
return hr;
if (!(tls->dwFlags & OLETLS_APARTMENTTHREADED))
{
if (!gfMTAChannelInitialized)
{
if (g_cMTAInits > 0)
{
return MTAChannelInitialize();
}
return CO_E_NOTINITIALIZED;
}
}
else if (!(tls->dwFlags & OLETLS_CHANNELTHREADINITIALZED))
{
if (tls->cComInits > 0 &&
!(tls->dwFlags & OLETLS_THREADUNINITIALIZING))
return STAChannelInitialize();
return CO_E_NOTINITIALIZED;
}
return S_OK;
}
/***************************************************************************/
CChannelCallInfo *MakeAsyncCopy( CChannelCallInfo *original )
{
void *pBuffer = NULL;
WireThat *outb;
BOOL success;
ASSERT_LOCK_HELD
working_call *copy = new working_call( original->category,
original->pmessage,
original->iFlags,
original->ipid,
original->iDestCtx,
original->pChannel,
original->lAuthnLevel );
if (copy != NULL)
{
original->hResult = S_OK;
if (original->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
{
copy->message.Buffer = original->pmessage->Buffer;
}
else
{
pBuffer = PrivMemAlloc8(original->pmessage->cbBuffer);
Win4Assert(((ULONG)pBuffer & 0x7) == 0 && "Buffer not aligned properly");
if (pBuffer != NULL)
{
copy->message.Buffer = pBuffer;
memcpy(pBuffer, original->pmessage->Buffer,
original->pmessage->cbBuffer);
}
else
{
original->hResult = RPC_E_OUT_OF_RESOURCES;
}
}
if (SUCCEEDED(original->hResult))
{
copy->message.rpcFlags |= RPCFLG_LOCAL_CALL;
original->pmessage->cbBuffer = SIZENEEDED_ORPCTHAT(0) + 4;
if (original->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
{
original->pmessage->Buffer = PrivMemAlloc8(original->pmessage->cbBuffer);
success = original->pmessage->Buffer != NULL;
}
else
{
success = I_RpcGetBuffer((RPC_MESSAGE *) original->pmessage) == RPC_S_OK;
}
if (success)
{
outb = (WireThat *) original->pmessage->Buffer;
outb->c.flags = ORPCF_NULL;
outb->c.unique = 0;
*(SCODE *)((WireThatPart1 *)outb + 1) = S_OK;
return copy;
}
}
PrivMemFree(pBuffer);
delete copy;
}
return NULL;
}
/***************************************************************************/
STDMETHODIMP_(ULONG) CRpcChannelBuffer::AddRef( THIS )
{
InterlockedIncrement( (long *) &ref_count );
return ref_count;
}
/***************************************************************************/
HRESULT CRpcChannelBuffer::AppInvoke( CChannelCallInfo *call,
IRpcStubBuffer *stub,
void *pv,
void *orig_stub_buffer,
LocalThis *localb )
{
ASSERT_LOCK_RELEASED
RPC_MESSAGE *message = (RPC_MESSAGE *) call->pmessage;
void *orig_buffer = message->Buffer;
WireThat *outb = NULL;
HRESULT result;
call->pHeader = message->Buffer;
message->BufferLength -= (char *) orig_stub_buffer - (char *) message->Buffer;
message->Buffer = orig_stub_buffer;
message->ProcNum &= ~RPC_FLAGS_VALID_BIT;
if (localb != NULL && localb->flags & LOCALF_NONNDR)
message->RpcFlags |= RPCFLG_NON_NDR;
if (IsMTAThread())
{
result = MTAInvoke((RPCOLEMESSAGE *)message, GetCallCat( call->pHeader ),
stub, this, &call->server_fault);
}
else
{
result = STAInvoke((RPCOLEMESSAGE *)message, GetCallCat( call->pHeader ),
stub, this, pv, &call->server_fault);
}
if (message->RpcFlags & RPCFLG_LOCAL_CALL)
PrivMemFree( orig_buffer );
if (message->Buffer == orig_stub_buffer)
{
if (message->RpcFlags & RPCFLG_LOCAL_CALL)
message->Buffer = NULL;
else
message->Buffer = orig_buffer;
}
else if (message->Buffer != NULL)
{
Win4Assert( call->pHeader != orig_buffer );
message->BufferLength += (char *) message->Buffer - (char *) call->pHeader;
message->Buffer = call->pHeader;
outb = (WireThat *) message->Buffer;
}
if (result == S_OK)
{
if (call->iDestCtx == MSHCTX_DIFFERENTMACHINE)
outb->c.flags = 0;
else
outb->c.flags = ORPCF_LOCAL;
if (message->RpcFlags & RPCFLG_LOCAL_CALL &&
call->category == CALLCAT_ASYNC)
{
PrivMemFree( message->Buffer );
message->Buffer = NULL;
}
}
else if (result == RPC_E_CALL_REJECTED)
{
if (call->iDestCtx != MSHCTX_DIFFERENTMACHINE && outb != NULL)
{
outb->c.flags = ORPCF_LOCAL | ORPCF_REJECTED;
result = S_OK;
}
}
else if (result == RPC_E_SERVERCALL_RETRYLATER)
{
if (call->iDestCtx != MSHCTX_DIFFERENTMACHINE && outb != NULL)
{
outb->c.flags = ORPCF_LOCAL | ORPCF_RETRY_LATER;
result = S_OK;
}
}
else if (message->RpcFlags & RPCFLG_LOCAL_CALL)
{
PrivMemFree( message->Buffer );
message->Buffer = NULL;
}
ASSERT_LOCK_RELEASED
return result;
}
#ifdef _CHICAGO_
inline LONG
AppInvokeExceptionFilter(
LPEXCEPTION_POINTERS lpep
)
{
return(EXCEPTION_EXECUTE_HANDLER);
}
#else
#include
#define SYM_HANDLE GetCurrentProcess()
#if defined(_M_IX86)
#define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
#elif defined(_M_MRX000)
#define MACHINE_TYPE IMAGE_FILE_MACHINE_R4000
#elif defined(_M_ALPHA)
#define MACHINE_TYPE IMAGE_FILE_MACHINE_ALPHA
#elif defined(_M_PPC)
#define MACHINE_TYPE IMAGE_FILE_MACHINE_POWERPC
#else
#error( "unknown target machine" );
#endif
LONG
AppInvokeExceptionFilter(
LPEXCEPTION_POINTERS lpep
)
{
#if DBG == 1
BOOL rVal;
STACKFRAME StackFrame;
CONTEXT Context;
SymSetOptions( SYMOPT_UNDNAME );
SymInitialize( SYM_HANDLE, NULL, TRUE );
ZeroMemory( &StackFrame, sizeof(StackFrame) );
Context = *lpep->ContextRecord;
#if defined(_M_IX86)
StackFrame.AddrPC.Offset = Context.Eip;
StackFrame.AddrPC.Mode = AddrModeFlat;
StackFrame.AddrFrame.Offset = Context.Ebp;
StackFrame.AddrFrame.Mode = AddrModeFlat;
StackFrame.AddrStack.Offset = Context.Esp;
StackFrame.AddrStack.Mode = AddrModeFlat;
#endif
ComDebOut((DEB_FORCE,"An Exception occurred while calling into app\n"));
ComDebOut((DEB_FORCE,
"Exception address = 0x%x Exception number 0x%x\n",
lpep->ExceptionRecord->ExceptionAddress,
lpep->ExceptionRecord->ExceptionCode ));
ComDebOut((DEB_FORCE,"The following stack trace is where the exception occured\n"));
ComDebOut((DEB_FORCE,"Frame RetAddr mod!symbol\n"));
do
{
rVal = StackWalk(MACHINE_TYPE,SYM_HANDLE,0,&StackFrame,&Context,ReadProcessMemory,
SymFunctionTableAccess,SymGetModuleBase,NULL);
if (rVal)
{
DWORD dump[200];
ULONG Displacement;
PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL) &dump;
IMAGEHLP_MODULE ModuleInfo;
LPSTR pModuleName = "???";
BOOL fSuccess;
sym->SizeOfStruct = sizeof(dump);
fSuccess = SymGetSymFromAddr(SYM_HANDLE,StackFrame.AddrPC.Offset,
&Displacement,sym);
if(SymGetModuleInfo(SYM_HANDLE,StackFrame.AddrPC.Offset,&ModuleInfo))
{
pModuleName = ModuleInfo.ModuleName;
}
if (fSuccess)
{
ComDebOut((DEB_FORCE,
"%08x %08x %s!%s + %x\n",
StackFrame.AddrFrame.Offset,
StackFrame.AddrReturn.Offset,
pModuleName,
sym->Name,
Displacement));
}
else
{
ComDebOut((DEB_FORCE,
"%08x %08x %s!%08x\n",
StackFrame.AddrFrame.Offset,
StackFrame.AddrReturn.Offset,
pModuleName,
StackFrame.AddrPC.Offset));
}
}
} while( rVal );
SymCleanup( SYM_HANDLE );
#endif
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
/***************************************************************************/
#if DBG == 1
DWORD AppInvoke_break = 0;
DWORD AppInvoke_count = 0;
#endif
HRESULT StubInvoke(RPCOLEMESSAGE *pMsg, IRpcStubBuffer *pStub,
IRpcChannelBuffer *pChnl, DWORD *pdwFault)
{
ComDebOut((DEB_CHANNEL, "StubInvoke pMsg:%x pStub:%x pChnl:%x pdwFault:%x\n",
pMsg, pStub, pChnl, pdwFault));
ASSERT_LOCK_RELEASED
HRESULT hr;
#if DBG==1
DWORD dwMethod = pMsg->iMethod;
IID iidBeingCalled = ((RPC_SERVER_INTERFACE *) pMsg->reserved2[1])->InterfaceId.SyntaxGUID;
#endif
_try
{
TRACECALL(TRACE_RPC, "StubInvoke");
#if DBG == 1
DWORD dwBreakCount = ++AppInvoke_count;
ComDebOut((DEB_CHANNEL, "AppInvoke(0x%x) calling method 0x%x iid %I\n",
dwBreakCount,dwMethod, &iidBeingCalled));
if(AppInvoke_break == dwBreakCount)
{
DebugBreak();
}
#endif
#ifdef WX86OLE
if (! gcwx86.IsN2XProxy(pStub))
{
IUnknown *pActual;
hr = pStub->DebugServerQueryInterface((void **)&pActual);
if (SUCCEEDED(hr))
{
if (gcwx86.IsN2XProxy(pActual))
{
gcwx86.SetStubInvokeFlag((BOOL)1);
}
pStub->DebugServerRelease(pActual);
}
}
#endif
hr = pStub->Invoke(pMsg, pChnl);
}
_except(AppInvokeExceptionFilter( GetExceptionInformation()))
{
hr = RPC_E_SERVERFAULT;
*pdwFault = GetExceptionCode();
#if DBG == 1
if (*pdwFault == STATUS_ACCESS_VIOLATION ||
*pdwFault == STATUS_POSSIBLE_DEADLOCK ||
*pdwFault == STATUS_INSTRUCTION_MISALIGNMENT ||
*pdwFault == STATUS_DATATYPE_MISALIGNMENT )
{
WCHAR iidName[256];
iidName[0] = 0;
char achProgname[256];
achProgname[0] = 0;
GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
GetInterfaceName(iidBeingCalled,iidName);
ComDebOut((DEB_FORCE,
"OLE has caught a fault 0x%08x on behalf of the server %s\n",
*pdwFault,
achProgname));
ComDebOut((DEB_FORCE,
"The fault occured when OLE called the interface %I (%ws) method 0x%x\n",
&iidBeingCalled,iidName,dwMethod));
Win4Assert(!"The server application has faulted processing an inbound RPC request. Check the kernel debugger for useful output. OLE can continue but you probably want to stop and debug the application.");
}
#endif
}
ASSERT_LOCK_RELEASED
ComDebOut((DEB_CHANNEL, "StubInvoke hr:%x dwFault:%x\n", hr, *pdwFault));
return hr;
}
/***************************************************************************/
#if DBG==1
LONG ComInvokeExceptionFilter( DWORD lCode,
LPEXCEPTION_POINTERS lpep )
{
ComDebOut((DEB_ERROR, "Exception 0x%x in ComInvoke at address 0x%x\n",
lCode, lpep->ExceptionRecord->ExceptionAddress));
DebugBreak();
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
/***************************************************************************/
HRESULT ComInvoke( CChannelCallInfo *call )
{
TRACECALL(TRACE_RPC, "ComInvoke");
ASSERT_LOCK_RELEASED
RPC_MESSAGE *message = (RPC_MESSAGE *) call->pmessage;
LocalThis *localb;
void *saved_buffer;
RPC_STATUS status;
HRESULT result;
IPIDEntry *ipid_entry = NULL;
CRpcChannelBuffer *server_channel = NULL;
DWORD TIDCallerSaved;
BOOL fLocalSaved;
UUID saved_threadid;
IUnknown *save_context;
DWORD saved_authn_level;
char *stub_data;
WireThis *inb = (WireThis *) message->Buffer;
OXIDEntry *oxid;
HANDLE hWakeup = NULL;
ComDebOut((DEB_CHANNEL, "ComInvoke callinfo:%x header:%x\n",
call, message->Buffer));
COleTls tls(result);
if (FAILED(result))
return result;
#if DBG == 1
_try
{
#endif
LOCK
ipid_entry = gIPIDTbl.LookupIPID( call->ipid );
Win4Assert( ipid_entry == NULL || ipid_entry->pOXIDEntry != NULL );
if (ipid_entry == NULL || (ipid_entry->dwFlags & IPIDF_DISCONNECTED) ||
(ipid_entry->pOXIDEntry->dwFlags & OXIDF_STOPPED) ||
ipid_entry->pChnl == NULL)
result = RPC_E_DISCONNECTED;
else if (ipid_entry->pStub == NULL)
result = E_NOINTERFACE;
if (SUCCEEDED(result))
{
oxid = ipid_entry->pOXIDEntry;
server_channel = ipid_entry->pChnl;
Win4Assert( server_channel != NULL && server_channel->pStdId != NULL );
server_channel->pStdId->LockServer();
InterlockedIncrement( &oxid->cCalls );
}
UNLOCK
ASSERT_LOCK_RELEASED
if (FAILED(result))
{
return result;
}
CServerSecurity security( call );
save_context = tls->pCallContext;
tls->pCallContext = &security;
if (!(tls->dwFlags & OLETLS_UUIDINITIALIZED))
{
UuidCreate(&tls->LogicalThreadId);
tls->dwFlags |= OLETLS_UUIDINITIALIZED;
}
saved_threadid = tls->LogicalThreadId;
tls->LogicalThreadId = inb->c.cid;
ComDebOut((DEB_CALLCONT, "ComInvoke: LogicalThreads Old:%I New:%I\n",
&saved_threadid, &tls->LogicalThreadId));
call->pNext = (CChannelCallInfo *) tls->pCallInfo;
tls->pCallInfo = call;
saved_authn_level = tls->dwAuthnLevel;
tls->dwAuthnLevel = call->lAuthnLevel;
result = ServerNotify(
((RPC_SERVER_INTERFACE *) message->RpcInterfaceInformation)->InterfaceId.SyntaxGUID,
(WireThis *) message->Buffer,
message->BufferLength,
(void **) &stub_data,
message->DataRepresentation );
if (inb->c.flags & ORPCF_LOCAL)
{
localb = (LocalThis *) stub_data;
stub_data += sizeof(LocalThis);
}
else
localb = NULL;
TIDCallerSaved = tls->dwTIDCaller;
fLocalSaved = tls->dwFlags & OLETLS_LOCALTID;
tls->dwTIDCaller = localb != NULL ? localb->client_thread : 0;
if (call->iFlags & CF_PROCESS_LOCAL)
tls->dwFlags |= OLETLS_LOCALTID;
else
tls->dwFlags &= ~OLETLS_LOCALTID;
if (result == S_OK)
{
result = server_channel->AppInvoke(
call,
(IRpcStubBuffer *) ipid_entry->pStub,
ipid_entry->pv,
stub_data,
localb );
}
tls->LogicalThreadId = saved_threadid;
tls->pCallInfo = call->pNext;
tls->dwTIDCaller = TIDCallerSaved;
tls->dwAuthnLevel = saved_authn_level;
if (fLocalSaved)
tls->dwFlags |= OLETLS_LOCALTID;
else
tls->dwFlags &= ~OLETLS_LOCALTID;
tls->pCallContext = save_context;
security.EndCall();
if (InterlockedDecrement( &oxid->cCalls ) == 0 &&
(oxid->dwFlags & (OXIDF_MTASERVER | OXIDF_STOPPED)) == (OXIDF_MTASERVER | OXIDF_STOPPED))
hWakeup = oxid->hComplete;
server_channel->pStdId->UnLockServer();
if (hWakeup)
SetEvent(hWakeup);
#if DBG == 1
}
_except( ComInvokeExceptionFilter(GetExceptionCode(),
GetExceptionInformation()) )
{
}
#endif
ASSERT_LOCK_RELEASED
return result;
}
/***************************************************************************/
CRpcChannelBuffer *CRpcChannelBuffer::Copy(OXIDEntry *pOXIDEntry,
REFIPID ripid, REFIID riid)
{
Win4Assert( !(state & server_cs) );
CRpcChannelBuffer *chan;
if (IsMTAThread())
{
chan = new CMTARpcChnl(pStdId, pOXIDEntry, state);
}
else
{
chan = new CAptRpcChnl(pStdId, pOXIDEntry, state);
}
if (chan != NULL)
{
chan->state = proxy_cs | (state & ~client_cs);
chan->lAuthnLevel = lAuthnLevel;
}
return chan;
}
/***************************************************************************/
HRESULT CRpcChannelBuffer::InitClientSideHandle()
{
Win4Assert((state & proxy_cs));
ASSERT_LOCK_HELD
if (state & initialized_cs)
return S_OK;
pInterfaceInfo = gRIFTbl.GetClientInterfaceInfo(pIPIDEntry->iid);
RPC_STATUS status;
#ifndef _CHICAGO_
if (state & process_local_cs)
{
handle = NULL;
status = RPC_S_OK;
}
else
#endif
{
status = RpcBindingCopy(pOXIDEntry->hServerSTA, &handle);
if (status == RPC_S_OK)
if (state & mswmsg_cs)
status = I_RpcBindingSetAsync(handle, OleModalLoopBlockFn);
#ifndef CHICAGO
else if (pOXIDEntry->dwTid != 0)
status = I_RpcBindingSetAsync(handle, NULL);
#endif
if (status == RPC_S_OK)
status = RpcBindingSetObject(handle, (GUID *)&pIPIDEntry->ipid);
}
if (status == RPC_S_OK)
{
state |= initialized_cs;
return S_OK;
}
return MAKE_WIN32(status);
}
/***************************************************************************/
CRpcChannelBuffer::CRpcChannelBuffer(CStdIdentity *standard_identity,
OXIDEntry *pOXID,
DWORD eState )
{
ComDebOut((DEB_MARSHAL, "CRpcChannelBuffer %s Created this:%x pOXID:%x\n",
(eState & client_cs) ? "CLIENT" : "SERVER", this, pOXID));
ref_count = 1;
pStdId = standard_identity;
handle = NULL;
pOXIDEntry = pOXID;
pIPIDEntry = NULL;
pInterfaceInfo = NULL;
hToken = NULL;
lAuthnLevel = gAuthnLevel;
state = eState;
state |= pOXID->dwPid == GetCurrentProcessId() ? process_local_cs : 0;
SetImpLevel( gImpLevel );
if ((pOXID->dwFlags & OXIDF_MSWMSG) && IsSTAThread())
{
state |= mswmsg_cs;
}
if (state & (client_cs | proxy_cs))
{
if (pOXID->dwFlags & OXIDF_MACHINE_LOCAL)
if (!IsWOWThread() && (state & process_local_cs))
iDestCtx = MSHCTX_INPROC;
else
iDestCtx = MSHCTX_LOCAL;
else
iDestCtx = MSHCTX_DIFFERENTMACHINE;
}
else
{
iDestCtx = 0;
}
}
/***************************************************************************/
CRpcChannelBuffer::~CRpcChannelBuffer()
{
ComDebOut((DEB_MARSHAL, "CRpcChannelBuffer %s Deleted this:%x\n",
(state & server_cs) ? "SERVER" : "CLIENT", this));
if (handle != NULL)
RpcBindingFree( &handle );
if (hToken != NULL)
CloseHandle( hToken );
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::FreeBuffer( RPCOLEMESSAGE *pMessage )
{
TRACECALL(TRACE_RPC, "CRpcChannelBuffer::FreeBuffer");
ASSERT_LOCK_RELEASED
AssertValid(FALSE, TRUE);
if (pMessage->Buffer == NULL)
return S_OK;
COleTls tls;
Win4Assert( tls->pCallInfo != NULL );
working_call *pCall = (working_call *) tls->pCallInfo;
tls->pCallInfo = pCall->pNext;
tls->dwAuthnLevel = pCall->lSavedAuthnLevel;
pMessage->Buffer = pCall->pHeader;;
DeallocateBuffer(pCall->pmessage);
ResumeImpersonate( tls->pCallContext, pCall->iFlags & CF_WAS_IMPERSONATING );
if (pCall->Locked())
pStdId->UnLockClient();
pMessage->Buffer = NULL;
delete pCall;
ASSERT_LOCK_RELEASED
return S_OK;
}
STDMETHODIMP CRpcChannelBuffer::GetBuffer( RPCOLEMESSAGE *pMessage,
REFIID riid )
{
gOXIDTbl.ValidateOXID();
if (state & proxy_cs)
return ClientGetBuffer( pMessage, riid );
else
return ServerGetBuffer( pMessage, riid );
}
HRESULT CRpcChannelBuffer::ClientGetBuffer( RPCOLEMESSAGE *pMessage,
REFIID riid )
{
TRACECALL(TRACE_RPC, "CRpcChannelBuffer::ClientGetBuffer");
ASSERT_LOCK_RELEASED
RPC_STATUS status;
CALLCATEGORY callcat = CALLCAT_SYNCHRONOUS;
ULONG debug_size;
ULONG num_extent;
WireThis *inb;
LocalThis *localb;
IID *logical_thread;
working_call *call;
DWORD flags;
BOOL resume;
DWORD orig_size = pMessage->cbBuffer;
COleTls tls;
Win4Assert(state & proxy_cs);
AssertValid(FALSE, TRUE);
if (gDisableDCOM && iDestCtx == MSHCTX_DIFFERENTMACHINE)
return RPC_E_REMOTE_DISABLED;
if (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS)
{
if (riid != IID_IAdviseSink && riid != IID_IAdviseSink2)
return E_UNEXPECTED;
callcat = CALLCAT_ASYNC;
}
else
{
logical_thread = TLSGetLogicalThread();
if (logical_thread == NULL)
{
return RPC_E_OUT_OF_RESOURCES;
}
if (pMessage->rpcFlags & RPCFLG_INPUT_SYNCHRONOUS)
{
callcat = CALLCAT_INPUTSYNC;
}
}
pMessage->rpcFlags |= RPC_BUFFER_COMPLETE;
pMessage->iMethod |= RPC_FLAGS_VALID_BIT;
if (state & process_local_cs)
{
pMessage->rpcFlags |= RPCFLG_LOCAL_CALL;
flags = CF_PROCESS_LOCAL;
}
else
flags = 0;
debug_size = ClientGetSize( riid, &num_extent );
LOCK
status = InitClientSideHandle();
if (status != RPC_S_OK)
{
UNLOCK;
ASSERT_LOCK_RELEASED;
return status;
}
if ((pMessage->rpcFlags & RPCFLG_LOCAL_CALL) == 0)
pMessage->reserved1 = handle;
pMessage->cbBuffer += SIZENEEDED_ORPCTHIS( pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL,
debug_size );
pMessage->reserved2[0] = 0;
pMessage->reserved2[1] = pInterfaceInfo;
Win4Assert( pMessage->reserved2[1] != NULL );
call = new working_call( callcat, pMessage, flags, pIPIDEntry->ipid,
iDestCtx, this, lAuthnLevel );
pMessage->cbBuffer = orig_size;
UNLOCK
ASSERT_LOCK_RELEASED
if (call == NULL)
return E_OUTOFMEMORY;
SuspendImpersonate( tls->pCallContext, &resume );
if (call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
{
call->pmessage->dataRepresentation = 0x00 | 0x10 | 0x0000;
call->pmessage->Buffer = PrivMemAlloc8( call->pmessage->cbBuffer );
if (call->pmessage->Buffer == NULL)
status = RPC_S_OUT_OF_MEMORY;
else
status = RPC_S_OK;
}
else
{
TRACECALL(TRACE_RPC, "I_RpcGetBuffer");
status = I_RpcGetBuffer( (RPC_MESSAGE *) call->pmessage );
}
if (status != RPC_S_OK)
{
ResumeImpersonate( tls->pCallContext, resume );
pMessage->cbBuffer = 0;
tls->fault = MAKE_WIN32( status );
delete call;
return MAKE_WIN32( status );
}
if (resume)
call->iFlags |= CF_WAS_IMPERSONATING;
call->pNext = (CChannelCallInfo *)tls->pCallInfo;
tls->pCallInfo = call;
call->pHeader = call->message.Buffer;
call->lSavedAuthnLevel = tls->dwAuthnLevel;
tls->dwAuthnLevel = lAuthnLevel;
pMessage->Buffer = call->message.Buffer;
inb = (WireThis *) pMessage->Buffer;
inb->c.version.MajorVersion = COM_MAJOR_VERSION;
inb->c.version.MinorVersion = COM_MINOR_VERSION;
inb->c.reserved1 = 0;
if (callcat == CALLCAT_ASYNC)
UuidCreate( &inb->c.cid );
else
inb->c.cid = *logical_thread;
if (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL)
inb->c.flags = ORPCF_LOCAL;
else
inb->c.flags = ORPCF_NULL;
if (debug_size != 0)
{
pMessage->Buffer = FillBuffer( riid, &inb->d.ea, debug_size, num_extent,
TRUE );
inb->c.unique = 0x77646853;
}
else
{
pMessage->Buffer = (void *) &inb->d.ea;
inb->c.unique = FALSE;
}
if (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL)
{
localb = (LocalThis *) pMessage->Buffer;
localb->client_thread = GetCurrentApartmentId();
localb->flags = 0;
pMessage->Buffer = localb + 1;
if (callcat == CALLCAT_ASYNC)
inb->c.flags |= ORPCF_ASYNC;
else if (callcat == CALLCAT_INPUTSYNC)
inb->c.flags |= ORPCF_INPUT_SYNC;
if (pIPIDEntry->dwFlags & (IPIDF_NONNDRPROXY | IPIDF_NONNDRSTUB))
localb->flags |= LOCALF_NONNDR;
}
ComDebOut((DEB_CALLCONT, "ClientGetBuffer: LogicalThreadId:%I\n",
&(tls->LogicalThreadId)));
ASSERT_LOCK_RELEASED
return S_OK;
}
HRESULT CRpcChannelBuffer::ServerGetBuffer( RPCOLEMESSAGE *pMessage,
REFIID riid )
{
TRACECALL(TRACE_RPC, "CRpcChannelBuffer::ServerGetBuffer");
ASSERT_LOCK_RELEASED
RPC_STATUS status;
ULONG debug_size;
ULONG num_extent;
HRESULT result = S_OK;
WireThis *inb;
WireThat *outb;
CChannelCallInfo *call;
void *stub_data;
DWORD orig_size = pMessage->cbBuffer;
Win4Assert( state & server_cs );
AssertValid(FALSE, TRUE);
COleTls tls;
call = (CChannelCallInfo *) tls->pCallInfo;
Win4Assert( call != NULL );
pMessage->Buffer = call->pHeader;
debug_size = ServerGetSize( riid, &num_extent );
pMessage->cbBuffer += SIZENEEDED_ORPCTHAT( debug_size );
if (pMessage->rpcFlags & RPCFLG_LOCAL_CALL)
{
pMessage->dataRepresentation = 0x00 | 0x10 | 0x0000;
pMessage->Buffer = PrivMemAlloc8( pMessage->cbBuffer );
if (pMessage->Buffer == NULL)
status = RPC_S_OUT_OF_MEMORY;
else
status = RPC_S_OK;
}
else
{
TRACECALL(TRACE_RPC, "I_RpcGetBuffer");
status = I_RpcGetBuffer( (RPC_MESSAGE *) pMessage );
Win4Assert( call->pHeader != pMessage->Buffer || status != RPC_S_OK );
}
if (status != RPC_S_OK)
{
pMessage->cbBuffer = 0;
pMessage->Buffer = NULL;
tls->fault = MAKE_WIN32( status );
return MAKE_WIN32( status );
}
call->pHeader = pMessage->Buffer;
outb = (WireThat *) pMessage->Buffer;
outb->c.flags = ORPCF_NULL;
pMessage->cbBuffer = orig_size;
if (debug_size != 0)
{
stub_data = FillBuffer( riid, &outb->d.ea, debug_size, num_extent, FALSE );
outb->c.unique = 0x77646853;
pMessage->Buffer = stub_data;
}
else
{
outb->c.unique = 0;
pMessage->Buffer = &outb->d.ea;
}
ComDebOut((DEB_CALLCONT, "ServerGetBuffer: LogicalThreadId:%I\n",
&(tls->LogicalThreadId)));
ASSERT_LOCK_RELEASED
return S_OK;
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::GetDestCtx( DWORD FAR* lpdwDestCtx,
LPVOID FAR* lplpvDestCtx )
{
TRACECALL(TRACE_RPC, "CRpcChannelBuffer::GetDestCtx");
AssertValid(FALSE, FALSE);
if (state & (client_cs | proxy_cs))
{
*lpdwDestCtx = iDestCtx;
}
else
{
COleTls tls;
Win4Assert( tls->pCallInfo != NULL );
*lpdwDestCtx = ((CChannelCallInfo *) tls->pCallInfo)->iDestCtx;
}
if (lplpvDestCtx != NULL)
*lplpvDestCtx = NULL;
return S_OK;
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::IsConnected( THIS )
{
AssertValid(FALSE, TRUE);
return S_OK;
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
{
AssertValid(FALSE, FALSE);
if (IsEqualIID(riid, IID_IMarshal))
{
*ppvObj = (IMarshal *) this;
}
else if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_IRpcChannelBuffer))
{
*ppvObj = (IRpcChannelBuffer *) this;
}
else if (IsEqualIID(riid, IID_INonNDRStub) &&
(state & proxy_cs) && pIPIDEntry &&
(pIPIDEntry->dwFlags & IPIDF_NONNDRSTUB))
{
*ppvObj = (IUnknown *) this;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
/***************************************************************************/
STDMETHODIMP_(ULONG) CRpcChannelBuffer::Release( THIS )
{
ULONG lRef = ref_count - 1;
if (InterlockedDecrement( (long*) &ref_count ) == 0)
{
delete this;
return 0;
}
else
{
return lRef;
}
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::SendReceive( THIS_ RPCOLEMESSAGE *pMessage,
ULONG *status )
{
return CRpcChannelBuffer::SendReceive2(pMessage, status);
}
/***************************************************************************/
STDMETHODIMP CRpcChannelBuffer::SendReceive2( THIS_ RPCOLEMESSAGE *pMessage,
ULONG *status )
{
TRACECALL(TRACE_RPC, "CRpcChannelBuffer::SendReceive");
ComDebOut((DEB_CHANNEL, "CRpcChannelBuffer::SendReceive pChnl:%x pMsg:%x\n",
this, pMessage));
AssertValid(FALSE, TRUE);
Win4Assert( state & proxy_cs );
gOXIDTbl.ValidateOXID();
ASSERT_LOCK_RELEASED
HRESULT result;
working_call *call;
working_call *next_call;
IID iid;
WireThis *inb;
WireThat *outb;
DWORD saved_authn_level;
BOOL resume;
char *stub_data;
COleTls tls;
call = (working_call *) tls->pCallInfo;
Win4Assert( call != NULL );
next_call = (working_call *) call->pNext;
saved_authn_level = call->lSavedAuthnLevel;
resume = call->iFlags & CF_WAS_IMPERSONATING;
inb = (WireThis *) call->pHeader;
iid =
((RPC_CLIENT_INTERFACE *) ((RPC_MESSAGE *) call->pmessage)->RpcInterfaceInformation)->InterfaceId.SyntaxGUID;
pStdId->LockClient();
#if DBG==1
DWORD CallCat = GetCallCat( inb );
DebugPrintORPCCall(ORPC_SENDRECEIVE_BEGIN, iid, call->message.iMethod, CallCat);
RpcSpy((CALLOUT_BEGIN, inb, iid, call->message.iMethod, 0));
#endif
if ((state & mswmsg_cs) || (IsMTAThread() && !call->Local()))
{
result = ThreadSendReceive( call );
}
else
{
if (call->Local())
call->message.reserved2[3] = NULL;
if (IsMTAThread())
{
LOCK
result = GetToSTA( pOXIDEntry, call);
UNLOCK
}
else
{
result = SwitchSTA( pOXIDEntry, (CChannelCallInfo **) &call );
}
}
#if DBG==1
DebugPrintORPCCall(ORPC_SENDRECEIVE_END, iid, pMessage->iMethod, CallCat);
RpcSpy((CALLOUT_END, inb, iid, pMessage->iMethod, result));
#endif
if (result != RPC_E_CALL_CANCELED)
{
if ((state & mswmsg_cs) && (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS))
outb = NULL;
else
outb = (WireThat *) call->message.Buffer;
call->pNext = next_call;
call->pHeader = call->message.Buffer;
}
else
outb = NULL;
if (result == S_OK)
{
if (outb == NULL)
*status = S_OK;
else if (IsMTAThread())
{
if (outb->c.flags & ORPCF_REJECTED)
result = RPC_E_CALL_REJECTED;
else if (outb->c.flags & ORPCF_RETRY_LATER)
result = RPC_E_SERVERCALL_RETRYLATER;
else
*status = S_OK;
}
else if (outb->c.flags & ORPCF_REJECTED)
*status = (ULONG) RPC_E_CALL_REJECTED;
else if (outb->c.flags & ORPCF_RETRY_LATER)
*status = (ULONG) RPC_E_SERVERCALL_RETRYLATER;
else
*status = S_OK;
}
if (result != RPC_E_CALL_CANCELED)
{
stub_data = (char *) call->message.Buffer;
result = ClientNotify( iid, outb, call->message.cbBuffer,
(void **) &stub_data,
call->message.dataRepresentation,
result );
}
else
result = ClientNotify( iid, outb, 0, (void **) &stub_data, 0, result );
if (result == S_OK && outb != NULL)
{
call->iFlags |= CF_LOCKED;
pMessage->Buffer = stub_data;
pMessage->cbBuffer = call->message.cbBuffer -
(stub_data - (char *) call->message.Buffer);
pMessage->dataRepresentation = call->message.dataRepresentation;
result = *status;
pMessage->reserved2[2] = call->message.reserved2[2];
}
else
{
ResumeImpersonate( tls->pCallContext, resume );
pStdId->UnLockClient();
tls->pCallInfo = next_call;
tls->dwAuthnLevel = saved_authn_level;
delete call;
pMessage->Buffer = NULL;
if (result == RPC_E_SERVERFAULT)
{
*status = call->server_fault;
}
else if (result != S_OK)
{
*status = result;
result = RPC_E_FAULT;
}
tls->fault = *status;
if (*status != S_OK)
ComDebOut((DEB_CHANNEL, "ORPC call failed. status = %x\n", *status));
}
ASSERT_LOCK_RELEASED
gOXIDTbl.ValidateOXID();
ComDebOut((DEB_CHANNEL, "CRpcChannelBuffer::SendReceive hr:%x\n", result));
return result;
}
/***************************************************************************/
HANDLE CRpcChannelBuffer::SwapSecurityToken( HANDLE hNew )
{
HANDLE hOld = hToken;
hToken = hNew;
return hOld;
}
#if DBG == 1
void CRpcChannelBuffer::AssertValid(BOOL fKnownDisconnected,
BOOL fMustBeOnCOMThread)
{
Win4Assert(state & (proxy_cs | client_cs | server_cs ));
if (state & (client_cs | proxy_cs))
{
;
}
else if (state & server_cs)
{
Win4Assert( !(state & freethreaded_cs) );
if (fMustBeOnCOMThread && IsSTAThread())
Win4Assert(IsMTAThread() || pOXIDEntry->dwTid == GetCurrentThreadId());
Win4Assert(ref_count < 0x7fff && "Channel ref count unreasonably high");
}
}
#endif
/***************************************************************************/
STDAPI_(ULONG) DebugCoGetRpcFault()
{
HRESULT hr;
COleTls tls(hr);
if (SUCCEEDED(hr))
return tls->fault;
return 0;
}
/***************************************************************************/
STDAPI_(void) DebugCoSetRpcFault( ULONG fault )
{
HRESULT hr;
COleTls tls(hr);
if (SUCCEEDED(hr))
tls->fault = fault;
}
/***************************************************************************/
extern "C"
BOOL _stdcall DllDebugObjectRPCHook( BOOL trace, LPORPC_INIT_ARGS pass_through )
{
if (!IsWOWThread())
{
DoDebuggerHooks = trace;
DebuggerArg = pass_through;
return TRUE;
}
else
return FALSE;
}
/***************************************************************************/
BOOL LocalCall()
{
CChannelCallInfo *call;
COleTls tls;
call = (CChannelCallInfo *) tls->pCallInfo;
Win4Assert( call != NULL );
return call->iFlags & CF_PROCESS_LOCAL;
}
/***************************************************************************/
LONG ThreadInvokeExceptionFilter( DWORD lCode,
LPEXCEPTION_POINTERS lpep )
{
ComDebOut((DEB_ERROR, "Exception 0x%x in ThreadInvoke at address 0x%x\n",
lCode, lpep->ExceptionRecord->ExceptionAddress));
DebugBreak();
return EXCEPTION_EXECUTE_HANDLER;
}
/***************************************************************************/
#ifdef _CHICAGO_
DWORD
#else
void
#endif
SSAPI(ThreadInvoke)(RPC_MESSAGE *message )
{
HRESULT result = S_OK;
TRACECALL(TRACE_RPC, "ThreadInvoke");
ComDebOut((DEB_CHANNEL,"ThreadInvoke pMsg:%x\n", message));
gOXIDTbl.ValidateOXID();
ASSERT_LOCK_RELEASED
BOOL success;
WireThis *inb = (WireThis *) message->Buffer;
IPID ipid;
RPC_STATUS status;
OXIDEntry *pOxid;
unsigned int transport_type;
DWORD authn_level;
ByteSwapThis( message->DataRepresentation, inb );
if (sizeof(WireThisPart1) > message->BufferLength ||
(inb->c.flags & ~(ORPCF_LOCAL | ORPCF_RESERVED1 |
ORPCF_RESERVED2 | ORPCF_RESERVED3 | ORPCF_RESERVED4)) != 0 ||
message->ProcNum < 3)
RETURN_COMM_STATUS( RPC_E_INVALID_HEADER );
if (inb->c.version.MajorVersion != COM_MAJOR_VERSION ||
inb->c.version.MinorVersion > COM_MINOR_VERSION)
RETURN_COMM_STATUS( RPC_E_VERSION_MISMATCH );
status = I_RpcServerInqTransportType( &transport_type );
if (status != RPC_S_OK)
RETURN_COMM_STATUS( RPC_E_SYS_CALL_FAILED );
if (inb->c.flags & ORPCF_LOCAL)
{
if (transport_type != TRANSPORT_TYPE_LPC &&
transport_type != TRANSPORT_TYPE_WMSG)
RETURN_COMM_STATUS( RPC_E_INVALID_HEADER );
authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
}
else if (gDisableDCOM &&
(transport_type == TRANSPORT_TYPE_CN || transport_type == TRANSPORT_TYPE_DG))
RETURN_COMM_STATUS( RPC_E_CALL_REJECTED );
else
{
result = RpcBindingInqAuthClient( message->Handle, NULL,
NULL, &authn_level, NULL, NULL );
if (result == RPC_S_BINDING_HAS_NO_AUTH)
authn_level = RPC_C_AUTHN_LEVEL_NONE;
else if (result != RPC_S_OK)
{
Win4Assert( result == RPC_S_OUT_OF_RESOURCES );
RETURN_COMM_STATUS( MAKE_WIN32( result ) );
}
if (gAuthnLevel > RPC_C_AUTHN_LEVEL_NONE ||
gImpLevel > 0)
{
if (authn_level < gAuthnLevel)
RETURN_COMM_STATUS( RPC_E_ACCESS_DENIED );
}
}
#if DBG==1
_try
{
#endif
status = RpcBindingInqObject( message->Handle, &ipid );
if (status == RPC_S_OK)
{
CChannelCallInfo call(
GetCallCat( inb ),
(RPCOLEMESSAGE *) message,
0,
ipid,
(inb->c.flags & ORPCF_LOCAL) ? MSHCTX_LOCAL : MSHCTX_DIFFERENTMACHINE,
NULL,
authn_level );
ASSERT_LOCK_RELEASED
LOCK
IPIDEntry *ipid_entry = gIPIDTbl.LookupIPID( ipid );
if (ipid_entry == NULL || (ipid_entry->dwFlags & IPIDF_DISCONNECTED)
|| ipid_entry->pChnl == NULL )
{
UNLOCK
ASSERT_LOCK_RELEASED
result = RPC_E_DISCONNECTED;
}
else
{
pOxid = ipid_entry->pOXIDEntry;
if (transport_type == TRANSPORT_TYPE_WMSG ||
#ifndef _CHICAGO_
transport_type == TRANSPORT_TYPE_LPC ||
#endif
(pOxid->dwFlags & OXIDF_MTASERVER))
{
UNLOCK
ASSERT_LOCK_RELEASED
result = ComInvoke( &call );
}
else
{
IncOXIDRefCnt( pOxid );
result = GetToSTA( pOxid, &call );
DecOXIDRefCnt( pOxid );
UNLOCK
ASSERT_LOCK_RELEASED
}
}
}
else
{
result = MAKE_WIN32( status );
}
#if DBG==1
}
_except( ThreadInvokeExceptionFilter(GetExceptionCode(),
GetExceptionInformation()) )
{
}
#endif
gOXIDTbl.ValidateOXID();
if (result == RPC_E_SERVERFAULT)
{
ASSERT_LOCK_RELEASED
RETURN_COMM_STATUS( RPC_E_SERVERFAULT );
}
else if (result != S_OK)
{
ASSERT_LOCK_RELEASED
RETURN_COMM_STATUS( result );
}
#ifdef _CHICAGO_
return 0;
#endif
}
/***************************************************************************/
HRESULT ThreadSendReceive( CChannelCallInfo *call )
{
TRACECALL(TRACE_RPC, "ThreadSendReceive");
ComDebOut((DEB_CHANNEL, "ThreadSendReceive pCall:%x\n", call));
ASSERT_LOCK_RELEASED
HRESULT result;
RPCOLEMESSAGE *message = call->pmessage;
WireThat *outb;
if (call->pChannel->state & mswmsg_cs)
{
CAptCallCtrl *pACC = GetAptCallCtrl();
CCliModalLoop *pCML = (pACC) ? pACC->GetTopCML() : NULL;
OXIDEntry *pOxidClient;
HWND hwnd = NULL;
if (IsWOWThread())
{
LOCK
result = gOXIDTbl.GetLocalEntry( &pOxidClient );
UNLOCK
Win4Assert( result == S_OK );
hwnd = (HWND) pOxidClient->hServerSTA;
}
TRACECALL(TRACE_RPC, "I_RpcAsyncSendReceive");
result = I_RpcAsyncSendReceive( (RPC_MESSAGE *) message, pCML, hwnd );
if (result == RPC_S_CALL_CANCELLED)
{
result = RPC_E_CALL_CANCELED;
delete call;
}
}
else
{
TRACECALL(TRACE_RPC, "I_RpcSendReceive");
result = I_RpcSendReceive( (RPC_MESSAGE *) message );
}
if (result != 0)
{
message->Buffer = NULL;
if ((ULONG) result > 0xfffffff7 || (ULONG) result < 0x2000)
result = MAKE_WIN32( result );
}
else
{
if ((call->pChannel->state & mswmsg_cs) == 0 ||
(message->rpcFlags & RPCFLG_ASYNCHRONOUS) == 0)
{
outb = (WireThat *) message->Buffer;
if (message->cbBuffer >= sizeof(WireThatPart1))
ByteSwapThat( message->dataRepresentation, outb);
else
result = RPC_E_INVALID_HEADER;
}
}
ComDebOut((DEB_CHANNEL, "ThreadSendReceive pCall:%x hr:%x\n", call, result));
return result;
}
/***************************************************************************/
void working_call::Cleanup()
{
ASSERT_LOCK_HELD
DWORD i;
if (next <= CALLCACHE_SIZE)
{
for (i = 0; i < next; i++)
if (list[i] != NULL)
{
PrivMemFree( list[i] );
list[i] = NULL;
}
next = 0;
}
}
/***************************************************************************/
void working_call::Initialize()
{
ASSERT_LOCK_HELD
next = 0;
}
void working_call::operator delete( void *call )
{
LOCK
if (next < CALLCACHE_SIZE && gfChannelProcessInitialized)
{
list[next] = call;
next += 1;
}
else
{
PrivMemFree( call );
}
UNLOCK
}
void *working_call::operator new( size_t size )
{
ASSERT_LOCK_HELD
void *call;
Win4Assert( size == sizeof( working_call ) );
if (next > 0 && next < CALLCACHE_SIZE+1)
{
next -= 1;
call = list[next];
list[next] = NULL;
}
else
call = PrivMemAlloc(size);
return call;
}
/**********************************************************************/
working_call::working_call( CALLCATEGORY callcat,
RPCOLEMESSAGE *original_msg,
DWORD flags,
REFIPID ipidServer,
DWORD destctx,
CRpcChannelBuffer *channel,
DWORD authn_level ) :
CChannelCallInfo( callcat, &message, flags, ipidServer, destctx, channel,
authn_level )
{
message = *original_msg;
}