Commit a37a5014 authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

ole: Change the Apartment Model field to a boolean.

Change the apartment model field to a boolean that just specifies whether the apartment is multi-threaded or not and fix up all the places where this is used. Fixes a bug where we would return an error if the previous apartment model passed into CoInitializeEx matches the new apartment model, but additional optimisation flags are specified.
parent 021a125d
...@@ -229,17 +229,17 @@ static APARTMENT *apartment_construct(DWORD model) ...@@ -229,17 +229,17 @@ static APARTMENT *apartment_construct(DWORD model)
InitializeCriticalSection(&apt->cs); InitializeCriticalSection(&apt->cs);
DEBUG_SET_CRITSEC_NAME(&apt->cs, "apartment"); DEBUG_SET_CRITSEC_NAME(&apt->cs, "apartment");
apt->model = model; apt->multi_threaded = !(model & COINIT_APARTMENTTHREADED);
if (model & COINIT_APARTMENTTHREADED) if (apt->multi_threaded)
{ {
/* FIXME: should be randomly generated by in an RPC call to rpcss */ /* FIXME: should be randomly generated by in an RPC call to rpcss */
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId(); apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
} }
else else
{ {
/* FIXME: should be randomly generated by in an RPC call to rpcss */ /* FIXME: should be randomly generated by in an RPC call to rpcss */
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe; apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
} }
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid)); TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
...@@ -292,6 +292,11 @@ static APARTMENT *apartment_get_or_create(DWORD model) ...@@ -292,6 +292,11 @@ static APARTMENT *apartment_get_or_create(DWORD model)
return apt; return apt;
} }
static inline BOOL apartment_is_model(APARTMENT *apt, DWORD model)
{
return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED));
}
DWORD apartment_addref(struct apartment *apt) DWORD apartment_addref(struct apartment *apt)
{ {
DWORD refs = InterlockedIncrement(&apt->refs); DWORD refs = InterlockedIncrement(&apt->refs);
...@@ -420,7 +425,7 @@ static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LP ...@@ -420,7 +425,7 @@ static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LP
HRESULT apartment_createwindowifneeded(struct apartment *apt) HRESULT apartment_createwindowifneeded(struct apartment *apt)
{ {
if (!(apt->model & COINIT_APARTMENTTHREADED)) if (apt->multi_threaded)
return S_OK; return S_OK;
if (!apt->win) if (!apt->win)
...@@ -443,7 +448,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt) ...@@ -443,7 +448,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt)
HWND apartment_getwindow(struct apartment *apt) HWND apartment_getwindow(struct apartment *apt)
{ {
assert(apt->model & COINIT_APARTMENTTHREADED); assert(!apt->multi_threaded);
return apt->win; return apt->win;
} }
...@@ -633,11 +638,13 @@ HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit) ...@@ -633,11 +638,13 @@ HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
apt = apartment_get_or_create(dwCoInit); apt = apartment_get_or_create(dwCoInit);
if (!apt) return E_OUTOFMEMORY; if (!apt) return E_OUTOFMEMORY;
} }
else if (dwCoInit != apt->model) else if (!apartment_is_model(apt, dwCoInit))
{ {
/* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
code then we are probably using the wrong threading model to implement that API. */ code then we are probably using the wrong threading model to implement that API. */
ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); ERR("Attempt to change threading model of this apartment from %s to %s\n",
apt->multi_threaded ? "multi-threaded" : "apartment threaded",
dwCoInit & COINIT_APARTMENTTHREADED ? "apartment threaded" : "multi-threaded");
return RPC_E_CHANGED_MODE; return RPC_E_CHANGED_MODE;
} }
else else
......
...@@ -132,10 +132,10 @@ struct proxy_manager ...@@ -132,10 +132,10 @@ struct proxy_manager
/* this needs to become a COM object that implements IRemUnknown */ /* this needs to become a COM object that implements IRemUnknown */
struct apartment struct apartment
{ {
struct list entry; struct list entry;
LONG refs; /* refcount of the apartment (LOCK) */ LONG refs; /* refcount of the apartment (LOCK) */
DWORD model; /* threading model (RO) */ BOOL multi_threaded; /* multi-threaded or single-threaded apartment? (RO) */
DWORD tid; /* thread id (RO) */ DWORD tid; /* thread id (RO) */
OXID oxid; /* object exporter ID (RO) */ OXID oxid; /* object exporter ID (RO) */
LONG ipidc; /* interface pointer ID counter, starts at 1 (LOCK) */ LONG ipidc; /* interface pointer ID counter, starts at 1 (LOCK) */
......
...@@ -277,7 +277,7 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac ...@@ -277,7 +277,7 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
RpcBindingInqObject(msg->Handle, &ipid); RpcBindingInqObject(msg->Handle, &ipid);
hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan); hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan);
if ((hr == S_OK) && (apt->model & COINIT_APARTMENTTHREADED)) if ((hr == S_OK) && !apt->multi_threaded)
{ {
params->handle = CreateEventW(NULL, FALSE, FALSE, NULL); params->handle = CreateEventW(NULL, FALSE, FALSE, NULL);
...@@ -536,7 +536,7 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg) ...@@ -536,7 +536,7 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
/* Note: this is the important difference between STAs and MTAs - we /* Note: this is the important difference between STAs and MTAs - we
* always execute RPCs to STAs in the thread that originally created the * always execute RPCs to STAs in the thread that originally created the
* apartment (i.e. the one that pumps messages to the window) */ * apartment (i.e. the one that pumps messages to the window) */
if (apt->model & COINIT_APARTMENTTHREADED) if (!apt->multi_threaded)
{ {
params->handle = CreateEventW(NULL, FALSE, FALSE, NULL); params->handle = CreateEventW(NULL, FALSE, FALSE, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment