23#include <winpr/error.h>
31 (void)fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, #cond); \
37typedef struct ITestFoo ITestFoo;
38typedef struct ITestBar ITestBar;
40WINPR_COM_DEFINE_GUID(IID_ITestFoo, 0x01234567, 0x89ab, 0xcdef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
42WINPR_COM_DEFINE_GUID(IID_ITestBar, 0x76543210, 0xba98, 0xfedc, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba,
53 const ITestFooVtbl* lpVtbl;
64 const ITestBarVtbl* lpVtbl;
81 return ((CSingle*)This)->value;
84static const ITestFooVtbl CSingle_vtbl = {
89static void CSingle_free(wComBase*
object)
95static BOOL test_single(
void)
98 WINPR_STATIC_ASSERT(offsetof(ITestFooVtbl, Foo) == 3 *
sizeof(
void*));
101 CSingle* obj = calloc(1,
sizeof(*obj));
105 ITestFoo* foo = (ITestFoo*)obj;
106 CHECK(obj->com.refCount == 1);
107 CHECK(foo->lpVtbl->Foo(foo) == 42);
110 ITestFoo* foo2 =
nullptr;
115 CHECK((
void*)unk == (
void*)foo);
116 CHECK(obj->com.refCount == 3);
121 CHECK(other ==
nullptr);
122 CHECK(foo->lpVtbl->iunknown.QueryInterface((
wIUnknown*)foo, &IID_ITestFoo,
nullptr) ==
125 CHECK(obj->com.refCount == 3);
127 CHECK(WINPR_COM_ADDREF(foo) == 4);
128 CHECK(WINPR_COM_RELEASE(foo) == 3);
129 CHECK(WINPR_COM_RELEASE(unk) == 2);
130 CHECK(WINPR_COM_RELEASE(foo2) == 1);
132 CHECK(WINPR_COM_RELEASE(foo) == 0);
142 const ITestBarVtbl* lpBar;
147static CDouble* CDouble_from_bar(
wIUnknown* This)
149 return (CDouble*)((BYTE*)This - offsetof(CDouble, lpBar));
152static HRESULT CDouble_query(CDouble* obj,
const IID* riid,
void** ppvObject)
156 *ppvObject =
nullptr;
162 *ppvObject = &obj->com;
164 *ppvObject = (
void*)&obj->lpBar;
166 return E_NOINTERFACE;
177 return CDouble_query((CDouble*)This, riid, ppvObject);
182 return ((CDouble*)This)->foo;
185static const ITestFooVtbl CDouble_vtbl = {
194 return CDouble_query(CDouble_from_bar(This), riid, ppvObject);
209 return CDouble_from_bar((
wIUnknown*)This)->bar;
212static const ITestBarVtbl CDoubleBar_vtbl = {
214 .Bar = CDoubleBar_Bar,
217static void CDouble_free(wComBase*
object)
223static BOOL test_double(
void)
226 CDouble* obj = calloc(1,
sizeof(*obj));
229 obj->lpBar = &CDoubleBar_vtbl;
232 ITestFoo* foo = (ITestFoo*)obj;
234 ITestBar* bar =
nullptr;
236 CHECK((
void*)bar != (
void*)foo);
237 CHECK(bar->lpVtbl->Bar(bar) == 2);
240 ITestFoo* foo2 =
nullptr;
243 CHECK(foo2->lpVtbl->Foo(foo2) == 1);
253 CHECK(obj->com.refCount == 5);
254 CHECK(WINPR_COM_RELEASE(unk1) == 4);
255 CHECK(WINPR_COM_RELEASE(unk2) == 3);
256 CHECK(WINPR_COM_RELEASE(foo2) == 2);
257 CHECK(WINPR_COM_RELEASE(foo) == 1);
259 CHECK(WINPR_COM_RELEASE(bar) == 0);
264static BOOL test_guid(
void)
269 char guid[64] = WINPR_C_ARRAY_INIT;
270 (void)snprintf(guid,
sizeof(guid),
WINPR_COM_GUID_FMT, WINPR_COM_GUID_ARGS(&IID_ITestFoo));
271 CHECK(strcmp(guid,
"{01234567-89AB-CDEF-0123-456789ABCDEF}") == 0);
275int TestCom(
int argc,
char* argv[])
280 if (!test_guid() || !test_single() || !test_double())
#define WINPR_COM_GUID_FMT
printf a GUID as {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}: WLog_DBG(TAG, "id=" WINPR_COM_GUID_FMT,...
static BOOL winpr_com_guid_equal(const GUID *a, const GUID *b)
IsEqualGUID.
#define WINPR_COM_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
defines a GUID constant visible in the including file only (nothing to link)
WINPR_API void winpr_com_base_init(wComBase *object, const char *className, const wIUnknownVtbl *vtbl, pfnwComBaseFree Free)
sets the vtable and the reference count to 1, the caller owns that first reference.
WINPR_API ULONG winpr_com_base_add_ref(wComBase *object)
AddRef of an object starting with a wComBase.
#define WINPR_COM_IUNKNOWN_THUNKS(prefix, iid)
WINPR_COM_REFCOUNT_THUNKS plus prefix_QueryInterface answering IUnknown and iid (a const IID*,...
#define WINPR_COM_IUNKNOWN_ENTRIES(prefix)
the initializer of a wIUnknownVtbl from prefix_QueryInterface (the thunk above or the object's own),...
#define WINPR_COM_QUERY_INTERFACE(obj, iid, ppv)
IUnknown calls on an interface in C form. In C++, the C++ form of wIUnknown is called directly: unkno...
#define WINPR_COM_CALL
the calling convention of COM methods (STDMETHODCALLTYPE)
#define WINPR_COM_REFCOUNT_THUNKS(prefix)
prefix_AddRef and prefix_Release, for an object starting with a wComBase
WINPR_API ULONG winpr_com_base_release(wComBase *object)
Release of an object starting with a wComBase: calls its Free at 0.
the vtable of IUnknown, the first entries of every COM vtable