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.

1520 lines
44 KiB

  1. //+-------------------------------------------------------------------
  2. // Microsoft OLE
  3. // Copyright (C) Microsoft Corporation, 1994-1995.
  4. //
  5. // File: cdbghelp.cxx
  6. //
  7. // Contents: OLE Debug Helper Object
  8. //
  9. // Classes: CDebugHelper
  10. //
  11. // History: 19-Nov-94 DeanE Created
  12. //---------------------------------------------------------------------
  13. #include <dfheader.hxx>
  14. #pragma hdrstop
  15. // Global library character constants - note alphabetical order for
  16. // easy reference
  17. //
  18. CONST TCHAR chBackSlash = TEXT('\\');
  19. CONST TCHAR chEqual = TEXT('=');
  20. CONST TCHAR chNewLine = TEXT('\n');
  21. CONST TCHAR chNull = TEXT('\0');
  22. CONST TCHAR chPeriod = TEXT('.');
  23. CONST TCHAR chSpace = TEXT(' ');
  24. CONST TCHAR chTrace = TEXT(' ');
  25. CONST TCHAR chTraceErr = TEXT('e');
  26. // Global library string contants - note alphabetical order for
  27. // easy reference
  28. //
  29. CONST TCHAR szCRLF[] = TEXT("\r\n");
  30. CONST TCHAR szError[] = TEXT("ERROR "); // Used TraceMsg for ERRORs
  31. CONST TCHAR szNewLine[] = TEXT("\n");
  32. CONST TCHAR szNull[] = TEXT("");
  33. CONST TCHAR szPeriod[] = TEXT(".");
  34. // Test Result Description strings
  35. //
  36. LPCTSTR szPass = TEXT("VAR_PASS");
  37. LPCTSTR szFail = TEXT("VAR_FAIL");
  38. LPCTSTR szAbort = TEXT("VAR_ABORT");
  39. LPCTSTR szWarn = TEXT("WARNING");
  40. LPCTSTR szInfo = TEXT("INFO");
  41. LPCTSTR szInvalid = TEXT("INVALID!!");
  42. // Debug Helper Usage String
  43. //
  44. LPTSTR gptszDebugHelperUsageString = {
  45. TEXT("Debug Object Command line options:\r\n")
  46. TEXT(" /logloc - where log output goes (bitfield)\r\n")
  47. TEXT(" /traceloc - where trace output goes (bitfield)\r\n")
  48. TEXT(" /tracelvl - trace levels (bitfield)\r\n")
  49. TEXT(" /spyclass - spy window\r\n")
  50. TEXT(" /labmode - do not use PopUp for errors\r\n")
  51. TEXT(" /breakmode - break on error\r\n")
  52. TEXT(" /verbose - trace hrchecks that are ok\r\n")
  53. };
  54. int giAlwaysNegativeOne = -1;
  55. // Global variable, the THREAD_VALIDATE_FLAG_ON bit of which at present is
  56. // used to do or skip thread validation DH_VDATETHREAD macro. Other bits
  57. // might be used in future. Initialize the variable to set its bit
  58. // THREAD_VALIDATE_FLAG_ON.
  59. ULONG g_fThreadValidate = THREAD_VALIDATE_FLAG_ON ;
  60. //+-------------------------------------------------------------------
  61. // Member: CDebugHelp::CDebugHelp
  62. //
  63. // Synopsis: Initializes CDebugHelp object. Makes object usable
  64. // in it's default state.
  65. //
  66. // Arguments: None.
  67. //
  68. // Returns: Nothing. Constructor cannot fail.
  69. //
  70. // History: 21-Nov-94 DeanE Created
  71. //--------------------------------------------------------------------
  72. CDebugHelp::CDebugHelp() :
  73. _fLogLoc(DH_LOC_TERM),
  74. _fTraceLoc(DH_LOC_TERM),
  75. _fTraceLvl(DH_LVL_ALWAYS|DH_LVL_ERROR),
  76. _fMode(DH_LABMODE),
  77. _hrExpectedError(S_OK),
  78. _fCreatedLog(FALSE),
  79. _plog(NULL),
  80. _hwndAssert(NULL),
  81. _cPass(0),
  82. _cAbort(0),
  83. _cFail(0),
  84. _cIndentLevel(0),
  85. _fSpyWarning(0),
  86. _pszSpyWindowClass((LPTSTR) SZ_DEFAULT_SPY_WINDOW_CLASS)
  87. {
  88. DWORD cchModule;
  89. TCHAR szModule[CCH_MAX_MODULE];
  90. TCHAR szModule1[CCH_MAX_MODULE];
  91. short ret=0;
  92. lstrcpy(_szDbgPrefix, TEXT("NoName"));
  93. // Initialize the debug prefix string - it is the first
  94. // CCH_MAX_DBGPREFIX characters in the name of this
  95. // .exe, without the extension
  96. //
  97. cchModule = GetModuleFileName(NULL, szModule1, CCH_MAX_MODULE);
  98. if ((0 != cchModule) && (cchModule < CCH_MAX_MODULE))
  99. {
  100. ret = GetFileTitle(szModule1, szModule, sizeof(szModule));
  101. if (0 == ret)
  102. {
  103. //
  104. // Strip the .exe extension if it exists
  105. //
  106. cchModule = _tcslen(szModule);
  107. if (cchModule >= 4) // if the name has at least 4 chars
  108. {
  109. if (0 == _tcsicmp(szModule + cchModule - 4, TEXT(".exe")))
  110. {
  111. szModule[cchModule - 4] = TEXT('\0');
  112. }
  113. }
  114. //
  115. // Save the module name as the debug prefix
  116. //
  117. _tcscpy(_szDbgPrefix, szModule);
  118. }
  119. }
  120. }
  121. //+-------------------------------------------------------------------
  122. // Member: CDebugHelp::~CDebugHelp
  123. //
  124. // Synopsis: Releases resources associated with the CDebugHelp class.
  125. // Sets member variables so the basic functions can work.
  126. //
  127. // Arguments: None
  128. //
  129. // Returns: Nothing.
  130. //
  131. // History: 21-Nov-94 DeanE Created
  132. //--------------------------------------------------------------------
  133. CDebugHelp::~CDebugHelp()
  134. {
  135. // Set all member variables to valid default values
  136. _fLogLoc = DH_LOC_TERM;
  137. _fTraceLoc = DH_LOC_TERM;
  138. _fTraceLvl = DH_LVL_ALWAYS|DH_LVL_ERROR;
  139. _fMode = DH_LABMODE;
  140. // Close the log by deleting the log object, if we created it
  141. if (_fCreatedLog)
  142. {
  143. delete _plog;
  144. }
  145. _plog = NULL;
  146. }
  147. //+-------------------------------------------------------------------
  148. // Member: CDebugHelp::GetRegDbgInfo
  149. //
  150. // Synopsis: Initializes CDebugHelp object from the registry. Even
  151. // if errors occur, the object is left in the usable
  152. // default state.
  153. //
  154. // Arguments: [pszRegKey] - Registy key holding necessary values.
  155. //
  156. // Returns: S_OK if values read and settings are valid, an error
  157. // code if not.
  158. //
  159. // History: 21-Nov-94 DeanE Created
  160. //--------------------------------------------------------------------
  161. HRESULT CDebugHelp::GetRegDbgInfo(LPTSTR pszRegKey)
  162. {
  163. CRegistryHelp *prhRegKey = NULL;
  164. HRESULT hr = E_FAIL;
  165. DWORD fLabMode = TRUE;
  166. DWORD fBreakMode= FALSE;
  167. DWORD fVerbose = FALSE;
  168. // Open the registry key
  169. prhRegKey = new(NullOnFail) CRegistryHelp(
  170. #ifndef _MAC
  171. HKEY_CURRENT_USER,
  172. #else // _MAC
  173. HKEY_CLASSES_ROOT,
  174. #endif // _MAC
  175. pszRegKey,
  176. REG_OPTION_NON_VOLATILE,
  177. KEY_READ,
  178. &hr);
  179. if (prhRegKey == NULL)
  180. {
  181. hr = MAKE_TH_ERROR_CODE(E_OUTOFMEMORY);
  182. }
  183. if (FAILED(hr))
  184. {
  185. delete prhRegKey;
  186. return(hr);
  187. }
  188. // Note: From this point, error returns don't mean return an
  189. // error, but set the default and return
  190. //
  191. // Get Trace Location value
  192. hr = prhRegKey->GetValueDword(
  193. NULL,
  194. SZ_REG_TRACE_LOC,
  195. &_fTraceLoc,
  196. REG_DWORD);
  197. if (SUCCEEDED(hr))
  198. {
  199. _fTraceLoc = ValidateLoc(_fTraceLoc);
  200. }
  201. // Get Log Location value
  202. hr = prhRegKey->GetValueDword(
  203. NULL,
  204. SZ_REG_LOG_LOC,
  205. &_fLogLoc,
  206. REG_DWORD);
  207. if (SUCCEEDED(hr))
  208. {
  209. _fLogLoc = ValidateLoc(_fLogLoc);
  210. }
  211. // Get Trace Level
  212. hr = prhRegKey->GetValueDword(
  213. NULL,
  214. SZ_REG_TRACE_LVL,
  215. &_fTraceLvl,
  216. REG_DWORD);
  217. if (SUCCEEDED(hr))
  218. {
  219. _fTraceLvl = ValidateLvl(_fTraceLvl) | DH_LVL_ALWAYS | DH_LVL_ERROR;
  220. }
  221. // Get Mode
  222. hr = prhRegKey->GetValueDword(
  223. NULL,
  224. SZ_REG_LABMODE,
  225. &fLabMode,
  226. REG_DWORD);
  227. if (SUCCEEDED(hr) && fLabMode)
  228. {
  229. _fMode = DH_LABMODE;
  230. }
  231. hr = prhRegKey->GetValueDword(
  232. NULL,
  233. SZ_REG_BREAKMODE,
  234. &fBreakMode,
  235. REG_DWORD);
  236. if (SUCCEEDED(hr) && fBreakMode)
  237. {
  238. _fMode |= DH_BREAKMODE;
  239. }
  240. hr = prhRegKey->GetValueDword(
  241. NULL,
  242. SZ_REG_VERBOSE,
  243. &fVerbose,
  244. REG_DWORD);
  245. if (SUCCEEDED(hr) && fVerbose)
  246. {
  247. _fMode |= DH_VERBOSE;
  248. }
  249. _fMode = ValidateMode(_fMode);
  250. // Clean up and exit
  251. delete prhRegKey;
  252. hr = S_OK;
  253. return(hr);
  254. }
  255. //+-------------------------------------------------------------------
  256. // Member: CDebugHelp::WriteRegDbgInfo
  257. //
  258. // Synopsis: Write the current state of the CDebugHelp object to
  259. // the registry.
  260. //
  261. // Arguments: [pszRegKey] - Registy key to write to.
  262. //
  263. // Returns: S_OK if values written, an error code if not.
  264. //
  265. // History: 21-Apr-96 Kennethm Created
  266. //--------------------------------------------------------------------
  267. HRESULT CDebugHelp::WriteRegDbgInfo(LPTSTR pszRegKey)
  268. {
  269. CRegistryHelp *prhRegKey = NULL;
  270. HRESULT hr = E_FAIL;
  271. // Open the registry key
  272. prhRegKey = new(NullOnFail) CRegistryHelp(
  273. #ifndef _MAC
  274. HKEY_CURRENT_USER,
  275. #else // _MAC
  276. HKEY_CLASSES_ROOT,
  277. #endif // _MAC
  278. pszRegKey,
  279. REG_OPTION_NON_VOLATILE,
  280. KEY_WRITE,
  281. &hr);
  282. if (prhRegKey == NULL)
  283. {
  284. hr = MAKE_TH_ERROR_CODE(E_OUTOFMEMORY);
  285. }
  286. if (FAILED(hr))
  287. {
  288. delete prhRegKey;
  289. return(hr);
  290. }
  291. // Write Trace Location value
  292. hr = prhRegKey->SetValueDword(
  293. NULL,
  294. SZ_REG_TRACE_LOC,
  295. _fTraceLoc,
  296. REG_DWORD);
  297. if (SUCCEEDED(hr))
  298. {
  299. // Write Log Location value
  300. hr = prhRegKey->SetValueDword(
  301. NULL,
  302. SZ_REG_LOG_LOC,
  303. _fLogLoc,
  304. REG_DWORD);
  305. }
  306. if (SUCCEEDED(hr))
  307. {
  308. // Write Trace Level
  309. hr = prhRegKey->SetValueDword(
  310. NULL,
  311. SZ_REG_TRACE_LVL,
  312. _fTraceLvl,
  313. REG_DWORD);
  314. }
  315. if (SUCCEEDED(hr))
  316. {
  317. // Write Lab Mode
  318. hr = prhRegKey->SetValueDword(
  319. NULL,
  320. SZ_REG_LABMODE,
  321. _fMode&DH_LABMODE ? TRUE : FALSE,
  322. REG_DWORD);
  323. }
  324. if (SUCCEEDED(hr))
  325. {
  326. // Write Break Mode
  327. hr = prhRegKey->SetValueDword(
  328. NULL,
  329. SZ_REG_BREAKMODE,
  330. _fMode&DH_BREAKMODE ? TRUE : FALSE,
  331. REG_DWORD);
  332. }
  333. if (SUCCEEDED(hr))
  334. {
  335. // Write Verbose
  336. hr = prhRegKey->SetValueDword(
  337. NULL,
  338. SZ_REG_VERBOSE,
  339. _fMode&DH_VERBOSE ? TRUE : FALSE,
  340. REG_DWORD);
  341. }
  342. // Clean up and exit
  343. delete prhRegKey;
  344. return(hr);
  345. }
  346. //+-------------------------------------------------------------------
  347. // Member: CDebugHelp::CreateLog, public
  348. //
  349. // Synopsis: Creates a new log based on the parameters passed.
  350. //
  351. // Arguments: [argc] - Number of command line args
  352. // [argv] - Command line args
  353. //
  354. // Returns: S_OK if log created successfully or none is specified,
  355. // E_FAIL if not.
  356. //
  357. // History: 21-Nov-94 DeanE Created
  358. //--------------------------------------------------------------------
  359. HRESULT CDebugHelp::CreateLog(int argc, char **argv)
  360. {
  361. HRESULT hr = S_OK;
  362. // Check for existing log
  363. if ((_plog != NULL) && (_fCreatedLog == TRUE))
  364. {
  365. delete _plog;
  366. }
  367. // Create the new log
  368. _plog = new(NullOnFail) Log(argc, argv, LOG_ANSI);
  369. if (NULL == _plog)
  370. {
  371. hr = E_OUTOFMEMORY;
  372. }
  373. else
  374. if (NO_ERROR != _plog->ConfirmCreation())
  375. {
  376. delete _plog;
  377. hr = E_FAIL;
  378. }
  379. // Set _fCreatedLog flag to true so the log will get deleted during
  380. // cleanup (otherwise the calling process must delete it).
  381. //
  382. if (SUCCEEDED(hr))
  383. {
  384. _fCreatedLog = TRUE;
  385. }
  386. return(hr);
  387. }
  388. //+-------------------------------------------------------------------
  389. // Member: CDebugHelp::CreateLog, public
  390. //
  391. // Synopsis: Creates a new log based on the parameters passed.
  392. //
  393. // Arguments: [paszCmdline] - Windows-style ANSI command line.
  394. //
  395. // Returns: S_OK if log created successfully or none is specified,
  396. // E_FAIL if not.
  397. //
  398. // History: 21-Nov-94 DeanE Created
  399. //--------------------------------------------------------------------
  400. HRESULT CDebugHelp::CreateLog(LPSTR paszCmdline)
  401. {
  402. HRESULT hr = S_OK;
  403. int argc = 0;
  404. CHAR **argv = NULL;
  405. // Convert pszCmdline to argc/argv parameters
  406. hr = CmdlineToArgs(paszCmdline, &argc, &argv);
  407. if (FAILED(hr))
  408. {
  409. return(hr);
  410. }
  411. // Check for existing log
  412. if ((_plog != NULL) && (_fCreatedLog == TRUE))
  413. {
  414. delete _plog;
  415. }
  416. // Create the new log
  417. _plog = new(NullOnFail) Log(argc, argv, LOG_ANSI);
  418. if (NULL == _plog)
  419. {
  420. hr = E_OUTOFMEMORY;
  421. }
  422. else
  423. if (NO_ERROR != _plog->ConfirmCreation())
  424. {
  425. delete _plog;
  426. hr = E_FAIL;
  427. }
  428. // Set _fCreatedLog flag to true so the log will get deleted during
  429. // cleanup (otherwise the calling process must delete it).
  430. //
  431. if (SUCCEEDED(hr))
  432. {
  433. _fCreatedLog = TRUE;
  434. }
  435. //
  436. // Delete the argc/argv command line created by CmdlineToArgs
  437. //
  438. while (argc > 0)
  439. {
  440. --argc;
  441. delete argv[argc];
  442. }
  443. delete argv;
  444. return(hr);
  445. }
  446. //+-------------------------------------------------------------------
  447. // Member: CDebugHelp::SetLog, public
  448. //
  449. // Synopsis: Sets the log pointer to the one passed. This one should
  450. // not be deleted. Deletes existing log is appropriate. If
  451. // NULL is passed, the old log is deleted and the new log
  452. // is set to NULL (none).
  453. //
  454. // Arguments: [plog] - Pointer to new log.
  455. //
  456. // Returns: S_OK if log set successfully, E_FAIL if not.
  457. //
  458. // History: 21-Nov-94 DeanE Created
  459. //--------------------------------------------------------------------
  460. HRESULT CDebugHelp::SetLog(Log *plog)
  461. {
  462. HRESULT hr = E_FAIL;
  463. // Make sure new log pointer is valid
  464. if ((NULL == plog) || (FALSE == IsBadReadPtr(plog, sizeof(Log *))))
  465. {
  466. // Free old log if we have one
  467. if ((_plog != NULL) && (_fCreatedLog == TRUE))
  468. {
  469. delete _plog;
  470. }
  471. // Set new log; we should not delete the pointer
  472. _plog = plog;
  473. _fCreatedLog = FALSE;
  474. hr = S_OK;
  475. }
  476. else
  477. {
  478. OutputDebugString(TEXT("Invalid log pointer"));
  479. }
  480. return(hr);
  481. }
  482. //+-------------------------------------------------------------------
  483. // Member: CDebugHelp::SetDebugInfo, public
  484. //
  485. // Synopsis: Sets debug information.
  486. //
  487. // Arguments: [fLogLoc] - New Log Location setting.
  488. // [fTraceLoc] - New Trace Location setting.
  489. // [fTraceLvl] - New Trace Level setting.
  490. // [fMode] - New Mode setting.
  491. //
  492. // Returns: S_OK
  493. //
  494. // History: 21-Nov-94 DeanE Created
  495. // 10-Apr-97 SCousens revamp fMode
  496. //--------------------------------------------------------------------
  497. HRESULT CDebugHelp::SetDebugInfo(
  498. DWORD fLogLoc,
  499. DWORD fTraceLoc,
  500. DWORD fTraceLvl,
  501. DWORD fMode)
  502. {
  503. // Validate New settings
  504. fLogLoc = ValidateLoc(fLogLoc);
  505. fTraceLoc = ValidateLoc(fTraceLoc);
  506. fTraceLvl = ValidateLvl(fTraceLvl);
  507. fMode = ValidateMode(fMode);
  508. // Assign new values
  509. if (fLogLoc != DH_LOC_SAME)
  510. {
  511. _fLogLoc = fLogLoc;
  512. }
  513. if (fTraceLoc != DH_LOC_SAME)
  514. {
  515. _fTraceLoc = fTraceLoc;
  516. }
  517. if (fTraceLvl != DH_LVL_SAME)
  518. {
  519. _fTraceLvl = DH_LVL_ALWAYS|DH_LVL_ERROR|fTraceLvl;
  520. }
  521. // Set mode bits, one by one
  522. if ((fMode & DH_LABMODE_SET) ||
  523. (fMode & DH_BREAKMODE_SET) ||
  524. (fMode & DH_VERBOSE_SET))
  525. {
  526. DWORD fNewMode;
  527. fNewMode = fMode & DH_LABMODE_SET ?
  528. fMode & DH_LABMODE :
  529. _fMode & DH_LABMODE;
  530. fNewMode |= fMode & DH_BREAKMODE_SET ?
  531. fMode & DH_BREAKMODE :
  532. _fMode & DH_BREAKMODE;
  533. fNewMode |= fMode & DH_VERBOSE_SET ?
  534. fMode & DH_VERBOSE :
  535. _fMode & DH_VERBOSE;
  536. // mask off the SET bits
  537. _fMode = fNewMode &
  538. ~(DH_LABMODE_SET |
  539. DH_BREAKMODE_SET |
  540. DH_VERBOSE_SET) ;
  541. }
  542. // Reset the warning flag (in OutputMsg)
  543. _fSpyWarning = FALSE;
  544. return(S_OK);
  545. }
  546. //+-------------------------------------------------------------------
  547. // Member: CDebugHelp::SetPopupWindow, public
  548. //
  549. // Synopsis: Associates the window handle passed with the Assert
  550. // popups that can occur if Lab Mode is set FALSE. Simply
  551. // replaces any existing window handle - does not close
  552. // it, etc.
  553. //
  554. // Arguments: [hwnd] - New window handle
  555. //
  556. // Returns: S_OK if set successfully, E_FAIL if not.
  557. //
  558. // History: 1-Dec-94 DeanE Created
  559. //--------------------------------------------------------------------
  560. HRESULT CDebugHelp::SetPopupWindow(HWND hwnd)
  561. {
  562. _hwndAssert = hwnd;
  563. return(S_OK);
  564. }
  565. //+-------------------------------------------------------------------
  566. // Member: CDebughelp::SetSpyWindowClass, public
  567. //
  568. //
  569. // Synopsis: Set the window class that all spy window output will
  570. // go to.
  571. //
  572. // Arguments: [pszSpyWindowClass] -- pointer to class name
  573. //
  574. // Returns: S_OK
  575. //
  576. // Algorithm: If the old spy class is not equal to the default one,
  577. // free up the buffer we allocated. Then create a new
  578. // buffer and copy the new class string into it.
  579. //
  580. // History: 09-Aug-95 MikeW Created
  581. //
  582. // Notes: If an error is returned the old class is preserved.
  583. //--------------------------------------------------------------------
  584. HRESULT CDebugHelp::SetSpyWindowClass(const LPTSTR pszSpyWindowClass)
  585. {
  586. HRESULT hr = S_OK;
  587. LPTSTR pszTemp;
  588. if (_pszSpyWindowClass != SZ_DEFAULT_SPY_WINDOW_CLASS)
  589. {
  590. delete [] _pszSpyWindowClass;
  591. }
  592. pszTemp = new TCHAR[_tcslen(pszSpyWindowClass) + 1];
  593. if (NULL == pszTemp)
  594. {
  595. hr = E_OUTOFMEMORY;
  596. }
  597. else
  598. {
  599. _pszSpyWindowClass = pszTemp;
  600. _tcscpy(_pszSpyWindowClass, pszSpyWindowClass);
  601. }
  602. return S_OK;
  603. }
  604. //+-------------------------------------------------------------------
  605. // Member: CDebugHelp::TraceMsg, public
  606. //
  607. // Synopsis: Outputs the debug string to the current location setting
  608. // if any set bit in the level passed match set bits in the
  609. // global level.
  610. //
  611. // Arguments: [fLvl] - Trace level.
  612. // [pszFmt] - Trace message format string.
  613. // [...] - Arguments for format string.
  614. //
  615. // Returns: Nothing.
  616. //
  617. // History: 20-Oct-93 DeanE Created
  618. // 10-Apr-97 SCousens Spiff up output string on error
  619. //--------------------------------------------------------------------
  620. void CDebugHelp::TraceMsg(DWORD fLvl, LPTSTR pszFmt, ...)
  621. {
  622. TCHAR szBuffer[CCH_MAX_DBG_CHARS];
  623. TCHAR szDebug[CCH_MAX_DBG_CHARS +
  624. CCH_MAX_DBGPREFIX +
  625. CCH_MAX_INDENTPRINT + 6 ];
  626. TCHAR szSpaces[CCH_MAX_INDENTPRINT];
  627. va_list varArgs;
  628. // If the level has DH_LVL_ENTRY in it indent by one
  629. //
  630. if (fLvl & DH_LVL_ENTRY)
  631. {
  632. _cIndentLevel++;
  633. }
  634. // If all of the bits match, then we will output the string to the
  635. // current location(s)
  636. //
  637. if ((fLvl & _fTraceLvl) == fLvl)
  638. {
  639. // Print the caller's string to a buffer
  640. va_start(varArgs, pszFmt);
  641. _vsntprintf(szBuffer, CCH_MAX_DBG_CHARS, pszFmt, varArgs);
  642. szBuffer[CCH_MAX_DBG_CHARS-1] = chNull;
  643. va_end(varArgs);
  644. // Add correct number of space for indentation
  645. lstrcpy(szSpaces, TEXT(" "));
  646. if (_cIndentLevel < CCH_MAX_INDENTPRINT)
  647. {
  648. szSpaces[_cIndentLevel]=TEXT('\0');
  649. }
  650. // Now prepend it with the debug prefix
  651. _sntprintf(szDebug,
  652. CCH_MAX_DBG_CHARS,
  653. TEXT("%s: %c %s%s%s"),
  654. _szDbgPrefix,
  655. DH_LVL_ERROR & fLvl ? chTraceErr : chTrace,
  656. szSpaces,
  657. DH_LVL_ERROR & fLvl ? szError : szNull,
  658. szBuffer);
  659. szDebug[CCH_MAX_DBG_CHARS-1] = chNull;
  660. // Now, spit the thing out to the proper places
  661. OutputMsg(_fTraceLoc, szDebug);
  662. }
  663. // If the level has DH_LVL_EXIT in it unindent by one
  664. //
  665. if (fLvl & DH_LVL_EXIT)
  666. {
  667. _cIndentLevel--;
  668. }
  669. }
  670. //+-------------------------------------------------------------------
  671. // Member: CDebugHelp::ReportResult, public
  672. //
  673. // Synopsis: Outputs the test variation and result to the location(s)
  674. // currently specified.
  675. //
  676. // Arguments: [usResult] - Result of the test
  677. // [pszFmt] - Format of the log message
  678. // [...] - Parameters for message
  679. //
  680. // Returns: Nothing.
  681. //
  682. // History: 21-Nov-94 DeanE Created
  683. //--------------------------------------------------------------------
  684. void CDebugHelp::ReportResult(USHORT usResult, LPTSTR pszFmt, ...)
  685. {
  686. HRESULT hr = E_FAIL;
  687. TCHAR szFmtBuffer[CCH_MAX_LOG_CHARS];
  688. TCHAR szLogBuffer[CCH_MAX_LOG_CHARS];
  689. va_list varArgs;
  690. // format variable arg list into a buffer.
  691. va_start(varArgs, pszFmt);
  692. _vsntprintf(szFmtBuffer, CCH_MAX_LOG_CHARS, pszFmt, varArgs);
  693. szFmtBuffer[CCH_MAX_LOG_CHARS-1] = chNull;
  694. va_end(varArgs);
  695. // Set up log buffer. Truncate any extra chars.
  696. _sntprintf(szLogBuffer,
  697. CCH_MAX_LOG_CHARS,
  698. TEXT("%s: %s"),
  699. GetResultText(usResult),
  700. szFmtBuffer);
  701. szLogBuffer[CCH_MAX_LOG_CHARS-1] = chNull;
  702. SetStats(usResult);
  703. // Send it out
  704. OutputMsg(_fLogLoc, szLogBuffer);
  705. }
  706. //+-------------------------------------------------------------------
  707. // Member: CDebugHelp::ReportStats, public
  708. //
  709. // Synopsis: Outputs statistics about test variations run so far,
  710. // such as #tests run, #passed, #failed, etc to the Log
  711. // Location (_fLogLoc).
  712. //
  713. // Arguments: None.
  714. //
  715. // Returns: Nothing.
  716. //
  717. // History: 21-Nov-94 DeanE Created
  718. //--------------------------------------------------------------------
  719. void CDebugHelp::ReportStats()
  720. {
  721. TCHAR szBuffer[CCH_MAX_LOG_CHARS];
  722. _sntprintf(szBuffer, CCH_MAX_LOG_CHARS,
  723. TEXT("Summary--> Passed: %lu ; Failed: %lu ; Aborted: %lu"),
  724. _cPass,
  725. _cFail,
  726. _cAbort);
  727. szBuffer[CCH_MAX_LOG_CHARS-1] = chNull;
  728. OutputMsg(_fLogLoc, szBuffer);
  729. }
  730. //+-------------------------------------------------------------------
  731. // Member: CDebugHelp::LabAssertEx, public
  732. //
  733. // Synopsis: Produces an assert message to the current debug
  734. // location(s) or to a dialog box, if running in non-Lab
  735. // mode.
  736. //
  737. // Arguments: [szFile] - File assert occurred in.
  738. // [nLine] - Line assert occurred.
  739. // [nszMsg] - Assert message.
  740. //
  741. // Returns: Nothing.
  742. //
  743. // History: 20-Oct-93 DeanE Created
  744. //--------------------------------------------------------------------
  745. void CDebugHelp::LabAssertEx(LPCTSTR szFile, int nLine, LPCTSTR szMsg)
  746. {
  747. TCHAR szBuffer[CCH_MAX_ASSERT_CHARS];
  748. int nAnswer;
  749. _sntprintf(szBuffer,
  750. CCH_MAX_ASSERT_CHARS,
  751. TEXT("Assert!!! File: %s, Line: %d, %s\n"),
  752. szFile,
  753. nLine,
  754. szMsg);
  755. szBuffer[CCH_MAX_ASSERT_CHARS-1] = chNull;
  756. // always spew
  757. OutputMsg(_fTraceLoc, szBuffer);
  758. // if labmode, popup
  759. if (FALSE == (_fMode & DH_LABMODE))
  760. {
  761. nAnswer = MessageBox(
  762. _hwndAssert,
  763. szBuffer,
  764. TEXT("CT OLE Assert"),
  765. MB_ICONEXCLAMATION | MB_OKCANCEL);
  766. if (IDCANCEL==nAnswer)
  767. {
  768. DebugBreak();
  769. }
  770. }
  771. // if break, break
  772. else if (FALSE != (_fMode & DH_BREAKMODE))
  773. {
  774. DebugBreak();
  775. }
  776. }
  777. //+-------------------------------------------------------------------
  778. // Member: CDebugHelp::CheckResult, public
  779. //
  780. // Synopsis: Compares the hr passed in with expected hr passed in
  781. //
  782. // Arguments: [hrCheck] - Result to check.
  783. // [hrExpected] - Result expected.
  784. // [pszFuncName] - Name of the current function
  785. // [pszMsg] - Debug message if result not in list passed.
  786. // [nLine] - __LINE__ macro
  787. // [pszFile] - __FILE__ macro
  788. //
  789. // Returns: Nothing.
  790. //
  791. // History: 12-Aug-94 KennethM Created
  792. // 1-Dec-94 DeanE Incorporated into CDebugHelp class
  793. // 12-Apr-95 KennethM Only checks against S_OK
  794. // 10-Apr-97 SCousens Check against errors also
  795. //--------------------------------------------------------------------
  796. HRESULT CDebugHelp::CheckResult (HRESULT hrCheck,
  797. HRESULT hrExpected,
  798. LPTSTR pszFuncName,
  799. LPTSTR pszMsg,
  800. int nLine,
  801. LPTSTR pszFile)
  802. {
  803. TCHAR szAssertBuf[CCH_MAX_ASSERT_CHARS];
  804. TCHAR szAssertTitle[CCH_MAX_ASSERT_CHARS];
  805. TCHAR szMsgBuffer[CCH_MAX_ASSERT_CHARS];
  806. DWORD cchMsgBuffer = 0;
  807. int nAnswer;
  808. HRESULT hr = S_OK;
  809. // If _dwExpectedError is set, then someone up the call chain
  810. // wants us to ignore that error code, even if our direct caller
  811. // does not. If the incoming error code matches _dwExpectedError,
  812. // then ignore it and return.
  813. if ( ( _hrExpectedError != S_OK ) && ( hrCheck == _hrExpectedError ) )
  814. {
  815. return S_OK;
  816. }
  817. // figure out if we have a problem
  818. if (hrCheck != hrExpected)
  819. {
  820. if (FAILED(hrCheck))
  821. {
  822. hr = hrCheck;
  823. }
  824. else
  825. {
  826. hr = E_FAIL;
  827. }
  828. }
  829. // No problem, prepare to bail
  830. if (S_OK == hr)
  831. {
  832. // if we are verbose, call tracemsg
  833. if (FALSE != (DH_VERBOSE & _fMode))
  834. {
  835. TraceMsg(DH_LVL_ALWAYS,
  836. S_OK == hrExpected ? // different output if HRCHECK
  837. TEXT("%s; %s; ok") :
  838. TEXT("%s; %s; hr=%#lx; ok"),
  839. pszFuncName,
  840. pszMsg,
  841. hrCheck);
  842. }
  843. return hr;
  844. }
  845. // Get the text for the HRESULT from the system
  846. cchMsgBuffer = FormatMessage(
  847. FORMAT_MESSAGE_FROM_SYSTEM |
  848. FORMAT_MESSAGE_IGNORE_INSERTS,
  849. NULL,
  850. hrCheck,
  851. GetSystemDefaultLangID(),
  852. szMsgBuffer,
  853. CCH_MAX_ASSERT_CHARS,
  854. NULL);
  855. szMsgBuffer[CCH_MAX_ASSERT_CHARS-1] = chNull;
  856. if (0 == cchMsgBuffer)
  857. {
  858. _sntprintf(
  859. szMsgBuffer,
  860. CCH_MAX_ASSERT_CHARS,
  861. TEXT("Error 0x%08x"),
  862. hrCheck);
  863. }
  864. else // zap any \r\n from the FormatMessage
  865. {
  866. while ('\r' == szMsgBuffer[cchMsgBuffer-1] ||
  867. '\n' == szMsgBuffer[cchMsgBuffer-1])
  868. {
  869. szMsgBuffer[--cchMsgBuffer] = chNull;
  870. }
  871. }
  872. // Output to Trace Location
  873. TraceMsg(DH_LVL_ERROR,
  874. S_OK == hrExpected ? // different output if HRCHECK
  875. TEXT("%s; %s; hr=%lx; %s") :
  876. TEXT("%s; %s; hr=%lx;"),
  877. pszFuncName,
  878. pszMsg,
  879. hr,
  880. szMsgBuffer);
  881. // If we are comparing against failure, show what we expected and got.
  882. if (S_OK != hrExpected)
  883. {
  884. TraceMsg(DH_LVL_ALWAYS,
  885. TEXT("+ hr Expected:%#lx; Got:%#lx; %s"),
  886. hrExpected,
  887. hrCheck,
  888. szMsgBuffer);
  889. }
  890. TraceMsg(DH_LVL_ALWAYS,
  891. TEXT("+ File:%s; Line:%d"),
  892. pszFile,
  893. nLine);
  894. // labmode - display an error popup
  895. if (FALSE == (_fMode & DH_LABMODE))
  896. {
  897. _sntprintf(szAssertBuf,
  898. CCH_MAX_ASSERT_CHARS,
  899. TEXT("%s : hr=%#lx : Expected %#lx\n%s\n"),
  900. pszMsg,
  901. hrCheck,
  902. hrExpected,
  903. szMsgBuffer);
  904. szAssertBuf[CCH_MAX_ASSERT_CHARS-1] = chNull;
  905. _sntprintf(szAssertTitle,
  906. CCH_MAX_ASSERT_CHARS,
  907. TEXT("CT OLE - %s Error"),
  908. _szDbgPrefix);
  909. szAssertTitle[CCH_MAX_ASSERT_CHARS-1] = chNull;
  910. // Do we want to debug this?
  911. nAnswer = MessageBox(
  912. _hwndAssert,
  913. szAssertBuf,
  914. szAssertTitle,
  915. MB_ICONSTOP | MB_OKCANCEL);
  916. // yes we do?
  917. if (IDCANCEL==nAnswer)
  918. {
  919. DebugBreak();
  920. }
  921. }
  922. // break mode, break into the debugger
  923. else if (FALSE != (_fMode & DH_BREAKMODE))
  924. {
  925. DebugBreak();
  926. }
  927. return hr;
  928. }
  929. //+-------------------------------------------------------------------
  930. // Member: CDebugHelp::SetExpectedError, public
  931. //
  932. // Synopsis: Disables error logging for the specified error code.
  933. //
  934. // Arguments: [hrExpectedError] - Error code to disable. Pass S_OK
  935. // for no expected errors.
  936. //
  937. // Returns: Nothing.
  938. //
  939. // History: 16-Sep-97 BWill Created
  940. //
  941. // Notes: -- Use this call to temporarily disable error logging
  942. // in client code.
  943. // -- Call this function with S_OK to enable all checks.
  944. // -- See also DH_EXPECTEDERROR/DH_NOEXPECTEDERROR in
  945. // cdbghelp.hxx.
  946. //--------------------------------------------------------------------
  947. void CDebugHelp::SetExpectedError( HRESULT hrExpectedError )
  948. {
  949. _hrExpectedError = hrExpectedError;
  950. }
  951. //+-------------------------------------------------------------------
  952. // Member: CDebugHelp::ValidateLoc, private
  953. //
  954. // Synopsis: Checks the location flag passed to insure it is a legal
  955. // value.
  956. //
  957. // Arguments: [fLoc] - Location flag to check.
  958. //
  959. // Returns: Legal version of what we were to check.
  960. //
  961. // History: 21-Nov-94 DeanE Created
  962. // 10-Apr-97 SCousens Return legal value
  963. //--------------------------------------------------------------------
  964. DWORD CDebugHelp::ValidateLoc(DWORD fLoc)
  965. {
  966. // Get what we can out of supplied location
  967. return (DH_LOC_VALID & fLoc);
  968. }
  969. //+-------------------------------------------------------------------
  970. // Member: CDebugHelp::ValidateLvl, private
  971. //
  972. // Synopsis: Checks the Trace Level flag passed to insure it is a
  973. // legal value.
  974. //
  975. // Arguments: [fLvl] - Trace Level to check.
  976. //
  977. // Returns: Legal version of what we were to check.
  978. //
  979. // History: 21-Nov-94 DeanE Created
  980. // 10-Apr-97 SCousens Return legal value
  981. //--------------------------------------------------------------------
  982. DWORD CDebugHelp::ValidateLvl(DWORD fLvl)
  983. {
  984. // Make sure a valid setting is passed
  985. return (~DH_LVL_INVMASK & fLvl);
  986. }
  987. //+-------------------------------------------------------------------
  988. // Member: CDebugHelp::ValidateMode, private
  989. //
  990. // Synopsis: Checks the Lab Mode flag passed to insure it is a
  991. // legal value.
  992. //
  993. // Arguments: [fMode] - Flag to check.
  994. //
  995. // Returns: Legal version of what we were to check.
  996. //
  997. // History: 21-Nov-94 DeanE Created
  998. // 10-Apr-97 SCousens Return legal value
  999. //--------------------------------------------------------------------
  1000. DWORD CDebugHelp::ValidateMode(DWORD fMode)
  1001. {
  1002. return (fMode & (~DH_INVMODE));
  1003. }
  1004. //+-------------------------------------------------------------------
  1005. // Member: CDebugHelp::SetStats, private
  1006. //
  1007. // Synopsis: Sets stats based on result
  1008. //
  1009. // Arguments: [usResult] - Result to add.
  1010. //
  1011. // Returns: nothing.
  1012. //
  1013. // History: 20-Oct-93 DeanE Created
  1014. //--------------------------------------------------------------------
  1015. VOID CDebugHelp::SetStats(USHORT usResult)
  1016. {
  1017. switch (usResult)
  1018. {
  1019. case LOG_PASS:
  1020. _cPass++;
  1021. break;
  1022. case LOG_FAIL:
  1023. _cFail++;
  1024. break;
  1025. case LOG_ABORT:
  1026. _cAbort++;
  1027. break;
  1028. default:
  1029. // do nothing.
  1030. break;
  1031. }
  1032. }
  1033. //+-------------------------------------------------------------------
  1034. // Member: CDebugHelp::GetResultText, private
  1035. //
  1036. // Synopsis: Determines the correct text to printf for the result code
  1037. // passed. Result code corresponds to LogServer result codes.
  1038. //
  1039. // Arguments: [usResult] - Result to look up.
  1040. //
  1041. // Returns: Pointer to output string corresponding to the result
  1042. // code passed (ie "PASSED" for LOG_PASS).
  1043. //
  1044. // History: 21-Nov-94 DeanE Created
  1045. //--------------------------------------------------------------------
  1046. LPCTSTR CDebugHelp::GetResultText(USHORT usResult)
  1047. {
  1048. LPCTSTR szResult = NULL;
  1049. TCHAR szAssert[CCH_MAX_DBG_CHARS];
  1050. switch (usResult)
  1051. {
  1052. case LOG_PASS:
  1053. szResult = szPass;
  1054. break;
  1055. case LOG_FAIL:
  1056. szResult = szFail;
  1057. break;
  1058. case LOG_ABORT:
  1059. szResult = szAbort;
  1060. break;
  1061. case LOG_WARN:
  1062. szResult = szWarn;
  1063. break;
  1064. case LOG_INFO:
  1065. szResult = szInfo;
  1066. break;
  1067. default:
  1068. szResult = szInvalid;
  1069. _sntprintf(szAssert,
  1070. CCH_MAX_DBG_CHARS,
  1071. TEXT("Invalid Test Result=%ld"),
  1072. usResult);
  1073. szAssert[CCH_MAX_DBG_CHARS-1] = chNull;
  1074. LabAssertEx(TEXT(__FILE__), __LINE__, szAssert);
  1075. break;
  1076. }
  1077. return(szResult);
  1078. }
  1079. //+-------------------------------------------------------------------
  1080. // Member: CDebugHelp::OutputMsg, private
  1081. //
  1082. // Synopsis: Outputs the buffer to the locations specified.
  1083. // Location, log, and buffer are all assumed to be valid,
  1084. // so no error checking is done.
  1085. //
  1086. // Arguments: [fLoc] - Location(s) to output buffer to.
  1087. // [pszBuffer] - Buffer to output.
  1088. //
  1089. // Returns: Nothing.
  1090. //
  1091. // History: 21-Nov-94 DeanE Created
  1092. // 08-Mar-95 MikeW Added DH_LOC_SPYWIN stuff
  1093. //--------------------------------------------------------------------
  1094. void CDebugHelp::OutputMsg(DWORD fLoc, LPTSTR pszBuffer)
  1095. {
  1096. CHAR szLogBuf[CCH_MAX_LOG_CHARS];
  1097. if (fLoc & DH_LOC_TERM)
  1098. {
  1099. OutputDebugString(pszBuffer);
  1100. OutputDebugString(szNewLine);
  1101. }
  1102. if (fLoc & DH_LOC_STDOUT)
  1103. {
  1104. _tprintf(TEXT("%s\n"), pszBuffer);
  1105. }
  1106. if (fLoc & DH_LOC_LOG)
  1107. {
  1108. if (FALSE == IsBadReadPtr(_plog, sizeof(Log *)))
  1109. {
  1110. // Buffer must be ANSI regardless of platform
  1111. #ifdef UNICODE
  1112. _snprintf(szLogBuf, CCH_MAX_LOG_CHARS, "%ls", pszBuffer);
  1113. #else
  1114. _snprintf(szLogBuf, CCH_MAX_LOG_CHARS, "%s", pszBuffer);
  1115. #endif
  1116. szLogBuf[CCH_MAX_LOG_CHARS-1] = chNull;
  1117. _plog->WriteData(szLogBuf);
  1118. }
  1119. else
  1120. {
  1121. // Trying to write to log that doesn't exist!
  1122. OutputDebugString(TEXT("CDebugHelp: Unable to write to Log File!\n"));
  1123. }
  1124. }
  1125. if (fLoc & DH_LOC_SPYWIN)
  1126. {
  1127. HWND hWndSpy;
  1128. hWndSpy = FindWindow(_pszSpyWindowClass, NULL);
  1129. if (NULL != hWndSpy)
  1130. {
  1131. SendMessage(hWndSpy, LB_ADDSTRING, 0, (LPARAM) pszBuffer);
  1132. SendMessage(hWndSpy, LB_ADDSTRING, 0, (LPARAM) szCRLF);
  1133. }
  1134. else if (FALSE == _fSpyWarning)
  1135. {
  1136. //only spew this once, till someone changes the settings.
  1137. _fSpyWarning = TRUE;
  1138. // Unable to find SpyWindow
  1139. OutputDebugString(TEXT("CDebugHelp: Spy Window not found!\n"));
  1140. }
  1141. }
  1142. }
  1143. //+-------------------------------------------------------------------------
  1144. //
  1145. // Function: InitializeDebugObject
  1146. //
  1147. // Synopsis: Initialize the debug helper (trace levels, etc.)
  1148. //
  1149. // Arguments: (none)
  1150. //
  1151. // Returns: S_OK if all went well
  1152. // S_FALSE if we encountered /? and spewed and bailed.
  1153. //
  1154. // History: 29-Apr-05 kennethm Created
  1155. // 09-Aug-95 MikeW Override defaults w/ command line
  1156. // 10-Apr-97 SCousens move into CDebugHelp
  1157. //--------------------------------------------------------------------------
  1158. HRESULT CDebugHelp::Initialize()
  1159. {
  1160. HRESULT hr = S_OK;
  1161. int nRet;
  1162. LPTSTR pszSpyClass = NULL;
  1163. CUlongCmdlineObj cmdTraceLvl (OLESTR("tracelvl"), OLESTR("Trace levels"));
  1164. CUlongCmdlineObj cmdTraceLoc (OLESTR("traceloc"), OLESTR("Trace output"));
  1165. CUlongCmdlineObj cmdLogLoc (OLESTR("logloc"), OLESTR("Log output"));
  1166. CBoolCmdlineObj cmdDebugUI (OLESTR("DebugUI"), OLESTR("Popup debug dialog"), OLESTR("FALSE"));
  1167. CBoolCmdlineObj cmdLabMode (OLESTR("labmode"), OLESTR("Popup on error"), OLESTR("FALSE"));
  1168. CBoolCmdlineObj cmdBreak (OLESTR("breakmode"), OLESTR("Break on error"), OLESTR("FALSE"));
  1169. CBoolCmdlineObj cmdVerbose (OLESTR("verbose"), OLESTR("Trace HRCHECK for a noisy log"), OLESTR("FALSE"));
  1170. CBaseCmdlineObj cmdSpyClass (OLESTR("spyclass"), OLESTR("Classname for Spy Window"));
  1171. CCmdline cmdlineArgs;
  1172. CBaseCmdlineObj *aPossCmdline[] = {
  1173. &cmdTraceLvl,
  1174. &cmdTraceLoc,
  1175. &cmdLogLoc,
  1176. &cmdDebugUI,
  1177. &cmdLabMode,
  1178. &cmdVerbose,
  1179. &cmdBreak,
  1180. &cmdSpyClass };
  1181. //
  1182. // Read the debug options from the registry
  1183. //
  1184. hr = GetRegDbgInfo (DEFAULT_REG_LOC);
  1185. //
  1186. // Now that we have the defaults from the registry read the command
  1187. // line to over-ride them.
  1188. //
  1189. if (hr == S_OK)
  1190. {
  1191. //
  1192. // Make sure there were no errors starting up the cmd line objects
  1193. //
  1194. nRet = cmdlineArgs.QueryError();
  1195. if (nRet != CMDLINE_NO_ERROR)
  1196. {
  1197. hr = E_FAIL;
  1198. TraceMsg (DH_LVL_ERROR, TEXT("cmdlineArgs.QueryError"));
  1199. }
  1200. }
  1201. if (hr == S_OK)
  1202. {
  1203. //
  1204. // Now parse the command line
  1205. //
  1206. nRet = cmdlineArgs.Parse(aPossCmdline,
  1207. sizeof(aPossCmdline)/sizeof(CBaseCmdlineObj *),
  1208. FALSE);
  1209. if (nRet != CMDLINE_NO_ERROR)
  1210. {
  1211. hr = E_FAIL;
  1212. TraceMsg (DH_LVL_ERROR, TEXT("cmdlineArgs.Parse"));
  1213. }
  1214. }
  1215. if (hr == S_OK)
  1216. {
  1217. DWORD dwLogLoc = DH_LOC_SAME;
  1218. DWORD dwTraceLoc = DH_LOC_SAME;
  1219. DWORD dwTraceLvl = DH_LVL_SAME;
  1220. DWORD dwMode = 0;
  1221. if (cmdLabMode.IsFound())
  1222. {
  1223. dwMode = *cmdLabMode.GetValue () ? DH_LABMODE_ON : DH_LABMODE_OFF;
  1224. }
  1225. if (cmdVerbose.IsFound())
  1226. {
  1227. dwMode |= *cmdVerbose.GetValue () ? DH_VERBOSE_ON : DH_VERBOSE_OFF;
  1228. }
  1229. if (cmdBreak.IsFound())
  1230. {
  1231. dwMode |= *cmdBreak.GetValue () ? DH_BREAKMODE_ON : DH_BREAKMODE_OFF;
  1232. }
  1233. if (cmdTraceLvl.IsFound())
  1234. {
  1235. dwTraceLvl = *cmdTraceLvl.GetValue();
  1236. }
  1237. if (cmdTraceLoc.IsFound())
  1238. {
  1239. dwTraceLoc = *cmdTraceLoc.GetValue();
  1240. }
  1241. if (cmdLogLoc.IsFound())
  1242. {
  1243. dwLogLoc = *cmdLogLoc.GetValue();
  1244. }
  1245. SetDebugInfo( \
  1246. dwLogLoc, \
  1247. dwTraceLoc, \
  1248. dwTraceLvl, \
  1249. dwMode);
  1250. if (cmdSpyClass.IsFound())
  1251. {
  1252. OleStringToTString(cmdSpyClass.GetValue(), &pszSpyClass);
  1253. if (NULL != pszSpyClass)
  1254. {
  1255. SetSpyWindowClass (pszSpyClass);
  1256. delete [] pszSpyClass;
  1257. }
  1258. }
  1259. if (cmdDebugUI.IsFound())
  1260. {
  1261. HRESULT hr2 = OptionsDialog (GetModuleHandle (NULL), GetActiveWindow ());
  1262. if (FAILED(hr2))
  1263. {
  1264. TraceMsg (DH_LVL_ERROR,
  1265. TEXT("DialogBoxParam failed; hr=%#x. (Is dlg in res?)"),
  1266. hr2);
  1267. }
  1268. }
  1269. }
  1270. return hr;
  1271. }
  1272. //+-------------------------------------------------------------------------
  1273. //
  1274. // Member: CEntryExitTrace::CEntryExitTrace
  1275. //
  1276. // Synopsis: Displays a debug line saying the current function is being
  1277. // entered. Saves the information so it can be displayed
  1278. // when the destructor is called.
  1279. //
  1280. // Arguments: [pDebugObject] -- The parent debug log object
  1281. // [plExitOutput] -- The 32 value to display on exit (can be
  1282. // NULL)
  1283. // [fLvl] -- The trace level of this function
  1284. // [pszFuncName] -- The name of this function
  1285. //
  1286. // Returns:
  1287. //
  1288. // History: 4-10-95 kennethm Created
  1289. //
  1290. // Notes:
  1291. //
  1292. //--------------------------------------------------------------------------
  1293. CEntryExitTrace::CEntryExitTrace(
  1294. CDebugHelp *pDebugObject,
  1295. PLONG plExitOutput,
  1296. DWORD fLvl,
  1297. LPTSTR pszFuncName)
  1298. {
  1299. // Save the paramters
  1300. _pDebugObject = pDebugObject;
  1301. _plExitOutput = plExitOutput;
  1302. _pszFuncName = pszFuncName;
  1303. _fLvl = fLvl;
  1304. // Display the trace information
  1305. _pDebugObject->TraceMsg(
  1306. (_fLvl | DH_LVL_ENTRY),
  1307. TEXT("%s _IN"),
  1308. _pszFuncName);
  1309. }
  1310. //+-------------------------------------------------------------------------
  1311. //
  1312. // Member: CEntryExitTrace::~CEntryExitTrace
  1313. //
  1314. // Synopsis: Destructor. Display a trace output line
  1315. //
  1316. // Arguments: (none)
  1317. //
  1318. // Returns:
  1319. //
  1320. // History: 4-17-95 kennethm Created
  1321. //
  1322. // Notes:
  1323. //
  1324. //--------------------------------------------------------------------------
  1325. CEntryExitTrace::~CEntryExitTrace(void)
  1326. {
  1327. // Display the trace information
  1328. if (_plExitOutput != NULL)
  1329. {
  1330. _pDebugObject->TraceMsg(
  1331. (_fLvl | DH_LVL_EXIT),
  1332. TEXT("%s _OUT:%#08lx"),
  1333. _pszFuncName,
  1334. *_plExitOutput);
  1335. }
  1336. else
  1337. {
  1338. _pDebugObject->TraceMsg(
  1339. (_fLvl | DH_LVL_EXIT),
  1340. TEXT("%s _OUT"),
  1341. _pszFuncName);
  1342. }
  1343. }