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.

434 lines
11 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. //+-------------------------------------------------------------------------
  3. //
  4. // Microsoft Windows
  5. //
  6. // File: debug.cxx
  7. //
  8. // Contents: Debug support.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. //
  15. //
  16. // History: 18-Nov-96 BillMo Created.
  17. //
  18. // Notes:
  19. //
  20. // Codework:
  21. //
  22. //--------------------------------------------------------------------------
  23. #include "pch.cxx"
  24. #pragma hdrstop
  25. #include "trklib.hxx"
  26. #include <stdio.h> // vsprintf
  27. #if DBG == 1
  28. //CFailPoint * CFailPoint::g_pList = NULL;
  29. #define TRKSVC_LOG_FILE TEXT("%SystemRoot%\\debug\\trksvcs.log")
  30. CHAR TrkGlobalDebugBuffer[ 1024]; // arbitrary
  31. DWORD TrkGlobalDebug;
  32. HANDLE g_LogFile = INVALID_HANDLE_VALUE;
  33. // This critical section is used to serialize simultaneous dbgout calls.
  34. CRITICAL_SECTION g_csDebugOut;
  35. LONG g_cCritSecInit = 0;
  36. CHAR g_szDebugBuffer[ 1024]; // arbitrary
  37. TCHAR g_tszDebugBuffer[ 1024 ];
  38. ULONG g_grfDebugFlags = 0;
  39. ULONG g_grfLogFlags = 0;
  40. CHAR g_szModuleName[ MAX_PATH ] = { "" };
  41. LONG g_cInitializations = 0;
  42. VOID TrkDebugDelete( VOID)
  43. {
  44. // This isn't thread safe, so we won't ever delete it.
  45. // It just means there's a one-time leak in the chk build
  46. // when the service gets stopped.
  47. //if( 0 == InterlockedDecrement( &g_cCritSecInit ))
  48. // DeleteCriticalSection( &g_csDebugOut);
  49. InterlockedDecrement(&g_cInitializations);
  50. if( INVALID_HANDLE_VALUE != g_LogFile )
  51. {
  52. CloseHandle( g_LogFile );
  53. g_LogFile = INVALID_HANDLE_VALUE;
  54. }
  55. }
  56. VOID TrkDebugCreate( ULONG grfLogFlags, CHAR *pszModuleName )
  57. {
  58. TCHAR Buffer[ MAX_PATH];
  59. DWORD Length;
  60. if( 1 < InterlockedIncrement(&g_cInitializations) ) return;
  61. strncpy( g_szModuleName, pszModuleName, sizeof(g_szModuleName) );
  62. g_szModuleName[ sizeof(g_szModuleName) - 1 ] = TEXT('\0');
  63. if( 1 == InterlockedIncrement( &g_cCritSecInit ))
  64. InitializeCriticalSection( &g_csDebugOut );
  65. if( (TRK_DBG_FLAGS_WRITE_TO_FILE | TRK_DBG_FLAGS_APPEND_TO_FILE) & grfLogFlags )
  66. {
  67. //
  68. // Length returned by ExpandEnvironmentalStrings includes terminating
  69. // NULL byte.
  70. //
  71. Length = ExpandEnvironmentStrings( TRKSVC_LOG_FILE, Buffer, sizeof( Buffer));
  72. if ( Length == 0) {
  73. TrkLog(( TRKDBG_ERROR, TEXT("Error=%d"), GetLastError()));
  74. return;
  75. }
  76. if ( Length > sizeof( Buffer) || Length != _tcslen(Buffer) + 1) {
  77. Beep(2000,2000);
  78. TrkLog(( TRKDBG_ERROR, TEXT("Buffer=%x, Length = %d"), Buffer, Length));
  79. return;
  80. }
  81. g_LogFile = CreateFile( Buffer,
  82. GENERIC_WRITE,
  83. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  84. NULL,
  85. (TRK_DBG_FLAGS_APPEND_TO_FILE & grfLogFlags)
  86. ? OPEN_ALWAYS
  87. : CREATE_ALWAYS,
  88. FILE_ATTRIBUTE_NORMAL,
  89. NULL );
  90. if ( g_LogFile == INVALID_HANDLE_VALUE ) {
  91. TCHAR tsz[ 2 * MAX_PATH ];
  92. _stprintf( tsz, TEXT("Cannot open %s (%lu)\n"),
  93. Buffer, GetLastError() );
  94. OutputDebugString( tsz );
  95. return;
  96. }
  97. if( TRK_DBG_FLAGS_APPEND_TO_FILE & grfLogFlags )
  98. {
  99. //
  100. // Position the log file at the end
  101. //
  102. (VOID) SetFilePointer( g_LogFile,
  103. 0,
  104. NULL,
  105. FILE_END );
  106. }
  107. else
  108. {
  109. //
  110. // Truncate the file
  111. //
  112. SetFilePointer( g_LogFile, 0, NULL, FILE_BEGIN );
  113. SetEndOfFile( g_LogFile );
  114. }
  115. }
  116. g_grfLogFlags = grfLogFlags;
  117. }
  118. VOID TrkLogRoutine(
  119. IN DWORD DebugFlag,
  120. IN LPTSTR Format,
  121. ...
  122. )
  123. {
  124. LONG l = GetLastError();
  125. va_list Arguments;
  126. va_start( Arguments, Format );
  127. TrkLogErrorRoutineInternal( DebugFlag, NULL, Format, Arguments );
  128. SetLastError(l);
  129. }
  130. VOID TrkLogErrorRoutine(
  131. IN DWORD DebugFlag,
  132. IN HRESULT hr,
  133. IN LPTSTR Format,
  134. ...
  135. )
  136. {
  137. CHAR szHR[8];
  138. va_list Arguments;
  139. va_start( Arguments, Format );
  140. sprintf( szHR, "%08X", hr );
  141. TrkLogErrorRoutineInternal( DebugFlag, szHR, Format, Arguments );
  142. }
  143. VOID TrkLogErrorRoutineInternal(
  144. IN DWORD DebugFlag,
  145. IN LPSTR pszHR,
  146. IN LPTSTR Format,
  147. IN va_list Arguments
  148. )
  149. {
  150. // va_list arglist;
  151. ULONG length = 0;
  152. DWORD BytesWritten;
  153. ULONG iFormatStart = 0;
  154. // Skip if TrkDebugCreate hasn't been called yet.
  155. if( 0 == g_grfLogFlags )
  156. return;
  157. //
  158. // If we aren't debugging this type of message and it's not an
  159. // error, then we're done.
  160. //
  161. if( !( (g_grfDebugFlags | TRKDBG_ERROR ) & DebugFlag ) )
  162. return;
  163. //
  164. // vsprintf isn't multithreaded + we don't want to intermingle output
  165. // from different threads. Therefore we can use just a single output
  166. // debug buffer.
  167. //
  168. EnterCriticalSection( &g_csDebugOut );
  169. //
  170. // Prefix the line with any newlines
  171. //
  172. for( iFormatStart = 0; TEXT('\n') == Format[iFormatStart]; iFormatStart++ )
  173. g_szDebugBuffer[length++] = '\n';
  174. //
  175. // Put our name/time at the beginning of the line.
  176. //
  177. CFILETIME cftLocal(0);
  178. cftLocal.SetToLocal();
  179. SYSTEMTIME st = static_cast<SYSTEMTIME>( cftLocal );
  180. length += (ULONG) sprintf( &g_szDebugBuffer[length],
  181. "[%s/%02d%02d%02d.%03d:%03x] ",
  182. g_szModuleName,
  183. st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
  184. GetCurrentThreadId() );
  185. //
  186. // Put the information requested by the caller onto the line
  187. //
  188. _vstprintf( g_tszDebugBuffer, &Format[iFormatStart], Arguments );
  189. tcstombs( &g_szDebugBuffer[length], g_tszDebugBuffer );
  190. length = strlen( g_szDebugBuffer );
  191. if( NULL != pszHR )
  192. length += (ULONG) sprintf( &g_szDebugBuffer[length], " %s", pszHR );
  193. length += (ULONG) sprintf( &g_szDebugBuffer[length], "\n" );
  194. TrkAssert(length <= sizeof(g_szDebugBuffer));
  195. if( TRK_DBG_FLAGS_WRITE_TO_DBG & g_grfLogFlags )
  196. (void) OutputDebugStringA( (PCH) g_szDebugBuffer);
  197. if( TRK_DBG_FLAGS_WRITE_TO_STDOUT & g_grfLogFlags )
  198. printf( (PCH) g_szDebugBuffer );
  199. if( (TRK_DBG_FLAGS_WRITE_TO_FILE | TRK_DBG_FLAGS_APPEND_TO_FILE) & g_grfLogFlags )
  200. {
  201. if ( INVALID_HANDLE_VALUE == g_LogFile
  202. ||
  203. !WriteFile( g_LogFile,
  204. g_szDebugBuffer,
  205. length,
  206. &BytesWritten,
  207. NULL ) )
  208. {
  209. (void) OutputDebugStringA( (PCH) g_szDebugBuffer);
  210. }
  211. }
  212. LeaveCriticalSection( &g_csDebugOut );
  213. }
  214. VOID TrkAssertFailed(
  215. IN PVOID FailedAssertion,
  216. IN PVOID FileName,
  217. IN ULONG LineNumber,
  218. IN PCHAR Message OPTIONAL
  219. )
  220. /*++
  221. Have my own version of RtlAssert so debug versions of netlogon really assert on
  222. free builds.
  223. --*/
  224. {
  225. char Response[ 2 ];
  226. for ( ; ; ) {
  227. DbgPrint( "\n*** Assertion failed: %s%s\n*** Source File: %s, line %ld\n\n",
  228. Message ? Message : "",
  229. FailedAssertion,
  230. FileName,
  231. LineNumber
  232. );
  233. DbgPrompt( "Break, Ignore, terminate Process, Sleep 30 seconds, or terminate Thread (bipst)? ",
  234. Response, sizeof( Response));
  235. switch ( toupper(Response[0])) {
  236. case 'B':
  237. DbgBreakPoint();
  238. break;
  239. case 'I':
  240. return;
  241. break;
  242. case 'P':
  243. NtTerminateProcess( NtCurrentProcess(), STATUS_UNSUCCESSFUL );
  244. break;
  245. case 'S':
  246. Sleep( 30000L);
  247. break;
  248. case 'T':
  249. NtTerminateThread( NtCurrentThread(), STATUS_UNSUCCESSFUL );
  250. break;
  251. }
  252. }
  253. DbgBreakPoint();
  254. NtTerminateProcess( NtCurrentProcess(), STATUS_UNSUCCESSFUL );
  255. }
  256. typedef void (*PFNWin4AssertEx)( char const *pszFile, int iLine, char const *pszMsg);
  257. VOID TrkAssertFailedDlg(
  258. IN PVOID FailedAssertion,
  259. IN PVOID FileName,
  260. IN ULONG LineNumber,
  261. IN PCHAR Message OPTIONAL
  262. )
  263. {
  264. static HINSTANCE hinstOLE32 = NULL;
  265. static PFNWin4AssertEx pfnWin4AssertEx = NULL;
  266. if( NULL == hinstOLE32 )
  267. {
  268. hinstOLE32 = LoadLibraryEx( TEXT("ole32.dll"), NULL, 0 );
  269. if( NULL == hinstOLE32 )
  270. {
  271. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't load ole32.dll for Win4AssertEx (%#08x)"),
  272. GetLastError() ));
  273. return;
  274. }
  275. }
  276. if( NULL == pfnWin4AssertEx )
  277. {
  278. pfnWin4AssertEx = (PFNWin4AssertEx) GetProcAddress( hinstOLE32, "Win4AssertEx" );
  279. if( NULL == pfnWin4AssertEx )
  280. {
  281. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get Win4AssertEx from ole32.dll (%#08x)"),
  282. GetLastError() ));
  283. return;
  284. }
  285. }
  286. pfnWin4AssertEx( (char*) FileName, (int) LineNumber, (char*) FailedAssertion );
  287. return;
  288. }
  289. VOID TrkLogRuntimeList( IN PCHAR Comment)
  290. {
  291. PLIST_ENTRY pListEntry;
  292. TrkLog(( TRKDBG_ERROR, TEXT("%s\n"), Comment));
  293. }
  294. HANDLE hTestThread = NULL;
  295. /*
  296. DWORD WINAPI _TestWorkManagerThread(LPVOID pParam)
  297. {
  298. __try
  299. {
  300. ((CWorkManager*) pParam)->WorkManagerThread();
  301. }
  302. __except (EXCEPTION_EXECUTE_HANDLER)
  303. {
  304. TrkAssert(GetExceptionCode() != STATUS_ACCESS_VIOLATION);
  305. }
  306. return(0);
  307. }
  308. void
  309. StartTestWorkerThread(CWorkManager * pwm)
  310. {
  311. DWORD dwThreadId;
  312. hTestThread = CreateThread( NULL,
  313. 0,
  314. _TestWorkManagerThread,
  315. pwm,
  316. 0,
  317. &dwThreadId );
  318. TrkAssert(hTestThread != NULL);
  319. // Hack: make sure the work manager has a chance to init
  320. Sleep( 500 );
  321. }
  322. void
  323. WaitTestThreadExit()
  324. {
  325. if (hTestThread != NULL)
  326. {
  327. WaitForSingleObject(hTestThread, INFINITE);
  328. CloseHandle(hTestThread);
  329. }
  330. }
  331. */
  332. #endif // #if DBG == 1