Commit dd8a736c authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: The identity functions can be used from apartments other than the one the…

ole32: The identity functions can be used from apartments other than the one the proxy was unmarshaled into. In this case, don't use the cached This->remunk and don't cache the unmarshaled object in This->remunk.
parent bf2b49b4
......@@ -298,7 +298,7 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL
ULONG index = mapping[i];
HRESULT hrobj = qiresults[i].hResult;
if (hrobj == S_OK)
hrobj = unmarshal_object(&qiresults[i].std, This->parent,
hrobj = unmarshal_object(&qiresults[i].std, COM_CurrentApt(),
This->dest_context,
This->dest_context_data,
pMQIs[index].pIID, &This->oxid_info,
......@@ -964,14 +964,25 @@ static void proxy_manager_disconnect(struct proxy_manager * This)
static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnknown **remunk)
{
HRESULT hr = S_OK;
struct apartment *apt;
BOOL called_in_original_apt;
/* we don't want to try and unmarshal or use IRemUnknown if we don't want
* lifetime management */
if (This->sorflags & SORFP_NOLIFETIMEMGMT)
return S_FALSE;
apt = COM_CurrentApt();
if (!apt)
return CO_E_NOTINITIALIZED;
called_in_original_apt = This->parent && (This->parent->oxid == apt->oxid);
EnterCriticalSection(&This->cs);
if (This->remunk)
/* only return the cached object if called from the original apartment.
* in future, we might want to make the IRemUnknown proxy callable from any
* apartment to avoid these checks */
if (This->remunk && called_in_original_apt)
{
/* already created - return existing object */
*remunk = This->remunk;
......@@ -994,10 +1005,10 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
stdobjref.ipid = This->oxid_info.ipidRemUnknown;
/* do the unmarshal */
hr = unmarshal_object(&stdobjref, This->parent, This->dest_context,
hr = unmarshal_object(&stdobjref, COM_CurrentApt(), This->dest_context,
This->dest_context_data, &IID_IRemUnknown,
&This->oxid_info, (void**)remunk);
if (hr == S_OK)
if (hr == S_OK && called_in_original_apt)
{
This->remunk = *remunk;
IRemUnknown_AddRef(This->remunk);
......
......@@ -1283,6 +1283,24 @@ static DWORD CALLBACK bad_thread_proc(LPVOID p)
HRESULT hr;
IUnknown * proxy = NULL;
hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
todo_wine
ok(hr == CO_E_NOTINITIALIZED,
"COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
hr);
hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
/* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
if (SUCCEEDED(hr))
IUnknown_Release(proxy);
hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
/* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
if (SUCCEEDED(hr))
IUnknown_Release(proxy);
pCoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
......@@ -1291,6 +1309,19 @@ static DWORD CALLBACK bad_thread_proc(LPVOID p)
"COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
hr);
hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
/* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
/* this statement causes Win9x DCOM to crash during CoUninitialize of
* other apartment, so don't test this on Win9x (signified by NT-only
* export of CoRegisterSurrogateEx) */
if (GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
/* now be really bad and release the proxy from the wrong apartment */
IUnknown_Release(cf);
else
skip("skipping test for releasing proxy from wrong apartment that will succeed, but cause a crash during CoUninitialize\n");
CoUninitialize();
return 0;
......@@ -1321,13 +1352,18 @@ static void test_proxy_used_in_wrong_thread(void)
ok_more_than_one_lock();
/* do a call that will fail, but result in IRemUnknown being used by the proxy */
IClassFactory_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
/* create a thread that we can misbehave in */
thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
IUnknown_Release(pProxy);
/* do release statement on Win9x that we should have done above */
if (!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
IUnknown_Release(pProxy);
ok_no_locks();
......
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