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 <stdlib.h> 15 #include <stdio.h> 16 #include <stdarg.h> 17 int g_tests_executed = 0; 18 int g_tests_failed = 0; 19 void ok_func(const char *file, int line, BOOL value, const char *fmt, ...) 20 { 21 va_list va; 22 va_start(va, fmt); 23 if (!value) 24 { 25 printf("%s (%d): ", file, line); 26 vprintf(fmt, va); 27 g_tests_failed++; 28 } 29 g_tests_executed++; 30 va_end(va); 31 } 32 #undef ok 33 #define ok(value, ...) ok_func(__FILE__, __LINE__, value, __VA_ARGS__) 34 #define START_TEST(x) int main(void) 35 #endif 36 37 38 static LONG g_QI = 0; 39 40 class CQITestObject : 41 public IPersist, 42 public IStdMarshalInfo 43 { 44 public: 45 LONG m_dwRef; 46 47 CQITestObject() 48 :m_dwRef(1) 49 { 50 } 51 ~CQITestObject() 52 { 53 } 54 55 STDMETHOD_(ULONG, AddRef)() 56 { 57 InterlockedIncrement(&m_dwRef); 58 return 2; 59 } 60 61 STDMETHOD_(ULONG, Release)() 62 { 63 InterlockedDecrement(&m_dwRef); 64 return 1; 65 } 66 67 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) 68 { 69 InterlockedIncrement(&g_QI); 70 if (iid == IID_IUnknown || iid == IID_IPersist) 71 { 72 AddRef(); 73 *ppvObject = static_cast<IPersist*>(this); 74 return S_OK; 75 } 76 else if (iid == IID_IStdMarshalInfo) 77 { 78 AddRef(); 79 *ppvObject = static_cast<IStdMarshalInfo*>(this); 80 return S_OK; 81 } 82 return E_NOINTERFACE; 83 } 84 85 // *** IPersist methods *** 86 STDMETHOD(GetClassID)(CLSID *pClassID) 87 { 88 return E_NOTIMPL; 89 } 90 91 // *** IStdMarshalInfo methods *** 92 STDMETHOD(GetClassForHandler)(DWORD dwDestContext, void *pvDestContext, CLSID *pClsid) 93 { 94 return E_NOTIMPL; 95 } 96 }; 97 98 // Yes this sucks, but we have to support GCC. (CORE-12710) 99 #ifdef __REACTOS__ 100 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)> 101 #elif defined(__GNUC__) 102 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)> 103 #else 104 #define DECLARE_QIPTR(type) CComQIPtr<type> 105 #endif 106 107 START_TEST(CComQIPtr) 108 { 109 CQITestObject testObject; 110 IUnknown* unk = static_cast<IPersist*>(&testObject); 111 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef); 112 ok(g_QI == 0, "Expected g_QI 0, got %lu\n", g_QI); 113 114 { 115 DECLARE_QIPTR(IPersist) ppPersist(unk); 116 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef); 117 ok(g_QI == 1, "Expected g_QI 1, got %lu\n", g_QI); 118 119 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal(ppPersist); 120 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef); 121 ok(g_QI == 2, "Expected g_QI 2, got %lu\n", g_QI); 122 } 123 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef); 124 { 125 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal; 126 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef); 127 ok(g_QI == 2, "Expected g_QI 2, got %lu\n", g_QI); 128 129 ppMarshal = unk; 130 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef); 131 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI); 132 133 ppMarshal = static_cast<IUnknown*>(NULL); 134 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef); 135 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI); 136 137 CComPtr<IUnknown> spUnk(unk); 138 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef); 139 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI); 140 141 ppMarshal = spUnk; 142 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef); 143 ok(g_QI == 4, "Expected g_QI 4, got %lu\n", g_QI); 144 145 spUnk.Release(); 146 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef); 147 ok(g_QI == 4, "Expected g_QI 4, got %lu\n", g_QI); 148 149 spUnk = ppMarshal; 150 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef); 151 #ifdef __REACTOS__ 152 // CORE-12710 153 todo_if(1) 154 #endif 155 ok(g_QI == 5, "Expected g_QI 5, got %lu\n", g_QI); 156 } 157 158 #ifndef HAVE_APITEST 159 printf("CComQIPtr: %i tests executed (0 marked as todo, %i failures), 0 skipped.\n", g_tests_executed, g_tests_failed); 160 return g_tests_failed; 161 #endif 162 } 163