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.

433 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2002.
  5. //
  6. // File: assert.cxx
  7. //
  8. // Contents: Debugging output routines for idsmgr.dll
  9. //
  10. // Functions: Assert
  11. // PopUpError
  12. //
  13. // History: 23-Jul-91 KyleP Created.
  14. // 09-Oct-91 KevinRo Major changes and comments added
  15. // 18-Oct-91 vich moved debug print routines out
  16. // 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
  17. // 30-Sep-93 KyleP DEVL obsolete
  18. // 04-Mar-2002 KitmanH Got rid of the debug shared memory
  19. // buffer
  20. //
  21. //----------------------------------------------------------------------------
  22. #include <pch.cxx>
  23. #pragma hdrstop
  24. //
  25. // This one file **always** uses debugging options
  26. //
  27. #if CIDBG == 1
  28. // needed for CT TOM assert events trapping
  29. #include <assert.hxx>
  30. #include <namesem.hxx>
  31. #include <smem.hxx>
  32. #include <ciregkey.hxx>
  33. #include <regacc.hxx>
  34. #include <dprintf.h> // w4printf, w4dprintf prototypes
  35. #include <cidllsem.hxx>
  36. #undef FAR
  37. #undef NEAR
  38. unsigned long Win4InfoLevel = DEF_INFOLEVEL;
  39. unsigned long Win4InfoMask = 0xffffffff;
  40. unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_STRESSBREAK;
  41. //+---------------------------------------------------------------------------
  42. //
  43. // Function: _asdprintf
  44. //
  45. // Synopsis: Calls vdprintf to output a formatted message.
  46. //
  47. // History: 18-Oct-91 vich Created
  48. //
  49. //----------------------------------------------------------------------------
  50. inline void __cdecl
  51. _asdprintf(
  52. char const *pszfmt, ...)
  53. {
  54. va_list va;
  55. va_start(va, pszfmt);
  56. vdprintf(DEB_FORCE, "Assert", pszfmt, va);
  57. va_end(va);
  58. }
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Function: _Win4Assert, private
  62. //
  63. // Synopsis: Display assertion information
  64. //
  65. // Effects: Called when an assertion is hit.
  66. //
  67. // History: 12-Jul-91 AlexT Created.
  68. // 05-Sep-91 AlexT Catch Throws and Catches
  69. // 19-Oct-92 HoiV Added events for TOM
  70. //
  71. //----------------------------------------------------------------------------
  72. EXPORTIMP void APINOT
  73. Win4AssertEx(
  74. char const * szFile,
  75. int iLine,
  76. char const * szMessage)
  77. {
  78. //
  79. // Always check to make sure the assert flag hasn't changed.
  80. //
  81. CRegAccess regAdmin( RTL_REGISTRY_CONTROL, wcsRegAdmin );
  82. ULONG ulLevel = regAdmin.Read( wcsWin4AssertLevel, 0xFFFFFFFF );
  83. if (ulLevel != 0xFFFFFFFF )
  84. SetWin4AssertLevel( ulLevel );
  85. //
  86. // Do the assert
  87. //
  88. if (Win4AssertLevel & ASSRT_MESSAGE)
  89. {
  90. DWORD tid = GetCurrentThreadId();
  91. _asdprintf("%s File: %s Line: %u, thread id %d\n",
  92. szMessage, szFile, iLine, tid);
  93. }
  94. if (Win4AssertLevel & ASSRT_POPUP)
  95. {
  96. int id = PopUpError(szMessage,iLine,szFile);
  97. if (id == IDCANCEL)
  98. {
  99. DebugBreak();
  100. }
  101. }
  102. else if (Win4AssertLevel & ASSRT_STRESSBREAK)
  103. {
  104. //
  105. // See if a debugger is attachable. If not, then put up a popup.
  106. //
  107. BOOL fOk = FALSE;
  108. try
  109. {
  110. CRegAccess regAeDebug( RTL_REGISTRY_ABSOLUTE,
  111. L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" );
  112. WCHAR wcsTemp[100];
  113. regAeDebug.Get( L"Auto", wcsTemp, sizeof(wcsTemp)/sizeof(WCHAR) );
  114. if ( L'1' == wcsTemp[0] && 0 == wcsTemp[1] )
  115. {
  116. regAeDebug.Get( L"Debugger", wcsTemp, sizeof(wcsTemp)/sizeof(WCHAR) );
  117. if ( 0 != wcsTemp[0] && 0 == wcsstr( wcsTemp, L"drwtsn" ) )
  118. {
  119. fOk = TRUE;
  120. }
  121. }
  122. }
  123. catch( ... )
  124. {
  125. }
  126. //
  127. // Debugger is attachable, break in.
  128. //
  129. if ( fOk )
  130. {
  131. w4dprintf( "***\n***\n*** Restartable software exception used to activate user-mode\n" );
  132. w4dprintf( "*** debugger. Enter 'g' to continue past assert (if you can't wait).\n" );
  133. RaiseException( ASSRT_STRESSEXCEPTION, 0, 0, 0 );
  134. }
  135. //
  136. // No debugger. Put up a popup.
  137. //
  138. else
  139. {
  140. int id = PopUpError(szMessage,iLine,szFile);
  141. if (id == IDCANCEL)
  142. {
  143. DebugBreak();
  144. }
  145. }
  146. }
  147. else if (Win4AssertLevel & ASSRT_BREAK)
  148. {
  149. DebugBreak();
  150. }
  151. }
  152. //+------------------------------------------------------------
  153. // Function: SetWin4InfoLevel(unsigned long ulNewLevel)
  154. //
  155. // Synopsis: Sets the global info level for debugging output
  156. // Returns: Old info level
  157. //
  158. //-------------------------------------------------------------
  159. EXPORTIMP unsigned long APINOT
  160. SetWin4InfoLevel(
  161. unsigned long ulNewLevel)
  162. {
  163. unsigned long ul;
  164. ul = Win4InfoLevel;
  165. Win4InfoLevel = ulNewLevel;
  166. return(ul);
  167. }
  168. //+------------------------------------------------------------
  169. // Function: _SetWin4InfoMask(unsigned long ulNewMask)
  170. //
  171. // Synopsis: Sets the global info mask for debugging output
  172. // Returns: Old info mask
  173. //
  174. //-------------------------------------------------------------
  175. EXPORTIMP unsigned long APINOT
  176. SetWin4InfoMask(
  177. unsigned long ulNewMask)
  178. {
  179. unsigned long ul;
  180. ul = Win4InfoMask;
  181. Win4InfoMask = ulNewMask;
  182. return(ul);
  183. }
  184. //+------------------------------------------------------------
  185. // Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
  186. //
  187. // Synopsis: Sets the global assert level for debugging output
  188. // Returns: Old assert level
  189. //
  190. //-------------------------------------------------------------
  191. EXPORTIMP unsigned long APINOT
  192. SetWin4AssertLevel(
  193. unsigned long ulNewLevel)
  194. {
  195. unsigned long ul;
  196. ul = Win4AssertLevel;
  197. Win4AssertLevel = ulNewLevel;
  198. return(ul);
  199. }
  200. //+------------------------------------------------------------
  201. // Function: PopUpError
  202. //
  203. // Synopsis: Displays a dialog box using provided text,
  204. // and presents the user with the option to
  205. // continue or cancel.
  206. //
  207. // Arguments:
  208. // szMsg -- The string to display in main body of dialog
  209. // iLine -- Line number of file in error
  210. // szFile -- Filename of file in error
  211. //
  212. // Returns:
  213. // IDCANCEL -- User selected the CANCEL button
  214. // IDOK -- User selected the OK button
  215. //-------------------------------------------------------------
  216. EXPORTIMP int APINOT
  217. PopUpError(
  218. char const *szMsg,
  219. int iLine,
  220. char const *szFile)
  221. {
  222. static char szModuleName[MAX_PATH];
  223. DWORD tid = GetCurrentThreadId();
  224. DWORD pid = GetCurrentProcessId();
  225. char * pszModuleName;
  226. if (GetModuleFileNameA( 0, szModuleName, NUMELEM( szModuleName ) ))
  227. {
  228. szModuleName[ NUMELEM( szModuleName ) - 1 ] = 0;
  229. pszModuleName = strrchr(szModuleName, '\\');
  230. if ( 0 == pszModuleName )
  231. pszModuleName = szModuleName;
  232. else
  233. pszModuleName++;
  234. }
  235. else
  236. {
  237. pszModuleName = "Unknown";
  238. }
  239. static char szAssertCaption[MAX_PATH * 3];
  240. sprintf( szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
  241. pszModuleName, szFile, iLine, pid, tid);
  242. UINT uiOldMode = SetErrorMode( 0 );
  243. int id = MessageBoxA( 0,
  244. (char *) szMsg,
  245. (LPSTR) szAssertCaption,
  246. MB_SERVICE_NOTIFICATION |
  247. MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL );
  248. SetErrorMode( uiOldMode );
  249. //
  250. // If id == 0, then an error occurred. There are two possibilities
  251. // that can cause the error: Access Denied, which means that this
  252. // process does not have access to the default desktop, and everything
  253. // else (usually out of memory).
  254. //
  255. if (!id)
  256. {
  257. if (GetLastError() == ERROR_ACCESS_DENIED)
  258. {
  259. //
  260. // Retry this one with the SERVICE_NOTIFICATION flag on. That
  261. // should get us to the right desktop.
  262. //
  263. id = MessageBoxA( NULL,
  264. (char *) szMsg,
  265. (LPSTR) szAssertCaption,
  266. MB_SETFOREGROUND | MB_SERVICE_NOTIFICATION |
  267. MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL );
  268. }
  269. else
  270. {
  271. // default: break if you can't display the messagebox
  272. id = IDCANCEL;
  273. }
  274. }
  275. return id;
  276. }
  277. //+------------------------------------------------------------
  278. // Function: vdprintf
  279. //
  280. // Synopsis: Prints debug output using a pointer to the
  281. // variable information. Used primarily by the
  282. // xxDebugOut macros
  283. //
  284. // Arguements:
  285. // ulCompMask -- Component level mask used to determine
  286. // output ability
  287. // pszComp -- String const of component prefix.
  288. // ppszfmt -- Pointer to output format and data
  289. //
  290. //-------------------------------------------------------------
  291. //
  292. // This semaphore is *outside* vdprintf because the compiler isn't smart
  293. // enough to serialize access for construction if it's function-local and
  294. // protected by a guard variable.
  295. //
  296. // KyleP - 20 May, 1993
  297. //
  298. CDLLStaticMutexSem g_mxsAssert;
  299. BOOLEAN * pfIsBeingDebugged = 0;
  300. //
  301. // Very special version of the debug allocator. Doesn't record allocation
  302. // in log. Failure to free is not considered a leak.
  303. //
  304. #if CIDBG == 1
  305. void * ciNewDebugNoRecord( size_t size );
  306. enum eAlloc { NoRecordAlloc };
  307. inline void * __cdecl operator new ( size_t size, eAlloc )
  308. {
  309. return ciNewDebugNoRecord( size );
  310. }
  311. #endif
  312. EXPORTIMP void APINOT
  313. vdprintf(
  314. unsigned long ulCompMask,
  315. char const *pszComp,
  316. char const *ppszfmt,
  317. va_list pargs)
  318. {
  319. if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
  320. ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
  321. {
  322. DWORD tid = GetCurrentThreadId();
  323. DWORD pid = GetCurrentProcessId();
  324. g_mxsAssert.Request();
  325. if ( 0 == pfIsBeingDebugged )
  326. {
  327. //
  328. // We can look here to tell when a process is being debugged.
  329. //
  330. pfIsBeingDebugged = &NtCurrentPeb()->BeingDebugged;
  331. }
  332. if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
  333. {
  334. if (! (ulCompMask & DEB_NOCOMPNAME))
  335. {
  336. w4dprintf( "%d.%03d> ", pid, tid );
  337. w4dprintf("%s: ", pszComp);
  338. }
  339. w4vdprintf(ppszfmt, pargs);
  340. }
  341. if (Win4InfoLevel & DEB_STDOUT)
  342. {
  343. if (! (ulCompMask & DEB_NOCOMPNAME))
  344. {
  345. w4printf( "%03d> ", tid );
  346. w4printf("%s: ", pszComp);
  347. }
  348. w4vprintf(ppszfmt, pargs);
  349. }
  350. g_mxsAssert.Release();
  351. }
  352. }
  353. #else
  354. int assertDontUseThisName(void)
  355. {
  356. return 1;
  357. }
  358. #endif // CIDBG == 1