Implement proxy manager.
This commit is contained in:
parent
ffc55dad79
commit
2835633789
|
@ -226,6 +226,7 @@ APARTMENT* COM_CreateApartment(DWORD model)
|
||||||
else
|
else
|
||||||
apt = NtCurrentTeb()->ReservedForOle;
|
apt = NtCurrentTeb()->ReservedForOle;
|
||||||
|
|
||||||
|
list_init(&apt->proxies);
|
||||||
list_init(&apt->stubmgrs);
|
list_init(&apt->stubmgrs);
|
||||||
apt->oidc = 1;
|
apt->oidc = 1;
|
||||||
|
|
||||||
|
@ -263,6 +264,14 @@ static void COM_DestroyApartment(APARTMENT *apt)
|
||||||
apt->prev = NULL; apt->next = NULL;
|
apt->prev = NULL; apt->next = NULL;
|
||||||
LeaveCriticalSection(&csApartment);
|
LeaveCriticalSection(&csApartment);
|
||||||
if (apt->model & COINIT_APARTMENTTHREADED) {
|
if (apt->model & COINIT_APARTMENTTHREADED) {
|
||||||
|
/* disconnect proxies to release the corresponding stubs.
|
||||||
|
* It is confirmed in "Essential COM" in the sub-chapter on
|
||||||
|
* "Lifecycle Management and Marshalling" that the native version also
|
||||||
|
* disconnects proxies in this function. */
|
||||||
|
/* FIXME: this should also be called for MTA destruction, but that
|
||||||
|
* requires restructuring how apartments work slightly. */
|
||||||
|
MARSHAL_Disconnect_Proxies(apt);
|
||||||
|
|
||||||
if (apt->win) DestroyWindow(apt->win);
|
if (apt->win) DestroyWindow(apt->win);
|
||||||
DeleteCriticalSection(&apt->cs);
|
DeleteCriticalSection(&apt->cs);
|
||||||
}
|
}
|
||||||
|
@ -545,14 +554,6 @@ void WINAPI CoUninitialize(void)
|
||||||
|
|
||||||
RunningObjectTableImpl_UnInitialize();
|
RunningObjectTableImpl_UnInitialize();
|
||||||
|
|
||||||
/* disconnect proxies to release the corresponding stubs.
|
|
||||||
* It is confirmed in "Essential COM" in the sub-chapter on
|
|
||||||
* "Lifecycle Management and Marshalling" that the native version also
|
|
||||||
* does some kind of proxy cleanup in this function.
|
|
||||||
* FIXME: does it just disconnect or completely destroy the proxies?
|
|
||||||
* FIXME: should this be in the apartment destructor? */
|
|
||||||
MARSHAL_Disconnect_Proxies();
|
|
||||||
|
|
||||||
/* Release the references to the registered class objects */
|
/* Release the references to the registered class objects */
|
||||||
COM_RevokeAllClasses();
|
COM_RevokeAllClasses();
|
||||||
|
|
||||||
|
|
|
@ -68,29 +68,30 @@ typedef struct tagXOBJECT {
|
||||||
DWORD refs; /* external reference count */
|
DWORD refs; /* external reference count */
|
||||||
} XOBJECT;
|
} XOBJECT;
|
||||||
|
|
||||||
/* imported interface */
|
/* imported interface proxy */
|
||||||
typedef struct tagIIF {
|
struct ifproxy
|
||||||
struct tagIIF *next;
|
{
|
||||||
|
struct list entry;
|
||||||
LPVOID iface; /* interface pointer */
|
LPVOID iface; /* interface pointer */
|
||||||
IID iid; /* interface ID */
|
IID iid; /* interface ID */
|
||||||
IPID ipid; /* imported interface ID */
|
IPID ipid; /* imported interface ID */
|
||||||
LPRPCPROXYBUFFER proxy; /* interface proxy */
|
LPRPCPROXYBUFFER proxy; /* interface proxy */
|
||||||
DWORD refs; /* imported (public) references */
|
DWORD refs; /* imported (public) references */
|
||||||
HRESULT hres; /* result of proxy creation attempt */
|
};
|
||||||
} IIF;
|
|
||||||
|
|
||||||
/* imported object */
|
/* imported object / proxy manager */
|
||||||
typedef struct tagIOBJECT {
|
struct proxy_manager
|
||||||
IRemUnknownVtbl *lpVtbl;
|
{
|
||||||
|
const IInternalUnknownVtbl *lpVtbl;
|
||||||
struct tagAPARTMENT *parent;
|
struct tagAPARTMENT *parent;
|
||||||
struct tagIOBJECT *next;
|
struct list entry;
|
||||||
LPRPCCHANNELBUFFER chan; /* channel to object */
|
LPRPCCHANNELBUFFER chan; /* channel to object */
|
||||||
OXID oxid; /* object exported ID */
|
OXID oxid; /* object exported ID */
|
||||||
OID oid; /* object ID */
|
OID oid; /* object ID */
|
||||||
IPID ipid; /* first imported interface ID */
|
struct list interfaces; /* imported interfaces */
|
||||||
IIF *ifaces; /* imported interfaces */
|
|
||||||
DWORD refs; /* proxy reference count */
|
DWORD refs; /* proxy reference count */
|
||||||
} IOBJECT;
|
CRITICAL_SECTION cs; /* thread safety for this object and children */
|
||||||
|
};
|
||||||
|
|
||||||
/* apartment */
|
/* apartment */
|
||||||
typedef struct tagAPARTMENT {
|
typedef struct tagAPARTMENT {
|
||||||
|
@ -105,7 +106,7 @@ typedef struct tagAPARTMENT {
|
||||||
CRITICAL_SECTION cs; /* thread safety */
|
CRITICAL_SECTION cs; /* thread safety */
|
||||||
LPMESSAGEFILTER filter; /* message filter */
|
LPMESSAGEFILTER filter; /* message filter */
|
||||||
XOBJECT *objs; /* exported objects */
|
XOBJECT *objs; /* exported objects */
|
||||||
IOBJECT *proxies; /* imported objects */
|
struct list proxies; /* imported objects */
|
||||||
LPUNKNOWN state; /* state object (see Co[Get,Set]State) */
|
LPUNKNOWN state; /* state object (see Co[Get,Set]State) */
|
||||||
LPVOID ErrorInfo; /* thread error info */
|
LPVOID ErrorInfo; /* thread error info */
|
||||||
DWORD listenertid; /* id of apartment_listener_thread */
|
DWORD listenertid; /* id of apartment_listener_thread */
|
||||||
|
@ -139,7 +140,7 @@ MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT MARSHAL_Disconnect_Proxies(void);
|
HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);
|
||||||
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
||||||
|
|
||||||
/* an interface stub */
|
/* an interface stub */
|
||||||
|
|
|
@ -81,14 +81,6 @@ typedef struct _wine_marshal_data {
|
||||||
DWORD mshlflags;
|
DWORD mshlflags;
|
||||||
} wine_marshal_data;
|
} wine_marshal_data;
|
||||||
|
|
||||||
typedef struct _mid2unknown {
|
|
||||||
wine_marshal_id mid;
|
|
||||||
LPUNKNOWN pUnk;
|
|
||||||
} mid2unknown;
|
|
||||||
|
|
||||||
static mid2unknown *proxies = NULL;
|
|
||||||
static int nrofproxies = 0;
|
|
||||||
|
|
||||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
|
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
|
||||||
{
|
{
|
||||||
struct stub_manager *m;
|
struct stub_manager *m;
|
||||||
|
@ -132,40 +124,285 @@ static HRESULT register_ifstub(wine_marshal_id *mid, IUnknown *obj, IRpcStubBuff
|
||||||
return ifstub ? S_OK : E_OUTOFMEMORY;
|
return ifstub ? S_OK : E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
|
||||||
MARSHAL_Disconnect_Proxies() {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
TRACE("Disconnecting %d proxies\n", nrofproxies);
|
|
||||||
|
|
||||||
for (i = 0; i < nrofproxies; i++)
|
/* Client-side identity of the server object */
|
||||||
IRpcProxyBuffer_Disconnect((IRpcProxyBuffer*)proxies[i].pUnk);
|
|
||||||
|
static void proxy_manager_destroy(struct proxy_manager * This);
|
||||||
|
static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found);
|
||||||
|
|
||||||
|
static HRESULT WINAPI ClientIdentity_QueryInterface(IInternalUnknown * iface, REFIID riid, void ** ppv)
|
||||||
|
{
|
||||||
|
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||||
|
HRESULT hr;
|
||||||
|
struct ifproxy * ifproxy;
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_guid(riid));
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||||
|
IsEqualIID(riid, &IID_IInternalUnknown))
|
||||||
|
{
|
||||||
|
*ppv = (void *)iface;
|
||||||
|
IInternalUnknown_AddRef(iface);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = proxy_manager_find_ifproxy(This, riid, &ifproxy);
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
*ppv = ifproxy->iface;
|
||||||
|
IUnknown_AddRef((IUnknown *)*ppv);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("interface not found %s\n", debugstr_guid(riid));
|
||||||
|
|
||||||
|
/* FIXME: call IRemUnknown::RemQueryInterface */
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI ClientIdentity_AddRef(IInternalUnknown * iface)
|
||||||
|
{
|
||||||
|
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||||
|
TRACE("%p\n", iface);
|
||||||
|
return InterlockedIncrement(&This->refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI ClientIdentity_Release(IInternalUnknown * iface)
|
||||||
|
{
|
||||||
|
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||||
|
ULONG refs = InterlockedDecrement(&This->refs);
|
||||||
|
TRACE("%p\n", iface);
|
||||||
|
if (!refs)
|
||||||
|
proxy_manager_destroy(This);
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI ClientIdentity_QueryInternalInterface(IInternalUnknown * iface, REFIID riid, void ** ppv)
|
||||||
|
{
|
||||||
|
FIXME("(%s, %p): stub!\n", debugstr_guid(riid), ppv);
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IInternalUnknownVtbl ClientIdentity_Vtbl =
|
||||||
|
{
|
||||||
|
ClientIdentity_QueryInterface,
|
||||||
|
ClientIdentity_AddRef,
|
||||||
|
ClientIdentity_Release,
|
||||||
|
ClientIdentity_QueryInternalInterface
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT ifproxy_get_public_ref(struct ifproxy * This)
|
||||||
|
{
|
||||||
|
/* FIXME: call IRemUnknown::RemAddRef if necessary */
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT
|
static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
|
||||||
MARSHAL_Register_Proxy(wine_marshal_id *mid,LPUNKNOWN punk) {
|
{
|
||||||
int i;
|
/* FIXME: call IRemUnknown::RemRelease */
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0;i<nrofproxies;i++) {
|
static void ifproxy_disconnect(struct ifproxy * This)
|
||||||
if (MARSHAL_Compare_Mids(mid,&(proxies[i].mid))) {
|
{
|
||||||
/* this will happen if the program attempts to marshal two
|
IRpcProxyBuffer_Disconnect(This->proxy);
|
||||||
* objects that implement the same interface */
|
}
|
||||||
|
|
||||||
FIXME("need to use IPIDs, already have mid oxid=%s, oid=%s, iid=%s\n",
|
static void ifproxy_destroy(struct ifproxy * This)
|
||||||
wine_dbgstr_longlong(mid->oxid), wine_dbgstr_longlong(mid->oid), debugstr_guid(&mid->iid));
|
{
|
||||||
return E_FAIL;
|
/* release public references to this object so that the stub can know
|
||||||
}
|
* when to destroy itself */
|
||||||
|
ifproxy_release_public_refs(This);
|
||||||
|
|
||||||
|
list_remove(&This->entry);
|
||||||
|
|
||||||
|
if (This->proxy) IRpcProxyBuffer_Release(This->proxy);
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT proxy_manager_construct(APARTMENT * apt, OXID oxid, OID oid, IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager)
|
||||||
|
{
|
||||||
|
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||||
|
if (!This) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
This->lpVtbl = &ClientIdentity_Vtbl;
|
||||||
|
|
||||||
|
list_init(&This->entry);
|
||||||
|
list_init(&This->interfaces);
|
||||||
|
|
||||||
|
InitializeCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
/* the apartment the object was unmarshaled into */
|
||||||
|
This->parent = apt;
|
||||||
|
|
||||||
|
/* the source apartment and id of the object */
|
||||||
|
This->oxid = oxid;
|
||||||
|
This->oid = oid;
|
||||||
|
|
||||||
|
This->refs = 0; /* will be incremented on creation of first proxy */
|
||||||
|
|
||||||
|
This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
|
||||||
|
|
||||||
|
EnterCriticalSection(&apt->cs);
|
||||||
|
list_add_head(&apt->proxies, &This->entry);
|
||||||
|
LeaveCriticalSection(&apt->cs);
|
||||||
|
|
||||||
|
*proxy_manager = This;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT proxy_manager_create_ifproxy(struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs, struct ifproxy ** iif_out)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
IPSFactoryBuffer * psfb;
|
||||||
|
struct ifproxy * ifproxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*ifproxy));
|
||||||
|
if (!ifproxy) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
list_init(&ifproxy->entry);
|
||||||
|
|
||||||
|
ifproxy->ipid = ipid;
|
||||||
|
ifproxy->iid = *riid;
|
||||||
|
ifproxy->refs = cPublicRefs;
|
||||||
|
ifproxy->proxy = NULL;
|
||||||
|
|
||||||
|
hr = get_facbuf_for_iid(riid, &psfb);
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
/* important note: the outer unknown is set to the proxy manager.
|
||||||
|
* This ensures the COM identity rules are not violated, by having a
|
||||||
|
* one-to-one mapping of objects on the proxy side to objects on the
|
||||||
|
* stub side, no matter which interface you view the object through */
|
||||||
|
hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown *)&This->lpVtbl, riid,
|
||||||
|
&ifproxy->proxy, &ifproxy->iface);
|
||||||
|
IPSFactoryBuffer_Release(psfb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hr == S_OK)
|
||||||
|
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan);
|
||||||
|
|
||||||
|
/* get at least one external reference to the object to keep it alive */
|
||||||
|
if (hr == S_OK)
|
||||||
|
hr = ifproxy_get_public_ref(ifproxy);
|
||||||
|
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&This->cs);
|
||||||
|
list_add_tail(&This->interfaces, &ifproxy->entry);
|
||||||
|
LeaveCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
*iif_out = ifproxy;
|
||||||
}
|
}
|
||||||
if (nrofproxies)
|
|
||||||
proxies = HeapReAlloc(GetProcessHeap(),0,proxies,sizeof(proxies[0])*(nrofproxies+1));
|
|
||||||
else
|
else
|
||||||
proxies = HeapAlloc(GetProcessHeap(),0,sizeof(proxies[0]));
|
ifproxy_destroy(ifproxy);
|
||||||
memcpy(&(proxies[nrofproxies].mid),mid,sizeof(*mid));
|
|
||||||
proxies[nrofproxies].pUnk = punk;
|
return hr;
|
||||||
nrofproxies++;
|
}
|
||||||
IUnknown_AddRef(punk);
|
|
||||||
|
static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found)
|
||||||
|
{
|
||||||
|
HRESULT hr = E_NOINTERFACE; /* assume not found */
|
||||||
|
struct list * cursor;
|
||||||
|
|
||||||
|
EnterCriticalSection(&This->cs);
|
||||||
|
LIST_FOR_EACH(cursor, &This->interfaces)
|
||||||
|
{
|
||||||
|
struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
|
||||||
|
if (IsEqualIID(riid, &ifproxy->iid))
|
||||||
|
{
|
||||||
|
*ifproxy_found = ifproxy;
|
||||||
|
hr = S_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proxy_manager_disconnect(struct proxy_manager * This)
|
||||||
|
{
|
||||||
|
struct list * cursor;
|
||||||
|
|
||||||
|
EnterCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
LIST_FOR_EACH(cursor, &This->interfaces)
|
||||||
|
{
|
||||||
|
struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
|
||||||
|
ifproxy_disconnect(ifproxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apartment is being destroyed so don't keep a pointer around to it */
|
||||||
|
This->parent = NULL;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&This->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proxy_manager_destroy(struct proxy_manager * This)
|
||||||
|
{
|
||||||
|
struct list * cursor;
|
||||||
|
|
||||||
|
if (This->parent)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&This->parent->cs);
|
||||||
|
|
||||||
|
/* remove ourself from the list of proxy objects in the apartment */
|
||||||
|
LIST_FOR_EACH(cursor, &This->parent->proxies)
|
||||||
|
{
|
||||||
|
if (cursor == &This->entry)
|
||||||
|
{
|
||||||
|
list_remove(&This->entry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&This->parent->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* destroy all of the interface proxies */
|
||||||
|
while (!(cursor = list_head(&This->interfaces)))
|
||||||
|
{
|
||||||
|
struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
|
||||||
|
ifproxy_destroy(ifproxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL find_proxy_manager(APARTMENT * apt, OXID oxid, OID oid, struct proxy_manager ** proxy_found)
|
||||||
|
{
|
||||||
|
BOOL found = FALSE;
|
||||||
|
struct list * cursor;
|
||||||
|
|
||||||
|
EnterCriticalSection(&apt->cs);
|
||||||
|
LIST_FOR_EACH(cursor, &apt->proxies)
|
||||||
|
{
|
||||||
|
struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry);
|
||||||
|
if ((oxid == proxy->oxid) && (oid == proxy->oid))
|
||||||
|
{
|
||||||
|
*proxy_found = proxy;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&apt->cs);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt)
|
||||||
|
{
|
||||||
|
struct list * cursor;
|
||||||
|
|
||||||
|
EnterCriticalSection(&apt->cs);
|
||||||
|
LIST_FOR_EACH(cursor, &apt->proxies)
|
||||||
|
{
|
||||||
|
struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry);
|
||||||
|
proxy_manager_disconnect(proxy);
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&apt->cs);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +539,14 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
|
||||||
wine_marshal_data md;
|
wine_marshal_data md;
|
||||||
ULONG res;
|
ULONG res;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
IPSFactoryBuffer *psfacbuf;
|
|
||||||
IRpcProxyBuffer *rpcproxy;
|
|
||||||
IRpcChannelBuffer *chanbuf;
|
IRpcChannelBuffer *chanbuf;
|
||||||
|
struct proxy_manager *proxy_manager;
|
||||||
|
APARTMENT *apt = COM_CurrentApt();
|
||||||
|
|
||||||
TRACE("(...,%s,....)\n",debugstr_guid(riid));
|
TRACE("(...,%s,....)\n",debugstr_guid(riid));
|
||||||
|
|
||||||
|
if (!apt) return CO_E_NOTINITIALIZED;
|
||||||
|
|
||||||
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
||||||
if (hres) return hres;
|
if (hres) return hres;
|
||||||
hres = IStream_Read(pStm,&md,sizeof(md),&res);
|
hres = IStream_Read(pStm,&md,sizeof(md),&res);
|
||||||
|
@ -326,36 +566,27 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
|
||||||
stub_manager_unref(stubmgr, 1);
|
stub_manager_unref(stubmgr, 1);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_NULL)) {
|
if (!find_proxy_manager(apt, mid.oxid, mid.oid, &proxy_manager))
|
||||||
/* should return proxy manager IUnknown object */
|
{
|
||||||
FIXME("Special treatment required for IID of %s\n", debugstr_guid(riid));
|
hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
|
||||||
}
|
if (hres == S_OK)
|
||||||
hres = get_facbuf_for_iid(riid,&psfacbuf);
|
hres = proxy_manager_construct(apt, mid.oxid, mid.oid, chanbuf, &proxy_manager);
|
||||||
if (hres) return hres;
|
|
||||||
hres = IPSFactoryBuffer_CreateProxy(psfacbuf,NULL,riid,&rpcproxy,ppv);
|
|
||||||
if (hres) {
|
|
||||||
FIXME("Failed to create a proxy for %s\n",debugstr_guid(riid));
|
|
||||||
return hres;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MARSHAL_Register_Proxy(&mid, (LPUNKNOWN) rpcproxy);
|
if (hres == S_OK)
|
||||||
|
{
|
||||||
|
struct ifproxy * ifproxy;
|
||||||
|
hres = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
|
||||||
|
if (hres == S_OK)
|
||||||
|
IUnknown_AddRef((IUnknown *)ifproxy->iface);
|
||||||
|
else if (hres == E_NOINTERFACE)
|
||||||
|
hres = proxy_manager_create_ifproxy(proxy_manager, mid.iid /* FIXME: ipid */, riid, 1, &ifproxy);
|
||||||
|
|
||||||
hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
|
if (hres == S_OK)
|
||||||
IPSFactoryBuffer_Release(psfacbuf);
|
*ppv = ifproxy->iface; /* AddRef'd above */
|
||||||
if (hres) {
|
|
||||||
ERR("Failed to get an rpc channel buffer for %s\n",debugstr_guid(riid));
|
|
||||||
} else {
|
|
||||||
/* Connect the channel buffer to the proxy and release the no longer
|
|
||||||
* needed proxy.
|
|
||||||
* NOTE: The proxy should have taken an extra reference because it also
|
|
||||||
* aggregates the object, so we can safely release our reference to it. */
|
|
||||||
IRpcProxyBuffer_Connect(rpcproxy,chanbuf);
|
|
||||||
IRpcProxyBuffer_Release(rpcproxy);
|
|
||||||
/* IRpcProxyBuffer takes a reference on the channel buffer and
|
|
||||||
* we no longer need it, so release it */
|
|
||||||
IRpcChannelBuffer_Release(chanbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue