Proxies/stubs for IRemUnknown methods, based on code written by Ove

Kåven.
This commit is contained in:
Robert Shearman 2005-01-25 19:02:54 +00:00 committed by Alexandre Julliard
parent b9bfc8e909
commit 6e042873d5

View file

@ -2,6 +2,7 @@
* OLE32 proxy/stub handler
*
* Copyright 2002 Marcus Meissner
* Copyright 2001 Ove Kåven, TransGaming Technologies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -266,8 +267,8 @@ CFStub_Construct(LPRPCSTUBBUFFER *ppv) {
* the refcount.
*/
typedef struct _CFProxy {
IClassFactoryVtbl *lpvtbl_cf;
IRpcProxyBufferVtbl *lpvtbl_proxy;
const IClassFactoryVtbl *lpvtbl_cf;
const IRpcProxyBufferVtbl *lpvtbl_proxy;
DWORD ref;
IRpcChannelBuffer *chanbuf;
@ -453,6 +454,452 @@ CFProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
}
/********************* IRemUnknown Proxy/Stub ********************************/
typedef struct
{
const IRpcStubBufferVtbl *lpVtbl;
ULONG refs;
IRemUnknown *iface;
} RemUnkStub;
static HRESULT WINAPI RemUnkStub_QueryInterface(LPRPCSTUBBUFFER iface,
REFIID riid,
LPVOID *obj)
{
RemUnkStub *This = (RemUnkStub *)iface;
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
if (IsEqualGUID(&IID_IUnknown,riid) ||
IsEqualGUID(&IID_IRpcStubBuffer,riid)) {
*obj = This;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI RemUnkStub_AddRef(LPRPCSTUBBUFFER iface)
{
RemUnkStub *This = (RemUnkStub *)iface;
TRACE("(%p)->AddRef()\n",This);
return InterlockedIncrement(&This->refs);
}
static ULONG WINAPI RemUnkStub_Release(LPRPCSTUBBUFFER iface)
{
RemUnkStub *This = (RemUnkStub *)iface;
ULONG refs;
TRACE("(%p)->Release()\n",This);
refs = InterlockedDecrement(&This->refs);
if (!refs)
HeapFree(GetProcessHeap(), 0, This);
return refs;
}
static HRESULT WINAPI RemUnkStub_Connect(LPRPCSTUBBUFFER iface,
LPUNKNOWN lpUnkServer)
{
RemUnkStub *This = (RemUnkStub *)iface;
TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);
This->iface = (IRemUnknown*)lpUnkServer;
IRemUnknown_AddRef(This->iface);
return S_OK;
}
static void WINAPI RemUnkStub_Disconnect(LPRPCSTUBBUFFER iface)
{
RemUnkStub *This = (RemUnkStub *)iface;
TRACE("(%p)->Disconnect()\n",This);
}
static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface,
PRPCOLEMESSAGE pMsg,
LPRPCCHANNELBUFFER pChannel)
{
RemUnkStub *This = (RemUnkStub *)iface;
ULONG iMethod = pMsg->iMethod;
LPBYTE buf = pMsg->Buffer;
HRESULT hr = RPC_E_INVALIDMETHOD;
TRACE("(%p)->Invoke(%p,%p) method %ld\n", This, pMsg, pChannel, iMethod);
switch (iMethod)
{
case 3: /* RemQueryInterface */
{
IPID ipid;
ULONG cRefs;
USHORT cIids;
IID *iids;
REMQIRESULT *pQIResults = NULL;
/* in */
memcpy(&ipid, buf, sizeof(ipid));
buf += sizeof(ipid);
memcpy(&cRefs, buf, sizeof(cRefs));
buf += sizeof(cRefs);
memcpy(&cIids, buf, sizeof(cIids));
buf += sizeof(cIids);
iids = (IID *)buf;
hr = IRemUnknown_RemQueryInterface(This->iface, &ipid, cRefs, cIids, iids, &pQIResults);
/* out */
pMsg->cbBuffer = cIids * sizeof(REMQIRESULT);
if (pMsg->Buffer)
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
else
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
buf = pMsg->Buffer;
/* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */
memcpy(buf, pQIResults, cIids * sizeof(REMQIRESULT));
break;
}
case 4: /* RemAddRef */
{
USHORT cIids;
REMINTERFACEREF *ir;
HRESULT *pResults;
/* in */
memcpy(&cIids, buf, sizeof(USHORT));
buf += sizeof(USHORT);
ir = (REMINTERFACEREF*)buf;
pResults = CoTaskMemAlloc(cIids * sizeof(HRESULT));
if (!pResults) return E_OUTOFMEMORY;
hr = IRemUnknown_RemAddRef(This->iface, cIids, ir, pResults);
/* out */
pMsg->cbBuffer = cIids * sizeof(HRESULT);
if (pMsg->Buffer)
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
else
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
buf = pMsg->Buffer;
memcpy(buf, pResults, cIids * sizeof(HRESULT));
CoTaskMemFree(pResults);
break;
}
case 5: /* RemRelease */
{
USHORT cIids;
REMINTERFACEREF *ir;
/* in */
memcpy(&cIids, buf, sizeof(USHORT));
buf += sizeof(USHORT);
ir = (REMINTERFACEREF*)buf;
hr = IRemUnknown_RemRelease(This->iface, cIids, ir);
/* out */
pMsg->cbBuffer = 0;
break;
}
}
return hr;
}
static LPRPCSTUBBUFFER WINAPI RemUnkStub_IsIIDSupported(LPRPCSTUBBUFFER iface,
REFIID riid)
{
RemUnkStub *This = (RemUnkStub *)iface;
TRACE("(%p)->IsIIDSupported(%s)\n", This, debugstr_guid(riid));
return IsEqualGUID(&IID_IRemUnknown, riid) ? iface : NULL;
}
static ULONG WINAPI RemUnkStub_CountRefs(LPRPCSTUBBUFFER iface)
{
RemUnkStub *This = (RemUnkStub *)iface;
FIXME("(%p)->CountRefs()\n", This);
return 1;
}
static HRESULT WINAPI RemUnkStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,
LPVOID *ppv)
{
RemUnkStub *This = (RemUnkStub *)iface;
FIXME("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);
return E_NOINTERFACE;
}
static void WINAPI RemUnkStub_DebugServerRelease(LPRPCSTUBBUFFER iface,
LPVOID pv)
{
RemUnkStub *This = (RemUnkStub *)iface;
FIXME("(%p)->DebugServerRelease(%p)\n", This, pv);
}
static const IRpcStubBufferVtbl RemUnkStub_VTable =
{
RemUnkStub_QueryInterface,
RemUnkStub_AddRef,
RemUnkStub_Release,
RemUnkStub_Connect,
RemUnkStub_Disconnect,
RemUnkStub_Invoke,
RemUnkStub_IsIIDSupported,
RemUnkStub_CountRefs,
RemUnkStub_DebugServerQueryInterface,
RemUnkStub_DebugServerRelease
};
static HRESULT RemUnkStub_Construct(IRpcStubBuffer **ppStub)
{
RemUnkStub *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This) return E_OUTOFMEMORY;
This->lpVtbl = &RemUnkStub_VTable;
This->refs = 0;
This->iface = NULL;
*ppStub = (IRpcStubBuffer*)This;
return S_OK;
}
typedef struct _RemUnkProxy {
const IRemUnknownVtbl *lpvtbl_remunk;
const IRpcProxyBufferVtbl *lpvtbl_proxy;
DWORD refs;
IRpcChannelBuffer *chan;
IUnknown *outer_unknown;
} RemUnkProxy;
static HRESULT WINAPI RemUnkProxy_QueryInterface(LPREMUNKNOWN iface, REFIID riid, void **ppv)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
if (This->outer_unknown)
return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IRemUnknown))
{
IRemUnknown_AddRef(iface);
*ppv = (LPVOID)iface;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI RemUnkProxy_AddRef(LPREMUNKNOWN iface)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
TRACE("(%p)->AddRef()\n",This);
return InterlockedIncrement(&This->refs);
}
static ULONG WINAPI RemUnkProxy_Release(LPREMUNKNOWN iface)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
ULONG refs;
TRACE("(%p)->Release()\n",This);
if (This->outer_unknown)
refs = IUnknown_Release(This->outer_unknown);
else
refs = InterlockedDecrement(&This->refs);
if (!refs) {
if (This->chan) IRpcChannelBuffer_Release(This->chan);
HeapFree(GetProcessHeap(),0,This);
}
return refs;
}
static HRESULT WINAPI RemUnkProxy_RemQueryInterface(LPREMUNKNOWN iface,
REFIPID ripid,
ULONG cRefs,
USHORT cIids,
IID* iids,
REMQIRESULT** ppQIResults)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
RPCOLEMESSAGE msg;
HRESULT hr = S_OK;
ULONG status;
TRACE("(%p)->(%s,%ld,%d,%p,%p)\n",This,
debugstr_guid(ripid),cRefs,cIids,iids,ppQIResults);
*ppQIResults = NULL;
memset(&msg, 0, sizeof(msg));
msg.iMethod = 3;
msg.cbBuffer = sizeof(IPID) + sizeof(ULONG) +
sizeof(USHORT) + cIids*sizeof(IID);
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
if (SUCCEEDED(hr)) {
LPBYTE buf = msg.Buffer;
memcpy(buf, ripid, sizeof(IPID));
buf += sizeof(IPID);
memcpy(buf, &cRefs, sizeof(ULONG));
buf += sizeof(ULONG);
memcpy(buf, &cIids, sizeof(USHORT));
buf += sizeof(USHORT);
memcpy(buf, iids, cIids*sizeof(IID));
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
if (SUCCEEDED(hr)) {
buf = msg.Buffer;
*ppQIResults = CoTaskMemAlloc(cIids*sizeof(REMQIRESULT));
memcpy(*ppQIResults, buf, cIids*sizeof(REMQIRESULT));
}
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
}
return hr;
}
static HRESULT WINAPI RemUnkProxy_RemAddRef(LPREMUNKNOWN iface,
USHORT cInterfaceRefs,
REMINTERFACEREF* InterfaceRefs,
HRESULT* pResults)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
RPCOLEMESSAGE msg;
HRESULT hr = S_OK;
ULONG status;
TRACE("(%p)->(%d,%p,%p)\n",This,
cInterfaceRefs,InterfaceRefs,pResults);
memset(&msg, 0, sizeof(msg));
msg.iMethod = 4;
msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
if (SUCCEEDED(hr)) {
LPBYTE buf = msg.Buffer;
memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
buf += sizeof(USHORT);
memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
if (SUCCEEDED(hr)) {
buf = msg.Buffer;
memcpy(pResults, buf, cInterfaceRefs*sizeof(HRESULT));
}
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
}
return hr;
}
static HRESULT WINAPI RemUnkProxy_RemRelease(LPREMUNKNOWN iface,
USHORT cInterfaceRefs,
REMINTERFACEREF* InterfaceRefs)
{
RemUnkProxy *This = (RemUnkProxy *)iface;
RPCOLEMESSAGE msg;
HRESULT hr = S_OK;
ULONG status;
TRACE("(%p)->(%d,%p)\n",This,
cInterfaceRefs,InterfaceRefs);
memset(&msg, 0, sizeof(msg));
msg.iMethod = 5;
msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
if (SUCCEEDED(hr)) {
LPBYTE buf = msg.Buffer;
memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
buf += sizeof(USHORT);
memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
}
return hr;
}
static const IRemUnknownVtbl RemUnkProxy_VTable =
{
RemUnkProxy_QueryInterface,
RemUnkProxy_AddRef,
RemUnkProxy_Release,
RemUnkProxy_RemQueryInterface,
RemUnkProxy_RemAddRef,
RemUnkProxy_RemRelease
};
static HRESULT WINAPI RURpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
*ppv = NULL;
if (IsEqualIID(riid,&IID_IRpcProxyBuffer)||IsEqualIID(riid,&IID_IUnknown)) {
IRpcProxyBuffer_AddRef(iface);
*ppv = (LPVOID)iface;
return S_OK;
}
FIXME("(%s), no interface.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI RURpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
return InterlockedIncrement(&This->refs);
}
static ULONG WINAPI RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
ULONG ref = InterlockedDecrement(&This->refs);
if (!ref) {
IRpcChannelBuffer_Release(This->chan);This->chan = NULL;
HeapFree(GetProcessHeap(),0,This);
}
return ref;
}
static HRESULT WINAPI RURpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) {
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
This->chan = pRpcChannelBuffer;
IRpcChannelBuffer_AddRef(This->chan);
return S_OK;
}
static void WINAPI RURpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
if (This->chan) {
IRpcChannelBuffer_Release(This->chan);
This->chan = NULL;
}
}
static const IRpcProxyBufferVtbl RURpcProxyBuffer_VTable = {
RURpcProxyBufferImpl_QueryInterface,
RURpcProxyBufferImpl_AddRef,
RURpcProxyBufferImpl_Release,
RURpcProxyBufferImpl_Connect,
RURpcProxyBufferImpl_Disconnect
};
static HRESULT
RemUnkProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
RemUnkProxy *This;
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*This));
if (!This)
return E_OUTOFMEMORY;
This->lpvtbl_remunk = &RemUnkProxy_VTable;
This->lpvtbl_proxy = &RURpcProxyBuffer_VTable;
/* only one reference for the proxy buffer */
This->refs = 1;
This->outer_unknown = pUnkOuter;
*ppv = &(This->lpvtbl_remunk);
*ppProxy = &(This->lpvtbl_proxy);
return S_OK;
}
/********************* OLE Proxy/Stub Factory ********************************/
static HRESULT WINAPI
PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
@ -473,10 +920,10 @@ PSFacBuf_CreateProxy(
LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
IRpcProxyBuffer **ppProxy, LPVOID *ppv
) {
if (IsEqualIID(&IID_IClassFactory,riid) ||
IsEqualIID(&IID_IUnknown,riid)
)
if (IsEqualIID(&IID_IClassFactory,riid))
return CFProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
else if (IsEqualIID(&IID_IRemUnknown,riid))
return RemUnkProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid));
return E_FAIL;
}
@ -490,13 +937,17 @@ PSFacBuf_CreateStub(
TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
if (IsEqualIID(&IID_IClassFactory,riid) ||
IsEqualIID(&IID_IUnknown,riid)
) {
if (IsEqualIID(&IID_IClassFactory, riid) ||
IsEqualIID(&IID_IUnknown, riid) /* FIXME: fixup stub manager and remove this*/) {
hres = CFStub_Construct(ppStub);
if (!hres)
IRpcStubBuffer_Connect((*ppStub),pUnkServer);
return hres;
} else if (IsEqualIID(&IID_IRemUnknown,riid)) {
hres = RemUnkStub_Construct(ppStub);
if (!hres)
IRpcStubBuffer_Connect((*ppStub),pUnkServer);
return hres;
}
FIXME("stubbing not implemented for (%s) yet!\n",debugstr_guid(riid));
return E_FAIL;