Coverage Report

Created: 2026-07-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/include/winpr/wlog.h
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * WinPR Logger
4
 *
5
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2015 Thincast Technologies GmbH
7
 * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
8
 *
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 *     http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22
23
#ifndef WINPR_LOG_H
24
#define WINPR_LOG_H
25
26
#ifdef __cplusplus
27
extern "C"
28
{
29
#endif
30
31
#include <stdarg.h>
32
33
#include <winpr/platform.h>
34
#include <winpr/wtypes.h>
35
#include <winpr/winpr.h>
36
#include <winpr/synch.h>
37
#include <winpr/thread.h>
38
39
/**
40
 * Log Levels
41
 */
42
typedef enum WINPR_C23_ENUM_TYPE(uint32_t)
43
{
44
  WLOG_TRACE = 0,
45
  WLOG_DEBUG = 1,
46
  WLOG_INFO = 2,
47
  WLOG_WARN = 3,
48
  WLOG_ERROR = 4,
49
  WLOG_FATAL = 5,
50
  WLOG_OFF = 6,
51
  WLOG_LEVEL_INHERIT = 0xFFFF
52
} wLogLevel;
53
54
/** @defgroup LogMessageTypes Log Message
55
 *  @{
56
 */
57
typedef enum WINPR_C23_ENUM_TYPE(uint32_t)
58
{
59
  WLOG_MESSAGE_TEXT = 0,
60
  WLOG_MESSAGE_DATA = 1,
61
  WLOG_MESSAGE_IMAGE = 2,
62
  WLOG_MESSAGE_PACKET = 3
63
} wLogMessageType;
64
65
/**
66
 * @}
67
 */
68
69
/**
70
 * Log Appenders
71
 */
72
typedef enum WINPR_C23_ENUM_TYPE(uint32_t)
73
{
74
  WLOG_APPENDER_CONSOLE = 0,
75
  WLOG_APPENDER_FILE = 1,
76
  WLOG_APPENDER_BINARY = 2,
77
  WLOG_APPENDER_CALLBACK = 3,
78
  WLOG_APPENDER_SYSLOG = 4,
79
  WLOG_APPENDER_JOURNALD = 5,
80
  WLOG_APPENDER_UDP = 6
81
} wLogAppenderType;
82
83
typedef struct
84
{
85
  DWORD Type;
86
87
  DWORD Level;
88
89
  LPSTR PrefixString;
90
91
  LPCSTR FormatString;
92
  LPCSTR TextString;
93
94
  size_t LineNumber;   /* __LINE__ */
95
  LPCSTR FileName;     /* __FILE__ */
96
  LPCSTR FunctionName; /* __func__ */
97
98
  /* Data Message */
99
100
  void* Data;
101
  size_t Length;
102
103
  /* Image Message */
104
105
  void* ImageData;
106
  size_t ImageWidth;
107
  size_t ImageHeight;
108
  size_t ImageBpp;
109
110
  /* Packet Message */
111
112
  void* PacketData;
113
  size_t PacketLength;
114
  DWORD PacketFlags;
115
} wLogMessage;
116
  typedef struct s_wLogLayout wLogLayout;
117
  typedef struct s_wLogAppender wLogAppender;
118
  typedef struct s_wLog wLog;
119
120
#define WLOG_PACKET_INBOUND 1
121
0
#define WLOG_PACKET_OUTBOUND 2
122
123
  /** @brief specialized function to print text log messages.
124
   *  Same as @ref WLog_PrintMessage with \b type = WLOG_MESSAGE_TEXT but with compile time checks
125
   * for issues in format string.
126
   *
127
   *  @param log A pointer to the logger to use
128
   *  @param line the file line the log message originates from
129
   *  @param file the file name the log message originates from
130
   *  @param function the function name the log message originates from
131
   *  @param fmt the printf style format string
132
   *
133
   *  @return \b TRUE for success, \b FALSE otherwise.
134
   *  @since version 3.17.0
135
   */
136
  WINPR_ATTR_FORMAT_ARG(6, 7)
137
  WINPR_API BOOL WLog_PrintTextMessage(wLog* log, DWORD level, size_t line, const char* file,
138
                                       const char* function, WINPR_FORMAT_ARG const char* fmt,
139
                                       ...);
140
141
  /** @brief specialized function to print text log messages.
142
   *  Same as @ref WLog_PrintMessageVA with \b type = WLOG_MESSAGE_TEXT but with compile time
143
   * checks for issues in format string.
144
   *
145
   *  @param log A pointer to the logger to use
146
   *  @param line the file line the log message originates from
147
   *  @param file the file name the log message originates from
148
   *  @param function the function name the log message originates from
149
   *  @param fmt the printf style format string
150
   *
151
   *  @return \b TRUE for success, \b FALSE otherwise.
152
   *  @since version 3.17.0
153
   */
154
  WINPR_ATTR_FORMAT_ARG(6, 0)
155
  WINPR_API BOOL WLog_PrintTextMessageVA(wLog* log, DWORD level, size_t line, const char* file,
156
                                         const char* function, WINPR_FORMAT_ARG const char* fmt,
157
                                         va_list args);
158
159
  /** @brief log something of a specified type.
160
   *  @bug For /b WLOG_MESSAGE_TEXT the format string is not validated at compile time. Use \ref
161
   * WLog_PrintTextMessage instead.
162
   *
163
   *  @param log A pointer to the logger to use
164
   *  @param type The type of message to log, can be any of \ref LogMessageTypes
165
   *  @param line the file line the log message originates from
166
   *  @param file the file name the log message originates from
167
   *  @param function the function name the log message originates from
168
   *
169
   *  @return \b TRUE for success, \b FALSE otherwise.
170
   */
171
  WINPR_API BOOL WLog_PrintMessage(wLog* log, DWORD type, DWORD level, size_t line,
172
                                   const char* file, const char* function, ...);
173
174
  /** @brief log something of a specified type.
175
   *  @bug For /b WLOG_MESSAGE_TEXT the format string is not validated at compile time. Use \ref
176
   * WLog_PrintTextMessageVA instead.
177
   *
178
   *  @param log A pointer to the logger to use
179
   *  @param type The type of message to log, can be any of \ref LogMessageTypes
180
   *  @param line the file line the log message originates from
181
   *  @param file the file name the log message originates from
182
   *  @param function the function name the log message originates from
183
   *
184
   *  @return \b TRUE for success, \b FALSE otherwise.
185
   */
186
  WINPR_API BOOL WLog_PrintMessageVA(wLog* log, DWORD type, DWORD level, size_t line,
187
                                     const char* file, const char* function, va_list args);
188
189
  WINPR_ATTR_NODISCARD
190
  WINPR_API wLog* WLog_GetRoot(void);
191
192
  WINPR_ATTR_NODISCARD
193
  WINPR_API wLog* WLog_Get(LPCSTR name);
194
195
  /** @brief discard a WLog instance created by \b WLog_Discard and not managed internally.
196
   *
197
   *  @param log The logger instance to discard.
198
   *  @since version 3.25.0
199
   */
200
  WINPR_API void WLog_Discard(wLog* log);
201
202
  /** @brief Create an independent logger instance. Management of this logger
203
   *  is up to the caller.
204
   *
205
   *  @param name The name of the logger, must not be \b nullptr
206
   *  @param root The parent logger this instance should copy defaults from.
207
   *  @return A new logger instance or \b nullptr in case of failures.
208
   *  @since version 3.25.0
209
   */
210
  WINPR_ATTR_MALLOC(WLog_Discard, 1)
211
  WINPR_API wLog* WLog_Create(LPCSTR name, wLog* root);
212
213
  WINPR_ATTR_NODISCARD
214
  WINPR_API DWORD WLog_GetLogLevel(wLog* log);
215
216
  WINPR_ATTR_NODISCARD
217
  WINPR_API BOOL WLog_IsLevelActive(wLog* _log, DWORD _log_level);
218
219
  /** @brief Set a custom context for a dynamic logger.
220
   *  This can be used to print a customized prefix, e.g. some session id for a specific context
221
   *
222
   *  @warning In multi instance applications only use this with loggers created with \b
223
   * WLog_Create otherwise there may be out of bound reads as the internally managed loggers only
224
   * support a single context
225
   *
226
   *  @param log The logger to ste the context for. Must not be \b nullptr
227
   *  @param fkt A function pointer that is called to get the custimized string.
228
   *  @param context A context \b fkt is called with. Caller must ensure it is still allocated
229
   * when \b log is used
230
   *
231
   *  @return \b TRUE for success, \b FALSE otherwise.
232
   */
233
  WINPR_API BOOL WLog_SetContext(wLog* log, const char* (*fkt)(void*), void* context);
234
235
  /** @brief Set a application wide global logger prefix.
236
   *  This can be used to distinguish WLog entries from different applicatiions like
237
   * freerpd-shadow-cli and xfreerdp. It also allows setting a dynamic prefix depending on command
238
   * line arguments to separate different xfreerdp instances.
239
   *
240
   * @warning This function should only be called directly after \b main before any threads start
241
   * up. Thread safety is undefined!
242
   *
243
   *  @param globalprefix Set a global prefix string prepended to all logger entries. Use \b
244
   * nullptr to disable prefix.
245
   *  @return \b TRUE for success, \b FALSE otherwise.
246
   *  @version since 3.25.0
247
   */
248
  WINPR_API BOOL WLog_SetGlobalContext(const char* globalprefix);
249
250
#define WLog_Print_unchecked(_log, _log_level, ...)                                         \
251
2.39k
  do                                                                                      \
252
2.39k
  {                                                                                       \
253
2.39k
    WLog_PrintTextMessage(_log, _log_level, __LINE__, __FILE__, __func__, __VA_ARGS__); \
254
2.39k
  } while (0)
255
256
#define WLog_Print(_log, _log_level, ...)                        \
257
2.39k
  do                                                           \
258
2.39k
  {                                                            \
259
2.39k
    if (WLog_IsLevelActive(_log, _log_level))                \
260
2.39k
    {                                                        \
261
2.39k
      WLog_Print_unchecked(_log, _log_level, __VA_ARGS__); \
262
2.39k
    }                                                        \
263
2.39k
  } while (0)
264
265
#define WLog_Print_tag(_tag, _log_level, ...)                 \
266
  do                                                        \
267
  {                                                         \
268
    static wLog* _log_cached_ptr = nullptr;               \
269
    if (!_log_cached_ptr)                                 \
270
      _log_cached_ptr = WLog_Get(_tag);                 \
271
    WLog_Print(_log_cached_ptr, _log_level, __VA_ARGS__); \
272
  } while (0)
273
274
#define WLog_PrintVA_unchecked(_log, _log_level, _fmt, _args)                                 \
275
  do                                                                                        \
276
  {                                                                                         \
277
    WLog_PrintTextMessageVA(_log, _log_level, __LINE__, __FILE__, __func__, _fmt, _args); \
278
  } while (0)
279
280
#define WLog_PrintVA(_log, _log_level, _fmt, _args)                \
281
  do                                                             \
282
  {                                                              \
283
    if (WLog_IsLevelActive(_log, _log_level))                  \
284
    {                                                          \
285
      WLog_PrintVA_unchecked(_log, _log_level, _fmt, _args); \
286
    }                                                          \
287
  } while (0)
288
289
#define WLog_Data(_log, _log_level, ...)                                                         \
290
  do                                                                                           \
291
  {                                                                                            \
292
    if (WLog_IsLevelActive(_log, _log_level))                                                \
293
    {                                                                                        \
294
      WLog_PrintMessage(_log, WLOG_MESSAGE_DATA, _log_level, __LINE__, __FILE__, __func__, \
295
                        __VA_ARGS__);                                                      \
296
    }                                                                                        \
297
  } while (0)
298
299
#define WLog_Image(_log, _log_level, ...)                                                        \
300
  do                                                                                           \
301
  {                                                                                            \
302
    if (WLog_IsLevelActive(_log, _log_level))                                                \
303
    {                                                                                        \
304
      WLog_PrintMessage(_log, WLOG_MESSAGE_DATA, _log_level, __LINE__, __FILE__, __func__, \
305
                        __VA_ARGS__);                                                      \
306
    }                                                                                        \
307
  } while (0)
308
309
#define WLog_Packet(_log, _log_level, ...)                                                         \
310
  do                                                                                             \
311
  {                                                                                              \
312
    if (WLog_IsLevelActive(_log, _log_level))                                                  \
313
    {                                                                                          \
314
      WLog_PrintMessage(_log, WLOG_MESSAGE_PACKET, _log_level, __LINE__, __FILE__, __func__, \
315
                        __VA_ARGS__);                                                        \
316
    }                                                                                          \
317
  } while (0)
318
319
  WINPR_ATTR_FORMAT_ARG(6, 7)
320
  static inline void WLog_Print_dbg_tag(const char* WINPR_RESTRICT tag, DWORD log_level,
321
                                        size_t line, const char* file, const char* fkt,
322
                                        WINPR_FORMAT_ARG const char* fmt, ...)
323
0
  {
324
0
    static wLog* log_cached_ptr = nullptr;
325
0
    if (!log_cached_ptr)
326
0
      log_cached_ptr = WLog_Get(tag);
327
328
0
    if (WLog_IsLevelActive(log_cached_ptr, log_level))
329
0
    {
330
0
      va_list ap = WINPR_C_ARRAY_INIT;
331
0
      va_start(ap, fmt);
332
0
      WLog_PrintTextMessageVA(log_cached_ptr, log_level, line, file, fkt, fmt, ap);
333
0
      va_end(ap);
334
0
    }
335
0
  }
Unexecuted instantiation: TestFuzzDrdynvc.c:WLog_Print_dbg_tag
Unexecuted instantiation: stream.c:WLog_Print_dbg_tag
Unexecuted instantiation: debug.c:WLog_Print_dbg_tag
Unexecuted instantiation: wlog.c:WLog_Print_dbg_tag
Unexecuted instantiation: Appender.c:WLog_Print_dbg_tag
Unexecuted instantiation: FileAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: BinaryAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: CallbackAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: ConsoleAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: UdpAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: SyslogAppender.c:WLog_Print_dbg_tag
Unexecuted instantiation: process.c:WLog_Print_dbg_tag
Unexecuted instantiation: winsock.c:WLog_Print_dbg_tag
Unexecuted instantiation: unicode.c:WLog_Print_dbg_tag
Unexecuted instantiation: string.c:WLog_Print_dbg_tag
Unexecuted instantiation: assert.c:WLog_Print_dbg_tag
Unexecuted instantiation: unicode_builtin.c:WLog_Print_dbg_tag
Unexecuted instantiation: critical.c:WLog_Print_dbg_tag
Unexecuted instantiation: event.c:WLog_Print_dbg_tag
Unexecuted instantiation: init.c:WLog_Print_dbg_tag
Unexecuted instantiation: sleep.c:WLog_Print_dbg_tag
Unexecuted instantiation: wait.c:WLog_Print_dbg_tag
Unexecuted instantiation: generic.c:WLog_Print_dbg_tag
Unexecuted instantiation: namedPipeClient.c:WLog_Print_dbg_tag
Unexecuted instantiation: pattern.c:WLog_Print_dbg_tag
Unexecuted instantiation: file.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm_ioctl.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm_serial_sys.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm_sercx_sys.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm_sercx2_sys.c:WLog_Print_dbg_tag
Unexecuted instantiation: pipe.c:WLog_Print_dbg_tag
Unexecuted instantiation: interlocked.c:WLog_Print_dbg_tag
Unexecuted instantiation: environment.c:WLog_Print_dbg_tag
Unexecuted instantiation: path.c:WLog_Print_dbg_tag
Unexecuted instantiation: shell.c:WLog_Print_dbg_tag
Unexecuted instantiation: atexit.c:WLog_Print_dbg_tag
Unexecuted instantiation: winpr.c:WLog_Print_dbg_tag
Unexecuted instantiation: ArrayList.c:WLog_Print_dbg_tag
Unexecuted instantiation: Layout.c:WLog_Print_dbg_tag
Unexecuted instantiation: Message.c:WLog_Print_dbg_tag
Unexecuted instantiation: DataMessage.c:WLog_Print_dbg_tag
Unexecuted instantiation: ImageMessage.c:WLog_Print_dbg_tag
Unexecuted instantiation: PacketMessage.c:WLog_Print_dbg_tag
Unexecuted instantiation: error.c:WLog_Print_dbg_tag
Unexecuted instantiation: sysinfo.c:WLog_Print_dbg_tag
Unexecuted instantiation: handle.c:WLog_Print_dbg_tag
Unexecuted instantiation: apc.c:WLog_Print_dbg_tag
Unexecuted instantiation: argv.c:WLog_Print_dbg_tag
Unexecuted instantiation: thread.c:WLog_Print_dbg_tag
Unexecuted instantiation: nt.c:WLog_Print_dbg_tag
Unexecuted instantiation: pollset.c:WLog_Print_dbg_tag
Unexecuted instantiation: comm_io.c:WLog_Print_dbg_tag
Unexecuted instantiation: image.c:WLog_Print_dbg_tag
336
337
#define WLog_LVL(tag, lvl, ...) \
338
  WLog_Print_dbg_tag(tag, lvl, __LINE__, __FILE__, __func__, __VA_ARGS__)
339
#define WLog_VRB(tag, ...) \
340
  WLog_Print_dbg_tag(tag, WLOG_TRACE, __LINE__, __FILE__, __func__, __VA_ARGS__)
341
#define WLog_DBG(tag, ...) \
342
0
  WLog_Print_dbg_tag(tag, WLOG_DEBUG, __LINE__, __FILE__, __func__, __VA_ARGS__)
343
#define WLog_INFO(tag, ...) \
344
  WLog_Print_dbg_tag(tag, WLOG_INFO, __LINE__, __FILE__, __func__, __VA_ARGS__)
345
#define WLog_WARN(tag, ...) \
346
0
  WLog_Print_dbg_tag(tag, WLOG_WARN, __LINE__, __FILE__, __func__, __VA_ARGS__)
347
#define WLog_ERR(tag, ...) \
348
0
  WLog_Print_dbg_tag(tag, WLOG_ERROR, __LINE__, __FILE__, __func__, __VA_ARGS__)
349
#define WLog_FATAL(tag, ...) \
350
0
  WLog_Print_dbg_tag(tag, WLOG_FATAL, __LINE__, __FILE__, __func__, __VA_ARGS__)
351
352
  WINPR_ATTR_NODISCARD
353
  WINPR_API BOOL WLog_SetLogLevel(wLog* log, DWORD logLevel);
354
355
  WINPR_ATTR_NODISCARD
356
  WINPR_API BOOL WLog_SetStringLogLevel(wLog* log, LPCSTR level);
357
358
  WINPR_ATTR_NODISCARD
359
  WINPR_API BOOL WLog_AddStringLogFilters(LPCSTR filter);
360
361
  WINPR_ATTR_NODISCARD
362
  WINPR_API BOOL WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType);
