FreeRDP
Loading...
Searching...
No Matches
com.h File Reference
#include <string.h>
#include <winpr/platform.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/error.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  wIUnknownVtbl
 the vtable of IUnknown, the first entries of every COM vtable More...
 
struct  wIUnknown
 IUnknown, C form. More...
 
struct  wComBase
 

Macros

#define WINPR_COM_CALL
 the calling convention of COM methods (STDMETHODCALLTYPE)
 
#define WINPR_COM_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)    static const 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)
 
#define WINPR_COM_GUID_FMT
 printf a GUID as {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}: WLog_DBG(TAG, "id=" WINPR_COM_GUID_FMT, WINPR_COM_GUID_ARGS(guid))
 
#define WINPR_COM_GUID_ARGS(g)
 
#define WINPR_COM_IUNKNOWN_VTBL(obj)   ((const wIUnknownVtbl*)(obj)->lpVtbl)
 the wIUnknownVtbl of obj, an interface in C form (wIUnknown itself or one whose vtable starts with iunknown)
 
#define WINPR_COM_QUERY_INTERFACE(obj, iid, ppv)    (WINPR_COM_IUNKNOWN_VTBL(obj)->QueryInterface((wIUnknown*)(obj), (iid), (void**)(ppv)))
 IUnknown calls on an interface in C form. In C++, the C++ form of wIUnknown is called directly: unknown->Release()
 
#define WINPR_COM_ADDREF(obj)   (WINPR_COM_IUNKNOWN_VTBL(obj)->AddRef((wIUnknown*)(obj)))
 
#define WINPR_COM_RELEASE(obj)   (WINPR_COM_IUNKNOWN_VTBL(obj)->Release((wIUnknown*)(obj)))
 
#define WINPR_COM_REFCOUNT_THUNKS(prefix)
 prefix_AddRef and prefix_Release, for 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*, nullptr for IUnknown only)
 
