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 __REACTOS__
13     #include <apitest.h>
14 #else
15     #include <stdlib.h>
16     #include <stdio.h>
17     #include <stdarg.h>
18     int g_tests_executed = 0;
19     int g_tests_failed = 0;
20     void ok_func(const char *file, int line, BOOL value, const char *fmt, ...)
21     {
22         va_list va;
23         va_start(va, fmt);
24         if (!value)
25         {
26             printf("%s (%d): ", file, line);
27             vprintf(fmt, va);
28             g_tests_failed++;
29         }
30         g_tests_executed++;
31         va_end(va);
32     }
33     #undef ok
34     #define ok(value, ...)  ok_func(__FILE__, __LINE__, value, __VA_ARGS__)
35     #define START_TEST(x)   int main(void)
36 #endif
37 
38 
39 static LONG g_CTOR = 0;
40 static LONG g_DTOR = 0;
41 static LONG g_BLIND = 0;
42 
43 class CTestObject :
44     public CComObjectRootEx<CComMultiThreadModelNoCS>,
45     public IPersist,
46     public IStdMarshalInfo
47 {
48 public:
49     CTestObject()
50     {
51         InterlockedIncrement(&g_CTOR);
52     }
53     ~CTestObject()
54     {
55         InterlockedIncrement(&g_DTOR);
56     }
57 
58     // *** IPersist methods ***
59     virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID)
60     {
61         return E_NOTIMPL;
62     }
63 
64     // *** IStdMarshalInfo methods ***
65     virtual HRESULT STDMETHODCALLTYPE GetClassForHandler(DWORD dwDestContext, void *pvDestContext, CLSID *pClsid)
66     {
67         return E_NOTIMPL;
68     }
69 
70     static HRESULT WINAPI FuncBlind(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw)
71     {
72         InterlockedIncrement(&g_BLIND);
73         return E_FAIL;
74     }
75 
76     DECLARE_NOT_AGGREGATABLE(CTestObject)
77     DECLARE_PROTECT_FINAL_CONSTRUCT()
78 
79     BEGIN_COM_MAP(CTestObject)
80         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) /* First entry has to be a simple entry, otherwise ATL asserts */
81         COM_INTERFACE_ENTRY_FUNC_BLIND(0, FuncBlind)    /* Showing that even after a Blind func, entryies can be found */
82         COM_INTERFACE_ENTRY_IID(IID_IStdMarshalInfo, IStdMarshalInfo)
83     END_COM_MAP()
84 };
85 
86 
87 class CDumExe: public CAtlExeModuleT<CDumExe>
88 {
89 
90 };
91 CDumExe dum;
92 
93 
94 START_TEST(CComObject)
95 {
96     g_CTOR = g_DTOR = g_BLIND = 0;
97 
98     CComObject<CTestObject>* pTest;
99     HRESULT hr = CComObject<CTestObject>::CreateInstance(&pTest);
100 
101     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
102 
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     if (hr == S_OK)
108     {
109         ULONG ref = pTest->AddRef();
110         ok(ref == 1, "Expected 1, got %lu\n", ref);
111 
112         {
113             CComPtr<IUnknown> ppv;
114             hr = pTest->QueryInterface(IID_IUnknown, (void **) &ppv);
115             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
116             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
117             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
118             ok(g_BLIND == 0, "Expected 0, got %lu\n", g_BLIND);
119 
120             CComPtr<IPersist> ppersist;
121             hr = pTest->QueryInterface(IID_IPersist, (void **)&ppersist);
122             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
123             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
124             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
125             ok(g_BLIND == 0, "Expected 0, got %lu\n", g_BLIND);
126 
127         }
128 
129         {
130             CComPtr<IStdMarshalInfo> pstd;
131             hr = pTest->QueryInterface(IID_IStdMarshalInfo, (void **)&pstd);
132             ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
133             ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
134             ok(g_DTOR == 0, "Expected 0, got %lu\n", g_DTOR);
135             ok(g_BLIND == 1, "Expected 1, got %lu\n", g_BLIND);
136         }
137 
138         ref = pTest->Release();
139         ok(ref == 0, "Expected 0, got %lu\n", ref);
140         ok(g_CTOR == 1, "Expected 1, got %lu\n", g_CTOR);
141         ok(g_DTOR == 1, "Expected 1, got %lu\n", g_DTOR);
142         ok(g_BLIND == 1, "Expected 1, got %lu\n", g_BLIND);
143     }
144 
145 #ifndef __REACTOS__
146     printf("CComObject: %i tests executed (0 marked as todo, %i failures), 0 skipped.\n", g_tests_executed, g_tests_failed);
147     return g_tests_failed;
148 #endif
149 }
150