1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for CComQIPtr
5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include <atlbase.h>
9 #include <atlcom.h>
10
11 #ifdef HAVE_APITEST
12 #include <apitest.h>
13 #else
14 #include "atltest.h"
15 #endif
16
17
18 static LONG g_QI = 0;
19
20 class CQITestObject :
21 public IPersist,
22 public IStdMarshalInfo
23 {
24 public:
25 LONG m_dwRef;
26
CQITestObject()27 CQITestObject()
28 :m_dwRef(1)
29 {
30 }
~CQITestObject()31 ~CQITestObject()
32 {
33 }
34
STDMETHOD_(ULONG,AddRef)35 STDMETHOD_(ULONG, AddRef)()
36 {
37 InterlockedIncrement(&m_dwRef);
38 return 2;
39 }
40
STDMETHOD_(ULONG,Release)41 STDMETHOD_(ULONG, Release)()
42 {
43 InterlockedDecrement(&m_dwRef);
44 return 1;
45 }
46
STDMETHOD(QueryInterface)47 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
48 {
49 InterlockedIncrement(&g_QI);
50 if (iid == IID_IUnknown || iid == IID_IPersist)
51 {
52 AddRef();
53 *ppvObject = static_cast<IPersist*>(this);
54 return S_OK;
55 }
56 else if (iid == IID_IStdMarshalInfo)
57 {
58 AddRef();
59 *ppvObject = static_cast<IStdMarshalInfo*>(this);
60 return S_OK;
61 }
62 return E_NOINTERFACE;
63 }
64
65 // *** IPersist methods ***
STDMETHOD(GetClassID)66 STDMETHOD(GetClassID)(CLSID *pClassID)
67 {
68 return E_NOTIMPL;
69 }
70
71 // *** IStdMarshalInfo methods ***
STDMETHOD(GetClassForHandler)72 STDMETHOD(GetClassForHandler)(DWORD dwDestContext, void *pvDestContext, CLSID *pClsid)
73 {
74 return E_NOTIMPL;
75 }
76 };
77
78 // Yes this sucks, but we have to support GCC. (CORE-12710)
79 #ifdef __REACTOS__
80 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)>
81 #elif defined(__GNUC__)
82 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)>
83 #elif defined(__RATL__)
84 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)>
85 #else
86 #define DECLARE_QIPTR(type) CComQIPtr<type>
87 #endif
88
START_TEST(CComQIPtr)89 START_TEST(CComQIPtr)
90 {
91 CQITestObject testObject;
92 IUnknown* unk = static_cast<IPersist*>(&testObject);
93 ok_long(testObject.m_dwRef, 1);
94 ok_long(g_QI, 0);
95
96 {
97 DECLARE_QIPTR(IPersist) ppPersist(unk);
98 ok_long(testObject.m_dwRef, 2);
99 ok_long(g_QI, 1);
100
101 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal(ppPersist);
102 ok_long(testObject.m_dwRef, 3);
103 ok_long(g_QI, 2);
104 }
105 ok_long(testObject.m_dwRef, 1);
106 {
107 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal;
108 ok_long(testObject.m_dwRef, 1);
109 ok_long(g_QI, 2);
110
111 ppMarshal = unk;
112 ok_long(testObject.m_dwRef, 2);
113 ok_long(g_QI, 3);
114
115 ppMarshal = static_cast<IUnknown*>(NULL);
116 ok_long(testObject.m_dwRef, 1);
117 ok_long(g_QI, 3);
118
119 CComPtr<IUnknown> spUnk(unk);
120 ok_long(testObject.m_dwRef, 2);
121 ok_long(g_QI, 3);
122
123 ppMarshal = spUnk;
124 ok_long(testObject.m_dwRef, 3);
125 ok_long(g_QI, 4);
126
127 spUnk.Release();
128 ok_long(testObject.m_dwRef, 2);
129 ok_long(g_QI, 4);
130
131 spUnk = ppMarshal;
132 ok_long(testObject.m_dwRef, 3);
133 #ifdef __REACTOS__
134 // CORE-12710
135 todo_if(1)
136 #endif
137 ok_long(g_QI, 5);
138 }
139 }
140