#define WINPR_COM_IUNKNOWN_ENTRIES(prefix)    { prefix##_QueryInterface, prefix##_AddRef, prefix##_Release }
 the initializer of a wIUnknownVtbl from prefix_QueryInterface (the thunk above or the object's own), prefix_AddRef and prefix_Release
 

Typedefs

typedef void(* pfnwComBaseFree) (wComBase *object)
 called when the last reference goes away: releases what the object holds and frees it
 

Functions

 WINPR_COM_DEFINE_GUID (WINPR_IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
 IID_IUnknown, {00000000-0000-0000-C000-000000000046}.
 
static BOOL winpr_com_guid_equal (const GUID *a, const GUID *b)
 IsEqualGUID.
 
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.
 
WINPR_API ULONG winpr_com_base_release (wComBase *object)
 Release of an object starting with a wComBase: calls its Free at 0.
 
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 the object, with a new reference.
 

Detailed Description

WinPR: Windows Portable Runtime Minimal COM object support

Copyright 2026 David Fort conta.nosp@m.ct@h.nosp@m.arden.nosp@m.ing-.nosp@m.consu.nosp@m.ltin.nosp@m.g.com

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Just enough COM to implement and use objects that are binary compatible with Windows COM objects, on all platforms.

The SDK COM headers (unknwn.h, objbase.h) are never included (codespell:ignore unknwn), even on Windows: everything here has its own name (wIUnknown, WINPR_IID_IUnknown, ...), so it coexists with them in a file that includes them. The binary layout and calling convention are the Windows ones: a wIUnknown* can be passed where Windows expects an IUnknown*, and the other way around.

In C, an interface is a struct whose only member is lpVtbl, and its vtable starts with a wIUnknownVtbl named iunknown, followed by the interface's own methods:

typedef struct IFoo IFoo; typedef struct { wIUnknownVtbl iunknown; UINT32(WINPR_COM_CALL* Foo)(IFoo* This); } IFooVtbl; struct IFoo { const IFooVtbl* lpVtbl; };

This is the layout of a MIDL vtable (the three IUnknown entries, then the others), and &vtbl->iunknown is a wIUnknownVtbl without any cast. The IUnknown entries take a wIUnknown*; the WINPR_COM_QUERY_INTERFACE / ADDREF / RELEASE macros call them on any interface.

In C++, wIUnknown is also given as a class with pure virtual methods, which has the same layout (define WINPR_COM_CINTERFACE to get the C form in C++ too). Such C++ interfaces must not have a virtual destructor nor overloaded methods, and only use single inheritance, or the vtable layout differs between compilers.

IIDs are passed as const IID* (winpr's POSIX REFIID is not const; on Windows it is the same pointer).

Since
version 3.34.0

Definition in file com.h.


Data Structure Documentation

◆ wIUnknown

struct wIUnknown

IUnknown, C form.

Definition at line 110 of file com.h.

Collaboration diagram for wIUnknown:
Data Fields
const wIUnknownVtbl * lpVtbl

◆ s_wComBase

struct s_wComBase

Definition at line 187 of file com.h.

Collaboration diagram for wComBase:
Data Fields
const char * className
pfnwComBaseFree Free
const wIUnknownVtbl * lpVtbl
volatile LONG refCount

Macro Definition Documentation

◆ WINPR_COM_ADDREF

#define WINPR_COM_ADDREF (   obj)    (WINPR_COM_IUNKNOWN_VTBL(obj)->AddRef((wIUnknown*)(obj)))

Definition at line 152 of file com.h.

◆ WINPR_COM_CALL

#define WINPR_COM_CALL

the calling convention of COM methods (STDMETHODCALLTYPE)

Definition at line 73 of file com.h.

◆ WINPR_COM_DEFINE_GUID

#define WINPR_COM_DEFINE_GUID (   name,
  l,
  w1,
  w2,
  b1,
  b2,
  b3,
  b4,
  b5,
  b6,
  b7,
  b8 
)     static const 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 at line 122 of file com.h.

123 { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }

◆ WINPR_COM_GUID_ARGS

#define WINPR_COM_GUID_ARGS (   g)
Value:
(UINT32)(g)->Data1, (UINT16)(g)->Data2, (UINT16)(g)->Data3, (g)->Data4[0], (g)->Data4[1], \
(g)->Data4[2], (g)->Data4[3], (g)->Data4[4], (g)->Data4[5], (g)->Data4[6], (g)->Data4[7]

Definition at line 140 of file com.h.

◆ WINPR_COM_GUID_FMT

#define WINPR_COM_GUID_FMT
Value:
"{%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 \
"%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "}"

printf a GUID as {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}: WLog_DBG(TAG, "id=" WINPR_COM_GUID_FMT, WINPR_COM_GUID_ARGS(guid))

Definition at line 137 of file com.h.

138 {%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 \
139 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "}"

◆ WINPR_COM_IUNKNOWN_ENTRIES

#define WINPR_COM_IUNKNOWN_ENTRIES (   prefix)     { prefix##_QueryInterface, prefix##_AddRef, prefix##_Release }

the initializer of a wIUnknownVtbl from prefix_QueryInterface (the thunk above or the object's own), prefix_AddRef and prefix_Release

Definition at line 241 of file com.h.

242 { prefix##_QueryInterface, prefix##_AddRef, prefix##_Release }

◆ WINPR_COM_IUNKNOWN_THUNKS

#define WINPR_COM_IUNKNOWN_THUNKS (   prefix,
  iid 
)
Value:
static HRESULT WINPR_COM_CALL prefix##_QueryInterface(wIUnknown* This, const IID* riid, \
void** ppvObject) \
{ \
return winpr_com_base_query((wComBase*)This, (iid), riid, ppvObject); \
} \
WINPR_COM_REFCOUNT_THUNKS(prefix)
#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
IUnknown, C form.
Definition com.h:111

WINPR_COM_REFCOUNT_THUNKS plus prefix_QueryInterface answering IUnknown and iid (a const IID*, nullptr for IUnknown only)

Definition at line 231 of file com.h.

234 { \
235 return winpr_com_base_query((wComBase*)This, (iid), riid, ppvObject); \
236 } \
237 WINPR_COM_REFCOUNT_THUNKS(prefix)

◆ WINPR_COM_IUNKNOWN_VTBL

#define WINPR_COM_IUNKNOWN_VTBL (   obj)    ((const wIUnknownVtbl*)(obj)->lpVtbl)

the wIUnknownVtbl of obj, an interface in C form (wIUnknown itself or one whose vtable starts with iunknown)

Definition at line 146 of file com.h.

◆ WINPR_COM_QUERY_INTERFACE

#define WINPR_COM_QUERY_INTERFACE (   obj,
  iid,
  ppv 
)     (WINPR_COM_IUNKNOWN_VTBL(obj)->QueryInterface((wIUnknown*)(obj), (iid), (void**)(ppv)))

IUnknown calls on an interface in C form. In C++, the C++ form of wIUnknown is called directly: unknown->Release()

Definition at line 150 of file com.h.

◆ WINPR_COM_REFCOUNT_THUNKS

#define WINPR_COM_REFCOUNT_THUNKS (   prefix)
Value:
static ULONG WINPR_COM_CALL prefix##_AddRef(wIUnknown* This) \
{ \
return winpr_com_base_add_ref((wComBase*)This); \
} \
static ULONG WINPR_COM_CALL prefix##_Release(wIUnknown* This) \
{ \
return winpr_com_base_release((wComBase*)This); \
}
WINPR_API ULONG winpr_com_base_add_ref(wComBase *object)
AddRef of an object starting with a wComBase.
Definition com.c:43
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

prefix_AddRef and prefix_Release, for an object starting with a wComBase

Definition at line 219 of file com.h.

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 }

◆ WINPR_COM_RELEASE

#define WINPR_COM_RELEASE (   obj)    (WINPR_COM_IUNKNOWN_VTBL(obj)->Release((wIUnknown*)(obj)))

Definition at line 153 of file com.h.

Typedef Documentation

◆ pfnwComBaseFree

typedef void(* pfnwComBaseFree) (wComBase *object)

called when the last reference goes away: releases what the object holds and frees it

Definition at line 185 of file com.h.

Function Documentation

◆ winpr_com_base_add_ref()

WINPR_API ULONG winpr_com_base_add_ref ( wComBase *  object)

AddRef of an object starting with a wComBase.

Since
version 3.34.0

Definition at line 43 of file com.c.

44{
45 WINPR_ASSERT(object);
46 const LONG count = InterlockedIncrement(&object->refCount);
47 WLog_VRB(TAG, "%s::AddRef() -> %" PRId32, object->className, (INT32)count);
48 return (ULONG)count;
49}

References winpr_com_base_add_ref().

Referenced by winpr_com_base_add_ref(), and winpr_com_base_query().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ winpr_com_base_init()

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.

Parameters
vtblthe iunknown member of the vtable of the object's first interface
Since
version 3.34.0

Definition at line 30 of file com.c.

32{
33 WINPR_ASSERT(object);
34 WINPR_ASSERT(vtbl);
35 WINPR_ASSERT(Free);
36
37 object->lpVtbl = vtbl;
38 object->refCount = 1;
39 object->className = className ? className : "wComBase";
40 object->Free = Free;
41}

References winpr_com_base_init().

Referenced by freerdp_client_window_info_service_new(), plugin_services_new(), and winpr_com_base_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ winpr_com_base_query()

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 the object, with a new reference.

Since
version 3.34.0

Definition at line 63 of file com.c.

64{
65 WINPR_ASSERT(object);
66
67 if (!ppv)
68 return E_POINTER;
69 *ppv = nullptr;
70 if (!riid)
71 return E_POINTER;
72
73 if (!winpr_com_guid_equal(riid, &WINPR_IID_IUnknown) &&
74 (!iid || !winpr_com_guid_equal(riid, iid)))
75 {
76 WLog_DBG(TAG, "%s::QueryInterface(" WINPR_COM_GUID_FMT ") -> E_NOINTERFACE",
77 object->className, WINPR_COM_GUID_ARGS(riid));
78 return E_NOINTERFACE;
79 }
80
81 (void)winpr_com_base_add_ref(object);
82 *ppv = object;
83 return S_OK;
84}
#define WINPR_COM_GUID_FMT
printf a GUID as {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}: WLog_DBG(TAG, "id=" WINPR_COM_GUID_FMT,...
Definition com.h:137
static BOOL winpr_com_guid_equal(const GUID *a, const GUID *b)
IsEqualGUID.
Definition com.h:130

References winpr_com_base_add_ref(), winpr_com_base_query(), winpr_com_guid_equal(), and WINPR_COM_GUID_FMT.

Referenced by winpr_com_base_query().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ winpr_com_base_release()

WINPR_API ULONG winpr_com_base_release ( wComBase *  object)

Release of an object starting with a wComBase: calls its Free at 0.

Since
version 3.34.0

Definition at line 51 of file com.c.

52{
53 WINPR_ASSERT(object);
54 const LONG count = InterlockedDecrement(&object->refCount);
55 WLog_VRB(TAG, "%s::Release() -> %" PRId32, object->className, (INT32)count);
56 if (count == 0)
57 object->Free(object);
58 else if (count < 0)
59 WLog_ERR(TAG, "%s: released more often than referenced", object->className);
60 return (ULONG)count;
61}

References winpr_com_base_release().

Referenced by shared_subscribe(), shared_unsubscribe(), and winpr_com_base_release().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ winpr_com_guid_equal()

static BOOL winpr_com_guid_equal ( const GUID *  a,
const GUID *  b 
)
inlinestatic

IsEqualGUID.

Definition at line 130 of file com.h.

131 {
132 return memcmp(a, b, sizeof(*a)) == 0;
133 }

Referenced by winpr_com_base_query().

Here is the caller graph for this function: