1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Test for CComObject
5  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 
9 #include <atlbase.h>
10 #include <atlcom.h>
11 
12 #ifdef HAVE_APITEST
13     #include <apitest.h>
14 #else
15     #include "atltest.h"
16 #endif
17 
18 
19 static LONG g_CTOR = 0;
20 static LONG g_DTOR = 0;
21 static LONG g_BLIND = 0;
22 
23 class CTestObject :
24     public CComObjectRootEx<CComMultiThreadModelNoCS>,
25     public IPersist,
26     public IStdMarshalInfo
27 {
28 public:
29     CTestObject()
30     {
31         InterlockedIncrement(&g_CTOR);
32     }
33     ~CTestObject()
34     {
35         InterlockedIncrement(&g_DTOR);
36     }
37 
38     // *** IPersist methods ***
39     virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID)
40     {
41         return E_NOTIMPL;
42     }
43 
44     // *** IStdMarshalInfo methods ***
45     virtual HRESULT STDMETHODCALLTYPE GetClassForHandler(DWORD dwDestContext, void *pvDestContext, CLSID *pClsid)
46     {
47         return E_NOTIMPL;
48     }
49 
50     static HRESULT WINAPI FuncBlind(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw)
51     {
52         InterlockedIncrement(&g_BLIND);
53         return E_FAIL;
54     }
55 
56     DECLARE_NOT_AGGREGATABLE(CTestObject)
57     DECLARE_PROTECT_FINAL_CONSTRUCT()
58 
59     BEGIN_COM_MAP(CTestObject)
60         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) /* First entry has to be a simple entry, otherwise ATL asserts */
61         COM_INTERFACE_ENTRY_FUNC_BLIND(0, FuncBlind)    /* Showing that even after a Blind func, entryies can be found */
62         COM_INTERFACE_ENTRY_IID(IID_IStdMarshalInfo, IStdMarshalInfo)
63     END_COM_MAP()
64 };
65 
66 #ifndef __RATL__ // Avoid conflict (causing assertion at CAtlModule::CAtlModule)
67 class CDumExe: public CAtlExeModuleT<CDumExe>
68 {
69 
70 };
71 CDumExe dum;
72 #endif
73 
74 START_TEST(CComObject)
75 {
76     g_CTOR = g_DTOR = g_BLIND = 0;
77 
78     CComObject<CTestObject>* pTest;
79     HRESULT hr = CComObject<CTestObject>::CreateInstance(&pTest);
80 
81     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
82 
83     ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
84     ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
85     ok(g_BLIND == 0, "Expected 0, got %lu\n", g_BLIND);
86 
87     if (hr == S_OK)
88     {
89         ULONG ref = pTest->AddRef();
90         ok(ref == 1, "Expected 1, got %lu\n", ref);
91 
92         {
93             CComPtr<IUnknown> ppv;
94             hr = pTest->QueryInterface(IID_IUnknown, (void **) &ppv);
95             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
96             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
97             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
98             ok(g_BLIND == 0, "Expected 0, got %lu\n", g_BLIND);
99 
100             CComPtr<IPersist> ppersist;
101             hr = pTest->QueryInterface(IID_IPersist, (void **)&ppersist);
102             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
103             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
104             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
105             ok(g_BLIND == 0, "Expected 0, got %lu\n", g_BLIND);
106 
107         }
108 
109         {
110             CComPtr<IStdMarshalInfo> pstd;
111             hr = pTest->QueryInterface(IID_IStdMarshalInfo, (void **)&pstd);
112             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
113             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
114             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
115             ok(g_BLIND == 1, "Expected 1, got %lu\n", g_BLIND);
116         }
117 
118         ref = pTest->Release();
119         ok(ref == 0, "Expected 0, got %lu\n", ref);
120         ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
121         ok(g_DTOR == 1, "Expected 1, got %lu\n", g_DTOR);
122         ok(g_BLIND == 1, "Expected 1, got %lu\n", g_BLIND);
123     }
124 }
125