From e5edbc6fa00192a8048a3b81c70075537eaa2c97 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 28 Aug 2015 14:58:55 +0200 Subject: [PATCH] ole32: Use proper IUnknown implementation when finding and creating stub manager. --- dlls/ole32/compobj.c | 36 ++++++++++-------------------------- dlls/ole32/compobj_private.h | 3 +-- dlls/ole32/marshal.c | 14 +++----------- dlls/ole32/stubmanager.c | 21 +++++++++++++++++---- 4 files changed, 31 insertions(+), 43 deletions(-) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 6a30d7db424..23c825ac0d1 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3605,32 +3605,8 @@ HRESULT WINAPI CoLockObjectExternal( apt = COM_CurrentApt(); if (!apt) return CO_E_NOTINITIALIZED; - stubmgr = get_stub_manager_from_object(apt, pUnk); - - if (stubmgr) - { - if (fLock) - stub_manager_ext_addref(stubmgr, 1, FALSE); - else - stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases); - - stub_manager_int_release(stubmgr); - - return S_OK; - } - else if (fLock) - { - stubmgr = new_stub_manager(apt, pUnk); - - if (stubmgr) - { - stub_manager_ext_addref(stubmgr, 1, FALSE); - stub_manager_int_release(stubmgr); - } - - return S_OK; - } - else + stubmgr = get_stub_manager_from_object(apt, pUnk, fLock); + if (!stubmgr) { WARN("stub object not found %p\n", pUnk); /* Note: native is pretty broken here because it just silently @@ -3638,6 +3614,14 @@ HRESULT WINAPI CoLockObjectExternal( * think that the object was disconnected, when it actually wasn't */ return S_OK; } + + if (fLock) + stub_manager_ext_addref(stubmgr, 1, FALSE); + else + stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases); + + stub_manager_int_release(stubmgr); + return S_OK; } /*********************************************************************** diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 933b71ce622..f11186cb46f 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -185,14 +185,13 @@ HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; /* Stub Manager */ ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN; -struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) DECLSPEC_HIDDEN; ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN; ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN; struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, DWORD dest_context, void *dest_context_data, MSHLFLAGS flags) DECLSPEC_HIDDEN; struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) DECLSPEC_HIDDEN; struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid) DECLSPEC_HIDDEN; -struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object) DECLSPEC_HIDDEN; +struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, IUnknown *object, BOOL alloc) DECLSPEC_HIDDEN; BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN; BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN; void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) DECLSPEC_HIDDEN; diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c index 9a640c9aa17..d142b935377 100644 --- a/dlls/ole32/marshal.c +++ b/dlls/ole32/marshal.c @@ -132,22 +132,14 @@ HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkno if (hr != S_OK) return hr; + if (!(manager = get_stub_manager_from_object(apt, object, TRUE))) + return E_OUTOFMEMORY; + stdobjref->flags = SORF_NULL; if (mshlflags & MSHLFLAGS_TABLEWEAK) stdobjref->flags |= SORFP_TABLEWEAK; if (mshlflags & MSHLFLAGS_NOPING) stdobjref->flags |= SORF_NOPING; - - if ((manager = get_stub_manager_from_object(apt, object))) - TRACE("registering new ifstub on pre-existing manager\n"); - else - { - TRACE("constructing new stub manager\n"); - - manager = new_stub_manager(apt, object); - if (!manager) - return E_OUTOFMEMORY; - } stdobjref->oid = manager->oid; tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK)); diff --git a/dlls/ole32/stubmanager.c b/dlls/ole32/stubmanager.c index fda494448c9..1f79ff5bc07 100644 --- a/dlls/ole32/stubmanager.c +++ b/dlls/ole32/stubmanager.c @@ -168,7 +168,7 @@ struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHL /* creates a new stub manager and adds it into the apartment. caller must * release stub manager when it is no longer required. the apartment and * external refs together take one implicit ref */ -struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) +static struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) { struct stub_manager *sm; HRESULT hres; @@ -298,10 +298,18 @@ ULONG stub_manager_int_release(struct stub_manager *This) /* gets the stub manager associated with an object - caller must have * a reference to the apartment while a reference to the stub manager is held. * it must also call release on the stub manager when it is no longer needed */ -struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object) +struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, IUnknown *obj, BOOL alloc) { struct stub_manager *result = NULL; struct list *cursor; + IUnknown *object; + HRESULT hres; + + hres = IUnknown_QueryInterface(obj, &IID_IUnknown, (void**)&object); + if (FAILED(hres)) { + ERR("QueryInterface(IID_IUnknown failed): %08x\n", hres); + return NULL; + } EnterCriticalSection(&apt->cs); LIST_FOR_EACH( cursor, &apt->stubmgrs ) @@ -317,11 +325,16 @@ struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object) } LeaveCriticalSection(&apt->cs); - if (result) + if (result) { TRACE("found %p for object %p\n", result, object); - else + }else if (alloc) { + TRACE("not found, creating new stub manager...\n"); + result = new_stub_manager(apt, object); + }else { TRACE("not found for object %p\n", object); + } + IUnknown_Release(object); return result; } -- 2.11.4.GIT