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 
27     CQITestObject()
28         :m_dwRef(1)
29     {
30     }
31     ~CQITestObject()
32     {
33     }
34 
35     STDMETHOD_(ULONG, AddRef)()
36     {
37         InterlockedIncrement(&m_dwRef);
38         return 2;
39     }
40 
41     STDMETHOD_(ULONG, Release)()
42     {
43         InterlockedDecrement(&m_dwRef);
44         return 1;
45     }
46 
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 ***
66     STDMETHOD(GetClassID)(CLSID *pClassID)
67     {
68         return E_NOTIMPL;
69     }
70 
71     // *** IStdMarshalInfo methods ***
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 
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