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