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