diff --git a/dlls/combase/Makefile.in b/dlls/combase/Makefile.in index 45e1ff189cb..ebf86708bbc 100644 --- a/dlls/combase/Makefile.in +++ b/dlls/combase/Makefile.in @@ -14,7 +14,9 @@ C_SRCS = \ roapi.c \ rpc.c \ string.c \ + stubmanager.c \ usrmarshal.c IDL_SRCS = \ + dcom.idl \ irpcss.idl diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c index 12637c8acdb..1637d674222 100644 --- a/dlls/combase/apartment.c +++ b/dlls/combase/apartment.c @@ -444,7 +444,6 @@ void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay) } extern HRESULT WINAPI Internal_apartment_disconnectproxies(struct apartment *apt); -extern ULONG WINAPI Internal_stub_manager_int_release(struct stub_manager *stubmgr); void WINAPI apartment_release(struct apartment *apt) { @@ -513,7 +512,7 @@ void WINAPI apartment_release(struct apartment *apt) * stub manager list in the apartment and all non-apartment users * must have a ref on the apartment and so it cannot be destroyed). */ - Internal_stub_manager_int_release(stubmgr); + stub_manager_int_release(stubmgr); } /* if this assert fires, then another thread took a reference to a @@ -654,7 +653,7 @@ struct apartment * WINAPI apartment_findfromoxid(OXID oxid) /* gets the apartment which has a given creator thread ID. The caller must * release the reference from the apartment as soon as the apartment pointer * is no longer required. */ -struct apartment * WINAPI apartment_findfromtid(DWORD tid) +struct apartment * apartment_findfromtid(DWORD tid) { struct apartment *result = NULL; struct list *cursor; diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index da91d66cc53..b3e3844a4db 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -2968,6 +2968,90 @@ ULONG WINAPI CoReleaseServerProcess(void) return refs; } +/****************************************************************************** + * CoDisconnectObject (combase.@) + */ +HRESULT WINAPI CoDisconnectObject(IUnknown *object, DWORD reserved) +{ + struct stub_manager *manager; + struct apartment *apt; + IMarshal *marshal; + HRESULT hr; + + TRACE("%p, %#x\n", object, reserved); + + if (!object) + return E_INVALIDARG; + + hr = IUnknown_QueryInterface(object, &IID_IMarshal, (void **)&marshal); + if (hr == S_OK) + { + hr = IMarshal_DisconnectObject(marshal, reserved); + IMarshal_Release(marshal); + return hr; + } + + if (!(apt = apartment_get_current_or_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + + manager = get_stub_manager_from_object(apt, object, FALSE); + if (manager) + { + stub_manager_disconnect(manager); + /* Release stub manager twice, to remove the apartment reference. */ + stub_manager_int_release(manager); + stub_manager_int_release(manager); + } + + /* Note: native is pretty broken here because it just silently + * fails, without returning an appropriate error code if the object was + * not found, making apps think that the object was disconnected, when + * it actually wasn't */ + + apartment_release(apt); + return S_OK; +} + +/****************************************************************************** + * CoLockObjectExternal (combase.@) + */ +HRESULT WINAPI CoLockObjectExternal(IUnknown *object, BOOL lock, BOOL last_unlock_releases) +{ + struct stub_manager *stubmgr; + struct apartment *apt; + + TRACE("%p, %d, %d\n", object, lock, last_unlock_releases); + + if (!(apt = apartment_get_current_or_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + + stubmgr = get_stub_manager_from_object(apt, object, lock); + if (!stubmgr) + { + WARN("stub object not found %p\n", object); + /* Note: native is pretty broken here because it just silently + * fails, without returning an appropriate error code, making apps + * think that the object was disconnected, when it actually wasn't */ + apartment_release(apt); + return S_OK; + } + + if (lock) + stub_manager_ext_addref(stubmgr, 1, FALSE); + else + stub_manager_ext_release(stubmgr, 1, FALSE, last_unlock_releases); + + stub_manager_int_release(stubmgr); + apartment_release(apt); + return S_OK; +} + /*********************************************************************** * DllMain (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index a888e6deeea..4ac93ff545d 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -89,7 +89,7 @@ @ stdcall CoDecrementMTAUsage(ptr) @ stdcall CoDisableCallCancellation(ptr) ole32.CoDisableCallCancellation @ stub CoDisconnectContext -@ stdcall CoDisconnectObject(ptr long) ole32.CoDisconnectObject +@ stdcall CoDisconnectObject(ptr long) @ stdcall CoEnableCallCancellation(ptr) ole32.CoEnableCallCancellation @ stdcall CoFileTimeNow(ptr) @ stdcall CoFreeUnusedLibraries() @@ -128,7 +128,7 @@ @ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW @ stub CoInvalidateRemoteMachineBindings @ stdcall CoIsHandlerConnected(ptr) ole32.CoIsHandlerConnected -@ stdcall CoLockObjectExternal(ptr long long) ole32.CoLockObjectExternal +@ stdcall CoLockObjectExternal(ptr long long) @ stdcall CoMarshalHresult(ptr long) @ stdcall CoMarshalInterThreadInterfaceInStream(ptr ptr ptr) @ stdcall CoMarshalInterface(ptr ptr ptr long ptr long) @@ -358,4 +358,15 @@ @ stdcall apartment_findfromoxid(int64) @ stdcall apartment_getwindow(ptr) @ stdcall apartment_createwindowifneeded(ptr) -@ stdcall apartment_findfromtid(long) +@ stdcall stub_manager_int_release(ptr) +@ stdcall get_stub_manager(ptr int64) +@ stdcall stub_manager_is_table_marshaled(ptr ptr) +@ stdcall stub_manager_notify_unmarshal(ptr ptr) +@ stdcall stub_manager_ext_release(ptr long long long) +@ stdcall stub_manager_release_marshal_data(ptr long ptr long) +@ stdcall get_stub_manager_from_object(ptr ptr long) +@ stdcall stub_manager_find_ifstub(ptr ptr long) +@ stdcall stub_manager_ext_addref(ptr long long) +@ stdcall stub_manager_new_ifstub(ptr ptr ptr long ptr long) +@ stdcall ipid_get_dispatch_params(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall start_apartment_remote_unknown(ptr) diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index e62204d289c..898d42b3c7b 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -113,34 +113,6 @@ HRESULT rpc_get_local_class_object(REFCLSID rclsid, REFIID riid, void **obj) DEC HRESULT rpc_start_local_server(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN; void rpc_stop_local_server(void *registration) DECLSPEC_HIDDEN; -/* stub managers hold refs on the object and each interface stub */ -struct stub_manager -{ - struct list entry; /* entry in apartment stubmgr list (CS apt->cs) */ - struct list ifstubs; /* list of active ifstubs for the object (CS lock) */ - CRITICAL_SECTION lock; - struct apartment *apt; /* owning apt (RO) */ - - ULONG extrefs; /* number of 'external' references (CS lock) */ - ULONG refs; /* internal reference count (CS apt->cs) */ - ULONG weakrefs; /* number of weak references (CS lock) */ - OID oid; /* apartment-scoped unique identifier (RO) */ - IUnknown *object; /* the object we are managing the stub for (RO) */ - ULONG next_ipid; /* currently unused (LOCK) */ - OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */ - - IExternalConnection *extern_conn; - - /* We need to keep a count of the outstanding marshals, so we can enforce the - * marshalling rules (ie, you can only unmarshal normal marshals once). Note - * that these counts do NOT include unmarshalled interfaces, once a stream is - * unmarshalled and a proxy set up, this count is decremented. - */ - - ULONG norm_refs; /* refcount of normal marshals (CS lock) */ - BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */ -}; - enum class_reg_data_origin { CLASS_REG_ACTCTX, @@ -175,7 +147,78 @@ HRESULT apartment_get_local_server_stream(struct apartment *apt, IStream **ret) IUnknown *com_get_registered_class_object(const struct apartment *apartment, REFCLSID rclsid, DWORD clscontext) DECLSPEC_HIDDEN; void apartment_revoke_all_classes(const struct apartment *apt) DECLSPEC_HIDDEN; +struct apartment * WINAPI apartment_findfromoxid(OXID oxid); +struct apartment * apartment_findfromtid(DWORD tid) DECLSPEC_HIDDEN; /* Stub Manager */ -ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN; +/* signal to stub manager that this is a rem unknown object */ +#define MSHLFLAGSP_REMUNKNOWN 0x80000000 + +/* Thread-safety Annotation Legend: + * + * RO - The value is read only. It never changes after creation, so no + * locking is required. + * LOCK - The value is written to only using Interlocked* functions. + * CS - The value is read or written to inside a critical section. + * The identifier following "CS" is the specific critical section that + * must be used. + * MUTEX - The value is read or written to with a mutex held. + * The identifier following "MUTEX" is the specific mutex that + * must be used. + */ + +typedef enum ifstub_state +{ + STUBSTATE_NORMAL_MARSHALED, + STUBSTATE_NORMAL_UNMARSHALED, + STUBSTATE_TABLE_WEAK_MARSHALED, + STUBSTATE_TABLE_WEAK_UNMARSHALED, + STUBSTATE_TABLE_STRONG, +} STUB_STATE; + +/* an interface stub */ +struct ifstub +{ + struct list entry; /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */ + IRpcStubBuffer *stubbuffer; /* RO */ + IID iid; /* RO */ + IPID ipid; /* RO */ + IUnknown *iface; /* RO */ + MSHLFLAGS flags; /* so we can enforce process-local marshalling rules (RO) */ + IRpcChannelBuffer*chan; /* channel passed to IRpcStubBuffer::Invoke (RO) */ +}; + +/* stub managers hold refs on the object and each interface stub */ +struct stub_manager +{ + struct list entry; /* entry in apartment stubmgr list (CS apt->cs) */ + struct list ifstubs; /* list of active ifstubs for the object (CS lock) */ + CRITICAL_SECTION lock; + struct apartment *apt; /* owning apt (RO) */ + + ULONG extrefs; /* number of 'external' references (CS lock) */ + ULONG refs; /* internal reference count (CS apt->cs) */ + ULONG weakrefs; /* number of weak references (CS lock) */ + OID oid; /* apartment-scoped unique identifier (RO) */ + IUnknown *object; /* the object we are managing the stub for (RO) */ + ULONG next_ipid; /* currently unused (LOCK) */ + OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */ + + IExternalConnection *extern_conn; + + /* We need to keep a count of the outstanding marshals, so we can enforce the + * marshalling rules (ie, you can only unmarshal normal marshals once). Note + * that these counts do NOT include unmarshalled interfaces, once a stream is + * unmarshalled and a proxy set up, this count is decremented. + */ + + ULONG norm_refs; /* refcount of normal marshals (CS lock) */ + BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */ +}; + +ULONG WINAPI stub_manager_int_release(struct stub_manager *stub_manager) DECLSPEC_HIDDEN; +struct stub_manager * WINAPI get_stub_manager_from_object(struct apartment *apt, IUnknown *object, BOOL alloc); +void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN; +ULONG WINAPI stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN; +ULONG WINAPI stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN; diff --git a/dlls/combase/dcom.idl b/dlls/combase/dcom.idl new file mode 100644 index 00000000000..56e3152456c --- /dev/null +++ b/dlls/combase/dcom.idl @@ -0,0 +1,62 @@ +/* + * Copyright 2003 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* see the official DCOM specification + * (there's a copy at http://www.grimes.demon.co.uk/DCOM/DCOMSpec.htm) */ + +#pragma makedep header + +#include "wine/orpc.idl" + +[ + object, + uuid(00000131-0000-0000-c000-000000000046) +] +interface IRemUnknown : IUnknown +{ + typedef [unique] IRemUnknown *LPREMUNKNOWN; + + typedef struct tagREMQIRESULT + { + HRESULT hResult; + STDOBJREF std; + } REMQIRESULT; + + typedef struct tagREMINTERFACEREF + { + IPID ipid; + unsigned long cPublicRefs; + unsigned long cPrivateRefs; + } REMINTERFACEREF; + + HRESULT RemQueryInterface( + [in] REFIPID ripid, + [in] ULONG cRefs, + [in] unsigned short cIids, + [in, size_is(cIids)] IID *iids, + [out, size_is(,cIids)] REMQIRESULT **ppQIResults); + + HRESULT RemAddRef( + [in] unsigned short cInterfaceRefs, + [in, size_is(cInterfaceRefs)] REMINTERFACEREF *InterfaceRefs, + [out, size_is(cInterfaceRefs)] HRESULT *pResults); + + HRESULT RemRelease( + [in] unsigned short cInterfaceRefs, + [in, size_is(cInterfaceRefs)] REMINTERFACEREF *InterfaceRefs); +} diff --git a/dlls/ole32/stubmanager.c b/dlls/combase/stubmanager.c similarity index 86% rename from dlls/ole32/stubmanager.c rename to dlls/combase/stubmanager.c index d38e22adb47..b1070c5683e 100644 --- a/dlls/ole32/stubmanager.c +++ b/dlls/combase/stubmanager.c @@ -38,10 +38,16 @@ #include "wine/debug.h" #include "wine/exception.h" -#include "compobj_private.h" +#include "initguid.h" +#include "dcom.h" +#include "combase_private.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); +extern HRESULT WINAPI marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object, + DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags); +extern HRESULT WINAPI RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan); +extern void WINAPI RPC_UnregisterInterface(REFIID riid, BOOL wait); /* generates an ipid in the following format (similar to native version): * Data1 = apartment-local ipid counter @@ -67,7 +73,7 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid) } /* registers a new interface stub COM object with the stub manager and returns registration record */ -struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context, +struct ifstub * WINAPI stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context, void *dest_context_data, MSHLFLAGS flags) { struct ifstub *stub; @@ -155,7 +161,7 @@ static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const return result; } -struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) +struct ifstub * WINAPI stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) { struct ifstub *result = NULL; struct ifstub *ifstub; @@ -182,15 +188,15 @@ static struct stub_manager *new_stub_manager(struct apartment *apt, IUnknown *ob struct stub_manager *sm; HRESULT hres; - assert( apt ); - + assert(apt); + sm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct stub_manager)); if (!sm) return NULL; list_init(&sm->ifstubs); InitializeCriticalSection(&sm->lock); - DEBUG_SET_CRITSEC_NAME(&sm->lock, "stub_manager"); + sm->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": stub_manager"); IUnknown_AddRef(object); sm->object = object; @@ -287,51 +293,46 @@ static void stub_manager_delete(struct stub_manager *m) } __ENDTRY - DEBUG_CLEAR_CRITSEC_NAME(&m->lock); + m->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&m->lock); HeapFree(GetProcessHeap(), 0, m); } /* increments the internal refcount */ -static ULONG stub_manager_int_addref(struct stub_manager *This) +static ULONG stub_manager_int_addref(struct stub_manager *m) { ULONG refs; - EnterCriticalSection(&This->apt->cs); - refs = ++This->refs; - LeaveCriticalSection(&This->apt->cs); + EnterCriticalSection(&m->apt->cs); + refs = ++m->refs; + LeaveCriticalSection(&m->apt->cs); TRACE("before %d\n", refs - 1); return refs; } -ULONG WINAPI Internal_stub_manager_int_release(struct stub_manager *m) -{ - return stub_manager_int_release(m); -} - /* decrements the internal refcount */ -ULONG stub_manager_int_release(struct stub_manager *This) +ULONG WINAPI stub_manager_int_release(struct stub_manager *m) { ULONG refs; - struct apartment *apt = This->apt; + struct apartment *apt = m->apt; EnterCriticalSection(&apt->cs); - refs = --This->refs; + refs = --m->refs; TRACE("after %d\n", refs); /* remove from apartment so no other thread can access it... */ if (!refs) - list_remove(&This->entry); + list_remove(&m->entry); LeaveCriticalSection(&apt->cs); /* ... so now we can delete it without being inside the apartment critsec */ if (!refs) - stub_manager_delete(This); + stub_manager_delete(m); return refs; } @@ -339,7 +340,7 @@ 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(struct apartment *apt, IUnknown *obj, BOOL alloc) +struct stub_manager * WINAPI get_stub_manager_from_object(struct apartment *apt, IUnknown *obj, BOOL alloc) { struct stub_manager *result = NULL; struct list *cursor; @@ -347,13 +348,14 @@ struct stub_manager *get_stub_manager_from_object(struct apartment *apt, IUnknow HRESULT hres; hres = IUnknown_QueryInterface(obj, &IID_IUnknown, (void**)&object); - if (FAILED(hres)) { + if (FAILED(hres)) + { ERR("QueryInterface(IID_IUnknown failed): %08x\n", hres); return NULL; } EnterCriticalSection(&apt->cs); - LIST_FOR_EACH( cursor, &apt->stubmgrs ) + LIST_FOR_EACH(cursor, &apt->stubmgrs) { struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); @@ -366,12 +368,17 @@ struct stub_manager *get_stub_manager_from_object(struct apartment *apt, IUnknow } LeaveCriticalSection(&apt->cs); - if (result) { + if (result) + { TRACE("found %p for object %p\n", result, object); - }else if (alloc) { + } + else if (alloc) + { TRACE("not found, creating new stub manager...\n"); result = new_stub_manager(apt, object); - }else { + } + else + { TRACE("not found for object %p\n", object); } @@ -382,15 +389,15 @@ struct stub_manager *get_stub_manager_from_object(struct apartment *apt, IUnknow /* gets the stub manager associated with an object id - 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(struct apartment *apt, OID oid) +struct stub_manager * WINAPI get_stub_manager(struct apartment *apt, OID oid) { struct stub_manager *result = NULL; struct list *cursor; EnterCriticalSection(&apt->cs); - LIST_FOR_EACH( cursor, &apt->stubmgrs ) + LIST_FOR_EACH(cursor, &apt->stubmgrs) { - struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); + struct stub_manager *m = LIST_ENTRY(cursor, struct stub_manager, entry); if (m->oid == oid) { @@ -410,7 +417,7 @@ struct stub_manager *get_stub_manager(struct apartment *apt, OID oid) } /* add some external references (ie from a client that unmarshaled an ifptr) */ -ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) +ULONG WINAPI stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) { BOOL first_extern_ref; ULONG rc; @@ -427,7 +434,7 @@ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak rc += ++m->weakrefs; LeaveCriticalSection(&m->lock); - + TRACE("added %u refs to %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc); /* @@ -441,7 +448,7 @@ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak } /* remove some external references */ -ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) +ULONG WINAPI stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) { BOOL last_extern_ref; ULONG rc; @@ -460,7 +467,7 @@ ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tablewea last_extern_ref = refs && !m->extrefs; LeaveCriticalSection(&m->lock); - + TRACE("removed %u refs from %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc); if (last_extern_ref && m->extern_conn) @@ -482,9 +489,9 @@ static struct stub_manager *get_stub_manager_from_ipid(struct apartment *apt, co struct list *cursor; EnterCriticalSection(&apt->cs); - LIST_FOR_EACH( cursor, &apt->stubmgrs ) + LIST_FOR_EACH(cursor, &apt->stubmgrs) { - struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); + struct stub_manager *m = LIST_ENTRY(cursor, struct stub_manager, entry); if ((*ifstub = stub_manager_ipid_to_ifstub(m, ipid))) { @@ -535,7 +542,7 @@ static HRESULT ipid_to_stub_manager(const IPID *ipid, struct apartment **stub_ap /* gets the apartment, stub and channel of an object. the caller must * release the references to all objects (except iface) if the function * returned success, otherwise no references are returned. */ -HRESULT ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, +HRESULT WINAPI ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub, IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) @@ -564,7 +571,7 @@ HRESULT ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, } /* returns TRUE if it is possible to unmarshal, FALSE otherwise. */ -BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) +BOOL WINAPI stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) { BOOL ret = TRUE; struct ifstub *ifstub; @@ -595,13 +602,13 @@ BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) } /* handles refcounting for CoReleaseMarshalData */ -void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) +void WINAPI stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) { struct ifstub *ifstub; - + if (!(ifstub = stub_manager_ipid_to_ifstub(m, ipid))) return; - + if (ifstub->flags & MSHLFLAGS_TABLEWEAK) refs = 0; else if (ifstub->flags & MSHLFLAGS_TABLESTRONG) @@ -611,16 +618,15 @@ void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const } /* is an ifstub table marshaled? */ -BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) +BOOL WINAPI stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) { struct ifstub *ifstub = stub_manager_ipid_to_ifstub(m, ipid); - assert( ifstub ); - + assert(ifstub); + return ifstub->flags & (MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK); } - /***************************************************************************** * * IRemUnknown implementation @@ -643,24 +649,24 @@ static inline RemUnknown *impl_from_IRemUnknown(IRemUnknown *iface) return CONTAINING_RECORD(iface, RemUnknown, IRemUnknown_iface); } - /* construct an IRemUnknown object with one outstanding reference */ static HRESULT RemUnknown_Construct(IRemUnknown **ppRemUnknown) { - RemUnknown *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + RemUnknown *object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object)); - if (!This) return E_OUTOFMEMORY; + if (!object) + return E_OUTOFMEMORY; - This->IRemUnknown_iface.lpVtbl = &RemUnknown_Vtbl; - This->refs = 1; + object->IRemUnknown_iface.lpVtbl = &RemUnknown_Vtbl; + object->refs = 1; - *ppRemUnknown = &This->IRemUnknown_iface; + *ppRemUnknown = &object->IRemUnknown_iface; return S_OK; } static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, void **ppv) { - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), ppv); if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IRemUnknown)) @@ -680,9 +686,9 @@ static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface) { ULONG refs; - RemUnknown *This = impl_from_IRemUnknown(iface); + RemUnknown *remunk = impl_from_IRemUnknown(iface); - refs = InterlockedIncrement(&This->refs); + refs = InterlockedIncrement(&remunk->refs); TRACE("%p before: %d\n", iface, refs-1); return refs; @@ -691,11 +697,11 @@ static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface) static ULONG WINAPI RemUnknown_Release(IRemUnknown *iface) { ULONG refs; - RemUnknown *This = impl_from_IRemUnknown(iface); + RemUnknown *remunk = impl_from_IRemUnknown(iface); - refs = InterlockedDecrement(&This->refs); + refs = InterlockedDecrement(&remunk->refs); if (!refs) - HeapFree(GetProcessHeap(), 0, This); + HeapFree(GetProcessHeap(), 0, remunk); TRACE("%p after: %d\n", iface, refs); return refs; @@ -714,7 +720,7 @@ static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface, DWORD dest_context; void *dest_context_data; - TRACE("(%p)->(%s, %d, %d, %p, %p)\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults); + TRACE("%p, %s, %d, %d, %p, %p\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults); hr = ipid_to_ifstub(ripid, &apt, &stubmgr, &ifstub); if (hr != S_OK) return hr; @@ -751,7 +757,7 @@ static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface, HRESULT hr = S_OK; USHORT i; - TRACE("(%p)->(%d, %p, %p)\n", iface, cInterfaceRefs, InterfaceRefs, pResults); + TRACE("%p, %d, %p, %p\n", iface, cInterfaceRefs, InterfaceRefs, pResults); for (i = 0; i < cInterfaceRefs; i++) { @@ -783,7 +789,7 @@ static HRESULT WINAPI RemUnknown_RemRelease(IRemUnknown *iface, HRESULT hr = S_OK; USHORT i; - TRACE("(%p)->(%d, %p)\n", iface, cInterfaceRefs, InterfaceRefs); + TRACE("%p, %d, %p\n", iface, cInterfaceRefs, InterfaceRefs); for (i = 0; i < cInterfaceRefs; i++) { @@ -820,7 +826,7 @@ static const IRemUnknownVtbl RemUnknown_Vtbl = }; /* starts the IRemUnknown listener for the current apartment */ -HRESULT start_apartment_remote_unknown(struct apartment *apt) +HRESULT WINAPI start_apartment_remote_unknown(struct apartment *apt) { IRemUnknown *pRemUnknown; HRESULT hr = S_OK; @@ -834,7 +840,8 @@ HRESULT start_apartment_remote_unknown(struct apartment *apt) { STDOBJREF stdobjref; /* dummy - not used */ /* register it with the stub manager */ - hr = marshal_object(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL|MSHLFLAGSP_REMUNKNOWN); + hr = marshal_object(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, + MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL|MSHLFLAGSP_REMUNKNOWN); /* release our reference to the object as the stub manager will manage the life cycle for us */ IRemUnknown_Release(pRemUnknown); if (hr == S_OK) diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index 1c1e28fa4c5..ddbdfab30de 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -37,7 +37,6 @@ C_SRCS = \ stg_prop.c \ stg_stream.c \ storage32.c \ - stubmanager.c \ usrmarshal.c RC_SRCS = ole32res.rc diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 39ccc86b352..b92dfd87267 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -529,69 +529,6 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved) return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED); } -/****************************************************************************** - * CoDisconnectObject [OLE32.@] - * - * Disconnects all connections to this object from remote processes. Dispatches - * pending RPCs while blocking new RPCs from occurring, and then calls - * IMarshal::DisconnectObject on the given object. - * - * Typically called when the object server is forced to shut down, for instance by - * the user. - * - * PARAMS - * lpUnk [I] The object whose stub should be disconnected. - * reserved [I] Reserved. Should be set to 0. - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - * - * SEE ALSO - * CoMarshalInterface, CoReleaseMarshalData, CoLockObjectExternal - */ -HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) -{ - struct stub_manager *manager; - HRESULT hr; - IMarshal *marshal; - struct apartment *apt; - - TRACE("(%p, 0x%08x)\n", lpUnk, reserved); - - if (!lpUnk) return E_INVALIDARG; - - hr = IUnknown_QueryInterface(lpUnk, &IID_IMarshal, (void **)&marshal); - if (hr == S_OK) - { - hr = IMarshal_DisconnectObject(marshal, reserved); - IMarshal_Release(marshal); - return hr; - } - - if (!(apt = apartment_get_current_or_mta())) - { - ERR("apartment not initialised\n"); - return CO_E_NOTINITIALIZED; - } - - manager = get_stub_manager_from_object(apt, lpUnk, FALSE); - if (manager) { - stub_manager_disconnect(manager); - /* Release stub manager twice, to remove the apartment reference. */ - stub_manager_int_release(manager); - stub_manager_int_release(manager); - } - - /* Note: native is pretty broken here because it just silently - * fails, without returning an appropriate error code if the object was - * not found, making apps think that the object was disconnected, when - * it actually wasn't */ - - apartment_release(apt); - return S_OK; -} - /* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */ HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey) { @@ -698,64 +635,6 @@ void WINAPI CoFreeAllLibraries(void) /* NOP */ } -/****************************************************************************** - * CoLockObjectExternal [OLE32.@] - * - * Increments or decrements the external reference count of a stub object. - * - * PARAMS - * pUnk [I] Stub object. - * fLock [I] If TRUE then increments the external ref-count, - * otherwise decrements. - * fLastUnlockReleases [I] If TRUE then the last unlock has the effect of - * calling CoDisconnectObject. - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - * - * NOTES - * If fLock is TRUE and an object is passed in that doesn't have a stub - * manager then a new stub manager is created for the object. - */ -HRESULT WINAPI CoLockObjectExternal( - LPUNKNOWN pUnk, - BOOL fLock, - BOOL fLastUnlockReleases) -{ - struct stub_manager *stubmgr; - struct apartment *apt; - - TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n", - pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE"); - - if (!(apt = apartment_get_current_or_mta())) - { - ERR("apartment not initialised\n"); - return CO_E_NOTINITIALIZED; - } - - 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 - * fails, without returning an appropriate error code, making apps - * think that the object was disconnected, when it actually wasn't */ - apartment_release(apt); - 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); - apartment_release(apt); - return S_OK; -} - /*********************************************************************** * CoInitializeWOW (OLE32.@) * diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 953574423aa..6f1cf7243e3 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -194,24 +194,8 @@ HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; /* Stub Manager */ -ULONG stub_manager_int_release(struct stub_manager *This) 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, 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(struct apartment *apt, OID oid) DECLSPEC_HIDDEN; -struct stub_manager *get_stub_manager_from_object(struct 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; -void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN; -HRESULT ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub, - IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN; -HRESULT start_apartment_remote_unknown(struct apartment *apt) DECLSPEC_HIDDEN; - -HRESULT marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, DWORD dest_context, - void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN; +extern ULONG WINAPI stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN; +extern struct stub_manager * WINAPI get_stub_manager(struct apartment *apt, OID oid) DECLSPEC_HIDDEN; /* RPC Backend */ @@ -222,9 +206,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, const OXID_INFO *oxid_info, const IID *iid, DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan, struct apartment *apt) DECLSPEC_HIDDEN; -HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN; HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN; -void RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN; HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook) DECLSPEC_HIDDEN; void RPC_UnregisterAllChannelHooks(void) DECLSPEC_HIDDEN; HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info) DECLSPEC_HIDDEN; @@ -235,7 +217,6 @@ void OLEDD_UnInitialize(void) DECLSPEC_HIDDEN; /* Apartment Functions */ extern struct apartment * WINAPI apartment_findfromoxid(OXID oxid) DECLSPEC_HIDDEN; -extern struct apartment * WINAPI apartment_findfromtid(DWORD tid) DECLSPEC_HIDDEN; extern void WINAPI apartment_release(struct apartment *apt) DECLSPEC_HIDDEN; static inline HRESULT apartment_getoxid(const struct apartment *apt, OXID *oxid) { diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c index d08144f619a..87017dbc922 100644 --- a/dlls/ole32/marshal.c +++ b/dlls/ole32/marshal.c @@ -39,6 +39,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +extern BOOL WINAPI stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid); +extern BOOL WINAPI stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid); +extern ULONG WINAPI stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases); +extern void WINAPI stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak); +extern struct stub_manager * WINAPI get_stub_manager_from_object(struct apartment *apt, IUnknown *object, BOOL alloc); +extern struct ifstub * WINAPI stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags); +extern ULONG WINAPI stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak); +extern struct ifstub * WINAPI stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, + DWORD dest_context, void *dest_context_data, MSHLFLAGS flags); + /* number of refs given out for normal marshaling */ #define NORMALEXTREFS 5 @@ -118,7 +128,7 @@ static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) } /* marshals an object into a STDOBJREF structure */ -HRESULT marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object, +HRESULT WINAPI marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) { struct stub_manager *manager; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index ca22e4c8f1a..972629ecb70 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -16,7 +16,7 @@ @ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) combase.CoCreateInstanceEx @ stdcall CoDecrementMTAUsage(ptr) combase.CoDecrementMTAUsage @ stdcall CoDisableCallCancellation(ptr) -@ stdcall CoDisconnectObject(ptr long) +@ stdcall CoDisconnectObject(ptr long) combase.CoDisconnectObject @ stdcall CoDosDateTimeToFileTime(long long ptr) kernel32.DosDateTimeToFileTime @ stdcall CoEnableCallCancellation(ptr) @ stdcall CoFileTimeNow(ptr) combase.CoFileTimeNow @@ -56,7 +56,7 @@ @ stdcall CoIsHandlerConnected(ptr) @ stdcall CoIsOle1Class (ptr) @ stdcall CoLoadLibrary(wstr long) -@ stdcall CoLockObjectExternal(ptr long long) +@ stdcall CoLockObjectExternal(ptr long long) combase.CoLockObjectExternal @ stdcall CoMarshalHresult(ptr long) combase.CoMarshalHresult @ stdcall CoMarshalInterThreadInterfaceInStream(ptr ptr ptr) combase.CoMarshalInterThreadInterfaceInStream @ stdcall CoMarshalInterface(ptr ptr ptr long ptr long) combase.CoMarshalInterface @@ -298,6 +298,9 @@ @ stdcall WriteFmtUserTypeStg(ptr long ptr) @ stub WriteOleStg @ stub WriteStringStream + @ stdcall Internal_apartment_disconnectproxies(ptr) @ stdcall Internal_RPC_ExecuteCall(ptr) -@ stdcall Internal_stub_manager_int_release(ptr) +@ stdcall marshal_object(ptr ptr ptr ptr long ptr long) +@ stdcall RPC_CreateServerChannel(long ptr ptr) +@ stdcall RPC_UnregisterInterface(ptr long) diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index 84d26c70c6c..0aa2ebb41fe 100644 --- a/dlls/ole32/rpc.c +++ b/dlls/ole32/rpc.c @@ -43,6 +43,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +extern HRESULT WINAPI ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, + struct stub_manager **manager, IRpcStubBuffer **stub, IRpcChannelBuffer **chan, IID *iid, IUnknown **iface); +extern HRESULT WINAPI start_apartment_remote_unknown(struct apartment *apt); + static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg); /* we only use one function to dispatch calls for all methods - we use the @@ -1159,7 +1163,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, return S_OK; } -HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) +HRESULT WINAPI RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) { RpcChannelBuffer *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); if (!This) @@ -1584,7 +1588,7 @@ HRESULT RPC_RegisterInterface(REFIID riid) } /* stub unregistration */ -void RPC_UnregisterInterface(REFIID riid, BOOL wait) +void WINAPI RPC_UnregisterInterface(REFIID riid, BOOL wait) { struct registered_if *rif; EnterCriticalSection(&csRegIf);