363
364
  WINPR_ATTR_NODISCARD
365
  WINPR_API wLogAppender* WLog_GetLogAppender(wLog* log);
366
367
  WINPR_ATTR_NODISCARD
368
  WINPR_API BOOL WLog_OpenAppender(wLog* log);
369
370
  WINPR_ATTR_NODISCARD
371
  WINPR_API BOOL WLog_CloseAppender(wLog* log);
372
373
  WINPR_ATTR_NODISCARD
374
  WINPR_API BOOL WLog_ConfigureAppender(wLogAppender* appender, const char* setting, void* value);
375
376
  /** @brief Set a custom context for an appender type
377
   *
378
   *  @note The context must stay valid until wLog is terminated!
379
   *
380
   *  @param appender The appender to configure, must not be nullptr
381
   *  @param type The logmessage type to set the context for
382
   *  @param context The custom context to pass to the logger
383
   *
384
   *  @return \b TRUE for success, \b FALSE otherwise
385
   *
386
   *  @since version 3.28.0
387
   */
388
  WINPR_ATTR_NODISCARD
389
  WINPR_API BOOL WLog_SetAppenderContext(wLogAppender* appender, wLogMessageType type,
390
                                         void* context);
391
392
  /** @brief Get a custom context for an appender
393
   *
394
   *  @param appender The appender to configure, must not be nullptr
395
   *  @param type The logmessage type to get the context for
396
   *
397
   *  @return the context set for the logmessage type, might be nullptr
398
   *  @since version 3.28.0
399
   */
