ole32: Use existing MTA in CoGetClassObject and CoCreateInstance.

Custom actions in the CS3 installer depend on this.
This commit is contained in:
Hans Leidekker 2009-05-05 12:49:17 +02:00 committed by Alexandre Julliard
parent d2820c0684
commit bd4975acb0
2 changed files with 52 additions and 8 deletions

View File

@ -493,6 +493,31 @@ static APARTMENT *apartment_findmain(void)
return result; return result;
} }
/* gets the multi-threaded apartment if it exists. The caller must
* release the reference from the apartment as soon as the apartment pointer
* is no longer required. */
static APARTMENT *apartment_find_multi_threaded(void)
{
APARTMENT *result = NULL;
struct list *cursor;
EnterCriticalSection(&csApartment);
LIST_FOR_EACH( cursor, &apts )
{
struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
if (apt->multi_threaded)
{
result = apt;
apartment_addref(result);
break;
}
}
LeaveCriticalSection(&csApartment);
return result;
}
struct host_object_params struct host_object_params
{ {
HKEY hkeydll; HKEY hkeydll;
@ -2237,6 +2262,7 @@ HRESULT WINAPI CoGetClassObject(
LPUNKNOWN regClassObject; LPUNKNOWN regClassObject;
HRESULT hres = E_UNEXPECTED; HRESULT hres = E_UNEXPECTED;
APARTMENT *apt; APARTMENT *apt;
BOOL release_apt = FALSE;
TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid));
@ -2245,12 +2271,15 @@ HRESULT WINAPI CoGetClassObject(
*ppv = NULL; *ppv = NULL;
apt = COM_CurrentApt(); if (!(apt = COM_CurrentApt()))
if (!apt) {
if (!(apt = apartment_find_multi_threaded()))
{ {
ERR("apartment not initialised\n"); ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED; return CO_E_NOTINITIALIZED;
} }
release_apt = TRUE;
}
if (pServerInfo) { if (pServerInfo) {
FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName)); FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
@ -2273,7 +2302,7 @@ HRESULT WINAPI CoGetClassObject(
* is good since we are not returning it in the "out" parameter. * is good since we are not returning it in the "out" parameter.
*/ */
IUnknown_Release(regClassObject); IUnknown_Release(regClassObject);
if (release_apt) apartment_release(apt);
return hres; return hres;
} }
@ -2284,7 +2313,10 @@ HRESULT WINAPI CoGetClassObject(
HKEY hkey; HKEY hkey;
if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler)) if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler))
{
if (release_apt) apartment_release(apt);
return FTMarshalCF_Create(iid, ppv); return FTMarshalCF_Create(iid, ppv);
}
hres = COM_OpenKeyForCLSID(rclsid, wszInprocServer32, KEY_READ, &hkey); hres = COM_OpenKeyForCLSID(rclsid, wszInprocServer32, KEY_READ, &hkey);
if (FAILED(hres)) if (FAILED(hres))
@ -2308,8 +2340,11 @@ HRESULT WINAPI CoGetClassObject(
/* return if we got a class, otherwise fall through to one of the /* return if we got a class, otherwise fall through to one of the
* other types */ * other types */
if (SUCCEEDED(hres)) if (SUCCEEDED(hres))
{
if (release_apt) apartment_release(apt);
return hres; return hres;
} }
}
/* Next try in-process handler */ /* Next try in-process handler */
if (CLSCTX_INPROC_HANDLER & dwClsContext) if (CLSCTX_INPROC_HANDLER & dwClsContext)
@ -2339,8 +2374,12 @@ HRESULT WINAPI CoGetClassObject(
/* return if we got a class, otherwise fall through to one of the /* return if we got a class, otherwise fall through to one of the
* other types */ * other types */
if (SUCCEEDED(hres)) if (SUCCEEDED(hres))
{
if (release_apt) apartment_release(apt);
return hres; return hres;
} }
}
if (release_apt) apartment_release(apt);
/* Next try out of process */ /* Next try out of process */
if (CLSCTX_LOCAL_SERVER & dwClsContext) if (CLSCTX_LOCAL_SERVER & dwClsContext)
@ -2418,6 +2457,7 @@ HRESULT WINAPI CoCreateInstance(
{ {
HRESULT hres; HRESULT hres;
LPCLASSFACTORY lpclf = 0; LPCLASSFACTORY lpclf = 0;
APARTMENT *apt;
TRACE("(rclsid=%s, pUnkOuter=%p, dwClsContext=%08x, riid=%s, ppv=%p)\n", debugstr_guid(rclsid), TRACE("(rclsid=%s, pUnkOuter=%p, dwClsContext=%08x, riid=%s, ppv=%p)\n", debugstr_guid(rclsid),
pUnkOuter, dwClsContext, debugstr_guid(iid), ppv); pUnkOuter, dwClsContext, debugstr_guid(iid), ppv);
@ -2433,11 +2473,15 @@ HRESULT WINAPI CoCreateInstance(
*/ */
*ppv = 0; *ppv = 0;
if (!COM_CurrentApt()) if (!(apt = COM_CurrentApt()))
{
if (!(apt = apartment_find_multi_threaded()))
{ {
ERR("apartment not initialised\n"); ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED; return CO_E_NOTINITIALIZED;
} }
apartment_release(apt);
}
/* /*
* The Standard Global Interface Table (GIT) object is a process-wide singleton. * The Standard Global Interface Table (GIT) object is a process-wide singleton.

View File

@ -276,7 +276,7 @@ static void test_CoCreateInstance(void)
pUnk = (IUnknown *)0xdeadbeef; pUnk = (IUnknown *)0xdeadbeef;
hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk); hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
todo_wine ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr); ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
if (pUnk) IUnknown_Release(pUnk); if (pUnk) IUnknown_Release(pUnk);
SetEvent(info.stop); SetEvent(info.stop);
@ -325,7 +325,7 @@ static void test_CoGetClassObject(void)
pUnk = (IUnknown *)0xdeadbeef; pUnk = (IUnknown *)0xdeadbeef;
hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk); hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
todo_wine ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr); ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
if (pUnk) IUnknown_Release(pUnk); if (pUnk) IUnknown_Release(pUnk);
SetEvent(info.stop); SetEvent(info.stop);