ole32: Add CoGetCallContext and CoSwitchCallContext implementations.

oldstable
Andrey Turkin 2009-01-18 17:17:45 +03:00 committed by Alexandre Julliard
parent 80e71e63f2
commit a06f568a2a
5 changed files with 145 additions and 4 deletions

View File

@ -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;
}
/***********************************************************************

View File

@ -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 */
};

View File

@ -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)

View File

@ -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();
}

View File

@ -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);