Leaked source code of windows server 2003
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.

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