combase: Move initialisation functions.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-08-27 11:37:45 +03:00 committed by Alexandre Julliard
parent 48bd5461ed
commit ee080a423a
5 changed files with 142 additions and 185 deletions

View File

@ -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.@)
*/

View File

@ -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

View File

@ -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;

View File

@ -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.@]
*

View File

@ -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)