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.

340 lines
8.8 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. //
  18. //----------------------------------------------------------------------------
  19. #if DBG == 1
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <stdarg.h>
  23. #include "debug.h"
  24. //////////////////////////////////////////////////////////////////////////////
  25. unsigned long Win4InfoLevel = DEF_INFOLEVEL;
  26. unsigned long Win4InfoMask = 0xffffffff;
  27. unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
  28. //////////////////////////////////////////////////////////////////////////////
  29. static int _cdecl w4dprintf(const char *format, ...);
  30. static int _cdecl w4vdprintf(const char *format, va_list arglist);
  31. //////////////////////////////////////////////////////////////////////////////
  32. static CRITICAL_SECTION s_csMessageBuf;
  33. static char g_szMessageBuf[500]; // this is the message buffer
  34. static int _cdecl w4dprintf(const char *format, ...)
  35. {
  36. int ret;
  37. va_list va;
  38. va_start(va, format);
  39. ret = w4vdprintf(format, va);
  40. va_end(va);
  41. return ret;
  42. }
  43. static int _cdecl w4vdprintf(const char *format, va_list arglist)
  44. {
  45. int ret;
  46. EnterCriticalSection(&s_csMessageBuf);
  47. ret = vsprintf(g_szMessageBuf, format, arglist);
  48. OutputDebugStringA(g_szMessageBuf);
  49. LeaveCriticalSection(&s_csMessageBuf);
  50. return ret;
  51. }
  52. //////////////////////////////////////////////////////////////////////////////
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: _asdprintf
  56. //
  57. // Synopsis: Calls vdprintf to output a formatted message.
  58. //
  59. // History: 18-Oct-91 vich Created
  60. //
  61. //----------------------------------------------------------------------------
  62. inline void __cdecl
  63. _asdprintf(
  64. char const *pszfmt, ...)
  65. {
  66. va_list va;
  67. va_start(va, pszfmt);
  68. vdprintf(DEB_FORCE, "Assert", pszfmt, va);
  69. va_end(va);
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: Win4AssertEx, private
  74. //
  75. // Synopsis: Display assertion information
  76. //
  77. // Effects: Called when an assertion is hit.
  78. //
  79. //----------------------------------------------------------------------------
  80. EXPORTIMP void APINOT
  81. Win4AssertEx(
  82. char const * szFile,
  83. int iLine,
  84. char const * szMessage)
  85. {
  86. if (Win4AssertLevel & ASSRT_MESSAGE)
  87. {
  88. DWORD tid = GetCurrentThreadId();
  89. _asdprintf("%s File: %s Line: %u, thread id %d\n",
  90. szMessage, szFile, iLine, tid);
  91. }
  92. if (Win4AssertLevel & ASSRT_POPUP)
  93. {
  94. int id = PopUpError(szMessage,iLine,szFile);
  95. if (id == IDCANCEL)
  96. {
  97. DebugBreak();
  98. }
  99. }
  100. else if (Win4AssertLevel & ASSRT_BREAK)
  101. {
  102. DebugBreak();
  103. }
  104. }
  105. //+------------------------------------------------------------
  106. // Function: SetWin4InfoLevel(unsigned long ulNewLevel)
  107. //
  108. // Synopsis: Sets the global info level for debugging output
  109. // Returns: Old info level
  110. //
  111. //-------------------------------------------------------------
  112. EXPORTIMP unsigned long APINOT
  113. SetWin4InfoLevel(
  114. unsigned long ulNewLevel)
  115. {
  116. unsigned long ul;
  117. ul = Win4InfoLevel;
  118. Win4InfoLevel = ulNewLevel;
  119. return(ul);
  120. }
  121. //+------------------------------------------------------------
  122. // Function: SetWin4InfoMask(unsigned long ulNewMask)
  123. //
  124. // Synopsis: Sets the global info mask for debugging output
  125. // Returns: Old info mask
  126. //
  127. //-------------------------------------------------------------
  128. EXPORTIMP unsigned long APINOT
  129. SetWin4InfoMask(
  130. unsigned long ulNewMask)
  131. {
  132. unsigned long ul;
  133. ul = Win4InfoMask;
  134. Win4InfoMask = ulNewMask;
  135. return(ul);
  136. }
  137. //+------------------------------------------------------------
  138. // Function: SetWin4AssertLevel(unsigned long ulNewLevel)
  139. //
  140. // Synopsis: Sets the global assert level for debugging output
  141. // Returns: Old assert level
  142. //
  143. //-------------------------------------------------------------
  144. EXPORTIMP unsigned long APINOT
  145. SetWin4AssertLevel(
  146. unsigned long ulNewLevel)
  147. {
  148. unsigned long ul;
  149. ul = Win4AssertLevel;
  150. Win4AssertLevel = ulNewLevel;
  151. return(ul);
  152. }
  153. //+------------------------------------------------------------
  154. // Function: PopUpError
  155. //
  156. // Synopsis: Displays a dialog box using provided text,
  157. // and presents the user with the option to
  158. // continue or cancel.
  159. //
  160. // Arguments:
  161. // szMsg -- The string to display in main body of dialog
  162. // iLine -- Line number of file in error
  163. // szFile -- Filename of file in error
  164. //
  165. // Returns:
  166. // IDCANCEL -- User selected the CANCEL button
  167. // IDOK -- User selected the OK button
  168. //-------------------------------------------------------------
  169. EXPORTIMP int APINOT
  170. PopUpError(
  171. char const *szMsg,
  172. int iLine,
  173. char const *szFile)
  174. {
  175. int id;
  176. static char szAssertCaption[128];
  177. static char szModuleName[128];
  178. DWORD tid = GetCurrentThreadId();
  179. DWORD pid = GetCurrentProcessId();
  180. char * pszModuleName;
  181. if (GetModuleFileNameA(NULL, szModuleName, 128))
  182. {
  183. pszModuleName = strrchr(szModuleName, '\\');
  184. if (!pszModuleName)
  185. {
  186. pszModuleName = szModuleName;
  187. }
  188. else
  189. {
  190. pszModuleName++;
  191. }
  192. }
  193. else
  194. {
  195. pszModuleName = "Unknown";
  196. }
  197. sprintf(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
  198. pszModuleName, szFile, iLine, pid, tid);
  199. id = MessageBoxA(NULL,
  200. szMsg,
  201. szAssertCaption,
  202. MB_SETFOREGROUND
  203. | MB_DEFAULT_DESKTOP_ONLY
  204. | MB_TASKMODAL
  205. | MB_ICONEXCLAMATION
  206. | MB_OKCANCEL);
  207. //
  208. // If id == 0, then an error occurred. There are two possibilities
  209. // that can cause the error: Access Denied, which means that this
  210. // process does not have access to the default desktop, and everything
  211. // else (usually out of memory).
  212. //
  213. if (0 == id)
  214. {
  215. if (GetLastError() == ERROR_ACCESS_DENIED)
  216. {
  217. //
  218. // Retry this one with the SERVICE_NOTIFICATION flag on. That
  219. // should get us to the right desktop.
  220. //
  221. id = MessageBoxA(NULL,
  222. szMsg,
  223. szAssertCaption,
  224. MB_SETFOREGROUND
  225. | MB_SERVICE_NOTIFICATION
  226. | MB_TASKMODAL
  227. | MB_ICONEXCLAMATION
  228. | MB_OKCANCEL);
  229. }
  230. }
  231. return id;
  232. }
  233. //+------------------------------------------------------------
  234. // Function: vdprintf
  235. //
  236. // Synopsis: Prints debug output using a pointer to the
  237. // variable information. Used primarily by the
  238. // xxDebugOut macros
  239. //
  240. // Arguements:
  241. // ulCompMask -- Component level mask used to determine
  242. // output ability
  243. // pszComp -- String const of component prefix.
  244. // ppszfmt -- Pointer to output format and data
  245. //
  246. //-------------------------------------------------------------
  247. static CRITICAL_SECTION s_csDebugPrint;
  248. EXPORTIMP void APINOT
  249. vdprintf(
  250. unsigned long ulCompMask,
  251. char const *pszComp,
  252. char const *ppszfmt,
  253. va_list pargs)
  254. {
  255. if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
  256. ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
  257. {
  258. EnterCriticalSection(&s_csDebugPrint);
  259. DWORD tid = GetCurrentThreadId();
  260. DWORD pid = GetCurrentProcessId();
  261. if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
  262. {
  263. if (! (ulCompMask & DEB_NOCOMPNAME))
  264. {
  265. w4dprintf("%d.%03d> %s: ", pid, tid, pszComp);
  266. }
  267. w4vdprintf(ppszfmt, pargs);
  268. }
  269. if (Win4InfoLevel & DEB_STDOUT)
  270. {
  271. if (! (ulCompMask & DEB_NOCOMPNAME))
  272. {
  273. printf("%d.%03d> %s: ", pid, tid, pszComp);
  274. }
  275. vprintf(ppszfmt, pargs);
  276. }
  277. LeaveCriticalSection(&s_csDebugPrint);
  278. }
  279. }
  280. void APINOT InitializeDebugging(void)
  281. {
  282. InitializeCriticalSection(&s_csMessageBuf);
  283. InitializeCriticalSection(&s_csDebugPrint);
  284. }
  285. #endif // DBG == 1