ole32: Add CoGetCallContext and CoSwitchCallContext implementations.
This commit is contained in:
parent
80e71e63f2
commit
a06f568a2a
|
@ -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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue