--- dlls/ole32/compobj.c (revision 67) +++ dlls/ole32/compobj.c (local) @@ -30,6 +30,8 @@ * - Rewrite the CoLockObjectExternal code, it does totally the wrong * thing currently (should be controlling the stub manager) * + * - Make the MTA dynamically allocated and refcounted + * * - Implement the service control manager (in rpcss) to keep track * of registered class objects: ISCM::ServerRegisterClsid et al * - Implement the OXID resolver so we don't need magic pipe names for @@ -99,7 +101,8 @@ static void COM_ExternalLockFreeList(voi const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} }; -APARTMENT MTA, *apts; +APARTMENT MTA; +struct list apts = LIST_INIT( apts ); static CRITICAL_SECTION csApartment; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -236,6 +239,7 @@ static void COM_UninitMTA(void) MTA.oxid = 0; } + /* creates an apartment structure which stores OLE thread-local * information. Call with COINIT_UNINITIALIZED to create an apartment * that will be initialized with a model later. Note: do not call @@ -243,100 +247,134 @@ static void COM_UninitMTA(void) * with a different COINIT value */ APARTMENT* COM_CreateApartment(DWORD model) { - APARTMENT *apt; - BOOL create = (NtCurrentTeb()->ReservedForOle == NULL); + APARTMENT *apt = COM_CurrentApt(); - if (create) + if (!apt) { + if (model & COINIT_MULTITHREADED) + { + TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId()); + COM_CurrentInfo()->apt = &MTA; + return apt; + } + + TRACE("creating new apartment, model=%ld\n", model); + apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT)); apt->tid = GetCurrentThreadId(); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apt->thread, THREAD_ALL_ACCESS, FALSE, 0); - } - else - apt = NtCurrentTeb()->ReservedForOle; - list_init(&apt->proxies); - list_init(&apt->stubmgrs); - apt->oidc = 1; - - apt->model = model; - if (model & COINIT_APARTMENTTHREADED) { - /* FIXME: how does windoze create OXIDs? */ - apt->oxid = MTA.oxid | GetCurrentThreadId(); - apt->win = CreateWindowA(aptWinClass, NULL, 0, - 0, 0, 0, 0, - 0, 0, OLE32_hInstance, NULL); - InitializeCriticalSection(&apt->cs); - } - else if (!(model & COINIT_UNINITIALIZED)) { - apt->parent = &MTA; - apt->oxid = MTA.oxid; - } - EnterCriticalSection(&csApartment); - if (create) - { - if (apts) apts->prev = apt; - apt->next = apts; - apts = apt; + list_init(&apt->stubmgrs); + apt->oidc = 1; + apt->refs = 1; + InitializeCriticalSection(&apt->cs); + + apt->model = model; + + /* we don't ref the apartment as CoInitializeEx will do it for us */ + + if (model & COINIT_APARTMENTTHREADED) + { + /* FIXME: how does windoze create OXIDs? */ + apt->oxid = MTA.oxid | GetCurrentThreadId(); + apt->win = CreateWindowA(aptWinClass, NULL, 0, + 0, 0, 0, 0, + 0, 0, OLE32_hInstance, NULL); + } + + EnterCriticalSection(&csApartment); + list_add_head(&apts, &apt->entry); + LeaveCriticalSection(&csApartment); + + COM_CurrentInfo()->apt = apt; } - LeaveCriticalSection(&csApartment); - NtCurrentTeb()->ReservedForOle = apt; + return apt; } -static void COM_DestroyApartment(APARTMENT *apt) +DWORD COM_ApartmentAddRef(struct apartment *apt) +{ + return InterlockedIncrement(&apt->refs); +} + +DWORD COM_ApartmentRelease(struct apartment *apt) { EnterCriticalSection(&csApartment); - if (apt->prev) apt->prev->next = apt->next; - if (apt->next) apt->next->prev = apt->prev; - if (apts == apt) apts = apt->next; - apt->prev = NULL; apt->next = NULL; - LeaveCriticalSection(&csApartment); - 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); - DeleteCriticalSection(&apt->cs); + if (InterlockedDecrement(&apt->refs) == 0) + { + TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid)); + + MARSHAL_Disconnect_Proxies(apt); + + list_remove(&apt->entry); + if ((apt->model & COINIT_APARTMENTTHREADED) && apt->win) DestroyWindow(apt->win); + + if (!list_empty(&apt->stubmgrs)) + { + FIXME("PANIC: Apartment being destroyed with outstanding stubs, what do we do now?\n"); + } + + if (apt->filter) IUnknown_Release(apt->filter); + + + DeleteCriticalSection(&apt->cs); + CloseHandle(apt->thread); + HeapFree(GetProcessHeap(), 0, apt); + + apt = NULL; } - CloseHandle(apt->thread); - HeapFree(GetProcessHeap(), 0, apt); -} -/* The given OXID must be local to this process: you cannot use apartment - windows to send RPCs to other processes. This all needs to move to rpcrt4 */ + LeaveCriticalSection(&csApartment); -APARTMENT *COM_ApartmentFromOXID(OXID oxid) + return apt ? apt->refs : 0; +} + +/* The given OXID must be local to this process: you cannot use + * apartment windows to send RPCs to other processes. This all needs + * to move to rpcrt4. + * + * The ref parameter is here mostly to ensure people remember that + * they get one, you should normally take a ref for thread safety. + */ +APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref) { - APARTMENT *apt = NULL; + APARTMENT *result = NULL; + struct list *cursor; EnterCriticalSection(&csApartment); - apt = apts; - while (apt && apt->oxid != oxid) apt = apt->next; + LIST_FOR_EACH( cursor, &apts ) + { + struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry ); + if (apt->oxid == oxid) + { + result = apt; + if (ref) COM_ApartmentAddRef(result); + break; + } + } LeaveCriticalSection(&csApartment); - return apt; + return result; } -HWND COM_GetApartmentWin(OXID oxid) +HWND COM_GetApartmentWin(OXID oxid, BOOL ref) { - APARTMENT *apt = COM_ApartmentFromOXID(oxid); + APARTMENT *apt; - return apt ? apt->win : NULL; + apt = COM_ApartmentFromOXID(oxid, ref); + if (!apt) return NULL; + + return apt->win; } /* Currently inter-thread marshalling is not fully implemented, so this does nothing */ static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hWnd, msg, wParam, lParam); -} +} /***************************************************************************** * This section contains OpenDllList implemantation @@ -467,8 +505,7 @@ HRESULT WINAPI CoInitialize( * CoUninitialize */ HRESULT WINAPI CoInitializeEx( - LPVOID lpReserved, /* [in] pointer to win32 malloc interface - (obsolete, should be NULL) */ + LPVOID lpReserved, /* [in] pointer to win32 malloc interface (obsolete, should be NULL) */ DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */ ) { @@ -482,21 +519,6 @@ HRESULT WINAPI CoInitializeEx( ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved); } - apt = NtCurrentTeb()->ReservedForOle; - if (apt && !(apt->model == COINIT_UNINITIALIZED)) - { - if (dwCoInit != apt->model) - { - /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine - code then we are probably using the wrong threading model to implement that API. */ - ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); - return RPC_E_CHANGED_MODE; - } - hr = S_FALSE; - } - else - hr = S_OK; - /* * Check the lock count. If this is the first time going through the initialize * process, we have to initialize the libraries. @@ -512,13 +534,27 @@ HRESULT WINAPI CoInitializeEx( COM_InitMTA(); + /* we may need to defer this until after apartment initialisation */ RunningObjectTableImpl_Initialize(); } - if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit); + if (!COM_CurrentInfo()->apt) + { + apt = COM_CreateApartment(dwCoInit); + } + else + { + InterlockedIncrement(&apt->refs); + } - InterlockedIncrement(&apt->inits); - if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt; + if (dwCoInit != apt->model) + { + /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine + code then we are probably using the wrong threading model to implement that API. */ + ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); + return RPC_E_CHANGED_MODE; + } + return hr; } @@ -529,14 +565,20 @@ HRESULT WINAPI CoInitializeEx( void COM_FlushMessageQueue(void) { MSG message; - APARTMENT *apt = NtCurrentTeb()->ReservedForOle; + APARTMENT *apt = COM_CurrentApt(); if (!apt || !apt->win) return; TRACE("Flushing STA message queue\n"); - while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) { - if (message.hwnd != apt->win) continue; + while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) + { + if (message.hwnd != apt->win) + { + WARN("discarding message 0x%x for window %p\n", message.message, message.hwnd); + continue; + } + TranslateMessage(&message); DispatchMessageA(&message); } @@ -561,17 +603,11 @@ void COM_FlushMessageQueue(void) void WINAPI CoUninitialize(void) { LONG lCOMRefCnt; - APARTMENT *apt; TRACE("()\n"); - apt = NtCurrentTeb()->ReservedForOle; - if (!apt) return; - if (InterlockedDecrement(&apt->inits)==0) { - NtCurrentTeb()->ReservedForOle = NULL; - COM_DestroyApartment(apt); - apt = NULL; - } + if (!COM_ApartmentRelease(COM_CurrentInfo()->apt)) + COM_CurrentInfo()->apt = NULL; /* * Decrease the reference count. @@ -1134,14 +1170,14 @@ end: /****************************************************************************** * CoRegisterClassObject [OLE32.@] - * + * * Registers the class object for a given class ID. Servers housed in EXE * files use this method instead of exporting DllGetClassObject to allow * other code to connect to their objects. * * RETURNS - * S_OK on success, - * E_INVALIDARG if lpdwRegister or pUnk are NULL, + * S_OK on success, + * E_INVALIDARG if lpdwRegister or pUnk are NULL, * CO_E_OBJISREG if the object is already registered. We should not return this. * * SEE ALSO @@ -1217,7 +1253,7 @@ HRESULT WINAPI CoRegisterClassObject( if (dwClsContext & CLSCTX_LOCAL_SERVER) { IClassFactory *classfac; - hr = IUnknown_QueryInterface(newClass->classObject, &IID_IClassFactory, + hr = IUnknown_QueryInterface(newClass->classObject, &IID_IClassFactory, (LPVOID*)&classfac); if (hr) return hr; @@ -1556,7 +1592,7 @@ HRESULT WINAPI CoCreateInstance( LPCLASSFACTORY lpclf = 0; if (!COM_CurrentApt()) return CO_E_NOTINITIALIZED; - + /* * Sanity check */ @@ -1573,15 +1609,15 @@ HRESULT WINAPI CoCreateInstance( * Rather than create a class factory, we can just check for it here */ if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) { - if (StdGlobalInterfaceTableInstance == NULL) + if (StdGlobalInterfaceTableInstance == NULL) StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); hres = IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, iid, ppv); if (hres) return hres; - + TRACE("Retrieved GIT (%p)\n", *ppv); return S_OK; } - + /* * Get a class factory to construct the object we want. */ @@ -2000,19 +2036,19 @@ HRESULT WINAPI CoInitializeWOW(DWORD x,D */ HRESULT WINAPI CoGetState(IUnknown ** ppv) { - APARTMENT * apt = COM_CurrentInfo(); + HRESULT hr = E_FAIL; - FIXME("\n"); + *ppv = NULL; - if(apt && apt->state) { - IUnknown_AddRef(apt->state); - *ppv = apt->state; - FIXME("-- %p\n", *ppv); - return S_OK; - } - *ppv = NULL; - return E_FAIL; + if (COM_CurrentInfo()->state) + { + IUnknown_AddRef(COM_CurrentInfo()->state); + *ppv = COM_CurrentInfo()->state; + TRACE("apt->state=%p\n", COM_CurrentInfo()->state); + hr = S_OK; + } + return hr; } /*********************************************************************** @@ -2021,22 +2057,17 @@ HRESULT WINAPI CoGetState(IUnknown ** pp */ HRESULT WINAPI CoSetState(IUnknown * pv) { - APARTMENT * apt = COM_CurrentInfo(); - - if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED); + if (pv) IUnknown_AddRef(pv); - FIXME("(%p),stub!\n", pv); + if (COM_CurrentInfo()->state) + { + TRACE("-- release %p now\n", COM_CurrentInfo()->state); + IUnknown_Release(COM_CurrentInfo()->state); + } - if (pv) { - IUnknown_AddRef(pv); - } + COM_CurrentInfo()->state = pv; - if (apt->state) { - TRACE("-- release %p now\n", apt->state); - IUnknown_Release(apt->state); - } - apt->state = pv; - return S_OK; + return S_OK; } @@ -2191,7 +2222,7 @@ HRESULT WINAPI CoGetTreatAsClass(REFCLSI done: if (hkey) RegCloseKey(hkey); return res; - + } /*********************************************************************** --- dlls/ole32/compobj_private.h (revision 67) +++ dlls/ole32/compobj_private.h (local) @@ -38,12 +38,8 @@ #include "winreg.h" #include "winternl.h" -/* Windows maps COINIT values to 0x80 for apartment threaded, 0x140 - * for free threaded, and 0 for uninitialized apartments. There is - * no real advantage in us doing this and certainly no release version - * of an app should be poking around with these flags. So we need a - * special value for uninitialized */ -#define COINIT_UNINITIALIZED 0x100 +struct apartment; + /* exported interface */ typedef struct tagXIF { @@ -59,7 +55,7 @@ typedef struct tagXIF { /* exported object */ typedef struct tagXOBJECT { IRpcStubBufferVtbl *lpVtbl; - struct tagAPARTMENT *parent; + struct apartment *parent; struct tagXOBJECT *next; LPUNKNOWN obj; /* object identity (IUnknown) */ OID oid; /* object ID */ @@ -83,7 +79,7 @@ struct ifproxy struct proxy_manager { const IInternalUnknownVtbl *lpVtbl; - struct tagAPARTMENT *parent; + struct apartment *parent; struct list entry; LPRPCCHANNELBUFFER chan; /* channel to object */ OXID oxid; /* object exported ID */ @@ -93,11 +89,13 @@ struct proxy_manager CRITICAL_SECTION cs; /* thread safety for this object and children */ }; -/* apartment */ -typedef struct tagAPARTMENT { - struct tagAPARTMENT *next, *prev, *parent; +/* this needs to become a COM object that implements IRemUnknown */ +struct apartment +{ + struct list entry; + + DWORD refs; /* refcount of the apartment */ DWORD model; /* threading model */ - DWORD inits; /* CoInitialize count */ DWORD tid; /* thread id */ HANDLE thread; /* thread handle */ OXID oxid; /* object exporter ID */ @@ -107,13 +105,11 @@ typedef struct tagAPARTMENT { LPMESSAGEFILTER filter; /* message filter */ XOBJECT *objs; /* exported objects */ struct list proxies; /* imported objects */ - LPUNKNOWN state; /* state object (see Co[Get,Set]State) */ - LPVOID ErrorInfo; /* thread error info */ DWORD listenertid; /* id of apartment_listener_thread */ struct list stubmgrs; /* stub managers for exported objects */ -} APARTMENT; +}; -extern APARTMENT MTA, *apts; +typedef struct apartment APARTMENT; extern void* StdGlobalInterfaceTable_Construct(void); extern void StdGlobalInterfaceTable_Destroy(void* self); @@ -196,27 +192,41 @@ int WINAPI FileMonikerImpl_DecomposePath HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id); +/* compobj.c */ +APARTMENT *COM_CreateApartment(DWORD model); +APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref); +DWORD COM_ApartmentAddRef(struct apartment *apt); +DWORD COM_ApartmentRelease(struct apartment *apt); + +extern CRITICAL_SECTION csApartment; + +/* this is what is stored in TEB->ReservedForOle */ +struct oletls +{ + struct apartment *apt; + IErrorInfo *errorinfo; /* see errorinfo.c */ + IUnknown *state; /* see CoSetState */ +}; + /* * Per-thread values are stored in the TEB on offset 0xF80, * see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm */ -static inline APARTMENT* COM_CurrentInfo(void) + +/* will create if necessary */ +static inline struct oletls *COM_CurrentInfo(void) { - APARTMENT* apt = NtCurrentTeb()->ReservedForOle; - return apt; + if (!NtCurrentTeb()->ReservedForOle) + NtCurrentTeb()->ReservedForOle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct oletls)); + + return NtCurrentTeb()->ReservedForOle; } + static inline APARTMENT* COM_CurrentApt(void) -{ - APARTMENT* apt = COM_CurrentInfo(); - if (apt && apt->parent) apt = apt->parent; - return apt; +{ + return COM_CurrentInfo()->apt; } -/* compobj.c */ -APARTMENT *COM_CreateApartment(DWORD model); -HWND COM_GetApartmentWin(OXID oxid); -APARTMENT *COM_ApartmentFromOXID(OXID oxid); - #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) #endif /* __WINE_OLE_COMPOBJ_H */ --- dlls/ole32/errorinfo.c (revision 67) +++ dlls/ole32/errorinfo.c (local) @@ -20,7 +20,7 @@ * NOTES: * * The errorinfo is a per-thread object. The reference is stored in the - * TEB at offset 0xf80 + * TEB at offset 0xf80. */ #include @@ -483,20 +483,20 @@ HRESULT WINAPI CreateErrorInfo(ICreateEr */ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) { - APARTMENT * apt = COM_CurrentInfo(); - - TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo); + TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->errorinfo); if(!pperrinfo) return E_INVALIDARG; - if (!apt || !apt->ErrorInfo) + + if (!COM_CurrentInfo()->errorinfo) { *pperrinfo = NULL; return S_FALSE; } - *pperrinfo = (IErrorInfo*)(apt->ErrorInfo); + *pperrinfo = COM_CurrentInfo()->errorinfo; + /* clear thread error state */ - apt->ErrorInfo = NULL; + COM_CurrentInfo()->errorinfo = NULL; return S_OK; } @@ -506,18 +506,16 @@ HRESULT WINAPI GetErrorInfo(ULONG dwRese HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo) { IErrorInfo * pei; - APARTMENT * apt = COM_CurrentInfo(); TRACE("(%ld, %p)\n", dwReserved, perrinfo); - if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED); - /* release old errorinfo */ - pei = (IErrorInfo*)apt->ErrorInfo; - if(pei) IErrorInfo_Release(pei); + pei = COM_CurrentInfo()->errorinfo; + if (pei) IErrorInfo_Release(pei); /* set to new value */ - apt->ErrorInfo = perrinfo; - if(perrinfo) IErrorInfo_AddRef(perrinfo); + COM_CurrentInfo()->errorinfo = perrinfo; + if (perrinfo) IErrorInfo_AddRef(perrinfo); + return S_OK; } --- dlls/ole32/marshal.c (revision 67) +++ dlls/ole32/marshal.c (local) @@ -109,9 +109,13 @@ static HRESULT register_ifstub(wine_mars } else { - TRACE("constructing new stub manager\n"); + struct apartment *apt; - manager = new_stub_manager(COM_ApartmentFromOXID(mid->oxid), obj); + TRACE("constructing new stub manager\n"); + + apt = COM_ApartmentFromOXID(mid->oxid, TRUE); + manager = new_stub_manager(apt, obj); + COM_ApartmentRelease(apt); if (!manager) return E_OUTOFMEMORY; if (!tablemarshal) stub_manager_ref(manager, 1); --- dlls/ole32/rpc.c (revision 67) +++ dlls/ole32/rpc.c (local) @@ -308,8 +308,6 @@ PipeBuf_Release(LPRPCCHANNELBUFFER iface if (ref) return ref; - FIXME("Free all stuff\n"); - memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id)); pipe = PIPE_FindByMID(&This->mid); @@ -892,7 +890,7 @@ static DWORD WINAPI apartment_listener_t HANDLE listenPipe; APARTMENT *apt = (APARTMENT *) param; - /* we must join the marshalling threads apartment */ + /* we must join the marshalling threads apartment. we already have a ref here */ NtCurrentTeb()->ReservedForOle = apt; sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); @@ -926,7 +924,7 @@ static DWORD WINAPI apartment_listener_t void start_apartment_listener_thread() { APARTMENT *apt = COM_CurrentApt(); - + assert( apt ); TRACE("apt->listenertid=%ld\n", apt->listenertid); --- dlls/ole32/stubmanager.c (revision 67) +++ dlls/ole32/stubmanager.c (local) @@ -41,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +/* this refs the apartment on success, otherwise there is no ref */ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) { struct stub_manager *sm; @@ -71,6 +72,7 @@ struct stub_manager *new_stub_manager(AP list_add_head(&apt->stubmgrs, &sm->entry); LeaveCriticalSection(&apt->cs); + COM_ApartmentAddRef(apt); TRACE("Created new stub manager (oid=%s) at %p for object with IUnknown %p\n", wine_dbgstr_longlong(sm->oid), sm, object); return sm; @@ -82,7 +84,7 @@ struct stub_manager *get_stub_manager_fr struct list *cursor; APARTMENT *apt; - if (!(apt = COM_ApartmentFromOXID(oxid))) + if (!(apt = COM_ApartmentFromOXID(oxid, TRUE))) { WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid)); return NULL; @@ -101,6 +103,8 @@ struct stub_manager *get_stub_manager_fr } LeaveCriticalSection(&apt->cs); + COM_ApartmentRelease(apt); + TRACE("found %p from object %p\n", result, object); return result; @@ -112,14 +116,13 @@ struct stub_manager *get_stub_manager(OX struct list *cursor; APARTMENT *apt; - if (!(apt = COM_ApartmentFromOXID(oxid))) + if (!(apt = COM_ApartmentFromOXID(oxid, TRUE))) { WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid)); return NULL; } EnterCriticalSection(&apt->cs); - LIST_FOR_EACH( cursor, &apt->stubmgrs ) { struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); @@ -130,9 +133,10 @@ struct stub_manager *get_stub_manager(OX break; } } - LeaveCriticalSection(&apt->cs); + COM_ApartmentRelease(apt); + TRACE("found %p from oid %s\n", result, wine_dbgstr_longlong(oid)); return result;