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.

421 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. // Copyright (C) 1991, Microsoft Corporation.
  3. //
  4. // File: assert.cxx
  5. //
  6. // Contents: Debugging output routines for idsmgr.dll
  7. //
  8. // Functions: Assert
  9. // PopUpError
  10. //
  11. // History: 23-Jul-91 KyleP Created.
  12. // 09-Oct-91 KevinRo Major changes and comments added
  13. // 18-Oct-91 vich moved debug print routines out
  14. // 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
  15. // 30-Sep-93 KyleP DEVL obsolete
  16. //
  17. //----------------------------------------------------------------------------
  18. #pragma hdrstop
  19. //
  20. // This one file **always** uses debugging options
  21. //
  22. #if DBG == 1
  23. // needed for CT TOM assert events trapping
  24. #include <assert.hxx>
  25. #include <stdarg.h>
  26. #include <stdio.h>
  27. # include <dprintf.h> // w4printf, w4dprintf prototypes
  28. # include <debnot.h>
  29. # ifdef FLAT
  30. # include <sem.hxx>
  31. # include <dllsem.hxx>
  32. # endif // FLAT
  33. extern "C"
  34. {
  35. # ifdef FLAT
  36. # undef FAR
  37. # undef NEAR
  38. # else
  39. # define MessageBoxA MessageBox
  40. # endif
  41. # include <windows.h>
  42. }
  43. #ifdef _CHICAGO_
  44. //int WINAPI SSMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType);
  45. #define SSMessageBox MessageBox
  46. #endif // _CHICAGO_
  47. extern BOOL gfService = FALSE;
  48. unsigned long Win4InfoLevel = DEF_INFOLEVEL;
  49. unsigned long Win4InfoMask = 0xffffffff;
  50. #ifdef _CAIRO_
  51. unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK;
  52. #else
  53. unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
  54. #endif
  55. //+------------------------------------------------------------
  56. // Function: vdprintf
  57. //
  58. // Synopsis: Prints debug output using a pointer to the
  59. // variable information. Used primarily by the
  60. // xxDebugOut macros
  61. //
  62. // Arguements:
  63. // ulCompMask -- Component level mask used to determine
  64. // output ability
  65. // pszComp -- String const of component prefix.
  66. // ppszfmt -- Pointer to output format and data
  67. //
  68. //-------------------------------------------------------------
  69. //
  70. // This semaphore is *outside* vdprintf because the compiler isn't smart
  71. // enough to serialize access for construction if it's function-local and
  72. // protected by a guard variable.
  73. //
  74. // KyleP - 20 May, 1993
  75. //
  76. static CDLLStaticMutexSem mxs;
  77. STDAPI_(void) vdprintf(
  78. unsigned long ulCompMask,
  79. char const *pszComp,
  80. char const *ppszfmt,
  81. va_list pargs)
  82. {
  83. if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
  84. ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
  85. {
  86. #if defined( FLAT )
  87. mxs.Request();
  88. DWORD tid = GetCurrentThreadId();
  89. DWORD pid = GetCurrentProcessId();
  90. if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
  91. #endif // FLAT
  92. {
  93. if (! (ulCompMask & DEB_NOCOMPNAME))
  94. {
  95. #ifdef FLAT
  96. #if defined(_CHICAGO_)
  97. //
  98. // Hex Process/Thread ID's are better for Chicago since both
  99. // are memory addresses.
  100. //
  101. w4dprintf( "%08x.%08x> ", pid, tid );
  102. #else
  103. w4dprintf( "%d.%03d> ", pid, tid );
  104. #endif
  105. #endif // FLAT
  106. w4dprintf("%s: ", pszComp);
  107. }
  108. w4vdprintf(ppszfmt, pargs);
  109. }
  110. #if defined( FLAT )
  111. if (Win4InfoLevel & DEB_STDOUT)
  112. {
  113. if (! (ulCompMask & DEB_NOCOMPNAME))
  114. {
  115. w4printf( "%03d> ", tid );
  116. w4printf("%s: ", pszComp);
  117. }
  118. w4vprintf(ppszfmt, pargs);
  119. }
  120. mxs.Release();
  121. #endif // FLAT
  122. }
  123. }
  124. //+---------------------------------------------------------------------------
  125. //
  126. // Function: _asdprintf
  127. //
  128. // Synopsis: Calls vdprintf to output a formatted message.
  129. //
  130. // History: 18-Oct-91 vich Created
  131. //
  132. //----------------------------------------------------------------------------
  133. inline void __cdecl
  134. _asdprintf(
  135. char const *pszfmt, ...)
  136. {
  137. va_list va;
  138. va_start(va, pszfmt);
  139. vdprintf(DEB_FORCE, "Assert", pszfmt, va);
  140. va_end(va);
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Function: _Win4Assert, private
  145. //
  146. // Synopsis: Display assertion information
  147. //
  148. // Effects: Called when an assertion is hit.
  149. //
  150. // History: 12-Jul-91 AlexT Created.
  151. // 05-Sep-91 AlexT Catch Throws and Catches
  152. // 19-Oct-92 HoiV Added events for TOM
  153. //
  154. //----------------------------------------------------------------------------
  155. STDAPI_(void) Win4AssertEx(
  156. char const * szFile,
  157. int iLine,
  158. char const * szMessage)
  159. {
  160. #if defined( FLAT )
  161. //
  162. // This code is for the CT Lab only. When running in the lab,
  163. // all assert popups will be trapped and notifications will
  164. // be sent to the manager. If running in the office (non-lab
  165. // mode), the event CTTOMTrapAssertEvent will not exist and
  166. // consequently, no event will be pulsed.
  167. //
  168. HANDLE hTrapAssertEvent,
  169. hThreadStartEvent;
  170. if (hTrapAssertEvent = OpenEvent(EVENT_ALL_ACCESS,
  171. FALSE,
  172. CAIRO_CT_TOM_TRAP_ASSERT_EVENT))
  173. {
  174. SetEvent(hTrapAssertEvent);
  175. //
  176. // This event is to allow TOM Manager time to perform
  177. // a CallBack to the dispatcher.
  178. //
  179. if (hThreadStartEvent = OpenEvent(EVENT_ALL_ACCESS,
  180. FALSE,
  181. CAIRO_CT_TOM_THREAD_START_EVENT))
  182. {
  183. //
  184. // Wait until it's ok to popup or until timed-out
  185. //
  186. WaitForSingleObject(hThreadStartEvent, TWO_MINUTES);
  187. }
  188. }
  189. #endif
  190. if (Win4AssertLevel & ASSRT_MESSAGE)
  191. {
  192. # ifdef FLAT
  193. DWORD tid = GetCurrentThreadId();
  194. _asdprintf("%s File: %s Line: %u, thread id %d\n",
  195. szMessage, szFile, iLine, tid);
  196. # else // FLAT
  197. _asdprintf("%s File: %s Line: %u\n", szMessage, szFile, iLine);
  198. # endif // FLAT
  199. }
  200. if (Win4AssertLevel & ASSRT_POPUP)
  201. {
  202. int id = PopUpError(szMessage,iLine,szFile);
  203. if (id == IDCANCEL)
  204. {
  205. #ifdef FLAT
  206. DebugBreak();
  207. #else
  208. _asm int 3;
  209. #endif
  210. }
  211. }
  212. else if (Win4AssertLevel & ASSRT_BREAK)
  213. {
  214. #ifdef FLAT
  215. DebugBreak();
  216. #else
  217. _asm int 3;
  218. #endif
  219. }
  220. }
  221. //+------------------------------------------------------------
  222. // Function: SetWin4InfoLevel(unsigned long ulNewLevel)
  223. //
  224. // Synopsis: Sets the global info level for debugging output
  225. // Returns: Old info level
  226. //
  227. //-------------------------------------------------------------
  228. EXPORTIMP unsigned long APINOT
  229. SetWin4InfoLevel(
  230. unsigned long ulNewLevel)
  231. {
  232. unsigned long ul;
  233. ul = Win4InfoLevel;
  234. Win4InfoLevel = ulNewLevel;
  235. return(ul);
  236. }
  237. //+------------------------------------------------------------
  238. // Function: _SetWin4InfoMask(unsigned long ulNewMask)
  239. //
  240. // Synopsis: Sets the global info mask for debugging output
  241. // Returns: Old info mask
  242. //
  243. //-------------------------------------------------------------
  244. EXPORTIMP unsigned long APINOT
  245. SetWin4InfoMask(
  246. unsigned long ulNewMask)
  247. {
  248. unsigned long ul;
  249. ul = Win4InfoMask;
  250. Win4InfoMask = ulNewMask;
  251. return(ul);
  252. }
  253. //+------------------------------------------------------------
  254. // Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
  255. //
  256. // Synopsis: Sets the global assert level for debugging output
  257. // Returns: Old assert level
  258. //
  259. //-------------------------------------------------------------
  260. EXPORTIMP unsigned long APINOT
  261. SetWin4AssertLevel(
  262. unsigned long ulNewLevel)
  263. {
  264. unsigned long ul;
  265. ul = Win4AssertLevel;
  266. Win4AssertLevel = ulNewLevel;
  267. return(ul);
  268. }
  269. //+------------------------------------------------------------
  270. // Function: PopUpError
  271. //
  272. // Synopsis: Displays a dialog box using provided text,
  273. // and presents the user with the option to
  274. // continue or cancel.
  275. //
  276. // Arguments:
  277. // szMsg -- The string to display in main body of dialog
  278. // iLine -- Line number of file in error
  279. // szFile -- Filename of file in error
  280. //
  281. // Returns:
  282. // IDCANCEL -- User selected the CANCEL button
  283. // IDOK -- User selected the OK button
  284. //-------------------------------------------------------------
  285. STDAPI_(int) PopUpError(
  286. char const *szMsg,
  287. int iLine,
  288. char const *szFile)
  289. {
  290. int id;
  291. static char szAssertCaption[128];
  292. static char szModuleName[128];
  293. DWORD tid = GetCurrentThreadId();
  294. DWORD pid = GetCurrentProcessId();
  295. char * pszModuleName;
  296. if (GetModuleFileNameA(NULL, szModuleName, 128))
  297. {
  298. pszModuleName = strrchr(szModuleName, '\\');
  299. if (!pszModuleName)
  300. {
  301. pszModuleName = szModuleName;
  302. }
  303. else
  304. {
  305. pszModuleName++;
  306. }
  307. }
  308. else
  309. {
  310. pszModuleName = "Unknown";
  311. }
  312. wsprintfA(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
  313. pszModuleName, szFile, iLine, pid, tid);
  314. DWORD dwMessageFlags = MB_SETFOREGROUND | MB_TASKMODAL |
  315. MB_ICONEXCLAMATION | MB_OKCANCEL;
  316. #ifndef _CHICAGO_
  317. // Since this code is also used by SCM.EXE, we pass
  318. // in the following flag which causes Service pop ups
  319. // to appear on the desktop correctly
  320. if (gfService)
  321. {
  322. dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
  323. }
  324. id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
  325. dwMessageFlags);
  326. # ifdef _CAIRO_
  327. // Other processes which are services also use this code, but they
  328. // have no access to set gfService, so if the above failed with an
  329. // access denied error (meaning no access to the default desktop)
  330. // retry as a service popup. Also, remember that we are a service
  331. // so we don't waste attempts later.
  332. if ( !gfService && !id
  333. && (GetLastError() == ERROR_ACCESS_DENIED) )
  334. {
  335. gfService = TRUE;
  336. dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
  337. id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
  338. dwMessageFlags);
  339. }
  340. # endif
  341. #else
  342. id = SSMessageBox(NULL, (char *) szMsg, (LPSTR) szAssertCaption,
  343. dwMessageFlags);
  344. #endif
  345. // If id == 0, then an error occurred. There are two possibilities
  346. // that can cause the error: Access Denied, which means that this
  347. // process does not have access to the default desktop, and everything
  348. // else (usually out of memory). Oh well.
  349. return id;
  350. }
  351. #else
  352. int assertDontUseThisName(void)
  353. {
  354. return 1;
  355. }
  356. #endif // DBG == 1