ReactOS  0.4.14-dev-49-gfb4591c
initializespy.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * PURPOSE: Tests for IInitializeSpy
5  * PROGRAMMERS: Mark Jansen
6  */
7 
8 #define WIN32_NO_STATUS
9 #define _INC_WINDOWS
10 #define COM_NO_WINDOWS_H
11 
12 #include <stdio.h>
13 #include <wine/test.h>
14 
15 #include <winuser.h>
16 #include <winreg.h>
17 
18 #include <shlwapi.h>
19 #include <unknownbase.h>
20 
21 #define test_S_OK(hres, message) ok((hres) == S_OK, "%s (0x%lx instead of S_OK)\n", (message), (hres))
22 #define test_HRES(hres, hresExpected, message) ok((hres) == (hresExpected), "%s (0x%lx instead of 0x%lx)\n", (message), (hres), (hresExpected))
23 #define test_ref(spy, expectedRef) ok((spy)->GetRef() == (expectedRef), "unexpected refcount, %ld instead of %d\n", (spy)->GetRef(), (expectedRef))
24 
25 
26 typedef HRESULT (WINAPI *pCoRegisterInitializeSpy_t)(_In_ LPINITIALIZESPY pSpy, _Out_ ULARGE_INTEGER *puliCookie);
30 
31 
32 const DWORD INVALID_VALUE = 0xdeadbeef;
33 
34 
35 class CTestSpy : public CUnknownBase<IInitializeSpy>
36 {
37 public:
40 
41  // expected values to check against
45 
46  // keeping count of the times called
51 
52  // fake out some
55 
57  : CUnknownBase( false, 0 ),
58  hr(0),
59  m_hrCoInit(0),
60  m_CoInit(0),
61  m_CurAptRefs(0),
64  {
66  Clear();
67  }
68 
70  {
71  // always try to revoke if we succeeded to register.
72  if (SUCCEEDED(hr))
73  {
75  test_S_OK(hr, "CoRevokeInitializeSpy");
76  }
77  // we should be done.
78  ok(GetRef() == 0, "Expected m_lRef to be 0, was: %ld\n", GetRef());
79  }
80 
82  {
84  {
85  return E_NOINTERFACE;
86  }
88  }
89 
90  const QITAB* GetQITab()
91  {
92  static const QITAB tab[] = { { &IID_IInitializeSpy, OFFSETOFCLASS(IInitializeSpy, CTestSpy) }, { 0 } };
93  return tab;
94  }
95 
96 
98  {
100  ok(m_CoInit == dwCoInit, "Unexpected dwCoInit: got %lx, expected %lx\n", dwCoInit, m_CoInit);
102  ok(expectApt == dwCurThreadAptRefs, "Unexpected dwCurThreadAptRefs: got %lx, expected %lx\n", dwCurThreadAptRefs, expectApt);
103  return S_OK;
104  }
105 
107  {
109  ok(m_PreInitCalled == m_PostInitCalled, "Expected balanced pre/post: %ld / %ld\n", m_PreInitCalled, m_PostInitCalled);
110  test_HRES(hrCoInit, m_hrCoInit, "Unexpected hrCoInit in PostInitialize");
111  ok(m_CoInit == dwCoInit, "Unexpected dwCoInit: got %lx, expected %lx\n", dwCoInit, m_CoInit);
112  ok(m_CurAptRefs == dwNewThreadAptRefs, "Unexpected dwNewThreadAptRefs: got %lx, expected %lx\n", dwNewThreadAptRefs, m_CurAptRefs);
113  if (m_AlwaysReturnOK)
114  return S_OK;
115  return hrCoInit;
116  }
117 
119  {
121  ok(m_CurAptRefs == dwCurThreadAptRefs, "Unexpected dwCurThreadAptRefs: got %lx, expected %lx\n", dwCurThreadAptRefs, m_CurAptRefs);
122  return S_OK;
123  }
124 
126  {
128  ok(m_PreUninitCalled == m_PostUninitCalled, "Expected balanced pre/post: %ld / %ld\n", m_PreUninitCalled, m_PostUninitCalled);
129  DWORD apt = m_CurAptRefs ? (m_CurAptRefs-1) : 0;
130  ok(apt == dwNewThreadAptRefs, "Unexpected dwNewThreadAptRefs: got %lx, expected %lx\n", dwNewThreadAptRefs, apt);
131  return S_OK;
132  }
133 
134  void Clear()
135  {
136  m_PreInitCalled = 0;
137  m_PostInitCalled = 0;
138  m_PreUninitCalled = 0;
139  m_PostUninitCalled = 0;
140  }
141 
142  void Expect(HRESULT hrCoInit, DWORD CoInit, DWORD CurAptRefs)
143  {
144  m_hrCoInit = hrCoInit;
145  m_CoInit = CoInit;
146  m_CurAptRefs = CurAptRefs;
147  }
148 
149  void Check(LONG PreInit, LONG PostInit, LONG PreUninit, LONG PostUninit)
150  {
151  ok(m_PreInitCalled == PreInit, "Expected PreInit to be %ld, was: %ld\n", PreInit, m_PreInitCalled);
152  ok(m_PostInitCalled == PostInit, "Expected PostInit to be %ld, was: %ld\n", PostInit, m_PostInitCalled);
153  ok(m_PreUninitCalled == PreUninit, "Expected PreUninit to be %ld, was: %ld\n", PreUninit, m_PreUninitCalled);
154  ok(m_PostUninitCalled == PostUninit, "Expected PostUninit to be %ld, was: %ld\n", PostUninit, m_PostUninitCalled);
155  }
156 };
157 
158 
160 {
161  CTestSpy spy, spy2;
162 
163  // first we register 2 spies
164  spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie);
165  test_S_OK(spy.hr, "CoRegisterInitializeSpy");
166  test_ref(&spy, 1);
167 
168  spy2.hr = pCoRegisterInitializeSpy(&spy2, &spy2.Cookie);
169  test_S_OK(spy2.hr, "CoRegisterInitializeSpy");
170  test_ref(&spy, 1);
171 
172  // tell them what we expect
175 
176  // Call CoInitializeEx and validate the results
178  test_S_OK(hr, "CoInitializeEx");
179  spy.Check(1, 1, 0, 0);
180  spy2.Check(1, 1, 0, 0);
181 
182  // Calling CoInit twice with the same apartment makes it return S_FALSE but still increment count
185 
187  test_HRES(hr, S_FALSE, "CoInitializeEx");
188  spy.Check(2, 2, 0, 0);
189  spy2.Check(2, 2, 0, 0);
190 
191  /* the order we registered the spies in is important here.
192  we have the second one to forcibly return S_OK, which makes the first spy see
193  S_OK instead of S_FALSE.. */
195  spy2.m_AlwaysReturnOK = true;
197 
198  // and the S_OK also influences the returned value from CoInit.
200  test_S_OK(hr, "CoInitializeEx");
201  spy.Check(3, 3, 0, 0);
202  spy2.Check(3, 3, 0, 0);
203 
204  CoUninitialize();
205  spy.Check(3, 3, 1, 1);
206  spy2.Check(3, 3, 1, 1);
207 
208  spy.m_CurAptRefs = spy2.m_CurAptRefs = 2;
209 
210  CoUninitialize();
211  spy.Check(3, 3, 2, 2);
212  spy2.Check(3, 3, 2, 2);
213 
214  spy.m_CurAptRefs = spy2.m_CurAptRefs = 1;
215 
216  CoUninitialize();
217  spy.Check(3, 3, 3, 3);
218  spy2.Check(3, 3, 3, 3);
219 
220  spy.m_CurAptRefs = spy2.m_CurAptRefs = 0;
221 
222  CoUninitialize();
223  spy.Check(3, 3, 4, 4);
224  spy2.Check(3, 3, 4, 4);
225 }
226 
228 {
229  CTestSpy spy;
230 
231  spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie);
232  test_S_OK(spy.hr, "CoRegisterInitializeSpy");
233  test_ref(&spy, 1);
234 
236 
238  test_S_OK(hr, "CoInitializeEx");
239  spy.Check(1, 1, 0, 0);
240 
242 
244  test_HRES(hr, RPC_E_CHANGED_MODE, "CoInitializeEx");
245  spy.Check(2, 2, 0, 0);
246 
247 
248  CoUninitialize();
249  spy.Check(2, 2, 1, 1);
250 
251  spy.m_CurAptRefs = 0;
252 
253  CoUninitialize();
254  spy.Check(2, 2, 2, 2);
255 
256  CoUninitialize();
257  spy.Check(2, 2, 3, 3);
258 }
259 
261 {
262  CTestSpy spy;
263 
264  spy.m_FailQueryInterface = true;
265 
266  spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie);
267  test_HRES(spy.hr, E_NOINTERFACE, "Unexpected hr while registering invalid interface");
268  test_ref(&spy, 0);
269  ok(spy.Cookie.HighPart == 0xffffffff, "Unexpected Cookie.HighPart, expected 0xffffffff got: 0x%08lx\n", spy.Cookie.HighPart);
270  ok(spy.Cookie.LowPart == 0xffffffff, "Unexpected Cookie.HighPart, expected 0xffffffff got: 0x%08lx\n", spy.Cookie.LowPart);
271 
272  spy.Cookie.HighPart = spy.Cookie.LowPart = 0xffffffff;
274  test_HRES(hr, E_INVALIDARG, "Unexpected hr while unregistering invalid interface");
275  test_ref(&spy, 0);
276 
277  spy.Cookie.HighPart = spy.Cookie.LowPart = 0;
279  test_HRES(hr, E_INVALIDARG, "Unexpected hr while unregistering invalid interface");
280  test_ref(&spy, 0);
281 
282  /* we should not crash here, just return E_NOINTERFACE
283  do note the Cookie is not even being touched at all, compared to calling this with an interface
284  that does not respond to IID_IInitializeSpy */
287  test_HRES(spy.hr, E_NOINTERFACE, "Unexpected hr while registering NULL interface");
288  ok(spy.Cookie.HighPart == INVALID_VALUE, "Unexpected Cookie.HighPart, expected 0xdeadbeef got: %lx\n", spy.Cookie.HighPart);
289  ok(spy.Cookie.LowPart == INVALID_VALUE, "Unexpected Cookie.HighPart, expected 0xdeadbeef got: %lx\n", spy.Cookie.LowPart);
290 }
291 
293 {
294  CTestSpy spy;
295 
296  spy.hr = pCoRegisterInitializeSpy(&spy, &spy.Cookie);
297  test_S_OK(spy.hr, "CoRegisterInitializeSpy");
298  test_ref(&spy, 1);
299 
302  test_S_OK(hr, "CoRegisterInitializeSpy");
303  test_ref(&spy, 2);
304 
306  test_S_OK(hr, "CoRevokeInitializeSpy");
307  test_ref(&spy, 1);
308 }
309 
310 
311 START_TEST(initializespy)
312 {
313  HMODULE ole32 = LoadLibraryA("ole32.dll");
314  pCoRegisterInitializeSpy = (pCoRegisterInitializeSpy_t)GetProcAddress(ole32, "CoRegisterInitializeSpy");
315  pCoRevokeInitializeSpy = (pCoRevokeInitializeSpy_t)GetProcAddress(ole32, "CoRevokeInitializeSpy");
316 
321 }
#define HRESULT
Definition: msvc.h:9
HRESULT STDMETHODCALLTYPE PreUninitialize(DWORD dwCurThreadAptRefs)
#define REFIID
Definition: guiddef.h:118
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT STDMETHODCALLTYPE PostInitialize(HRESULT hrCoInit, DWORD dwCoInit, DWORD dwNewThreadAptRefs)
#define test_S_OK(hres, message)
HRESULT hr
Definition: shlfolder.c:183
DWORD m_CoInit
#define test_HRES(hres, hresExpected, message)
LONG m_PostInitCalled
REFIID riid
Definition: precomp.h:44
HRESULT(WINAPI * pCoRegisterInitializeSpy_t)(_In_ LPINITIALIZESPY pSpy, _Out_ ULARGE_INTEGER *puliCookie)
void Clear()
static DWORD dwCoInit
Definition: compobj.c:68
REFIID LPVOID * ppv
Definition: atlbase.h:39
void test_IInitializeSpy_twice()
$ULONG LowPart
Definition: ntbasedef.h:576
#define OFFSETOFCLASS(base, derived)
Definition: shlwapi.h:2086
START_TEST(initializespy)
const QITAB * GetQITab()
long LONG
Definition: pedump.c:60
ULARGE_INTEGER Cookie
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
#define S_FALSE
Definition: winerror.h:2357
LONG m_PreUninitCalled
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
HRESULT STDMETHODCALLTYPE PostUninitialize(DWORD dwNewThreadAptRefs)
bool m_FailQueryInterface
LONG m_PostUninitCalled
HRESULT STDMETHODCALLTYPE PreInitialize(DWORD dwCoInit, DWORD dwCurThreadAptRefs)
#define test_ref(spy, expectedRef)
$ULONG HighPart
Definition: ntbasedef.h:577
const DWORD INVALID_VALUE
LONG HRESULT
Definition: typedefs.h:77
_In_opt_ PVOID _Out_ PLARGE_INTEGER Cookie
Definition: cmfuncs.h:13
#define WINAPI
Definition: msvc.h:8
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
unsigned long DWORD
Definition: ntddk_ex.h:95
HRESULT(WINAPI * pCoRevokeInitializeSpy_t)(_In_ ULARGE_INTEGER uliCookie)
#define RPC_E_CHANGED_MODE
Definition: winerror.h:2482
void test_IInitializeSpy_switch_apt()
static void PostInit(void)
Definition: main.c:325
pCoRegisterInitializeSpy_t pCoRegisterInitializeSpy
HRESULT m_hrCoInit
#define false
Definition: stdbool.h:38
#define _In_
Definition: no_sal2.h:204
#define S_OK
Definition: intsafe.h:59
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv)
void test_IInitializeSpy_register2()
#define InterlockedIncrement
Definition: armddk.h:53
static void PreInit(void)
Definition: main.c:267
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:1991
void Check(LONG PreInit, LONG PostInit, LONG PreUninit, LONG PostUninit)
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv)
Definition: unknownbase.h:34
#define ok(value,...)
Definition: atltest.h:57
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:1935
#define GetProcAddress(x, y)
Definition: compat.h:410
pCoRevokeInitializeSpy_t pCoRevokeInitializeSpy
LONG m_PreInitCalled
HRESULT hr
void Expect(HRESULT hrCoInit, DWORD CoInit, DWORD CurAptRefs)
void test_IInitializeSpy_fail()
#define SUCCEEDED(hr)
Definition: intsafe.h:57
bool m_AlwaysReturnOK
DWORD m_CurAptRefs