Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322/* * PROJECT: ReactOS api tests * LICENSE: BSD - See COPYING.ARM in the top level directory * PURPOSE: Tests for IInitializeSpy * PROGRAMMERS: Mark Jansen */
#define WIN32_NO_STATUS#define _INC_WINDOWS#define COM_NO_WINDOWS_H
#include <stdio.h>#include <wine/test.h>
#include <winuser.h>#include <winreg.h>
#include <shlwapi.h>#include <unknownbase.h>
#define test_S_OK(hres, message) ok((hres) == S_OK, "%s (0x%lx instead of S_OK)\n", (message), (hres))#define test_HRES(hres, hresExpected, message) ok((hres) == (hresExpected), "%s (0x%lx instead of 0x%lx)\n", (message), (hres), (hresExpected))#define test_ref(spy, expectedRef) ok((spy)->GetRef() == (expectedRef), "unexpected refcount, %ld instead of %d\n", (spy)->GetRef(), (expectedRef))
typedef HRESULT (WINAPI *pCoRegisterInitializeSpy_t)(_In_ LPINITIALIZESPY pSpy, _Out_ ULARGE_INTEGER *puliCookie);typedef HRESULT (WINAPI *pCoRevokeInitializeSpy_t)(_In_ ULARGE_INTEGER uliCookie);pCoRegisterInitializeSpy_t pCoRegisterInitializeSpy;pCoRevokeInitializeSpy_t pCoRevokeInitializeSpy;
const DWORD INVALID_VALUE = 0xdeadbeef;
class CTestSpy : public CUnknownBase<IInitializeSpy>{public: HRESULT hr; ULARGE_INTEGER Cookie;
// expected values to check against HRESULT m_hrCoInit; DWORD m_CoInit; DWORD m_CurAptRefs;
// keeping count of the times called LONG m_PreInitCalled; LONG m_PostInitCalled; LONG m_PreUninitCalled; LONG m_PostUninitCalled;
// fake out some bool m_FailQueryInterface; bool m_AlwaysReturnOK;
CTestSpy() : CUnknownBase( false, 0 ), hr(0), m_hrCoInit(0), m_CoInit(0), m_CurAptRefs(0), m_FailQueryInterface(false), m_AlwaysReturnOK(false) { Cookie.HighPart = Cookie.LowPart = INVALID_VALUE; Clear(); }
~CTestSpy() { // always try to revoke if we succeeded to register. if (SUCCEEDED(hr)) { hr = pCoRevokeInitializeSpy(Cookie); test_S_OK(hr, "CoRevokeInitializeSpy"); } // we should be done. ok(GetRef() == 0, "Expected m_lRef to be 0, was: %ld\n", GetRef()); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) { if (m_FailQueryInterface) { return E_NOINTERFACE; } return CUnknownBase::QueryInterface(riid, ppv); }
const QITAB* GetQITab() { static const QITAB tab[] = { { &IID_IInitializeSpy, OFFSETOFCLASS(IInitializeSpy, CTestSpy) }, { 0 } }; return tab; }
HRESULT STDMETHODCALLTYPE PreInitialize(DWORD dwCoInit, DWORD dwCurThreadAptRefs) { InterlockedIncrement(&m_PreInitCalled); ok(m_CoInit == dwCoInit, "Unexpected dwCoInit: got %lx, expected %lx\n", dwCoInit, m_CoInit); DWORD expectApt = m_hrCoInit == RPC_E_CHANGED_MODE ? m_CurAptRefs : m_CurAptRefs -1; ok(expectApt == dwCurThreadAptRefs, "Unexpected dwCurThreadAptRefs: got %lx, expected %lx\n", dwCurThreadAptRefs, expectApt); return S_OK; }
HRESULT STDMETHODCALLTYPE PostInitialize(HRESULT hrCoInit, DWORD dwCoInit, DWORD dwNewThreadAptRefs) { InterlockedIncrement(&m_PostInitCalled); ok(m_PreInitCalled == m_PostInitCalled, "Expected balanced pre/post: %ld / %ld\n", m_PreInitCalled, m_PostInitCalled); test_HRES(hrCoInit, m_hrCoInit, "Unexpected hrCoInit in PostInitialize"); ok(m_CoInit == dwCoInit, "Unexpected dwCoInit: got %lx, expected %lx\n", dwCoInit, m_CoInit); ok(m_CurAptRefs == dwNewThreadAptRefs, "Unexpected dwNewThreadAptRefs: got %lx, expected %lx\n", dwNewThreadAptRefs, m_CurAptRefs); if (m_AlwaysReturnOK) return S_OK; return hrCoInit; }
HRESULT STDMETHODCALLTYPE PreUninitialize(DWORD dwCurThreadAptRefs) { InterlockedIncrement(&m_PreUninitCalled); ok(m_CurAptRefs == dwCurThreadAptRefs, "Unexpected dwCurThreadAptRefs: got %lx, expected %lx\n", dwCurThreadAptRefs, m_CurAptRefs); return S_OK; }
HRESULT STDMETHODCALLTYPE PostUninitialize(DWORD dwNewThreadAptRefs) { InterlockedIncrement(&m_PostUninitCalled); ok(m_PreUninitCalled == m_PostUninitCalled, "Expected balanced pre/post: %ld / %ld\n", m_PreUninitCalled, m_PostUninitCalled); DWORD apt = m_CurAptRefs ? (m_CurAptRefs-1) : 0; ok(apt == dwNewThreadAptRefs, "Unexpected dwNewThreadAptRefs: got %lx, expected %lx\n", dwNewThreadAptRefs, apt); return S_OK; }
void Clear() { m_PreInitCalled = 0; m_PostInitCalled = 0; m_PreUninitCalled = 0; m_PostUninitCalled = 0; }
void Expect(HRESULT hrCoInit, DWORD CoInit, DWORD CurAptRefs) { m_hrCoInit = hrCoInit; m_CoInit = CoInit; m_CurAptRefs = CurAptRefs; }
void Check(LONG PreInit, LONG PostInit, LONG PreUninit, LONG PostUninit) { ok(m_PreInitCalled == PreInit, "Expected PreInit to be %ld, was: %ld\n", PreInit, m_PreInitCalled); ok(m_PostInitCalled == PostInit, "Expected PostInit to be %ld, was: %ld\n", PostInit, m_PostInitCalled); ok(m_PreUninitCalled == PreUninit, "Expected PreUninit to be %ld, was: %ld\n", PreUninit, m_PreUninitCalled); ok(m_PostUninitCalled == PostUninit, "Expected PostUninit to be %ld, was: %ld\n", PostUninit, m_PostUninitCalled); }};
void test_IInitializeSpy_register2(){ CTestSpy spy, spy2;
// first we register 2 spies spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie); test_S_OK(spy.hr, "CoRegisterInitializeSpy"); test_ref(&spy, 1);
spy2.hr = pCoRegisterInitializeSpy(&spy2, &spy2.Cookie); test_S_OK(spy2.hr, "CoRegisterInitializeSpy"); test_ref(&spy, 1);
// tell them what we expect spy.Expect(S_OK, COINIT_APARTMENTTHREADED, 1); spy2.Expect(S_OK, COINIT_APARTMENTTHREADED, 1);
// Call CoInitializeEx and validate the results HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); test_S_OK(hr, "CoInitializeEx"); spy.Check(1, 1, 0, 0); spy2.Check(1, 1, 0, 0);
// Calling CoInit twice with the same apartment makes it return S_FALSE but still increment count spy.Expect(S_FALSE, COINIT_APARTMENTTHREADED, 2); spy2.Expect(S_FALSE, COINIT_APARTMENTTHREADED, 2);
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); test_HRES(hr, S_FALSE, "CoInitializeEx"); spy.Check(2, 2, 0, 0); spy2.Check(2, 2, 0, 0);
/* the order we registered the spies in is important here. we have the second one to forcibly return S_OK, which makes the first spy see S_OK instead of S_FALSE.. */ spy.Expect(S_OK, COINIT_APARTMENTTHREADED, 3); spy2.m_AlwaysReturnOK = true; spy2.Expect(S_FALSE, COINIT_APARTMENTTHREADED, 3);
// and the S_OK also influences the returned value from CoInit. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); test_S_OK(hr, "CoInitializeEx"); spy.Check(3, 3, 0, 0); spy2.Check(3, 3, 0, 0);
CoUninitialize(); spy.Check(3, 3, 1, 1); spy2.Check(3, 3, 1, 1);
spy.m_CurAptRefs = spy2.m_CurAptRefs = 2;
CoUninitialize(); spy.Check(3, 3, 2, 2); spy2.Check(3, 3, 2, 2);
spy.m_CurAptRefs = spy2.m_CurAptRefs = 1;
CoUninitialize(); spy.Check(3, 3, 3, 3); spy2.Check(3, 3, 3, 3);
spy.m_CurAptRefs = spy2.m_CurAptRefs = 0;
CoUninitialize(); spy.Check(3, 3, 4, 4); spy2.Check(3, 3, 4, 4);}
void test_IInitializeSpy_switch_apt(){ CTestSpy spy;
spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie); test_S_OK(spy.hr, "CoRegisterInitializeSpy"); test_ref(&spy, 1);
spy.Expect(S_OK, COINIT_APARTMENTTHREADED, 1);
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); test_S_OK(hr, "CoInitializeEx"); spy.Check(1, 1, 0, 0);
spy.Expect(RPC_E_CHANGED_MODE, COINIT_MULTITHREADED, 1);
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); test_HRES(hr, RPC_E_CHANGED_MODE, "CoInitializeEx"); spy.Check(2, 2, 0, 0);
CoUninitialize(); spy.Check(2, 2, 1, 1);
spy.m_CurAptRefs = 0;
CoUninitialize(); spy.Check(2, 2, 2, 2);
CoUninitialize(); spy.Check(2, 2, 3, 3);}
void test_IInitializeSpy_fail(){ CTestSpy spy;
spy.m_FailQueryInterface = true;
spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie); test_HRES(spy.hr, E_NOINTERFACE, "Unexpected hr while registering invalid interface"); test_ref(&spy, 0); ok(spy.Cookie.HighPart == 0xffffffff, "Unexpected Cookie.HighPart, expected 0xffffffff got: 0x%08lx\n", spy.Cookie.HighPart); ok(spy.Cookie.LowPart == 0xffffffff, "Unexpected Cookie.HighPart, expected 0xffffffff got: 0x%08lx\n", spy.Cookie.LowPart);
spy.Cookie.HighPart = spy.Cookie.LowPart = 0xffffffff; HRESULT hr = pCoRevokeInitializeSpy(spy.Cookie); test_HRES(hr, E_INVALIDARG, "Unexpected hr while unregistering invalid interface"); test_ref(&spy, 0);
spy.Cookie.HighPart = spy.Cookie.LowPart = 0; hr = pCoRevokeInitializeSpy(spy.Cookie); test_HRES(hr, E_INVALIDARG, "Unexpected hr while unregistering invalid interface"); test_ref(&spy, 0);
/* we should not crash here, just return E_NOINTERFACE do note the Cookie is not even being touched at all, compared to calling this with an interface that does not respond to IID_IInitializeSpy */ spy.Cookie.HighPart = spy.Cookie.LowPart = INVALID_VALUE; hr = pCoRegisterInitializeSpy(NULL, &spy.Cookie); test_HRES(spy.hr, E_NOINTERFACE, "Unexpected hr while registering NULL interface"); ok(spy.Cookie.HighPart == INVALID_VALUE, "Unexpected Cookie.HighPart, expected 0xdeadbeef got: %lx\n", spy.Cookie.HighPart); ok(spy.Cookie.LowPart == INVALID_VALUE, "Unexpected Cookie.HighPart, expected 0xdeadbeef got: %lx\n", spy.Cookie.LowPart);}
void test_IInitializeSpy_twice(){ CTestSpy spy;
spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie); test_S_OK(spy.hr, "CoRegisterInitializeSpy"); test_ref(&spy, 1);
ULARGE_INTEGER Cookie = { { INVALID_VALUE, INVALID_VALUE } }; HRESULT hr = pCoRegisterInitializeSpy(&spy, &Cookie); test_S_OK(hr, "CoRegisterInitializeSpy"); test_ref(&spy, 2);
hr = pCoRevokeInitializeSpy(Cookie); test_S_OK(hr, "CoRevokeInitializeSpy"); test_ref(&spy, 1);}
START_TEST(initializespy){ HMODULE ole32 = LoadLibraryA("ole32.dll"); pCoRegisterInitializeSpy = (pCoRegisterInitializeSpy_t)GetProcAddress(ole32, "CoRegisterInitializeSpy"); pCoRevokeInitializeSpy = (pCoRevokeInitializeSpy_t)GetProcAddress(ole32, "CoRevokeInitializeSpy");
test_IInitializeSpy_register2(); test_IInitializeSpy_switch_apt(); test_IInitializeSpy_fail(); test_IInitializeSpy_twice();}