Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. // Copyright (C) 1991-1994, Microsoft Corporation.
  3. //
  4. // File: assert.cxx
  5. //
  6. // Contents: Debugging output routines
  7. //
  8. // History: 23-Jul-91 KyleP Created.
  9. // 09-Oct-91 KevinRo Major changes and comments added
  10. // 18-Oct-91 vich moved debug print routines out
  11. // 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
  12. // 30-Sep-93 KyleP DEVL obsolete
  13. // 7-Oct-94 BruceFo Ripped out all kernel, non-FLAT,
  14. // DLL-specific, non-Win32 functionality.
  15. // Now it's basically "print to the
  16. // debugger" code.
  17. // 20-Oct-95 EricB Set component debug level in the
  18. // registry.
  19. // 23-Feb-01 JBenton Added code to clean up crit sections
  20. //
  21. //----------------------------------------------------------------------------
  22. #if DBG == 1
  23. #include <windows.h>
  24. #include <stdarg.h>
  25. #include "smdebug.h"
  26. //////////////////////////////////////////////////////////////////////////////
  27. unsigned long SmInfoLevel = DEF_INFOLEVEL;
  28. unsigned long SmInfoMask = 0xffffffff;
  29. unsigned long SmAssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
  30. BOOL fCritSecInit = FALSE;
  31. BOOL fInfoLevelInit = FALSE;
  32. //////////////////////////////////////////////////////////////////////////////
  33. static int _cdecl w4dprintf(const char *format, ...);
  34. static int _cdecl w4smprintf(const char *format, va_list arglist);
  35. //////////////////////////////////////////////////////////////////////////////
  36. static CRITICAL_SECTION s_csMessageBuf;
  37. static char g_szMessageBuf[500]; // this is the message buffer
  38. static int _cdecl w4dprintf(const char *format, ...)
  39. {
  40. int ret;
  41. va_list va;
  42. va_start(va, format);
  43. ret = w4smprintf(format, va);
  44. va_end(va);
  45. return ret;
  46. }
  47. static int _cdecl w4smprintf(const char *format, va_list arglist)
  48. {
  49. int ret;
  50. EnterCriticalSection(&s_csMessageBuf);
  51. ret = wvsprintfA(g_szMessageBuf, format, arglist);
  52. OutputDebugStringA(g_szMessageBuf);
  53. LeaveCriticalSection(&s_csMessageBuf);
  54. return ret;
  55. }
  56. //////////////////////////////////////////////////////////////////////////////
  57. //+---------------------------------------------------------------------------
  58. //
  59. // Function: _asdprintf
  60. //
  61. // Synopsis: Calls smprintf to output a formatted message.
  62. //
  63. // History: 18-Oct-91 vich Created
  64. //
  65. //----------------------------------------------------------------------------
  66. inline void __cdecl
  67. _asdprintf(
  68. char const *pszfmt, ...)
  69. {
  70. va_list va;
  71. va_start(va, pszfmt);
  72. smprintf(DEB_FORCE, "Assert", pszfmt, va);
  73. va_end(va);
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Function: SmAssertEx, private
  78. //
  79. // Synopsis: Display assertion information
  80. //
  81. // Effects: Called when an assertion is hit.
  82. //
  83. //----------------------------------------------------------------------------
  84. EXPORTIMP void APINOT
  85. SmAssertEx(
  86. char const * szFile,
  87. int iLine,
  88. char const * szMessage)
  89. {
  90. if (SmAssertLevel & ASSRT_MESSAGE)
  91. {
  92. DWORD tid = GetCurrentThreadId();
  93. _asdprintf("%s File: %s Line: %u, thread id %d\n",
  94. szMessage, szFile, iLine, tid);
  95. }
  96. if (SmAssertLevel & ASSRT_POPUP)
  97. {
  98. int id = PopUpError(szMessage,iLine,szFile);
  99. if (id == IDCANCEL)
  100. {
  101. DebugBreak();
  102. }
  103. }
  104. else if (SmAssertLevel & ASSRT_BREAK)
  105. {
  106. DebugBreak();
  107. }
  108. }
  109. //+------------------------------------------------------------
  110. // Function: SetSmInfoLevel(unsigned long ulNewLevel)
  111. //
  112. // Synopsis: Sets the global info level for debugging output
  113. // Returns: Old info level
  114. //
  115. //-------------------------------------------------------------
  116. EXPORTIMP unsigned long APINOT
  117. SetSmInfoLevel(
  118. unsigned long ulNewLevel)
  119. {
  120. unsigned long ul;
  121. ul = SmInfoLevel;
  122. SmInfoLevel = ulNewLevel;
  123. return(ul);
  124. }
  125. //+------------------------------------------------------------
  126. // Function: SetSmInfoMask(unsigned long ulNewMask)
  127. //
  128. // Synopsis: Sets the global info mask for debugging output
  129. // Returns: Old info mask
  130. //
  131. //-------------------------------------------------------------
  132. EXPORTIMP unsigned long APINOT
  133. SetSmInfoMask(
  134. unsigned long ulNewMask)
  135. {
  136. unsigned long ul;
  137. ul = SmInfoMask;
  138. SmInfoMask = ulNewMask;
  139. return(ul);
  140. }
  141. //+------------------------------------------------------------
  142. // Function: SetSmAssertLevel(unsigned long ulNewLevel)
  143. //
  144. // Synopsis: Sets the global assert level for debugging output
  145. // Returns: Old assert level
  146. //
  147. //-------------------------------------------------------------
  148. EXPORTIMP unsigned long APINOT
  149. SetSmAssertLevel(
  150. unsigned long ulNewLevel)
  151. {
  152. unsigned long ul;
  153. ul = SmAssertLevel;
  154. SmAssertLevel = ulNewLevel;
  155. return(ul);
  156. }
  157. //+------------------------------------------------------------
  158. // Function: PopUpError
  159. //
  160. // Synopsis: Displays a dialog box using provided text,
  161. // and presents the user with the option to
  162. // continue or cancel.
  163. //
  164. // Arguments:
  165. // szMsg -- The string to display in main body of dialog
  166. // iLine -- Line number of file in error
  167. // szFile -- Filename of file in error
  168. //
  169. // Returns:
  170. // IDCANCEL -- User selected the CANCEL button
  171. // IDOK -- User selected the OK button
  172. //-------------------------------------------------------------
  173. EXPORTIMP int APINOT
  174. PopUpError(
  175. char const *szMsg,
  176. int iLine,
  177. char const *szFile)
  178. {
  179. int id;
  180. static char szAssertCaption[128];
  181. static char szModuleName[128];
  182. DWORD tid = GetCurrentThreadId();
  183. DWORD pid = GetCurrentProcessId();
  184. char * pszModuleName;
  185. if (GetModuleFileNameA(NULL, szModuleName, 128))
  186. {
  187. pszModuleName = szModuleName;
  188. }
  189. else
  190. {
  191. pszModuleName = "Unknown";
  192. }
  193. wsprintfA(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
  194. pszModuleName, szFile, iLine, pid, tid);
  195. id = MessageBoxA(NULL,
  196. szMsg,
  197. szAssertCaption,
  198. MB_SETFOREGROUND
  199. | MB_DEFAULT_DESKTOP_ONLY
  200. | MB_TASKMODAL
  201. | MB_ICONEXCLAMATION
  202. | MB_OKCANCEL);
  203. //
  204. // If id == 0, then an error occurred. There are two possibilities
  205. // that can cause the error: Access Denied, which means that this
  206. // process does not have access to the default desktop, and everything
  207. // else (usually out of memory).
  208. //
  209. if (0 == id)
  210. {
  211. if (GetLastError() == ERROR_ACCESS_DENIED)
  212. {
  213. //
  214. // Retry this one with the SERVICE_NOTIFICATION flag on. That
  215. // should get us to the right desktop.
  216. //
  217. id = MessageBoxA(NULL,
  218. szMsg,
  219. szAssertCaption,
  220. MB_SETFOREGROUND
  221. | MB_SERVICE_NOTIFICATION
  222. | MB_TASKMODAL
  223. | MB_ICONEXCLAMATION
  224. | MB_OKCANCEL);
  225. }
  226. }
  227. return id;
  228. }
  229. //+------------------------------------------------------------
  230. // Function: smprintf
  231. //
  232. // Synopsis: Prints debug output using a pointer to the
  233. // variable information. Used primarily by the
  234. // xxDebugOut macros
  235. //
  236. // Arguements:
  237. // ulCompMask -- Component level mask used to determine
  238. // output ability
  239. // pszComp -- String const of component prefix.
  240. // ppszfmt -- Pointer to output format and data
  241. //
  242. //-------------------------------------------------------------
  243. static CRITICAL_SECTION s_csDebugPrint;
  244. EXPORTIMP void APINOT
  245. smprintf(
  246. unsigned long ulCompMask,
  247. char const *pszComp,
  248. char const *ppszfmt,
  249. va_list pargs)
  250. {
  251. if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
  252. ((ulCompMask | SmInfoLevel) & SmInfoMask))
  253. {
  254. EnterCriticalSection(&s_csDebugPrint);
  255. DWORD tid = GetCurrentThreadId();
  256. DWORD pid = GetCurrentProcessId();
  257. if ((SmInfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
  258. {
  259. if (! (ulCompMask & DEB_NOCOMPNAME))
  260. {
  261. w4dprintf("%x.%03x> %s: ", pid, tid, pszComp);
  262. }
  263. SYSTEMTIME st;
  264. GetLocalTime(&st);
  265. w4dprintf("%02d:%02d:%02d.%03d ", st.wHour, st.wMinute,
  266. st.wSecond, st.wMilliseconds);
  267. w4smprintf(ppszfmt, pargs);
  268. }
  269. //if (SmInfoLevel & DEB_STDOUT)
  270. //{
  271. // if (! (ulCompMask & DEB_NOCOMPNAME))
  272. // {
  273. // printf("%x.%03x> %s: ", pid, tid, pszComp);
  274. // }
  275. // vprintf(ppszfmt, pargs);
  276. //}
  277. LeaveCriticalSection(&s_csDebugPrint);
  278. }
  279. }
  280. //+----------------------------------------------------------------------------
  281. //
  282. // SysMan debuggging library inititalization.
  283. //
  284. // To set a non-default debug info level outside of the debugger, create the
  285. // below registry key and in it create a value whose name is the component's
  286. // debugging tag name (the "comp" parameter to the DECLARE_INFOLEVEL macro) and
  287. // whose data is the desired infolevel in REG_DWORD format.
  288. //-----------------------------------------------------------------------------
  289. #define SMDEBUGKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SmDebug"
  290. //+----------------------------------------------------------------------------
  291. // Function: CheckInit
  292. //
  293. // Synopsis: Performs debugging library initialization
  294. // including reading the registry for the desired infolevel
  295. //
  296. //-----------------------------------------------------------------------------
  297. EXPORTDEF void APINOT
  298. CheckInit(char * pInfoLevelString, unsigned long * pulInfoLevel)
  299. {
  300. HKEY hKey;
  301. LONG lRet;
  302. DWORD dwSize;
  303. if (fInfoLevelInit) return;
  304. if (!fCritSecInit) InitializeDebugging();
  305. fInfoLevelInit = TRUE;
  306. lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SMDEBUGKEY, 0, KEY_READ, &hKey);
  307. if (lRet == ERROR_SUCCESS)
  308. {
  309. dwSize = sizeof(unsigned long);
  310. lRet = RegQueryValueExA(hKey, pInfoLevelString, NULL, NULL,
  311. (LPBYTE)pulInfoLevel, &dwSize);
  312. if (lRet != ERROR_SUCCESS)
  313. {
  314. *pulInfoLevel = DEF_INFOLEVEL;
  315. }
  316. RegCloseKey(hKey);
  317. }
  318. }
  319. void APINOT InitializeDebugging(void)
  320. {
  321. if (fCritSecInit) return;
  322. InitializeCriticalSection(&s_csMessageBuf);
  323. InitializeCriticalSection(&s_csDebugPrint);
  324. fCritSecInit = TRUE;
  325. }
  326. void APINOT CleanUpDebugging(void)
  327. {
  328. if (fCritSecInit)
  329. {
  330. DeleteCriticalSection(&s_csMessageBuf);
  331. DeleteCriticalSection(&s_csDebugPrint);
  332. fCritSecInit = FALSE;
  333. }
  334. }
  335. #endif // DBG == 1