FreeRDP
Loading...
Searching...
No Matches
com.h
Go to the documentation of this file.
1
20#ifndef WINPR_COM_H
21#define WINPR_COM_H
22
23#include <string.h>
24
25#include <winpr/platform.h>
26#include <winpr/winpr.h>
27#include <winpr/wtypes.h>
28#include <winpr/error.h>
29
70#if defined(_WIN32)
71#define WINPR_COM_CALL __stdcall
72#else
73#define WINPR_COM_CALL
74#endif
75
76#ifdef __cplusplus
77extern "C"
78{
79#endif
80
81 typedef struct wIUnknown wIUnknown;
82
84 typedef struct
85 {
86 HRESULT(WINPR_COM_CALL* QueryInterface)
87 (wIUnknown* This, const IID* riid, void** ppvObject);
88 ULONG(WINPR_COM_CALL* AddRef)(wIUnknown* This);
89 ULONG(WINPR_COM_CALL* Release)(wIUnknown* This);
91
92#ifdef __cplusplus
93}
94#endif
95
96#if defined(__cplusplus) && !defined(WINPR_COM_CINTERFACE)
98struct wIUnknown
99{
100 virtual HRESULT WINPR_COM_CALL QueryInterface(const IID* riid, void** ppvObject) = 0;
101 virtual ULONG WINPR_COM_CALL AddRef() = 0;
102 virtual ULONG WINPR_COM_CALL Release() = 0;
103
104 protected:
105 /* not virtual, which would add vtable entries: objects are freed by Release() */
106 ~wIUnknown() = default;
107};
108#else
111{
112 const wIUnknownVtbl* lpVtbl;
113};
114#endif
115
116#ifdef __cplusplus
117extern "C"
118{
119#endif
120
122#define WINPR_COM_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
123 static const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
124
126 WINPR_COM_DEFINE_GUID(WINPR_IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x46);
128
130 static inline BOOL winpr_com_guid_equal(const GUID* a, const GUID* b)
131 {
132 return memcmp(a, b, sizeof(*a)) == 0;
133 }
134
137#define WINPR_COM_GUID_FMT \
138 "{%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 \
139 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "}"
140#define WINPR_COM_GUID_ARGS(g) \
141 (UINT32)(g)->Data1, (UINT16)(g)->Data2, (UINT16)(g)->Data3, (g)->Data4[0], (g)->Data4[1], \
142 (g)->Data4[2], (g)->Data4[3], (g)->Data4[4], (g)->Data4[5], (g)->Data4[6], (g)->Data4[7]
143
146#define WINPR_COM_IUNKNOWN_VTBL(obj) ((const wIUnknownVtbl*)(obj)->lpVtbl)
147
150#define WINPR_COM_QUERY_INTERFACE(obj, iid, ppv) \
151 (WINPR_COM_IUNKNOWN_VTBL(obj)->QueryInterface((wIUnknown*)(obj), (iid), (void**)(ppv)))
152#define WINPR_COM_ADDREF(obj) (WINPR_COM_IUNKNOWN_VTBL(obj)->AddRef((wIUnknown*)(obj)))
153#define WINPR_COM_RELEASE(obj) (WINPR_COM_IUNKNOWN_VTBL(obj)->Release((wIUnknown*)(obj)))
154
155 /* ---- implementing COM objects in C ----
156 *
157 * An object starts with a wComBase, whose first member is lpVtbl: a pointer to the object is
158 * the pointer to its first interface, and methods cast This back to the object type.
159 *
160 * typedef struct {
161 * wComBase com; // IWTSFooService
162 * ...state...
163 * } CFooService;
164 *
165 * WINPR_COM_IUNKNOWN_THUNKS(CFooService, &IID_IWTSFooService)
166 * static const IWTSFooServiceVtbl vtbl = {
167 * .iunknown = WINPR_COM_IUNKNOWN_ENTRIES(CFooService),
168 * .DoSomething = CFooService_DoSomething,
169 * };
170 * ...
171 * winpr_com_base_init(&foo->com, "CFooService", &vtbl.iunknown, CFooService_free);
172 * return (IWTSFooService*)foo;
173 *
174 * WINPR_COM_IUNKNOWN_THUNKS answers QueryInterface for IUnknown and one interface. An object
175 * with several interfaces uses WINPR_COM_REFCOUNT_THUNKS and writes its own QueryInterface:
176 * each interface not derived from the first one needs its own vtable pointer in the object,
177 * QueryInterface hands out the address of that member, and the methods of that interface get
178 * the object back from it. QueryInterface(IID_IUnknown) must always give the same pointer.
179 */
180
181 typedef struct s_wComBase wComBase;
182
185 typedef void (*pfnwComBaseFree)(wComBase* object);
186
188 {
189 const wIUnknownVtbl* lpVtbl; /* the object's first interface, must stay first */
190 volatile LONG refCount;
191 const char* className; /* for logs */
192 pfnwComBaseFree Free;
193 };
194
198 WINPR_API void winpr_com_base_init(wComBase* object, const char* className,
199 const wIUnknownVtbl* vtbl, pfnwComBaseFree Free);
200
203 WINPR_API ULONG winpr_com_base_add_ref(wComBase* object);
204
207 WINPR_API ULONG winpr_com_base_release(wComBase* object);
208
212 WINPR_API HRESULT winpr_com_base_query(wComBase* object, const IID* iid, const IID* riid,
213 void** ppv);
214
215/* The IUnknown entries of a vtable, as static functions of the including file: a vtable is then
216 * a constant initializer (the address of a function imported from a DLL is not one for MSVC). */
217
219#define WINPR_COM_REFCOUNT_THUNKS(prefix) \
220 static ULONG WINPR_COM_CALL prefix##_AddRef(wIUnknown* This) \
221 { \
222 return winpr_com_base_add_ref((wComBase*)This); \
223 } \
224 static ULONG WINPR_COM_CALL prefix##_Release(wIUnknown* This) \
225 { \
226 return winpr_com_base_release((wComBase*)This); \
227 }
228
231#define WINPR_COM_IUNKNOWN_THUNKS(prefix, iid) \
232 static HRESULT WINPR_COM_CALL prefix##_QueryInterface(wIUnknown* This, const IID* riid, \
233 void** ppvObject) \
234 { \
235 return winpr_com_base_query((wComBase*)This, (iid), riid, ppvObject); \
236 } \
237 WINPR_COM_REFCOUNT_THUNKS(prefix)
238
241#define WINPR_COM_IUNKNOWN_ENTRIES(prefix) \
242 { prefix##_QueryInterface, prefix##_AddRef, prefix##_Release }
243
244#ifdef __cplusplus
245}
246#endif
247
248#endif /* WINPR_COM_H */
void(* pfnwComBaseFree)(wComBase *object)
called when the last reference goes away: releases what the object holds and frees it
Definition com.h:185
static BOOL winpr_com_guid_equal(const GUID *a, const GUID *b)
IsEqualGUID.
Definition com.h:130
#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)
Definition com.h:122
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.
Definition com.c:30
WINPR_API ULONG winpr_com_base_add_ref(wComBase *object)
AddRef of an object starting with a wComBase.
Definition com.c:43
#define WINPR_COM_CALL
the calling convention of COM methods (STDMETHODCALLTYPE)
Definition com.h:73
WINPR_API HRESULT winpr_com_base_query(wComBase *object, const IID *iid, const IID *riid, void **ppv)
QueryInterface of an object whose only interface is iid (nullptr: IUnknown only). On success *ppv is ...
Definition com.c:63
WINPR_API ULONG winpr_com_base_release(wComBase *object)
Release of an object starting with a wComBase: calls its Free at 0.
Definition com.c:51
IUnknown, C form.
Definition com.h:111
the vtable of IUnknown, the first entries of every COM vtable
Definition com.h:85