xref: /reactos/sdk/lib/atl/atltrace.h (revision 7f26a396)
1 /*
2  * PROJECT:     ReactOS ATL
3  * LICENSE:     LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:     Providing ATLTRACE macro
5  * COPYRIGHT:   Copyright 2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #pragma once
9 
10 #include "atldef.h"
11 
12 #ifdef _DEBUG
13 
14 #include <stdio.h>
15 #include <crtdbg.h>
16 
17 namespace ATL
18 {
19 
20 template <UINT t_category = (1 << 19), UINT t_level = 0>
21 class CTraceCategoryEx
22 {
23 public:
24     enum
25     {
26         TraceGeneral    = (1 << 0),
27         TraceCom        = (1 << 1),
28         TraceQI         = (1 << 2),
29         TraceRegistrar  = (1 << 3),
30         TraceRefcount   = (1 << 4),
31         TraceWindowing  = (1 << 5),
32         TraceControls   = (1 << 6),
33         TraceHosting    = (1 << 7),
34         TraceDBClient   = (1 << 8),
35         TraceDBProvider = (1 << 9),
36         TraceSnapin     = (1 << 10),
37         TraceNotImpl    = (1 << 11),
38         TraceAllocation = (1 << 12),
39         TraceException  = (1 << 13),
40         TraceTime       = (1 << 14),
41         TraceCache      = (1 << 15),
42         TraceStencil    = (1 << 16),
43         TraceString     = (1 << 17),
44         TraceMap        = (1 << 18),
45         TraceUtil       = (1 << 19),
46         TraceSecurity   = (1 << 20),
47         TraceSync       = (1 << 21),
48         TraceISAPI      = (1 << 22),
49         TraceUser       = TraceUtil
50     };
51 
52     CTraceCategoryEx(LPCTSTR name = NULL) : m_name(name)
53     {
54     }
55 
56     static UINT GetLevel()          { return t_level; }
57     static UINT GetCategory()       { return t_category; }
58     operator UINT() const           { return GetCategory(); }
59     LPCTSTR GetCategoryName() const { return m_name; }
60 
61 protected:
62     LPCTSTR m_name;
63 };
64 
65 class CTraceCategory : public CTraceCategoryEx<>
66 {
67     CTraceCategory(LPCTSTR name = NULL) : CTraceCategoryEx<>(name)
68     {
69     }
70 };
71 
72 #define DEFINE_TRACE_CATEGORY(name, cat) extern const DECLSPEC_SELECTANY CTraceCategoryEx<cat, 0> name(TEXT(#name))
73 DEFINE_TRACE_CATEGORY(atlTraceGeneral,    CTraceCategoryEx<>::TraceGeneral);
74 DEFINE_TRACE_CATEGORY(atlTraceCOM,        CTraceCategoryEx<>::TraceCom);
75 DEFINE_TRACE_CATEGORY(atlTraceQI,         CTraceCategoryEx<>::TraceQI);
76 DEFINE_TRACE_CATEGORY(atlTraceRegistrar,  CTraceCategoryEx<>::TraceRegistrar);
77 DEFINE_TRACE_CATEGORY(atlTraceRefcount,   CTraceCategoryEx<>::TraceRefcount);
78 DEFINE_TRACE_CATEGORY(atlTraceWindowing,  CTraceCategoryEx<>::TraceWindowing);
79 DEFINE_TRACE_CATEGORY(atlTraceControls,   CTraceCategoryEx<>::TraceControls);
80 DEFINE_TRACE_CATEGORY(atlTraceHosting,    CTraceCategoryEx<>::TraceHosting);
81 DEFINE_TRACE_CATEGORY(atlTraceDBClient,   CTraceCategoryEx<>::TraceDBClient);
82 DEFINE_TRACE_CATEGORY(atlTraceDBProvider, CTraceCategoryEx<>::TraceDBProvider);
83 DEFINE_TRACE_CATEGORY(atlTraceSnapin,     CTraceCategoryEx<>::TraceSnapin);
84 DEFINE_TRACE_CATEGORY(atlTraceNotImpl,    CTraceCategoryEx<>::TraceNotImpl);
85 DEFINE_TRACE_CATEGORY(atlTraceAllocation, CTraceCategoryEx<>::TraceAllocation);
86 DEFINE_TRACE_CATEGORY(atlTraceException,  CTraceCategoryEx<>::TraceException);
87 DEFINE_TRACE_CATEGORY(atlTraceTime,       CTraceCategoryEx<>::TraceTime);
88 DEFINE_TRACE_CATEGORY(atlTraceCache,      CTraceCategoryEx<>::TraceCache);
89 DEFINE_TRACE_CATEGORY(atlTraceStencil,    CTraceCategoryEx<>::TraceStencil);
90 DEFINE_TRACE_CATEGORY(atlTraceString,     CTraceCategoryEx<>::TraceString);
91 DEFINE_TRACE_CATEGORY(atlTraceMap,        CTraceCategoryEx<>::TraceMap);
92 DEFINE_TRACE_CATEGORY(atlTraceUtil,       CTraceCategoryEx<>::TraceUtil);
93 DEFINE_TRACE_CATEGORY(atlTraceSecurity,   CTraceCategoryEx<>::TraceSecurity);
94 DEFINE_TRACE_CATEGORY(atlTraceSync,       CTraceCategoryEx<>::TraceSync);
95 DEFINE_TRACE_CATEGORY(atlTraceISAPI,      CTraceCategoryEx<>::TraceISAPI);
96 #undef DEFINE_TRACE_CATEGORY
97 
98 struct CTraceCategoryEasy
99 {
100     UINT m_category;
101     UINT m_level;
102     LPCTSTR m_name;
103 
104     template <UINT t_category, UINT t_level>
105     CTraceCategoryEasy(const CTraceCategoryEx<t_category, t_level>& cat)
106     {
107         m_category = t_category;
108         m_level = t_level;
109         m_name = cat.GetCategoryName();
110     }
111 
112     operator UINT() const { return m_category; }
113 
114     BOOL IsGeneral() const
115     {
116         return lstrcmp(m_name, TEXT("atlTraceGeneral")) == 0;
117     }
118 };
119 
120 struct CTrace
121 {
122     enum
123     {
124         DefaultTraceLevel = 0,
125         DisableTracing = 0xFFFFFFFF,
126         EnableAllCategories = 0xFFFFFFFF
127     };
128 
129     static UINT GetLevel()                     { return s_level; }
130     static UINT GetCategories()                { return s_categories; }
131     static void SetLevel(UINT level)           { s_level = level; }
132     static void SetCategories(UINT categories) { s_categories = categories; }
133 
134     static bool IsTracingEnabled(UINT category, UINT level)
135     {
136         return (s_level != DisableTracing && s_level >= level && (s_categories & category));
137     }
138 
139 protected:
140     static UINT s_categories;
141     static UINT s_level;
142 };
143 
144 DECLSPEC_SELECTANY UINT CTrace::s_categories = CTrace::EnableAllCategories;
145 DECLSPEC_SELECTANY UINT CTrace::s_level      = CTrace::DefaultTraceLevel;
146 
147 template <typename X_CHAR>
148 inline VOID __stdcall
149 AtlTraceV(_In_opt_z_                     const X_CHAR *            file,
150           _In_                           INT                       line,
151           _In_                           const CTraceCategoryEasy& cat,
152           _In_                           UINT                      level,
153           _In_z_ _Printf_format_string_  PCSTR                     format,
154           _In_                           va_list                   va)
155 {
156     char szBuff[1024], szFile[MAX_PATH];
157     size_t cch = 0;
158     const BOOL bUnicode = (sizeof(TCHAR) == 2);
159 
160     if (!CTrace::IsTracingEnabled(cat, level))
161         return;
162 
163 #ifdef _STRSAFE_H_INCLUDED_
164     StringCchPrintfA(szFile, _countof(szFile), ((sizeof(X_CHAR) == 2) ? "%ls" : "%hs"), file);
165     if (!cat.IsGeneral())
166     {
167         StringCchPrintfA(szBuff, _countof(szBuff), (bUnicode ? "%ls - " : "%hs - "), cat.m_name);
168         StringCchLengthA(szBuff, _countof(szBuff), &cch);
169     }
170     StringCchVPrintfA(&szBuff[cch], _countof(szBuff) - cch, format, va);
171 #else
172     _snprintf(szFile, _countof(szFile), ((sizeof(X_CHAR) == 2) ? "%ls" : "%hs"), file);
173     if (!cat.IsGeneral())
174         cch = _snprintf(szBuff, _countof(szBuff), (bUnicode ? "%ls - " : "%hs - "), cat.m_name);
175     _vsnprintf(&szBuff[cch], _countof(szBuff) - cch, format, va);
176 #endif
177 
178     _CrtDbgReport(_CRT_WARN, szFile, line, NULL, "%hs", szBuff);
179 }
180 
181 template <typename X_CHAR>
182 inline VOID __stdcall
183 AtlTraceV(_In_opt_z_                     const X_CHAR *            file,
184           _In_                           INT                       line,
185           _In_                           const CTraceCategoryEasy& cat,
186           _In_                           UINT                      level,
187           _In_z_ _Printf_format_string_  PCWSTR                    format,
188           _In_                           va_list                   va)
189 {
190     WCHAR szBuff[1024], szFile[MAX_PATH];
191     size_t cch = 0;
192     const BOOL bUnicode = (sizeof(TCHAR) == 2);
193 
194     if (!CTrace::IsTracingEnabled(cat, level))
195         return;
196 
197 #ifdef _STRSAFE_H_INCLUDED_
198     StringCchPrintfW(szFile, _countof(szFile), ((sizeof(X_CHAR) == 2) ? L"%ls" : L"%hs"), file);
199     if (!cat.IsGeneral())
200     {
201         StringCchPrintfW(szBuff, _countof(szBuff), (bUnicode ? L"%ls - " : L"%hs - "), cat.m_name);
202         StringCchLengthW(szBuff, _countof(szBuff), &cch);
203     }
204     StringCchVPrintfW(&szBuff[cch], _countof(szBuff) - cch, format, va);
205 #else
206     _snwprintf(szFile, _countof(szFile), ((sizeof(X_CHAR) == 2) ? L"%ls" : L"%hs"), file);
207     if (!cat.IsGeneral())
208         cch = _snwprintf(szBuff, _countof(szBuff), (bUnicode ? L"%ls - " : L"%hs - "), cat.m_name);
209     _vsnwprintf(&szBuff[cch], _countof(szBuff) - cch, format, va);
210 #endif
211 
212     _CrtDbgReportW(_CRT_WARN, szFile, line, NULL, L"%ls", szBuff);
213 }
214 
215 template <typename X_CHAR, typename Y_CHAR>
216 inline VOID __cdecl
217 AtlTraceEx(_In_opt_z_                    const X_CHAR *            file,
218            _In_                          INT                       line,
219            _In_                          const CTraceCategoryEasy& cat,
220            _In_                          UINT                      level,
221            _In_z_ _Printf_format_string_ const Y_CHAR *            format,
222            ...)
223 {
224     va_list va;
225     va_start(va, format);
226     AtlTraceV(file, line, cat, level, format, va);
227     va_end(va);
228 }
229 
230 template <typename X_CHAR, typename Y_CHAR>
231 inline VOID __cdecl
232 AtlTraceEx(_In_opt_z_                    const X_CHAR *file,
233            _In_                          INT           line,
234            _In_z_ _Printf_format_string_ const Y_CHAR *format,
235            ...)
236 {
237     va_list va;
238     va_start(va, format);
239     AtlTraceV(file, line, atlTraceGeneral, 0, format, va);
240     va_end(va);
241 }
242 
243 inline VOID __stdcall
244 AtlTraceEx(_In_opt_z_ PCTSTR file,
245            _In_       INT    line,
246            _In_       DWORD  value)
247 {
248     AtlTraceEx(file, line, TEXT("%ld (0x%lX)\n"), value, value);
249 }
250 
251 template <typename X_CHAR>
252 inline VOID __cdecl
253 AtlTrace(_In_z_ _Printf_format_string_ const X_CHAR *format, ...)
254 {
255     va_list va;
256     va_start(va, format);
257     AtlTraceV(NULL, -1, atlTraceGeneral, 0, format, va);
258     va_end(va);
259 }
260 
261 } // namespace ATL
262 
263 #endif // _DEBUG
264 
265 #ifndef ATLTRACE
266     #ifdef _DEBUG
267         #define ATLTRACE(format, ...) ATL::AtlTraceEx(__FILE__, __LINE__, format, ##__VA_ARGS__)
268     #else
269         #define ATLTRACE(format, ...) ((void)0)
270     #endif
271 #endif
272 
273 #define ATLTRACE2 ATLTRACE
274 
275 #ifdef _DEBUG
276     #define ATLTRACENOTIMPL(funcname) do { \
277         ATLTRACE(atlTraceNotImpl, 0, #funcname " is not implemented.\n"); \
278         return E_NOTIMPL; \
279     } while (0)
280 #else
281     #define ATLTRACENOTIMPL(funcname) return E_NOTIMPL
282 #endif
283 
284 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
285 using namespace ATL;
286 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE
287