400
  WINPR_ATTR_NODISCARD
401
  WINPR_API void* WLog_GetAppenderContext(wLogAppender* appender, wLogMessageType type);
402
403
  WINPR_ATTR_NODISCARD
404
  WINPR_API wLogLayout* WLog_GetLogLayout(wLog* log);
405
406
  WINPR_ATTR_NODISCARD
407
  WINPR_API BOOL WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format);
408
409
#if defined(WITH_WINPR_DEPRECATED)
410
  /** Deprecated */
411
  WINPR_DEPRECATED(WINPR_ATTR_NODISCARD WINPR_API BOOL WLog_Init(void));
412
413
  /** Deprecated */
414
  WINPR_DEPRECATED(WINPR_ATTR_NODISCARD WINPR_API BOOL WLog_Uninit(void));
415
#endif
416
417
  typedef BOOL (*wLogCallbackMessage_t)(const wLogMessage* msg);
418
  typedef BOOL (*wLogCallbackData_t)(const wLogMessage* msg);
419
  typedef BOOL (*wLogCallbackImage_t)(const wLogMessage* msg);
420
  typedef BOOL (*wLogCallbackPackage_t)(const wLogMessage* msg);
421
422
  typedef struct
423
  {
424
    WINPR_ATTR_NODISCARD wLogCallbackData_t data;
425
    WINPR_ATTR_NODISCARD wLogCallbackImage_t image;
426
    WINPR_ATTR_NODISCARD wLogCallbackMessage_t message;
427
    WINPR_ATTR_NODISCARD wLogCallbackPackage_t package;
428
  } wLogCallbacks;
429
430
  /** @brief extended callback type with context
431
   *  @since version 3.28.0
432
   */
433
  typedef BOOL (*wLogCallbackMessageEx_t)(wLogAppender* appender, const wLogMessage* msg);
434
435
  /** @brief extended callback type with context
436
   *  @since version 3.28.0
437
   */
438
  typedef struct
439
  {
440
    WINPR_ATTR_NODISCARD wLogCallbackMessageEx_t data;
441
    WINPR_ATTR_NODISCARD wLogCallbackMessageEx_t image;
442
    WINPR_ATTR_NODISCARD wLogCallbackMessageEx_t message;
443
    WINPR_ATTR_NODISCARD wLogCallbackMessageEx_t package;
444
  } wLogCallbacksEx;
445
446
#ifdef __cplusplus
447
}
448
#endif
449
450
#endif /* WINPR_WLOG_H */