diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index a920b9c..ad8795a 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3353,10 +3353,71 @@ HRESULT WINAPI CoCopyProxy(IUnknown *pProxy, IUnknown **ppCopy) */ HRESULT WINAPI CoGetCallContext(REFIID riid, void **ppv) { - FIXME("(%s, %p): stub\n", debugstr_guid(riid), ppv); + struct oletls * info; + HRESULT hr; - *ppv = NULL; - return E_NOINTERFACE; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); + if( !ppv) + return E_INVALIDARG; + + /* get COM tls */ + info = COM_CurrentInfo(); + if( !info) + return E_OUTOFMEMORY; + + hr = RPC_E_CALL_COMPLETE; + if( info->ctx_call) + { + hr = IUnknown_QueryInterface( info->ctx_call, riid, ppv); + } + + if (FAILED(hr)) + { + ERR("call context QI(%p), hr=0x%08x\n", info->ctx_call, hr); + *ppv = NULL; + return hr; + } + + TRACE("call context QI(%p) -> %p\n", info->ctx_call, *ppv); + return hr; +} + +/*********************************************************************** + * CoSwitchCallContext [OLE32.@] + * + * Switches the call context object used by CoGetCallContext. + * + * PARAMS + * pNewObject [I] A pointer to an interface on the new call context object. + * ppOldObject [O] Address of pointer variable that receives a pointer to the + * call context object of the call currently in progress + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + */ +HRESULT WINAPI CoSwitchCallContext(IUnknown *pNewObject,IUnknown **ppOldObject) +{ + struct oletls * info; + + TRACE("(%p)\n", pNewObject); + + /* get COM tls */ + info = COM_CurrentInfo(); + if( !info) + return E_OUTOFMEMORY; + + /* Receives a pointer to the call context object of the call currently + in progress. This value is returned so that the original call context + can be restored by the custom marshaller. + The returned pointer will be NULL if there was no call in progress. */ + *ppOldObject = info->ctx_call; + + /* It may be NULL if you are calling CoSwitchCallContext to switch back + to the original call context and there was no original call context. */ + info->ctx_call = pNewObject; + + return S_OK; } /*********************************************************************** diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 4b88ad2..505036d 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -181,6 +181,7 @@ struct oletls GUID causality_id; /* unique identifier for each COM call */ LONG pending_call_count_client; /* number of client calls pending */ LONG pending_call_count_server; /* number of server calls pending */ + IUnknown *ctx_call; /* call context */ }; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 79376ac..b9a795c 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -73,7 +73,7 @@ @ stdcall CoSetProxyBlanket(ptr long long wstr long long ptr long) @ stdcall CoSetState(ptr) @ stdcall CoSuspendClassObjects() -@ stub CoSwitchCallContext +@ stdcall CoSwitchCallContext(ptr ptr) @ stdcall CoTaskMemAlloc(long) @ stdcall CoTaskMemFree(ptr) @ stdcall CoTaskMemRealloc(ptr long)