- 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)
|
||||
*
|
||||
* - Switch wine_marshal_id to use IPIDs not IIDs
|
||||
* - Once that's done, replace wine_marshal_id with STDOBJREF
|
||||
*
|
||||
* - Rewrite the CoLockObjectExternal code, it does totally the wrong
|
||||
* thing currently (should be controlling the stub manager)
|
||||
*
|
||||
* - Make the MTA dynamically allocated and refcounted
|
||||
* - Free the ReservedForOle data in DllMain(THREAD_DETACH)
|
||||
*
|
||||
* - 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} };
|
||||
|
||||
APARTMENT MTA;
|
||||
static struct list apts = LIST_INIT( apts );
|
||||
APARTMENT *MTA; /* protected by csApartment */
|
||||
static struct list apts = LIST_INIT( apts ); /* protected by csApartment */
|
||||
|
||||
static CRITICAL_SECTION csApartment;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
|
@ -217,50 +215,29 @@ void COMPOBJ_UninitProcess( void )
|
|||
* Manage apartments.
|
||||
*/
|
||||
|
||||
|
||||
/* 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 - 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 */
|
||||
/* creates an apartment structure which stores OLE apartment-local
|
||||
* information */
|
||||
APARTMENT* COM_CreateApartment(DWORD model)
|
||||
{
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
|
||||
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());
|
||||
COM_CurrentInfo()->apt = &MTA;
|
||||
return COM_CurrentInfo()->apt;
|
||||
TRACE("entering the multithreaded apartment %s\n", wine_dbgstr_longlong(MTA->oxid));
|
||||
apt = MTA;
|
||||
COM_ApartmentAddRef(apt);
|
||||
|
||||
LeaveCriticalSection(&csApartment);
|
||||
|
||||
COM_CurrentInfo()->apt = apt;
|
||||
return apt;
|
||||
}
|
||||
|
||||
TRACE("creating new apartment, model=%ld\n", model);
|
||||
|
@ -279,19 +256,23 @@ APARTMENT* COM_CreateApartment(DWORD model)
|
|||
|
||||
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();
|
||||
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
|
||||
/* FIXME: should be randomly generated by in an RPC call to rpcss */
|
||||
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
|
||||
apt->win = CreateWindowA(aptWinClass, NULL, 0,
|
||||
0, 0, 0, 0,
|
||||
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);
|
||||
LeaveCriticalSection(&csApartment);
|
||||
|
||||
|
@ -310,15 +291,22 @@ DWORD COM_ApartmentRelease(struct apartment *apt)
|
|||
{
|
||||
DWORD ret;
|
||||
|
||||
EnterCriticalSection(&csApartment);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (apt->win) DestroyWindow(apt->win);
|
||||
|
@ -330,12 +318,9 @@ DWORD COM_ApartmentRelease(struct apartment *apt)
|
|||
|
||||
if (apt->filter) IUnknown_Release(apt->filter);
|
||||
|
||||
|
||||
DeleteCriticalSection(&apt->cs);
|
||||
CloseHandle(apt->thread);
|
||||
HeapFree(GetProcessHeap(), 0, apt);
|
||||
|
||||
apt = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -541,8 +526,6 @@ HRESULT WINAPI CoInitializeEx(
|
|||
*/
|
||||
TRACE("() - Initializing the COM libraries\n");
|
||||
|
||||
COM_InitMTA();
|
||||
|
||||
/* we may need to defer this until after apartment initialisation */
|
||||
RunningObjectTableImpl_Initialize();
|
||||
}
|
||||
|
@ -653,8 +636,6 @@ void WINAPI CoUninitialize(void)
|
|||
|
||||
/* This ensures we deal with any pending RPCs */
|
||||
COM_FlushMessageQueue();
|
||||
|
||||
COM_UninitMTA();
|
||||
}
|
||||
else if (lCOMRefCnt<1) {
|
||||
ERR( "CoUninitialize() - not CoInitialized.\n" );
|
||||
|
|
Loading…
Reference in New Issue