Robert Shearman : ole32:
CoGetClassObject should host a single-threaded object in a
Alexandre Julliard
julliard at wine.codeweavers.com
Sat Aug 26 13:47:40 CDT 2006
Module: wine
Branch: master
Commit: 619ba90dbecaca7b4bc360b38bd7ba45f5b82546
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=619ba90dbecaca7b4bc360b38bd7ba45f5b82546
Author: Robert Shearman <rob at codeweavers.com>
Date: Sat Aug 26 11:42:40 2006 +0100
ole32: CoGetClassObject should host a single-threaded object in a
single-threaded apartment if executing in a multi-threaded apartment,
if one exists.
---
dlls/ole32/compobj.c | 77 +++++++++++++++++++++++++++++++++++++++++-
dlls/ole32/compobj_private.h | 1 +
2 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 1f13fd0..51e942b 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -82,6 +82,7 @@ #define ARRAYSIZE(array) (sizeof(array)/
static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN* ppUnk);
static void COM_RevokeAllClasses(void);
+static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv);
static APARTMENT *MTA; /* protected by csApartment */
static struct list apts = LIST_INIT( apts ); /* protected by csApartment */
@@ -427,6 +428,57 @@ APARTMENT *apartment_findfromtid(DWORD t
return result;
}
+/* gets an apartment which has a given type. The caller must
+ * release the reference from the apartment as soon as the apartment pointer
+ * is no longer required. */
+static APARTMENT *apartment_findfromtype(BOOL multi_threaded)
+{
+ APARTMENT *result = NULL;
+ struct apartment *apt;
+
+ EnterCriticalSection(&csApartment);
+ LIST_FOR_EACH_ENTRY( apt, &apts, struct apartment, entry )
+ {
+ if (apt->multi_threaded == multi_threaded)
+ {
+ result = apt;
+ apartment_addref(result);
+ break;
+ }
+ }
+ LeaveCriticalSection(&csApartment);
+
+ return result;
+}
+
+struct host_object_params
+{
+ HKEY hkeydll;
+ CLSID clsid; /* clsid of object to marshal */
+ IID iid; /* interface to marshal */
+ IStream *stream; /* stream that the object will be marshaled into */
+};
+
+static HRESULT apartment_hostobject(const struct host_object_params *params)
+{
+ IUnknown *object;
+ HRESULT hr;
+ static const LARGE_INTEGER llZero;
+
+ TRACE("\n");
+
+ hr = get_inproc_class_object(params->hkeydll, ¶ms->clsid, ¶ms->iid, (void **)&object);
+ if (FAILED(hr))
+ return hr;
+
+ hr = CoMarshalInterface(params->stream, ¶ms->iid, object, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ if (FAILED(hr))
+ IUnknown_Release(object);
+ IStream_Seek(params->stream, llZero, STREAM_SEEK_SET, NULL);
+
+ return hr;
+}
+
static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
@@ -434,6 +486,8 @@ static LRESULT CALLBACK apartment_wndpro
case DM_EXECUTERPC:
RPC_ExecuteCall((struct dispatch_params *)lParam);
return 0;
+ case DM_HOSTOBJECT:
+ return apartment_hostobject((const struct host_object_params *)lParam);
default:
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
@@ -1658,8 +1712,27 @@ static HRESULT get_inproc_class_object(H
APARTMENT *apt = COM_CurrentApt();
if (apt->multi_threaded)
{
- FIXME("should create object %s in single-threaded apartment\n",
- debugstr_guid(rclsid));
+ /* try to find an STA */
+ APARTMENT *host_apt = apartment_findfromtype(FALSE);
+ if (!host_apt)
+ FIXME("create a host apartment for apartment-threaded object %s\n", debugstr_guid(rclsid));
+ if (host_apt)
+ {
+ struct host_object_params params;
+ HWND hwnd = apartment_getwindow(host_apt);
+
+ params.hkeydll = hkeydll;
+ params.clsid = *rclsid;
+ params.iid = *riid;
+ hr = CreateStreamOnHGlobal(NULL, TRUE, ¶ms.stream);
+ if (FAILED(hr))
+ return hr;
+ hr = SendMessageW(hwnd, DM_HOSTOBJECT, 0, (LPARAM)¶ms);
+ if (SUCCEEDED(hr))
+ hr = CoUnmarshalInterface(params.stream, riid, ppv);
+ IStream_Release(params.stream);
+ return hr;
+ }
}
}
/* "Free" */
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 4d27bab..ac9243c 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -246,6 +246,7 @@ void apartment_joinmta(void);
/* DCOM messages used by the apartment window (not compatible with native) */
#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */
+#define DM_HOSTOBJECT (WM_USER + 1) /* WPARAM = 0, LPARAM = (struct host_object_params *) */
/*
* Per-thread values are stored in the TEB on offset 0xF80,
More information about the wine-cvs
mailing list