Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 136 ++++++++++++++++++++++++- dlls/combase/combase.spec | 5 +- dlls/combase/combase_private.h | 3 + dlls/ole32/compobj.c | 179 --------------------------------- dlls/ole32/ole32.spec | 4 +- 5 files changed, 142 insertions(+), 185 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 4ce43717fb4..cddc9e23067 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -40,6 +40,13 @@ HINSTANCE hProxyDll;
#define CHARS_IN_GUID 39
+extern void WINAPI DestroyRunningObjectTable(void); + +/* + * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed + */ +static LONG com_lockcount; + struct comclassredirect_data { ULONG size; @@ -1757,7 +1764,7 @@ HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter ** return S_OK; }
-void WINAPI InternalRevokeAllPSClsids(void) +static void com_revoke_all_ps_clsids(void) { struct registered_ps *cur, *cur2;
@@ -2267,6 +2274,133 @@ void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibrariesEx(DWORD unload_delay, DWORD apartment_freeunusedlibraries(apt, unload_delay); }
+/* + * When locked, don't modify list (unless we add a new head), so that it's + * safe to iterate it. Freeing of list entries is delayed and done on unlock. + */ +static inline void lock_init_spies(struct tlsdata *tlsdata) +{ + tlsdata->spies_lock++; +} + +static void unlock_init_spies(struct tlsdata *tlsdata) +{ + struct init_spy *spy, *next; + + if (--tlsdata->spies_lock) return; + + LIST_FOR_EACH_ENTRY_SAFE(spy, next, &tlsdata->spies, struct init_spy, entry) + { + if (spy->spy) continue; + list_remove(&spy->entry); + heap_free(spy); + } +} + +/****************************************************************************** + * CoInitializeEx (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(void *reserved, DWORD model) +{ + struct tlsdata *tlsdata; + struct init_spy *cursor; + HRESULT hr; + + TRACE("%p, %#x\n", reserved, model); + + if (reserved) + WARN("Unexpected reserved argument %p\n", reserved); + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + if (InterlockedExchangeAdd(&com_lockcount, 1) == 0) + TRACE("Initializing the COM libraries\n"); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, model, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + hr = enter_apartment(tlsdata, model); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, model, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + return hr; +} + +/*********************************************************************** + * CoUninitialize (combase.@) + */ +void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) +{ + struct tlsdata *tlsdata; + struct init_spy *cursor, *next; + LONG lockcount; + + TRACE("\n"); + + if (FAILED(com_get_tlsdata(&tlsdata))) + return; + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + /* sanity check */ + if (!tlsdata->inits) + { + ERR("Mismatched CoUninitialize\n"); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + return; + } + + leave_apartment(tlsdata); + + /* + * Decrease the reference count. + * If we are back to 0 locks on the COM library, make sure we free + * all the associated data structures. + */ + lockcount = InterlockedExchangeAdd(&com_lockcount, -1); + if (lockcount == 1) + { + TRACE("Releasing the COM libraries\n"); + + com_revoke_all_ps_clsids(); + DestroyRunningObjectTable(); + } + else if (lockcount < 1) + { + ERR("Unbalanced lock count %d\n", lockcount); + InterlockedExchangeAdd(&com_lockcount, 1); + } + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); +} + /*********************************************************************** * DllMain (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 00aea556d94..01377c8045e 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -123,7 +123,7 @@ @ stdcall CoGetTreatAsClass(ptr ptr) @ stdcall CoImpersonateClient() @ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage -@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx +@ stdcall CoInitializeEx(ptr long) @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) @ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW @ stub CoInvalidateRemoteMachineBindings @@ -163,7 +163,7 @@ @ stdcall CoTaskMemFree(ptr) @ stdcall CoTaskMemRealloc(ptr long) @ stub CoTestCancel -@ stdcall CoUninitialize() ole32.CoUninitialize +@ stdcall CoUninitialize() @ stub CoUnloadingWOW @ stdcall CoUnmarshalHresult(ptr ptr) @ stdcall CoUnmarshalInterface(ptr ptr ptr) ole32.CoUnmarshalInterface @@ -268,7 +268,6 @@ @ stub InternalNotifyDDStartOrStop @ stub InternalOleModalLoopBlockFn @ stub InternalRegisterWindowPropInterface -@ stdcall InternalRevokeAllPSClsids() @ stub InternalReleaseMarshalObjRef @ stub InternalSTAInvoke @ stub InternalServerExceptionFilter diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 7fe548af593..122522baad5 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -131,6 +131,9 @@ struct stub_manager BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */ };
+HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model); +void WINAPI leave_apartment(struct tlsdata *data); + /* Stub Manager */
ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN; diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 88482392d5e..5afacf3ee3f 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -142,12 +142,6 @@ struct class_reg_data } u; };
-/* - * This lock count counts the number of times CoInitialize is called. It is - * decreased every time CoUninitialize is called. When it hits 0, the COM - * libraries are freed - */ -static LONG s_COMLockCount = 0; /* Reference count used by CoAddRefServerProcess/CoReleaseServerProcess */ static LONG s_COMServerProcessReferences = 0;
@@ -182,8 +176,6 @@ static CRITICAL_SECTION_DEBUG class_cs_debug = }; static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
-extern void WINAPI InternalRevokeAllPSClsids(void); - static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect) { switch (aspect) @@ -661,29 +653,6 @@ DWORD WINAPI CoBuildVersion(void) return (rmm<<16)+rup; }
-/* - * When locked, don't modify list (unless we add a new head), so that it's - * safe to iterate it. Freeing of list entries is delayed and done on unlock. - */ -static inline void lock_init_spies(struct oletls *info) -{ - info->spies_lock++; -} - -static void unlock_init_spies(struct oletls *info) -{ - struct init_spy *spy, *next; - - if (--info->spies_lock) return; - - LIST_FOR_EACH_ENTRY_SAFE(spy, next, &info->spies, struct init_spy, entry) - { - if (spy->spy) continue; - list_remove(&spy->entry); - heap_free(spy); - } -} - /****************************************************************************** * CoInitialize [OLE32.@] * @@ -708,154 +677,6 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved) return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED); }
-/****************************************************************************** - * CoInitializeEx [OLE32.@] - * - * Initializes the COM libraries. - * - * PARAMS - * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL). - * dwCoInit [I] One or more flags from the COINIT enumeration. See notes. - * - * RETURNS - * S_OK if successful, - * S_FALSE if this function was called already. - * RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another - * threading model. - * - * NOTES - * - * The behavior used to set the IMalloc used for memory management is - * obsolete. - * The dwCoInit parameter must specify one of the following apartment - * threading models: - *| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA). - *| COINIT_MULTITHREADED - A multi-threaded apartment (MTA). - * The parameter may also specify zero or more of the following flags: - *| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support. - *| COINIT_SPEED_OVER_MEMORY - Trade memory for speed. - * - * SEE ALSO - * CoUninitialize - */ -HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit) -{ - struct oletls *info = COM_CurrentInfo(); - struct init_spy *cursor; - HRESULT hr; - - TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit); - - if (lpReserved!=NULL) - { - ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved); - } - - /* - * Check the lock count. If this is the first time going through the initialize - * process, we have to initialize the libraries. - * - * And crank-up that lock count. - */ - if (InterlockedExchangeAdd(&s_COMLockCount,1)==0) - TRACE("() - Initializing the COM libraries\n"); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits); - } - unlock_init_spies(info); - - hr = enter_apartment( info, dwCoInit ); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits); - } - unlock_init_spies(info); - - return hr; -} - -/*********************************************************************** - * CoUninitialize [OLE32.@] - * - * This method will decrement the refcount on the current apartment, freeing - * the resources associated with it if it is the last thread in the apartment. - * If the last apartment is freed, the function will additionally release - * any COM resources associated with the process. - * - * PARAMS - * - * RETURNS - * Nothing. - * - * SEE ALSO - * CoInitializeEx - */ -void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) -{ - struct oletls * info = COM_CurrentInfo(); - struct init_spy *cursor, *next; - LONG lCOMRefCnt; - - TRACE("()\n"); - - /* will only happen on OOM */ - if (!info) return; - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); - - /* sanity check */ - if (!info->inits) - { - ERR("Mismatched CoUninitialize\n"); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); - - return; - } - - leave_apartment( info ); - - /* - * Decrease the reference count. - * If we are back to 0 locks on the COM library, make sure we free - * all the associated data structures. - */ - lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1); - if (lCOMRefCnt==1) - { - TRACE("() - Releasing the COM libraries\n"); - - InternalRevokeAllPSClsids(); - DestroyRunningObjectTable(); - } - else if (lCOMRefCnt<1) { - ERR( "CoUninitialize() - not CoInitialized.\n" ); - InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */ - } - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); -} - /****************************************************************************** * CoDisconnectObject [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index c102bce1776..e80cafd3663 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -50,7 +50,7 @@ @ stdcall CoImpersonateClient() combase.CoImpersonateClient @ stdcall CoIncrementMTAUsage(ptr) @ stdcall CoInitialize(ptr) -@ stdcall CoInitializeEx(ptr long) +@ stdcall CoInitializeEx(ptr long) combase.CoInitializeEx @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) combase.CoInitializeSecurity @ stdcall CoInitializeWOW(long long) @ stdcall CoIsHandlerConnected(ptr) @@ -87,7 +87,7 @@ @ stdcall CoTaskMemFree(ptr) combase.CoTaskMemFree @ stdcall CoTaskMemRealloc(ptr long) combase.CoTaskMemRealloc @ stdcall CoTreatAsClass(ptr ptr) -@ stdcall CoUninitialize() +@ stdcall CoUninitialize() combase.CoUninitialize @ stub CoUnloadingWOW @ stdcall CoUnmarshalHresult(ptr ptr) combase.CoUnmarshalHresult @ stdcall CoUnmarshalInterface(ptr ptr ptr)