Andrey Turkin : ole32: Add CoGetCallContext and CoSwitchCallContext implementations.

Alexandre Julliard julliard at winehq.org
Mon Jan 19 08:59:06 CST 2009


Module: wine
Branch: master
Commit: a06f568a2a356a979c9371930023c1032e34e9b8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a06f568a2a356a979c9371930023c1032e34e9b8

Author: Andrey Turkin <andrey.turkin at gmail.com>
Date:   Sun Jan 18 17:17:45 2009 +0300

ole32: Add CoGetCallContext and CoSwitchCallContext implementations.

---

 dlls/ole32/compobj.c         |   42 ++++++++++++++++-
 dlls/ole32/compobj_private.h |    1 +
 dlls/ole32/ole32.spec        |    2 +-
 dlls/ole32/tests/compobj.c   |  103 ++++++++++++++++++++++++++++++++++++++++++
 include/objbase.h            |    1 +
 5 files changed, 145 insertions(+), 4 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 9501473..b291db4 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -3352,10 +3352,46 @@ 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 = COM_CurrentInfo();
 
-    *ppv = NULL;
-    return E_NOINTERFACE;
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+
+    if (!info)
+        return E_OUTOFMEMORY;
+
+    if (!info->call_state)
+        return RPC_E_CALL_COMPLETE;
+
+    return IUnknown_QueryInterface(info->call_state, riid, ppv);
+}
+
+/***********************************************************************
+ *           CoSwitchCallContext [OLE32.@]
+ *
+ * Switches the context of the currently executing server call in the current
+ * thread.
+ *
+ * PARAMS
+ *  pObject     [I] Pointer to new context object
+ *  ppOldObject [O] Pointer to memory that will receive old context object pointer
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: HRESULT code.
+ */
+HRESULT WINAPI CoSwitchCallContext(IUnknown *pObject, IUnknown **ppOldObject)
+{
+    struct oletls *info = COM_CurrentInfo();
+
+    TRACE("(%p, %p)\n", pObject, ppOldObject);
+
+    if (!info)
+        return E_OUTOFMEMORY;
+
+    *ppOldObject = info->call_state;
+    info->call_state = pObject; /* CoSwitchCallContext does not addref nor release objects */
+
+    return S_OK;
 }
 
 /***********************************************************************
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 3c3e96d..8f2cc2c 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        *call_state;   /* current call context */
 };
 
 
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index 49ff1d3..7d69bd8 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)
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index 63891b7..046b91a 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -37,6 +37,7 @@
 /* functions that are not present on all versions of Windows */
 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
 HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
+HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
 
 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
@@ -1039,6 +1040,106 @@ static void test_CoGetObjectContext(void)
     CoUninitialize();
 }
 
+typedef struct {
+    const IUnknownVtbl *lpVtbl;
+    LONG refs;
+} Test_CallContext;
+
+static HRESULT WINAPI Test_CallContext_QueryInterface(
+    IUnknown *iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown))
+    {
+        *ppvObj = iface;
+        IUnknown_AddRef(iface);
+        return S_OK;
+    }
+
+    *ppvObj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
+{
+    Test_CallContext *This = (Test_CallContext*)iface;
+    return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
+{
+    Test_CallContext *This = (Test_CallContext*)iface;
+    ULONG refs = InterlockedDecrement(&This->refs);
+    if (!refs)
+        HeapFree(GetProcessHeap(), 0, This);
+    return refs;
+}
+
+static const IUnknownVtbl TestCallContext_Vtbl =
+{
+    Test_CallContext_QueryInterface,
+    Test_CallContext_AddRef,
+    Test_CallContext_Release
+};
+
+static void test_CoGetCallContext(void)
+{
+    HRESULT hr;
+    ULONG refs;
+    IUnknown *pUnk;
+    IUnknown *test_object;
+
+    if (!pCoSwitchCallContext)
+    {
+        skip("CoSwitchCallContext not present\n");
+        return;
+    }
+
+    CoInitialize(NULL);
+
+    test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
+    ((Test_CallContext*)test_object)->lpVtbl = &TestCallContext_Vtbl;
+    ((Test_CallContext*)test_object)->refs = 1;
+
+    hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
+    ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
+
+    pUnk = (IUnknown*)0xdeadbeef;
+    hr = pCoSwitchCallContext(test_object, &pUnk);
+    ok_ole_success(hr, "CoSwitchCallContext");
+    ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
+    refs = IUnknown_AddRef(test_object);
+    ok(refs == 2, "Expected refcount 2, got %d\n", refs);
+    IUnknown_Release(test_object);
+
+    pUnk = (IUnknown*)0xdeadbeef;
+    hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
+    ok_ole_success(hr, "CoGetCallContext");
+    ok(pUnk == test_object, "expected %p, got %p\n", test_object, pUnk);
+    refs = IUnknown_AddRef(test_object);
+    ok(refs == 3, "Expected refcount 3, got %d\n", refs);
+    IUnknown_Release(test_object);
+    IUnknown_Release(pUnk);
+
+    pUnk = (IUnknown*)0xdeadbeef;
+    hr = pCoSwitchCallContext(NULL, &pUnk);
+    ok_ole_success(hr, "CoSwitchCallContext");
+    ok(pUnk == test_object, "expected %p, got %p\n", test_object, pUnk);
+    refs = IUnknown_AddRef(test_object);
+    ok(refs == 2, "Expected refcount 2, got %d\n", refs);
+    IUnknown_Release(test_object);
+
+    hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
+    ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
+
+    IUnknown_Release(test_object);
+
+    CoUninitialize();
+}
+
 static void test_CoInitializeEx(void)
 {
     HRESULT hr;
@@ -1064,6 +1165,7 @@ START_TEST(compobj)
 {
     HMODULE hOle32 = GetModuleHandle("ole32");
     pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
+    pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
     {
         trace("You need DCOM95 installed to run this test\n");
@@ -1088,5 +1190,6 @@ START_TEST(compobj)
     test_registered_object_thread_affinity();
     test_CoFreeUnusedLibraries();
     test_CoGetObjectContext();
+    test_CoGetCallContext();
     test_CoInitializeEx();
 }
diff --git a/include/objbase.h b/include/objbase.h
index 9f606c0..7e72fad 100644
--- a/include/objbase.h
+++ b/include/objbase.h
@@ -391,6 +391,7 @@ BOOL WINAPI CoIsHandlerConnected(LPUNKNOWN pUnk);
 /* security */
 HRESULT WINAPI CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc, SOLE_AUTHENTICATION_SERVICE* asAuthSvc, void* pReserved1, DWORD dwAuthnLevel, DWORD dwImpLevel, void* pReserved2, DWORD dwCapabilities, void* pReserved3);
 HRESULT WINAPI CoGetCallContext(REFIID riid, void** ppInterface);
+HRESULT WINAPI CoSwitchCallContext(IUnknown *pContext, IUnknown **ppOldContext);
 HRESULT WINAPI CoQueryAuthenticationServices(DWORD* pcAuthSvc, SOLE_AUTHENTICATION_SERVICE** asAuthSvc);
 
 HRESULT WINAPI CoQueryProxyBlanket(IUnknown* pProxy, DWORD* pwAuthnSvc, DWORD* pAuthzSvc, OLECHAR** pServerPrincName, DWORD* pAuthnLevel, DWORD* pImpLevel, RPC_AUTH_IDENTITY_HANDLE* pAuthInfo, DWORD* pCapabilities);




More information about the wine-cvs mailing list