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.

828 lines
24 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: WIADBGCL.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 9/4/1999
  12. *
  13. * DESCRIPTION: Debug client. Linked statically.
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <windows.h>
  19. #include "simreg.h"
  20. #include "wiadebug.h"
  21. #define DOESNT_MATTER_WHAT_THIS_IS ((UINT)7)
  22. //
  23. // Static class data members
  24. //
  25. CWiaDebugClient g_TheDebugClient;
  26. //
  27. // Sole constructor
  28. //
  29. CWiaDebugClient::CWiaDebugClient(void)
  30. : m_hDebugModule(NULL),
  31. m_hCurrentModuleInstance(NULL),
  32. m_pfnIncrementDebugIndentLevel(NULL),
  33. m_pfnDecrementDebugIndentLevel(NULL),
  34. m_pfnPrintDebugMessageW(NULL),
  35. m_pfnPrintDebugMessageA(NULL),
  36. m_pfnGetDebugMask(NULL),
  37. m_pfnSetDebugMask(NULL),
  38. m_pfnAllocateDebugColor(NULL),
  39. m_pfnGetStringFromGuidA(NULL),
  40. m_pfnGetStringFromGuidW(NULL),
  41. m_pfnDoRecordAllocation(NULL),
  42. m_pfnDoRecordFree(NULL),
  43. m_pfnDoReportLeaks(NULL),
  44. m_crForegroundColor(DEFAULT_DEBUG_COLOR),
  45. m_dwModuleDebugMask(0),
  46. m_bHaveModuleInformation(false),
  47. m_bDebugLibLoadAttempted(false),
  48. m_pfnGetStringFromMsgA(NULL),
  49. m_pfnGetStringFromMsgW(NULL)
  50. {
  51. CAutoCriticalSection cs(m_CriticalSection);
  52. m_szModuleNameW[0] = 0;
  53. m_szModuleNameA[0] = 0;
  54. if (LoadWiaDebugExports())
  55. {
  56. InitializeModuleInfo();
  57. }
  58. }
  59. template <class T>
  60. static T GetProc( HINSTANCE hModule, LPCSTR pszFunctionName )
  61. {
  62. return reinterpret_cast<T>(GetProcAddress( hModule, pszFunctionName ));
  63. }
  64. bool CWiaDebugClient::LoadWiaDebugExports()
  65. {
  66. CAutoCriticalSection cs(m_CriticalSection);
  67. //
  68. // No need to call this more than once, so return true if the
  69. // load was successful, false if it was not
  70. //
  71. if (m_bDebugLibLoadAttempted)
  72. {
  73. return (NULL != m_hDebugModule);
  74. }
  75. //
  76. // Prevent future loading attempts
  77. //
  78. m_bDebugLibLoadAttempted = true;
  79. //
  80. // Assume failure
  81. //
  82. bool bResult = false;
  83. //
  84. // Load the library
  85. //
  86. m_hDebugModule = LoadLibrary( DEBUG_DLL_NAME );
  87. if (m_hDebugModule)
  88. {
  89. m_pfnIncrementDebugIndentLevel = GetProc<IncrementDebugIndentLevelProc>( m_hDebugModule, INCREMENT_DEBUG_INDENT_LEVEL_NAME );
  90. m_pfnDecrementDebugIndentLevel = GetProc<DecrementDebugIndentLevelProc>( m_hDebugModule, DECREMENT_DEBUG_INDENT_LEVEL_NAME );
  91. m_pfnPrintDebugMessageA = GetProc<PrintDebugMessageAProc>( m_hDebugModule, PRINT_DEBUG_MESSAGE_NAMEA );
  92. m_pfnPrintDebugMessageW = GetProc<PrintDebugMessageWProc>( m_hDebugModule, PRINT_DEBUG_MESSAGE_NAMEW );
  93. m_pfnGetDebugMask = GetProc<GetDebugMaskProc>( m_hDebugModule, GET_DEBUG_MASK_NAME );
  94. m_pfnSetDebugMask = GetProc<SetDebugMaskProc>( m_hDebugModule, SET_DEBUG_MASK_NAME );
  95. m_pfnAllocateDebugColor = GetProc<AllocateDebugColorProc>( m_hDebugModule, ALLOCATE_DEBUG_COLOR_NAME );
  96. m_pfnGetStringFromGuidA = GetProc<GetStringFromGuidAProc>( m_hDebugModule, GET_STRING_FROM_GUID_NAMEA );
  97. m_pfnGetStringFromGuidW = GetProc<GetStringFromGuidWProc>( m_hDebugModule, GET_STRING_FROM_GUID_NAMEW );
  98. m_pfnDoRecordAllocation = GetProc<DoRecordAllocationProc>( m_hDebugModule, DO_RECORD_ALLOCATION );
  99. m_pfnDoRecordFree = GetProc<DoRecordFreeProc>( m_hDebugModule, DO_RECORD_FREE );
  100. m_pfnDoReportLeaks = GetProc<DoReportLeaksProc>( m_hDebugModule, DO_REPORT_LEAKS );
  101. m_pfnGetStringFromMsgA = GetProc<GetStringFromMsgAProc>( m_hDebugModule, GET_STRING_FROM_MSGA );
  102. m_pfnGetStringFromMsgW = GetProc<GetStringFromMsgWProc>( m_hDebugModule, GET_STRING_FROM_MSGW );
  103. bResult = (m_pfnIncrementDebugIndentLevel &&
  104. m_pfnDecrementDebugIndentLevel &&
  105. m_pfnPrintDebugMessageA &&
  106. m_pfnPrintDebugMessageW &&
  107. m_pfnGetDebugMask &&
  108. m_pfnSetDebugMask &&
  109. m_pfnAllocateDebugColor &&
  110. m_pfnGetStringFromGuidA &&
  111. m_pfnGetStringFromGuidW &&
  112. m_pfnDoRecordAllocation &&
  113. m_pfnDoRecordFree &&
  114. m_pfnDoReportLeaks &&
  115. m_pfnGetStringFromMsgA &&
  116. m_pfnGetStringFromMsgW);
  117. }
  118. return bResult;
  119. }
  120. bool CWiaDebugClient::IsInitialized()
  121. {
  122. bool bResult = false;
  123. CAutoCriticalSection cs(m_CriticalSection);
  124. if (LoadWiaDebugExports())
  125. {
  126. bResult = InitializeModuleInfo();
  127. }
  128. return bResult;
  129. }
  130. LPTSTR CWiaDebugClient::GetJustTheFileName( LPCTSTR pszPath, LPTSTR pszFileName, int nMaxLen )
  131. {
  132. //
  133. // Make sure we have valid arguments
  134. //
  135. if (!pszPath || !pszFileName || !nMaxLen)
  136. {
  137. return NULL;
  138. }
  139. //
  140. // Initialize the return string
  141. //
  142. lstrcpy( pszFileName, TEXT("") );
  143. //
  144. // Loop through the filename, looking for the last \
  145. //
  146. LPCTSTR pszLastBackslash = NULL;
  147. for (LPCTSTR pszCurr=pszPath;pszCurr && *pszCurr;pszCurr = CharNext(pszCurr))
  148. {
  149. if (TEXT('\\') == *pszCurr)
  150. {
  151. pszLastBackslash = pszCurr;
  152. }
  153. }
  154. //
  155. // If we found any \'s, point to the next character
  156. //
  157. if (pszLastBackslash)
  158. {
  159. pszLastBackslash = CharNext(pszLastBackslash);
  160. }
  161. //
  162. // Otherwise, we will copy the entire path
  163. //
  164. else
  165. {
  166. pszLastBackslash = pszPath;
  167. }
  168. //
  169. // If we have a valid starting point, copy the string to the target buffer and terminate it
  170. //
  171. if (pszLastBackslash)
  172. {
  173. lstrcpyn( pszFileName, pszLastBackslash, nMaxLen-1 );
  174. pszFileName[nMaxLen-1] = TEXT('\0');
  175. }
  176. return pszFileName;
  177. }
  178. bool CWiaDebugClient::InitializeModuleInfo()
  179. {
  180. CAutoCriticalSection cs(m_CriticalSection);
  181. //
  182. // If we've already been initialized, return true
  183. //
  184. if (m_bHaveModuleInformation)
  185. {
  186. return true;
  187. }
  188. //
  189. // If we haven't got a valid HINSTANCE, return false
  190. //
  191. if (!m_hCurrentModuleInstance)
  192. {
  193. return false;
  194. }
  195. //
  196. // Make sure we start out with empty module name strings
  197. //
  198. m_szModuleNameW[0] = 0;
  199. m_szModuleNameA[0] = 0;
  200. //
  201. // Get default debug setting
  202. //
  203. m_dwModuleDebugMask = CSimpleReg( HKEY_LOCAL_MACHINE, DEBUG_REGISTRY_PATH, false, KEY_READ ).Query( DEBUG_REGISTRY_DEFAULT_FLAGS, 0 );
  204. //
  205. // Initialize the module name, in case we can't determine it. It is OK
  206. // that wsprintfW will return ERROR_NOT_IMPLEMENTED under win9x, since
  207. // we won't be using this variable at all on this OS
  208. //
  209. wsprintfW( m_szModuleNameW, L"0x%08X", GetCurrentProcessId() );
  210. wsprintfA( m_szModuleNameA, "0x%08X", GetCurrentProcessId() );
  211. //
  212. // Get the next available color
  213. //
  214. m_crForegroundColor = m_pfnAllocateDebugColor();
  215. //
  216. // Get the module name
  217. //
  218. TCHAR szModulePathName[MAX_PATH] = TEXT("");
  219. if (GetModuleFileName( m_hCurrentModuleInstance, szModulePathName, ARRAYSIZE(szModulePathName)))
  220. {
  221. //
  222. // Get rid of the path
  223. //
  224. TCHAR szFilename[MAX_PATH] = TEXT("");
  225. GetJustTheFileName( szModulePathName, szFilename, ARRAYSIZE(szFilename) );
  226. //
  227. // Make sure we have a valid filename
  228. //
  229. if (lstrlen(szFilename))
  230. {
  231. m_dwModuleDebugMask = CSimpleReg( HKEY_LOCAL_MACHINE, DEBUG_REGISTRY_PATH_FLAGS, false, KEY_READ ).Query( szFilename, 0 );
  232. //
  233. // Save the ANSI and UNICODE versions of the module name
  234. //
  235. #ifdef UNICODE
  236. WideCharToMultiByte( CP_ACP, 0, szFilename, -1, m_szModuleNameA, ARRAYSIZE(m_szModuleNameA), NULL, NULL );
  237. lstrcpyn( m_szModuleNameW, szFilename, MAX_PATH );
  238. #else
  239. MultiByteToWideChar( CP_ACP, 0, szFilename, -1, m_szModuleNameW, ARRAYSIZE(m_szModuleNameW) );
  240. lstrcpyn( m_szModuleNameA, szFilename, MAX_PATH );
  241. #endif
  242. //
  243. // Success!
  244. //
  245. m_bHaveModuleInformation = true;
  246. //
  247. // Tell the debugger we're here. This way, the user can get the expected module name correct.
  248. //
  249. m_pfnPrintDebugMessageA( WiaDebugSeverityNormal, 0xFFFFFFFF, RGB(0xFF,0xFF,0xFF), RGB(0x00,0x00,0x00), m_szModuleNameA, "Created debug client" );
  250. }
  251. }
  252. return m_bHaveModuleInformation;
  253. }
  254. void CWiaDebugClient::Destroy(void)
  255. {
  256. CAutoCriticalSection cs(m_CriticalSection);
  257. //
  258. // NULL out all of the function pointers
  259. //
  260. m_pfnIncrementDebugIndentLevel = NULL;
  261. m_pfnDecrementDebugIndentLevel = NULL;
  262. m_pfnPrintDebugMessageA = NULL;
  263. m_pfnPrintDebugMessageW = NULL;
  264. m_pfnGetDebugMask = NULL;
  265. m_pfnSetDebugMask = NULL;
  266. m_pfnAllocateDebugColor = NULL;
  267. m_pfnGetStringFromGuidW = NULL;
  268. m_pfnGetStringFromGuidA = NULL;
  269. m_pfnDoRecordAllocation = NULL;
  270. m_pfnDoRecordFree = NULL;
  271. m_pfnDoReportLeaks = NULL;
  272. m_pfnGetStringFromMsgA = NULL;
  273. m_pfnGetStringFromMsgW = NULL;
  274. //
  275. // Unload the DLL
  276. //
  277. if (m_hDebugModule)
  278. {
  279. FreeLibrary( m_hDebugModule );
  280. m_hDebugModule = NULL;
  281. }
  282. m_bHaveModuleInformation = false;
  283. m_bDebugLibLoadAttempted = false;
  284. }
  285. CWiaDebugClient::~CWiaDebugClient(void)
  286. {
  287. CAutoCriticalSection cs(m_CriticalSection);
  288. Destroy();
  289. }
  290. DWORD CWiaDebugClient::GetDebugMask(void)
  291. {
  292. CAutoCriticalSection cs(m_CriticalSection);
  293. if (IsInitialized())
  294. {
  295. return m_pfnGetDebugMask();
  296. }
  297. return 0;
  298. }
  299. DWORD CWiaDebugClient::SetDebugMask( DWORD dwNewMask )
  300. {
  301. CAutoCriticalSection cs(m_CriticalSection);
  302. if (IsInitialized())
  303. {
  304. return m_pfnSetDebugMask( dwNewMask );
  305. }
  306. return 0;
  307. }
  308. int CWiaDebugClient::IncrementIndentLevel(void)
  309. {
  310. CAutoCriticalSection cs(m_CriticalSection);
  311. if (IsInitialized())
  312. {
  313. return m_pfnIncrementDebugIndentLevel();
  314. }
  315. return 0;
  316. }
  317. int CWiaDebugClient::DecrementIndentLevel(void)
  318. {
  319. CAutoCriticalSection cs(m_CriticalSection);
  320. if (IsInitialized())
  321. {
  322. return m_pfnDecrementDebugIndentLevel();
  323. }
  324. return 0;
  325. }
  326. void CWiaDebugClient::RecordAllocation( LPVOID pv, size_t Size )
  327. {
  328. CAutoCriticalSection cs(m_CriticalSection);
  329. if (IsInitialized())
  330. {
  331. m_pfnDoRecordAllocation( pv, Size );
  332. }
  333. }
  334. void CWiaDebugClient::RecordFree( LPVOID pv )
  335. {
  336. CAutoCriticalSection cs(m_CriticalSection);
  337. if (IsInitialized())
  338. {
  339. m_pfnDoRecordFree( pv );
  340. }
  341. }
  342. void CWiaDebugClient::ReportLeaks( VOID )
  343. {
  344. CAutoCriticalSection cs(m_CriticalSection);
  345. if (IsInitialized())
  346. {
  347. #ifdef UNICODE
  348. m_pfnDoReportLeaks(m_szModuleNameW);
  349. #else
  350. m_pfnDoReportLeaks(m_szModuleNameA);
  351. #endif
  352. }
  353. }
  354. CPushTraceMask::CPushTraceMask( DWORD dwTraceMask )
  355. : m_dwOldMask(0)
  356. {
  357. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  358. g_TheDebugClient.SetDebugMask( dwTraceMask );
  359. }
  360. CPushTraceMask::~CPushTraceMask(void)
  361. {
  362. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  363. g_TheDebugClient.SetDebugMask( m_dwOldMask );
  364. }
  365. CPushIndentLevel::CPushIndentLevel( LPCTSTR pszFmt, ... )
  366. : m_nIndentLevel(0)
  367. {
  368. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  369. m_nIndentLevel = g_TheDebugClient.IncrementIndentLevel();
  370. TCHAR szMsg[1024];
  371. va_list arglist;
  372. va_start( arglist, pszFmt );
  373. wvsprintf( szMsg, pszFmt, arglist );
  374. va_end( arglist );
  375. g_TheDebugClient.PrintTraceMessage( TEXT("Entering function %s [Level %d]"), szMsg, m_nIndentLevel );
  376. }
  377. CPushIndentLevel::~CPushIndentLevel(void)
  378. {
  379. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  380. if (m_nIndentLevel)
  381. {
  382. g_TheDebugClient.DecrementIndentLevel();
  383. g_TheDebugClient.PrintTraceMessage( TEXT("") );
  384. }
  385. }
  386. CPushTraceMaskAndIndentLevel::CPushTraceMaskAndIndentLevel( DWORD dwTraceMask, LPCTSTR pszFmt, ... )
  387. : m_dwOldMask(0), m_nIndentLevel(0)
  388. {
  389. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  390. m_dwOldMask = g_TheDebugClient.SetDebugMask( dwTraceMask );
  391. m_nIndentLevel = g_TheDebugClient.IncrementIndentLevel();
  392. TCHAR szMsg[1024];
  393. va_list arglist;
  394. va_start( arglist, pszFmt );
  395. wvsprintf( szMsg, pszFmt, arglist );
  396. va_end( arglist );
  397. g_TheDebugClient.PrintTraceMessage( TEXT("Entering function %s [Level %d]"), szMsg, m_nIndentLevel );
  398. }
  399. CPushTraceMaskAndIndentLevel::~CPushTraceMaskAndIndentLevel(void)
  400. {
  401. CAutoCriticalSection cs( g_TheDebugClient.m_CriticalSection );
  402. if (m_nIndentLevel)
  403. {
  404. g_TheDebugClient.DecrementIndentLevel();
  405. g_TheDebugClient.PrintTraceMessage( TEXT("") );
  406. g_TheDebugClient.SetDebugMask( m_dwOldMask );
  407. }
  408. }
  409. ////////////////////////////////////////////////////////////////
  410. // UNICODE Versions of the output functions
  411. ////////////////////////////////////////////////////////////////
  412. void CWiaDebugClient::PrintWarningMessage( LPCWSTR pszFmt, ... )
  413. {
  414. CAutoCriticalSection cs(m_CriticalSection);
  415. if (IsInitialized())
  416. {
  417. WCHAR szMsg[1024];
  418. va_list arglist;
  419. va_start( arglist, pszFmt );
  420. ::wvsprintfW( szMsg, pszFmt, arglist );
  421. va_end( arglist );
  422. m_pfnPrintDebugMessageW( WiaDebugSeverityWarning, m_dwModuleDebugMask, WARNING_FOREGROUND_COLOR, WARNING_BACKGROUND_COLOR, m_szModuleNameW, szMsg );
  423. }
  424. }
  425. void CWiaDebugClient::PrintErrorMessage( LPCWSTR pszFmt, ... )
  426. {
  427. CAutoCriticalSection cs(m_CriticalSection);
  428. if (IsInitialized())
  429. {
  430. WCHAR szMsg[1024];
  431. va_list arglist;
  432. va_start( arglist, pszFmt );
  433. ::wvsprintfW( szMsg, pszFmt, arglist );
  434. va_end( arglist );
  435. m_pfnPrintDebugMessageW( WiaDebugSeverityError, m_dwModuleDebugMask, ERROR_FOREGROUND_COLOR, ERROR_BACKGROUND_COLOR, m_szModuleNameW, szMsg );
  436. }
  437. }
  438. void CWiaDebugClient::PrintTraceMessage( LPCWSTR pszFmt, ... )
  439. {
  440. CAutoCriticalSection cs(m_CriticalSection);
  441. if (IsInitialized())
  442. {
  443. WCHAR szMsg[1024];
  444. va_list arglist;
  445. va_start( arglist, pszFmt );
  446. ::wvsprintfW( szMsg, pszFmt, arglist );
  447. va_end( arglist );
  448. m_pfnPrintDebugMessageW( WiaDebugSeverityNormal, m_dwModuleDebugMask, m_crForegroundColor, DEFAULT_DEBUG_COLOR, m_szModuleNameW, szMsg );
  449. }
  450. }
  451. void CWiaDebugClient::PrintMessage( DWORD dwSeverity, COLORREF crForegroundColor, COLORREF crBackgroundColor, LPCWSTR pszFmt, ... )
  452. {
  453. CAutoCriticalSection cs(m_CriticalSection);
  454. if (IsInitialized())
  455. {
  456. WCHAR szMsg[1024];
  457. va_list arglist;
  458. va_start( arglist, pszFmt );
  459. ::wvsprintfW( szMsg, pszFmt, arglist );
  460. va_end( arglist );
  461. m_pfnPrintDebugMessageW( dwSeverity, m_dwModuleDebugMask, crForegroundColor, crBackgroundColor, m_szModuleNameW, szMsg );
  462. }
  463. }
  464. void CWiaDebugClient::PrintHResult( HRESULT hr, LPCWSTR pszFmt, ... )
  465. {
  466. CAutoCriticalSection cs(m_CriticalSection);
  467. if (IsInitialized())
  468. {
  469. WCHAR szMsg[1024]=L"";
  470. va_list arglist;
  471. va_start( arglist, pszFmt );
  472. ::wvsprintfW( szMsg, pszFmt, arglist );
  473. va_end( arglist );
  474. DWORD dwLen = 0;
  475. LPTSTR pMsgBuf = NULL;
  476. dwLen = ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  477. NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  478. (LPWSTR)&pMsgBuf, 0, NULL);
  479. COLORREF crForegroundColor;
  480. COLORREF crBackgroundColor;
  481. DWORD dwSeverity;
  482. if (FAILED(hr))
  483. {
  484. crForegroundColor = ERROR_FOREGROUND_COLOR;
  485. crBackgroundColor = ERROR_BACKGROUND_COLOR;
  486. dwSeverity = WiaDebugSeverityError;
  487. }
  488. else if (S_OK == hr)
  489. {
  490. crForegroundColor = m_crForegroundColor;
  491. crBackgroundColor = DEFAULT_DEBUG_COLOR;
  492. dwSeverity = WiaDebugSeverityNormal;
  493. }
  494. else
  495. {
  496. crForegroundColor = WARNING_FOREGROUND_COLOR;
  497. crBackgroundColor = WARNING_BACKGROUND_COLOR;
  498. dwSeverity = WiaDebugSeverityWarning;
  499. }
  500. if (dwLen)
  501. {
  502. PrintMessage( dwSeverity, crForegroundColor, crBackgroundColor, TEXT("%ws: [0x%08X] %ws"), szMsg, hr, pMsgBuf );
  503. LocalFree(pMsgBuf);
  504. }
  505. else
  506. {
  507. PrintMessage( dwSeverity, crForegroundColor, crBackgroundColor, TEXT("%ws: Unable to format message [0x%08X]"), szMsg, hr );
  508. }
  509. }
  510. }
  511. void CWiaDebugClient::PrintGuid( const IID &iid, LPCWSTR pszFmt, ... )
  512. {
  513. CAutoCriticalSection cs(m_CriticalSection);
  514. if (IsInitialized())
  515. {
  516. WCHAR szMsg[1024]=L"";
  517. va_list arglist;
  518. va_start( arglist, pszFmt );
  519. ::wvsprintfW( szMsg, pszFmt, arglist );
  520. va_end( arglist );
  521. WCHAR szGuid[MAX_PATH]=L"";
  522. if (m_pfnGetStringFromGuidW( &iid, szGuid, sizeof(szGuid)/sizeof(szGuid[0]) ) )
  523. {
  524. PrintMessage( 0, m_crForegroundColor, DEFAULT_DEBUG_COLOR, TEXT("%ws: %ws"), szMsg, szGuid );
  525. }
  526. }
  527. }
  528. void CWiaDebugClient::PrintWindowMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPCWSTR szMessage )
  529. {
  530. CAutoCriticalSection cs(m_CriticalSection);
  531. if (IsInitialized())
  532. {
  533. WCHAR szWindowMessage[MAX_PATH]=L"";
  534. if (m_pfnGetStringFromMsgW( uMsg, szWindowMessage, sizeof(szWindowMessage)/sizeof(szWindowMessage[0]) ) )
  535. {
  536. PrintMessage( 0, m_crForegroundColor, DEFAULT_DEBUG_COLOR, TEXT("0x%p, %-30ws, 0x%p, 0x%p%ws%ws"), hWnd, szWindowMessage, wParam, lParam, (szMessage && lstrlenW(szMessage)) ? L" : " : L"", (szMessage && lstrlenW(szMessage)) ? szMessage : L"" );
  537. }
  538. }
  539. }
  540. ////////////////////////////////////////////////////////////////
  541. // ANSI Versions of the output functions
  542. ////////////////////////////////////////////////////////////////
  543. void CWiaDebugClient::PrintWarningMessage( LPCSTR pszFmt, ... )
  544. {
  545. CAutoCriticalSection cs(m_CriticalSection);
  546. if (IsInitialized())
  547. {
  548. CHAR szMsg[1024];
  549. va_list arglist;
  550. va_start( arglist, pszFmt );
  551. ::wvsprintfA( szMsg, pszFmt, arglist );
  552. va_end( arglist );
  553. m_pfnPrintDebugMessageA( WiaDebugSeverityWarning, m_dwModuleDebugMask, WARNING_FOREGROUND_COLOR, WARNING_BACKGROUND_COLOR, m_szModuleNameA, szMsg );
  554. }
  555. }
  556. void CWiaDebugClient::PrintErrorMessage( LPCSTR pszFmt, ... )
  557. {
  558. CAutoCriticalSection cs(m_CriticalSection);
  559. if (IsInitialized())
  560. {
  561. CHAR szMsg[1024];
  562. va_list arglist;
  563. va_start( arglist, pszFmt );
  564. ::wvsprintfA( szMsg, pszFmt, arglist );
  565. va_end( arglist );
  566. m_pfnPrintDebugMessageA( WiaDebugSeverityError, m_dwModuleDebugMask, ERROR_FOREGROUND_COLOR, ERROR_BACKGROUND_COLOR, m_szModuleNameA, szMsg );
  567. }
  568. }
  569. void CWiaDebugClient::PrintTraceMessage( LPCSTR pszFmt, ... )
  570. {
  571. CAutoCriticalSection cs(m_CriticalSection);
  572. if (IsInitialized())
  573. {
  574. CHAR szMsg[1024];
  575. va_list arglist;
  576. va_start( arglist, pszFmt );
  577. ::wvsprintfA( szMsg, pszFmt, arglist );
  578. va_end( arglist );
  579. m_pfnPrintDebugMessageA( WiaDebugSeverityNormal, m_dwModuleDebugMask, m_crForegroundColor, DEFAULT_DEBUG_COLOR, m_szModuleNameA, szMsg );
  580. }
  581. }
  582. void CWiaDebugClient::PrintMessage( DWORD dwSeverity, COLORREF crForegroundColor, COLORREF crBackgroundColor, LPCSTR pszFmt, ... )
  583. {
  584. CAutoCriticalSection cs(m_CriticalSection);
  585. if (IsInitialized())
  586. {
  587. CHAR szMsg[1024];
  588. va_list arglist;
  589. va_start( arglist, pszFmt );
  590. ::wvsprintfA( szMsg, pszFmt, arglist );
  591. va_end( arglist );
  592. m_pfnPrintDebugMessageA( dwSeverity, m_dwModuleDebugMask, crForegroundColor, crBackgroundColor, m_szModuleNameA, szMsg );
  593. }
  594. }
  595. void CWiaDebugClient::PrintHResult( HRESULT hr, LPCSTR pszFmt, ... )
  596. {
  597. CAutoCriticalSection cs(m_CriticalSection);
  598. if (IsInitialized())
  599. {
  600. CHAR szMsg[1024]="";
  601. va_list arglist;
  602. va_start( arglist, pszFmt );
  603. ::wvsprintfA( szMsg, pszFmt, arglist );
  604. va_end( arglist );
  605. DWORD dwLen = 0;
  606. LPTSTR pMsgBuf = NULL;
  607. dwLen = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  608. NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  609. (LPSTR)&pMsgBuf, 0, NULL);
  610. COLORREF crForegroundColor;
  611. COLORREF crBackgroundColor;
  612. DWORD dwSeverity;
  613. if (FAILED(hr))
  614. {
  615. crForegroundColor = ERROR_FOREGROUND_COLOR;
  616. crBackgroundColor = ERROR_BACKGROUND_COLOR;
  617. dwSeverity = WiaDebugSeverityError;
  618. }
  619. else if (S_OK == hr)
  620. {
  621. crForegroundColor = m_crForegroundColor;
  622. crBackgroundColor = DEFAULT_DEBUG_COLOR;
  623. dwSeverity = WiaDebugSeverityNormal;
  624. }
  625. else
  626. {
  627. crForegroundColor = WARNING_FOREGROUND_COLOR;
  628. crBackgroundColor = WARNING_BACKGROUND_COLOR;
  629. dwSeverity = WiaDebugSeverityWarning;
  630. }
  631. if (dwLen)
  632. {
  633. PrintMessage( dwSeverity, crForegroundColor, crBackgroundColor, TEXT("%hs: [0x%08X] %hs"), szMsg, hr, pMsgBuf );
  634. LocalFree(pMsgBuf);
  635. }
  636. else
  637. {
  638. PrintMessage( dwSeverity, crForegroundColor, crBackgroundColor, TEXT("%hs: Unable to format message [0x%08X]"), szMsg, hr );
  639. }
  640. }
  641. }
  642. void CWiaDebugClient::PrintGuid( const IID &iid, LPCSTR pszFmt, ... )
  643. {
  644. CAutoCriticalSection cs(m_CriticalSection);
  645. if (IsInitialized())
  646. {
  647. CHAR szMsg[1024]="";
  648. va_list arglist;
  649. va_start( arglist, pszFmt );
  650. ::wvsprintfA( szMsg, pszFmt, arglist );
  651. va_end( arglist );
  652. CHAR szGuid[MAX_PATH]="";
  653. if (m_pfnGetStringFromGuidA( &iid, szGuid, sizeof(szGuid)/sizeof(szGuid[0]) ) )
  654. {
  655. PrintMessage( 0, m_crForegroundColor, DEFAULT_DEBUG_COLOR, TEXT("%hs: %hs"), szMsg, szGuid );
  656. }
  657. }
  658. }
  659. void CWiaDebugClient::PrintWindowMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPCSTR szMessage )
  660. {
  661. CAutoCriticalSection cs(m_CriticalSection);
  662. if (IsInitialized())
  663. {
  664. CHAR szWindowMessage[MAX_PATH]="";
  665. if (m_pfnGetStringFromMsgA( uMsg, szWindowMessage, sizeof(szWindowMessage)/sizeof(szWindowMessage[0]) ) )
  666. {
  667. PrintMessage( 0, m_crForegroundColor, DEFAULT_DEBUG_COLOR, TEXT("0x%p, %-30hs, 0x%p, 0x%p%hs%hs"), hWnd, szWindowMessage, wParam, lParam, (szMessage && lstrlenA(szMessage)) ? " : " : "", (szMessage && lstrlenA(szMessage)) ? szMessage : "" );
  668. }
  669. }
  670. }
  671. void CWiaDebugClient::SetInstance( HINSTANCE hInstance )
  672. {
  673. m_hCurrentModuleInstance = hInstance;
  674. }
  675. static CSimpleString ForceFailureProgramKey( LPCTSTR pszProgramName )
  676. {
  677. CSimpleString strAppKey( REGSTR_FORCEERR_KEY );
  678. strAppKey += TEXT("\\");
  679. strAppKey += pszProgramName;
  680. return strAppKey;
  681. }
  682. DWORD CWiaDebugClient::GetForceFailurePoint( LPCTSTR pszProgramName )
  683. {
  684. return CSimpleReg( HKEY_FORCEERROR, ForceFailureProgramKey(pszProgramName) ).Query( REGSTR_ERROR_POINT, 0 );
  685. }
  686. HRESULT CWiaDebugClient::GetForceFailureValue( LPCTSTR pszProgramName, bool bPrintWarning )
  687. {
  688. HRESULT hr = HRESULT_FROM_WIN32(CSimpleReg( HKEY_FORCEERROR, ForceFailureProgramKey(pszProgramName) ).Query( REGSTR_ERROR_VALUE, 0 ));
  689. if (bPrintWarning)
  690. {
  691. g_TheDebugClient.PrintHResult( hr, TEXT("FORCEERR: Forcing error return for program %s"), pszProgramName );
  692. }
  693. return hr;
  694. }
  695. void CWiaDebugClient::SetForceFailurePoint( LPCTSTR pszProgramName, DWORD dwErrorPoint )
  696. {
  697. CSimpleReg( HKEY_FORCEERROR, ForceFailureProgramKey(pszProgramName), true ).Set( REGSTR_ERROR_POINT, dwErrorPoint );
  698. }
  699. void CWiaDebugClient::SetForceFailureValue( LPCTSTR pszProgramName, HRESULT hr )
  700. {
  701. CSimpleReg( HKEY_FORCEERROR, ForceFailureProgramKey(pszProgramName), true ).Set( REGSTR_ERROR_VALUE, hr );
  702. }