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 #else
84 #define DECLARE_QIPTR(type)     CComQIPtr<type>
85 #endif
86 
87 START_TEST(CComQIPtr)
88 {
89     CQITestObject testObject;
90     IUnknown* unk = static_cast<IPersist*>(&testObject);
91     ok_long(testObject.m_dwRef, 1);
92     ok_long(g_QI, 0);
93 
94     {
95         DECLARE_QIPTR(IPersist) ppPersist(unk);
96         ok_long(testObject.m_dwRef, 2);
97         ok_long(g_QI, 1);
98 
99         DECLARE_QIPTR(IStdMarshalInfo) ppMarshal(ppPersist);
100         ok_long(testObject.m_dwRef, 3);
101         ok_long(g_QI, 2);
102     }
103     ok_long(testObject.m_dwRef, 1);
104     {
105         DECLARE_QIPTR(IStdMarshalInfo) ppMarshal;
106         ok_long(testObject.m_dwRef, 1);
107         ok_long(g_QI, 2);
108 
109         ppMarshal = unk;
110         ok_long(testObject.m_dwRef, 2);
111         ok_long(g_QI, 3);
112 
113         ppMarshal = static_cast<IUnknown*>(NULL);
114         ok_long(testObject.m_dwRef, 1);
115         ok_long(g_QI, 3);
116 
117         CComPtr<IUnknown> spUnk(unk);
118         ok_long(testObject.m_dwRef, 2);
119         ok_long(g_QI, 3);
120 
121         ppMarshal = spUnk;
122         ok_long(testObject.m_dwRef, 3);
123         ok_long(g_QI, 4);
124 
125         spUnk.Release();
126         ok_long(testObject.m_dwRef, 2);
127         ok_long(g_QI, 4);
128 
129         spUnk = ppMarshal;
130         ok_long(testObject.m_dwRef, 3);
131 #ifdef __REACTOS__
132         // CORE-12710
133         todo_if(1)
134 #endif
135         ok_long(g_QI, 5);
136     }
137 }
138