- Make MTA dynamically allocated so that proxies and other resources
are freed at the proper time. - Changed/removed some incorrect comments regarding apartments.
This commit is contained in:
parent
b2bb57a484
commit
36f482cb7d
|
@ -28,13 +28,11 @@
|
||||||
*
|
*
|
||||||
* TODO list: (items bunched together depend on each other)
|
* TODO list: (items bunched together depend on each other)
|
||||||
*
|
*
|
||||||
* - Switch wine_marshal_id to use IPIDs not IIDs
|
|
||||||
* - Once that's done, replace wine_marshal_id with STDOBJREF
|
* - Once that's done, replace wine_marshal_id with STDOBJREF
|
||||||
*
|
*
|
||||||
* - Rewrite the CoLockObjectExternal code, it does totally the wrong
|
* - Rewrite the CoLockObjectExternal code, it does totally the wrong
|
||||||
* thing currently (should be controlling the stub manager)
|
* thing currently (should be controlling the stub manager)
|
||||||
*
|
*
|
||||||
* - Make the MTA dynamically allocated and refcounted
|
|
||||||
* - Free the ReservedForOle data in DllMain(THREAD_DETACH)
|
* - Free the ReservedForOle data in DllMain(THREAD_DETACH)
|
||||||
*
|
*
|
||||||
* - Implement the service control manager (in rpcss) to keep track
|
* - Implement the service control manager (in rpcss) to keep track
|
||||||
|
@ -106,8 +104,8 @@ static void COM_ExternalLockFreeList(void);
|
||||||
|
|
||||||
const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
|
const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
|
||||||
|
|
||||||
APARTMENT MTA;
|
APARTMENT *MTA; /* protected by csApartment */
|
||||||
static struct list apts = LIST_INIT( apts );
|
static struct list apts = LIST_INIT( apts ); /* protected by csApartment */
|
||||||
|
|
||||||
static CRITICAL_SECTION csApartment;
|
static CRITICAL_SECTION csApartment;
|
||||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||||
|
@ -217,50 +215,29 @@ void COMPOBJ_UninitProcess( void )
|
||||||
* Manage apartments.
|
* Manage apartments.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* creates an apartment structure which stores OLE apartment-local
|
||||||
/* The multi-threaded apartment (MTA) contains zero or more threads interacting
|
* information */
|
||||||
with free threaded (ie thread safe) COM objects. There is only ever one MTA
|
|
||||||
in a process - you can enter it by calling CoInitializeEx(COINIT_MULTITHREADED)
|
|
||||||
*/
|
|
||||||
static void COM_InitMTA(void)
|
|
||||||
{
|
|
||||||
/* OXIDs are object exporter IDs. Each apartment has an OXID, which is unique
|
|
||||||
within a network. That is, two different MTAs on different machines will have
|
|
||||||
different OXIDs.
|
|
||||||
|
|
||||||
This method of generating an OXID is therefore wrong as it doesn't work across
|
|
||||||
a network, but for local RPC only it's OK. We can distinguish between MTAs and
|
|
||||||
STAs because STAs use the thread ID as well, and no thread can have an ID of zero.
|
|
||||||
|
|
||||||
The algorithm Microsoft use is currently unknown.
|
|
||||||
*/
|
|
||||||
MTA.oxid = ((OXID)GetCurrentProcessId() << 32);
|
|
||||||
InitializeCriticalSection(&MTA.cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void COM_UninitMTA(void)
|
|
||||||
{
|
|
||||||
DeleteCriticalSection(&MTA.cs);
|
|
||||||
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
|
|
||||||
* with COINIT_UNINITIALIZED if the apartment has already been initialized
|
|
||||||
* with a different COINIT value */
|
|
||||||
APARTMENT* COM_CreateApartment(DWORD model)
|
APARTMENT* COM_CreateApartment(DWORD model)
|
||||||
{
|
{
|
||||||
APARTMENT *apt = COM_CurrentApt();
|
APARTMENT *apt = COM_CurrentApt();
|
||||||
|
|
||||||
if (!apt)
|
if (!apt)
|
||||||
{
|
{
|
||||||
if (!(model & COINIT_APARTMENTTHREADED)) /* See note 1 above */
|
/* The multi-threaded apartment (MTA) contains zero or more threads interacting
|
||||||
|
* with free threaded (ie thread safe) COM objects. There is only ever one MTA
|
||||||
|
* in a process
|
||||||
|
*/
|
||||||
|
EnterCriticalSection(&csApartment);
|
||||||
|
if (!(model & COINIT_APARTMENTTHREADED) && MTA) /* See note 1 above */
|
||||||
{
|
{
|
||||||
TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId());
|
TRACE("entering the multithreaded apartment %s\n", wine_dbgstr_longlong(MTA->oxid));
|
||||||
COM_CurrentInfo()->apt = &MTA;
|
apt = MTA;
|
||||||
return COM_CurrentInfo()->apt;
|
COM_ApartmentAddRef(apt);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&csApartment);
|
||||||
|
|
||||||
|
COM_CurrentInfo()->apt = apt;
|
||||||
|
return apt;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("creating new apartment, model=%ld\n", model);
|
TRACE("creating new apartment, model=%ld\n", model);
|
||||||
|
@ -279,19 +256,23 @@ APARTMENT* COM_CreateApartment(DWORD model)
|
||||||
|
|
||||||
apt->model = model;
|
apt->model = model;
|
||||||
|
|
||||||
/* we don't ref the apartment as CoInitializeEx will do it for us */
|
|
||||||
|
|
||||||
if (model & COINIT_APARTMENTTHREADED)
|
if (model & COINIT_APARTMENTTHREADED)
|
||||||
{
|
{
|
||||||
/* FIXME: how does windoze create OXIDs? */
|
/* FIXME: should be randomly generated by in an RPC call to rpcss */
|
||||||
apt->oxid = MTA.oxid | GetCurrentThreadId();
|
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
|
||||||
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
|
|
||||||
apt->win = CreateWindowA(aptWinClass, NULL, 0,
|
apt->win = CreateWindowA(aptWinClass, NULL, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, OLE32_hInstance, NULL);
|
0, 0, OLE32_hInstance, NULL);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: should be randomly generated by in an RPC call to rpcss */
|
||||||
|
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
|
||||||
|
MTA = apt;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
|
||||||
|
|
||||||
EnterCriticalSection(&csApartment);
|
|
||||||
list_add_head(&apts, &apt->entry);
|
list_add_head(&apts, &apt->entry);
|
||||||
LeaveCriticalSection(&csApartment);
|
LeaveCriticalSection(&csApartment);
|
||||||
|
|
||||||
|
@ -310,15 +291,22 @@ DWORD COM_ApartmentRelease(struct apartment *apt)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
EnterCriticalSection(&csApartment);
|
||||||
|
|
||||||
ret = InterlockedDecrement(&apt->refs);
|
ret = InterlockedDecrement(&apt->refs);
|
||||||
|
/* destruction stuff that needs to happen under csApartment CS */
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
if (apt == MTA) MTA = NULL;
|
||||||
|
list_remove(&apt->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&csApartment);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
|
TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
|
||||||
|
|
||||||
EnterCriticalSection(&csApartment);
|
|
||||||
list_remove(&apt->entry);
|
|
||||||
LeaveCriticalSection(&csApartment);
|
|
||||||
|
|
||||||
MARSHAL_Disconnect_Proxies(apt);
|
MARSHAL_Disconnect_Proxies(apt);
|
||||||
|
|
||||||
if (apt->win) DestroyWindow(apt->win);
|
if (apt->win) DestroyWindow(apt->win);
|
||||||
|
@ -330,12 +318,9 @@ DWORD COM_ApartmentRelease(struct apartment *apt)
|
||||||
|
|
||||||
if (apt->filter) IUnknown_Release(apt->filter);
|
if (apt->filter) IUnknown_Release(apt->filter);
|
||||||
|
|
||||||
|
|
||||||
DeleteCriticalSection(&apt->cs);
|
DeleteCriticalSection(&apt->cs);
|
||||||
CloseHandle(apt->thread);
|
CloseHandle(apt->thread);
|
||||||
HeapFree(GetProcessHeap(), 0, apt);
|
HeapFree(GetProcessHeap(), 0, apt);
|
||||||
|
|
||||||
apt = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -541,8 +526,6 @@ HRESULT WINAPI CoInitializeEx(
|
||||||
*/
|
*/
|
||||||
TRACE("() - Initializing the COM libraries\n");
|
TRACE("() - Initializing the COM libraries\n");
|
||||||
|
|
||||||
COM_InitMTA();
|
|
||||||
|
|
||||||
/* we may need to defer this until after apartment initialisation */
|
/* we may need to defer this until after apartment initialisation */
|
||||||
RunningObjectTableImpl_Initialize();
|
RunningObjectTableImpl_Initialize();
|
||||||
}
|
}
|
||||||
|
@ -653,8 +636,6 @@ void WINAPI CoUninitialize(void)
|
||||||
|
|
||||||
/* This ensures we deal with any pending RPCs */
|
/* This ensures we deal with any pending RPCs */
|
||||||
COM_FlushMessageQueue();
|
COM_FlushMessageQueue();
|
||||||
|
|
||||||
COM_UninitMTA();
|
|
||||||
}
|
}
|
||||||
else if (lCOMRefCnt<1) {
|
else if (lCOMRefCnt<1) {
|
||||||
ERR( "CoUninitialize() - not CoInitialized.\n" );
|
ERR( "CoUninitialize() - not CoInitialized.\n" );
|
||||||
|
|
Loading…
Reference in New Issue