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.

1505 lines
51 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 2000
  6. //
  7. // File: programoptions.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // ProgramOptions.cpp: implementation of the CProgramOptions class.
  11. //
  12. //////////////////////////////////////////////////////////////////////
  13. #ifndef NO_STRICT
  14. #ifndef STRICT
  15. #define STRICT 1
  16. #endif
  17. #endif /* NO_STRICT */
  18. #include <WINDOWS.H>
  19. #include <STDIO.H>
  20. #include <TCHAR.H>
  21. #include <stdlib.h>
  22. #include "ProgramOptions.h"
  23. #include "UtilityFunctions.h"
  24. #include "Version.h"
  25. const LPTSTR CProgramOptions::g_DefaultSymbolPath = TEXT("%systemroot%\\symbols");
  26. //////////////////////////////////////////////////////////////////////
  27. // Construction/Destruction
  28. //////////////////////////////////////////////////////////////////////
  29. CProgramOptions::CProgramOptions()
  30. {
  31. // Initialize default modes
  32. m_fSimpleHelpMode = false;
  33. m_fHelpMode = false;
  34. m_fInputProcessesFromLiveSystemMode = false;
  35. m_fInputDriversFromLiveSystemMode = false;
  36. m_fInputProcessesWithMatchingNameOrPID = false;
  37. m_fInputModulesDataFromFileSystemMode = false;
  38. m_fInputDmpFileMode = false;
  39. m_fMatchModuleMode = false;
  40. m_fPrintTaskListMode = false;
  41. m_fOutputSymbolInformationMode = false;
  42. m_fCollectVersionInfoMode = false;
  43. m_fVerifySymbolsMode = false;
  44. m_fVerifySymbolsModeWithSymbolPath = false;
  45. m_fVerifySymbolsModeWithSymbolPathOnly = false;
  46. m_fVerifySymbolsModeWithSymbolPathRecursion = false;
  47. m_fVerifySymbolsModeWithSQLServer = false;
  48. m_fVerifySymbolsModeWithSQLServer2 = false; // SQL2 - mjl 12/14/99
  49. m_iVerificationLevel = 1;
  50. m_fSymbolTreeToBuildMode = false;
  51. m_fInputCSVFileMode = false;
  52. m_fOutputCSVFileMode = false;
  53. m_fOutputDiscrepanciesOnly = false;
  54. m_fOverwriteOutputFileMode = false;
  55. m_fQuietMode = false;
  56. m_tszSymbolTreeToBuild = NULL;
  57. m_tszSymbolPath = NULL;
  58. m_tszProcessName = NULL;
  59. m_tszModuleToMatch = NULL;
  60. m_tszOutputCSVFilePath = NULL;
  61. m_tszInputCSVFilePath = NULL;
  62. m_tszInputDmpFilePath = NULL;
  63. m_tszInputModulesDataFromFileSystemPath = NULL;
  64. m_tszSQLServer = NULL;
  65. m_iProcessID = 0;
  66. m_dwDebugLevel = 0;
  67. m_fExceptionMonitorMode = false;
  68. }
  69. CProgramOptions::~CProgramOptions()
  70. {
  71. if (m_tszSymbolPath)
  72. delete [] m_tszSymbolPath;
  73. if (m_tszProcessName)
  74. delete [] m_tszProcessName;
  75. if (m_tszModuleToMatch)
  76. delete [] m_tszModuleToMatch;
  77. if (m_tszOutputCSVFilePath)
  78. delete [] m_tszOutputCSVFilePath;
  79. if (m_tszInputCSVFilePath)
  80. delete [] m_tszInputCSVFilePath;
  81. if (m_tszInputDmpFilePath)
  82. delete [] m_tszInputDmpFilePath;
  83. if (m_tszInputModulesDataFromFileSystemPath)
  84. delete [] m_tszInputModulesDataFromFileSystemPath;
  85. if (m_tszSymbolTreeToBuild)
  86. delete [] m_tszSymbolTreeToBuild;
  87. if (m_tszSQLServer)
  88. delete [] m_tszSQLServer;
  89. }
  90. // Intialize members that have to dynamically allocate memory...
  91. bool CProgramOptions::Initialize()
  92. {
  93. // Copy expanded default symbol search path (%systemroot%\symbols)
  94. m_tszSymbolPath = CUtilityFunctions::ExpandPath(g_DefaultSymbolPath);
  95. if (!m_tszSymbolPath)
  96. return false;
  97. #ifdef _DEBUG
  98. _tprintf(TEXT("Default Symbol Path = [%s]\n"), m_tszSymbolPath);
  99. #endif
  100. // Get the OS Version Info Stuff
  101. m_osver.dwOSVersionInfoSize = sizeof( m_osver ) ;
  102. if( !GetVersionExA( &m_osver ) )
  103. {
  104. _tprintf(TEXT("Couldn't figure out what version of Windows is running.\n"));
  105. return false ;
  106. }
  107. return true;
  108. }
  109. // This sets the mode requested, and returns the value it was set to (which is provided as input)
  110. bool CProgramOptions::SetMode(enum ProgramModes mode, bool fState)
  111. {
  112. switch (mode)
  113. {
  114. case HelpMode:
  115. m_fHelpMode = fState;
  116. break;
  117. case SimpleHelpMode:
  118. m_fSimpleHelpMode = fState;
  119. break;
  120. case InputProcessesFromLiveSystemMode:
  121. m_fInputProcessesFromLiveSystemMode = fState;
  122. break;
  123. case InputDriversFromLiveSystemMode:
  124. m_fInputDriversFromLiveSystemMode = fState;
  125. break;
  126. case InputProcessesWithMatchingNameOrPID:
  127. m_fInputProcessesWithMatchingNameOrPID = fState;
  128. break;
  129. case MatchModuleMode:
  130. m_fMatchModuleMode = fState;
  131. break;
  132. case InputModulesDataFromFileSystemMode:
  133. m_fInputModulesDataFromFileSystemMode = fState;
  134. break;
  135. case InputDmpFileMode:
  136. m_fInputDmpFileMode = fState;
  137. break;
  138. case PrintTaskListMode:
  139. m_fPrintTaskListMode = fState;
  140. break;
  141. case QuietMode:
  142. m_fQuietMode = fState;
  143. break;
  144. case OutputSymbolInformationMode:
  145. m_fOutputSymbolInformationMode = fState;
  146. break;
  147. case CollectVersionInfoMode:
  148. m_fCollectVersionInfoMode = fState;
  149. break;
  150. case VerifySymbolsMode:
  151. m_fVerifySymbolsMode = fState;
  152. break;
  153. case VerifySymbolsModeWithSymbolPath:
  154. m_fVerifySymbolsModeWithSymbolPath = fState;
  155. break;
  156. case VerifySymbolsModeWithSymbolPathOnly:
  157. m_fVerifySymbolsModeWithSymbolPathOnly = fState;
  158. break;
  159. case VerifySymbolsModeWithSymbolPathRecursion:
  160. m_fVerifySymbolsModeWithSymbolPathRecursion = fState;
  161. break;
  162. case VerifySymbolsModeUsingDBGInMISCSection:
  163. m_fVerifySymbolsModeUsingDBGInMISCSection = fState;
  164. break;
  165. case VerifySymbolsModeWithSQLServer:
  166. m_fVerifySymbolsModeWithSQLServer = fState;
  167. break;
  168. case VerifySymbolsModeWithSQLServer2:
  169. m_fVerifySymbolsModeWithSQLServer2 = fState;
  170. break;
  171. case BuildSymbolTreeMode:
  172. m_fSymbolTreeToBuildMode = fState;
  173. break;
  174. case OutputCSVFileMode:
  175. m_fOutputCSVFileMode = fState;
  176. break;
  177. case OutputDiscrepanciesOnly:
  178. m_fOutputDiscrepanciesOnly = fState;
  179. break;
  180. case OverwriteOutputFileMode:
  181. m_fOverwriteOutputFileMode = fState;
  182. break;
  183. case InputCSVFileMode:
  184. m_fInputCSVFileMode = fState;
  185. break;
  186. case ExceptionMonitorMode:
  187. m_fExceptionMonitorMode = fState;
  188. break;
  189. }
  190. return fState;
  191. }
  192. bool CProgramOptions::GetMode(enum ProgramModes mode)
  193. {
  194. switch (mode)
  195. {
  196. case HelpMode:
  197. return m_fHelpMode;
  198. case SimpleHelpMode:
  199. return m_fSimpleHelpMode;
  200. case InputProcessesFromLiveSystemMode:
  201. return m_fInputProcessesFromLiveSystemMode;
  202. case InputDriversFromLiveSystemMode:
  203. return m_fInputDriversFromLiveSystemMode;
  204. case InputProcessesWithMatchingNameOrPID:
  205. return m_fInputProcessesWithMatchingNameOrPID;
  206. case MatchModuleMode:
  207. return m_fMatchModuleMode;
  208. case InputModulesDataFromFileSystemMode:
  209. return m_fInputModulesDataFromFileSystemMode;
  210. case InputDmpFileMode:
  211. return m_fInputDmpFileMode;
  212. case BuildSymbolTreeMode:
  213. return m_fSymbolTreeToBuildMode;
  214. case PrintTaskListMode:
  215. return m_fPrintTaskListMode;
  216. case QuietMode:
  217. return m_fQuietMode;
  218. case OutputSymbolInformationMode:
  219. return m_fOutputSymbolInformationMode;
  220. case CollectVersionInfoMode:
  221. return m_fCollectVersionInfoMode;
  222. case VerifySymbolsMode:
  223. return m_fVerifySymbolsMode;
  224. case VerifySymbolsModeWithSymbolPath:
  225. return m_fVerifySymbolsModeWithSymbolPath;
  226. case VerifySymbolsModeWithSymbolPathOnly:
  227. return m_fVerifySymbolsModeWithSymbolPathOnly;
  228. case VerifySymbolsModeWithSymbolPathRecursion:
  229. return m_fVerifySymbolsModeWithSymbolPathRecursion;
  230. case VerifySymbolsModeUsingDBGInMISCSection:
  231. return m_fVerifySymbolsModeUsingDBGInMISCSection;
  232. case VerifySymbolsModeWithSQLServer:
  233. return m_fVerifySymbolsModeWithSQLServer;
  234. case VerifySymbolsModeWithSQLServer2:
  235. return m_fVerifySymbolsModeWithSQLServer2;
  236. case OutputCSVFileMode:
  237. return m_fOutputCSVFileMode;
  238. case OutputDiscrepanciesOnly:
  239. return m_fOutputDiscrepanciesOnly;
  240. case OverwriteOutputFileMode:
  241. return m_fOverwriteOutputFileMode;
  242. case InputCSVFileMode:
  243. return m_fInputCSVFileMode;
  244. case ExceptionMonitorMode:
  245. return m_fExceptionMonitorMode;
  246. }
  247. // Should never get here...
  248. #ifdef _DEBUG
  249. _tprintf(TEXT("ERROR! GetMode() - Unknown mode provided! %d"), mode);
  250. #endif
  251. return false;
  252. }
  253. bool CProgramOptions::SetProcessID(DWORD iPID)
  254. {
  255. m_iProcessID = iPID;
  256. return true;
  257. }
  258. bool CProgramOptions::ProcessCommandLineArguments(int argc, TCHAR *argv[])
  259. {
  260. // Skip past the executible filename
  261. DWORD PID = 0; // Process ID if specified
  262. int iArgumentNumber = 1;
  263. if (argc == 1)
  264. {
  265. // We'll now set some defaults
  266. SetMode(InputProcessesFromLiveSystemMode, true);
  267. SetMode(CollectVersionInfoMode, true);
  268. SetMode(VerifySymbolsMode, true);
  269. SetMode(VerifySymbolsModeWithSymbolPath, true);
  270. SetMode(OutputSymbolInformationMode, true);
  271. return true;
  272. }
  273. // Iterate through the arguments...
  274. while (iArgumentNumber < argc)
  275. {
  276. #ifdef _DEBUG
  277. _tprintf(TEXT("Arg%d = %s\n"), iArgumentNumber+1, argv[iArgumentNumber]);
  278. #endif
  279. if (argv[iArgumentNumber][0] == _T('-') || argv[iArgumentNumber][0] == _T('/'))
  280. {
  281. // Look for string matches first!
  282. if ( _tcsicmp(&argv[iArgumentNumber][1], TEXT("MATCH")) == 0)
  283. {
  284. // Get MATCH argument (the module to match against)
  285. #ifdef _DEBUG
  286. _tprintf(TEXT("MATCH argument provided!\n"));
  287. #endif
  288. iArgumentNumber++;
  289. if (iArgumentNumber < argc)
  290. {
  291. m_tszModuleToMatch = CUtilityFunctions::CopyString(argv[iArgumentNumber]);
  292. // Let's force upper-case matches for simplicity
  293. _tcsupr(m_tszModuleToMatch);
  294. if (!m_tszModuleToMatch)
  295. return false;
  296. SetMode(MatchModuleMode, true);
  297. #ifdef _DEBUG
  298. _tprintf(TEXT("Module to match set to [%s]\n"), m_tszModuleToMatch);
  299. #endif
  300. }
  301. else
  302. {
  303. _tprintf(TEXT("\nArgument Missing! -MATCH option requires module to match against!\n"));
  304. // Not enough arguments...
  305. return false;
  306. }
  307. } else
  308. if ( _tcsicmp(&argv[iArgumentNumber][1], TEXT("SQL2")) == 0)
  309. {
  310. // Get the SQL2 server name
  311. #ifdef _DEBUG
  312. _tprintf(TEXT("SQL2 Server name provided!\n"));
  313. #endif
  314. iArgumentNumber++;
  315. if (iArgumentNumber < argc)
  316. {
  317. m_tszSQLServer2 = CUtilityFunctions::CopyString(argv[iArgumentNumber]);
  318. if (!m_tszSQLServer2)
  319. return false;
  320. SetMode(VerifySymbolsMode, true);
  321. SetMode(VerifySymbolsModeWithSQLServer2, true);
  322. #ifdef _DEBUG
  323. _tprintf(TEXT("SQL2 Server set to [%s]\n"), m_tszSQLServer2);
  324. #endif
  325. }
  326. else
  327. {
  328. _tprintf(TEXT("\nArgument Missing! -SQL2 option requires SQL Server Name value!\n"));
  329. // Not enough arguments...
  330. return false;
  331. }
  332. } else
  333. if ( _tcsicmp(&argv[iArgumentNumber][1], TEXT("SQL")) == 0)
  334. {
  335. // Get the SQL server name
  336. #ifdef _DEBUG
  337. _tprintf(TEXT("SQL Server name provided!\n"));
  338. #endif
  339. iArgumentNumber++;
  340. if (iArgumentNumber < argc)
  341. {
  342. m_tszSQLServer = CUtilityFunctions::CopyString(argv[iArgumentNumber]);
  343. if (!m_tszSQLServer)
  344. return false;
  345. SetMode(VerifySymbolsMode, true);
  346. SetMode(VerifySymbolsModeWithSQLServer, true);
  347. #ifdef _DEBUG
  348. _tprintf(TEXT("SQL Server set to [%s]\n"), m_tszSQLServer);
  349. #endif
  350. }
  351. else
  352. {
  353. _tprintf(TEXT("\nArgument Missing! -SQL option requires SQL Server Name value!\n"));
  354. // Not enough arguments...
  355. return false;
  356. }
  357. } else
  358. if ( _tcsicmp(&argv[iArgumentNumber][1], TEXT("DEBUG")) == 0)
  359. {
  360. // Okay, we have the DEBUG switch... see what Debug Level is requested
  361. iArgumentNumber++;
  362. if (iArgumentNumber < argc)
  363. {
  364. // Save away the Debug Level
  365. m_dwDebugLevel = _ttoi(argv[iArgumentNumber]);
  366. }
  367. else
  368. {
  369. _tprintf(TEXT("\nArgument Missing! -DEBUG option requires Debug Level!\n"));
  370. // Not enough arguments...
  371. return false;
  372. }
  373. } else
  374. if ( _tcsicmp(&argv[iArgumentNumber][1], TEXT("???")) == 0)
  375. {
  376. SetMode(HelpMode, true);
  377. return true;
  378. } else
  379. {
  380. // We found a command directive..
  381. switch (argv[iArgumentNumber][1])
  382. {
  383. case _T('?'):
  384. case _T('h'):
  385. case _T('H'):
  386. SetMode(SimpleHelpMode, true);
  387. iArgumentNumber = argc;
  388. return true;
  389. case _T('t'):
  390. case _T('T'):
  391. SetMode(PrintTaskListMode, true);
  392. SetMode(InputProcessesFromLiveSystemMode, true);
  393. break;
  394. case _T('s'):
  395. case _T('S'):
  396. SetMode(OutputSymbolInformationMode, true);
  397. break;
  398. case _T('i'):
  399. case _T('I'):
  400. #ifdef _DEBUG
  401. _tprintf(TEXT("Input File path provided\n"));
  402. #endif
  403. iArgumentNumber++;
  404. if (iArgumentNumber < argc)
  405. {
  406. m_tszInputCSVFilePath = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  407. SetMode(InputCSVFileMode, true);
  408. }
  409. else
  410. { // Not enough arguments...
  411. _tprintf(TEXT("\nArgument Missing! -I option requires an input file!\n"));
  412. return false;
  413. }
  414. break;
  415. // This special version supports a new mode...
  416. case _T('e'):
  417. case _T('E'):
  418. SetMode(ExceptionMonitorMode, true);
  419. break;
  420. case _T('o'):
  421. case _T('O'):
  422. // Check to see if they want to overwrite the file if it exists?
  423. if (argv[iArgumentNumber][2])
  424. {
  425. if ( 2 == _ttoi(&argv[iArgumentNumber][2]) )
  426. {
  427. #ifdef _DEBUG
  428. _tprintf(TEXT("Overwrite Mode enabled!\n"));
  429. #endif
  430. SetMode(OverwriteOutputFileMode, true);
  431. }
  432. }
  433. #ifdef _DEBUG
  434. _tprintf(TEXT("Output File path provided\n"));
  435. #endif
  436. iArgumentNumber++;
  437. if (iArgumentNumber < argc)
  438. {
  439. m_tszOutputCSVFilePath = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  440. #ifdef _DEBUG
  441. _tprintf(TEXT("Output File Path set to [%s]\n"), GetOutputFilePath());
  442. #endif
  443. // Enable OutputCSVFileMode
  444. SetMode(OutputCSVFileMode, true);
  445. }
  446. else
  447. { // Not enough arguments...
  448. _tprintf(TEXT("\nArgument Missing! -O option requires an output file!\n"));
  449. return false;
  450. }
  451. break;
  452. case _T('q'):
  453. case _T('Q'):
  454. // Check to see if they only want to suppress matches?
  455. if (argv[iArgumentNumber][2])
  456. {
  457. if ( 2 == _ttoi(&argv[iArgumentNumber][2]) )
  458. {
  459. SetMode(OutputDiscrepanciesOnly, true);
  460. } else
  461. {
  462. SetMode(QuietMode, true);
  463. }
  464. } else
  465. {
  466. SetMode(QuietMode, true);
  467. }
  468. break;
  469. case _T('r'):
  470. case _T('R'):
  471. SetMode(CollectVersionInfoMode, true);
  472. break;
  473. case _T('v'):
  474. case _T('V'):
  475. SetMode(VerifySymbolsMode, true);
  476. if (argv[iArgumentNumber][2])
  477. {
  478. m_iVerificationLevel = _ttoi(&argv[iArgumentNumber][2]);
  479. if (m_iVerificationLevel == 0)
  480. {
  481. SetMode(HelpMode, true);
  482. iArgumentNumber = argc;
  483. }
  484. }
  485. break;
  486. case _T('f'):
  487. case _T('F'):
  488. iArgumentNumber++;
  489. if (iArgumentNumber < argc)
  490. {
  491. m_tszInputModulesDataFromFileSystemPath = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  492. if (VerifySemiColonSeparatedPath(m_tszInputModulesDataFromFileSystemPath))
  493. {
  494. SetMode(InputModulesDataFromFileSystemMode, true);
  495. }
  496. else
  497. {
  498. _tprintf(TEXT("\nFile Path specified to search is too long\n"));
  499. return false;
  500. }
  501. }
  502. else
  503. {
  504. // Not enough arguments...
  505. _tprintf(TEXT("\nArgument Missing! -F option requires a directory/file path!\n"));
  506. return false;
  507. }
  508. break;
  509. case _T('b'):
  510. case _T('B'):
  511. iArgumentNumber++;
  512. if (iArgumentNumber < argc)
  513. {
  514. SetMode(BuildSymbolTreeMode, true);
  515. // Okay, we have some string gymnastics below because we
  516. // want to expand any environment variables, and ensure
  517. // that we have a backslash appended...
  518. TCHAR tszPathBuffer[_MAX_PATH];
  519. LPTSTR tszExpandedPathBuffer = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  520. _tcscpy(tszPathBuffer, tszExpandedPathBuffer);
  521. delete [] tszExpandedPathBuffer;
  522. int cbLength = _tcsclen(tszPathBuffer);
  523. if (cbLength && tszPathBuffer[cbLength-1] != '\\')
  524. {
  525. _tcscat(tszPathBuffer, TEXT("\\"));
  526. }
  527. m_tszSymbolTreeToBuild = CUtilityFunctions::CopyString(tszPathBuffer);
  528. if (!m_tszSymbolTreeToBuild)
  529. return false;
  530. if (VerifySemiColonSeparatedPath(m_tszSymbolTreeToBuild))
  531. {
  532. #ifdef _DEBUG
  533. _tprintf(TEXT("Building a Symbol Path Requested at [%s]\n"), m_tszSymbolTreeToBuild);
  534. #endif
  535. }
  536. else
  537. {
  538. _tprintf(TEXT("\nPath provided to build symbol path is too long!\n"));
  539. return false;
  540. }
  541. }
  542. else
  543. {
  544. // Not enough arguments...
  545. _tprintf(TEXT("\nArgument Missing! -B option requires a directory symbol path\n"));
  546. return false;
  547. }
  548. break;
  549. case _T('p'):
  550. case _T('P'):
  551. #ifdef _DEBUG
  552. _tprintf(TEXT("Specific Process name (or PID) requested\n"));
  553. #endif
  554. iArgumentNumber++;
  555. // Do we have another argument (we should)...
  556. if (iArgumentNumber < argc)
  557. {
  558. // Well... we know that we have been asked to query processes...
  559. SetMode(InputProcessesFromLiveSystemMode, true);
  560. // Is the next argument a number? (Process ID)?
  561. if ((PID = _ttoi(argv[iArgumentNumber])) == 0)
  562. {
  563. // Process name provided!
  564. #ifdef _DEBUG
  565. _tprintf(TEXT("Process name: [%s]\n"), argv[iArgumentNumber]);
  566. #endif
  567. // Hey, wild-card matches everything... did they give us something else?
  568. if (*argv[iArgumentNumber] != '*')
  569. {
  570. // Set Process Name, only if * isn't used.
  571. // Leaving process name == NULL is our clue
  572. // to dump all processes
  573. m_tszProcessName = CUtilityFunctions::CopyString(argv[iArgumentNumber]);
  574. if (!m_tszProcessName)
  575. return false;
  576. _tcsupr(m_tszProcessName);
  577. SetMode(InputProcessesWithMatchingNameOrPID, true);
  578. }
  579. } else
  580. { // PID provided?
  581. #ifdef _DEBUG
  582. _tprintf(TEXT("Process ID: [%d]\n"), PID);
  583. #endif
  584. SetProcessID(PID);
  585. SetMode(InputProcessesWithMatchingNameOrPID, true);
  586. }
  587. }
  588. else
  589. {
  590. // Not enough arguments...
  591. _tprintf(TEXT("\nArgument Missing! -P option requires *, a Process ID, or a Process Name!\n"));
  592. return false;
  593. }
  594. break;
  595. case _T('d'):
  596. case _T('D'):
  597. // Do we have another argument (we should)...
  598. // Well... we know that we have been asked to query device drivers...
  599. SetMode(InputDriversFromLiveSystemMode, true);
  600. break;
  601. case _T('y'):
  602. case _T('Y'):
  603. #ifdef _DEBUG
  604. _tprintf(TEXT("Symbol path provided\n"));
  605. #endif
  606. // Check to see if they want some flavor of symbol searching...
  607. if (argv[iArgumentNumber][2])
  608. {
  609. DWORD dwSymbolPathSearchOptions = _ttoi(&argv[iArgumentNumber][2]);
  610. if (dwSymbolPathSearchOptions & enumSymbolPathOnly)
  611. {
  612. #ifdef _DEBUG
  613. _tprintf(TEXT("Symbol Path Searching ONLY mode enabled!\n"));
  614. #endif
  615. SetMode(VerifySymbolsModeWithSymbolPathOnly, true);
  616. }
  617. if (dwSymbolPathSearchOptions & enumSymbolPathRecursion)
  618. {
  619. #ifdef _DEBUG
  620. _tprintf(TEXT("Recursive Symbol Searching Mode enabled!\n"));
  621. #endif
  622. SetMode(VerifySymbolsModeWithSymbolPathRecursion, true);
  623. }
  624. if (dwSymbolPathSearchOptions & enumSymbolsModeUsingDBGInMISCSection)
  625. {
  626. _tprintf(TEXT("Verify Symbols Using DBG files found in MISC Section of PE Image!\n"));
  627. SetMode(VerifySymbolsModeUsingDBGInMISCSection, true);
  628. }
  629. }
  630. iArgumentNumber++;
  631. if (iArgumentNumber < argc)
  632. {
  633. if (m_tszSymbolPath)
  634. delete [] m_tszSymbolPath;
  635. m_tszSymbolPath = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  636. if (VerifySemiColonSeparatedPath(m_tszSymbolPath))
  637. {
  638. SetMode(VerifySymbolsModeWithSymbolPath, true);
  639. #ifdef _DEBUG
  640. _tprintf(TEXT("Symbol Path set to [%s]\n"), GetSymbolPath());
  641. #endif
  642. }
  643. else
  644. {
  645. _tprintf(TEXT("\nBad Symbol Path Provided! Multiple paths are semi-colon delimited!\n"));
  646. return false;
  647. }
  648. }
  649. else
  650. {
  651. // Not enough arguments...
  652. _tprintf(TEXT("\nArgument Missing! -Y option requires a symbol path!\n"));
  653. return false;
  654. }
  655. break;
  656. case _T('z'):
  657. case _T('Z'):
  658. #ifdef _DEBUG
  659. _tprintf(TEXT("DMP file provided!\n"));
  660. #endif
  661. iArgumentNumber++;
  662. if (iArgumentNumber < argc)
  663. {
  664. m_tszInputDmpFilePath = CUtilityFunctions::ExpandPath(argv[iArgumentNumber]);
  665. SetMode(InputDmpFileMode, true);
  666. #ifdef _DEBUG
  667. _tprintf(TEXT("Dmp File Path set to [%s]\n"), GetDmpFilePath());
  668. #endif
  669. }
  670. else
  671. { // Not enough arguments...
  672. _tprintf(TEXT("\nArgument Missing! -DMP option requires a DMP file!\n"));
  673. return false;
  674. }
  675. break;
  676. default:
  677. _tprintf(TEXT("\nUnknown command specified! [%s]\n"), argv[iArgumentNumber]);
  678. iArgumentNumber = argc;
  679. return false;
  680. }
  681. }
  682. } else
  683. {
  684. _tprintf(TEXT("\nUnknown option specified! [%s]\n"), argv[iArgumentNumber]);
  685. return false;
  686. }
  687. // Increment to the next argument...
  688. iArgumentNumber++;
  689. }
  690. if ( !GetMode(InputCSVFileMode) &&
  691. !GetMode(InputProcessesFromLiveSystemMode) &&
  692. !GetMode(InputDriversFromLiveSystemMode) &&
  693. !GetMode(InputModulesDataFromFileSystemMode) &&
  694. !GetMode(InputDmpFileMode) )
  695. {
  696. _tprintf(TEXT("\nAt least one input method must be specified!\n"));
  697. return false;
  698. }
  699. // If the user provided both a -I and a -P option, then silently ignore querying locally
  700. // for active processes... this will leave the possibility, however, of matching on
  701. // process ID or process name in the -I data...
  702. if ( GetMode(InputCSVFileMode) && ( GetMode(InputProcessesFromLiveSystemMode)))
  703. {
  704. SetMode(InputProcessesFromLiveSystemMode, false);
  705. }
  706. // Ensure that the input and output files aren't the same...
  707. if ( GetMode(InputCSVFileMode) && GetMode(OutputCSVFileMode) )
  708. {
  709. if (_tcscmp(m_tszInputCSVFilePath, m_tszOutputCSVFilePath) == 0)
  710. {
  711. _tprintf(TEXT("\nInput file and output file must be different!\n"));
  712. return false;
  713. }
  714. }
  715. // Now... enforce any overrides as necessary...
  716. // Inspect commandline options (for changes to these defaults)
  717. if ( GetMode(PrintTaskListMode) )
  718. {
  719. // Task list mode requires that you obtain process data, and print it...
  720. SetMode(InputProcessesFromLiveSystemMode, true);
  721. SetMode(QuietMode, false);
  722. SetMode(CollectVersionInfoMode, false);
  723. SetMode(VerifySymbolsModeWithSymbolPath, false);
  724. SetMode(InputCSVFileMode, false);
  725. SetMode(OutputCSVFileMode, false);
  726. SetMode(OutputSymbolInformationMode, false);
  727. }
  728. // We can't build a symbol tree without verifying symbols...
  729. if ( GetMode(BuildSymbolTreeMode) && !GetMode(VerifySymbolsMode) )
  730. {
  731. SetMode(VerifySymbolsMode, true);
  732. }
  733. /*
  734. // If we're verifying, and we're not reading from a CSV file,
  735. // then we should go ahead and collect symbol information (since we'll need it).
  736. if ( GetMode(VerifySymbolsMode) &&
  737. !GetMode(InputCSVFileMode) )
  738. {
  739. SetMode(OutputSymbolInformationMode, true);
  740. }
  741. */
  742. // If we're reading a dump file, we should collect symbol information (and we do not
  743. // want to read from a CSV file at the same time...
  744. if ( GetMode(InputDmpFileMode) )
  745. {
  746. // SetMode(OutputSymbolInformationMode, true);
  747. SetMode(InputCSVFileMode, false);
  748. }
  749. // If we've enabled Symbol Verification, then we default to VerifySymbolsModeWithSymbolPath
  750. // if neither method were specified...
  751. if ( GetMode(VerifySymbolsMode) &&
  752. !GetMode(VerifySymbolsModeWithSymbolPath) &&
  753. !GetMode(VerifySymbolsModeWithSQLServer) )
  754. {
  755. SetMode(VerifySymbolsModeWithSymbolPath, true);
  756. }
  757. return true;
  758. }
  759. bool CProgramOptions::VerifySemiColonSeparatedPath(LPTSTR tszPath)
  760. {
  761. enum { MAX_PATH_ELEMENT_LENGTH = MAX_PATH-12 }; // We append \SYMBOLS\EXT to the end of the symbol path
  762. if (!tszPath)
  763. return false;
  764. TCHAR chTemp;
  765. int iLength;
  766. LPTSTR tszPointerToDelimiter;
  767. LPTSTR tszStartOfPathElement = tszPath;
  768. tszPointerToDelimiter = _tcschr(tszStartOfPathElement, ';');
  769. if (tszPointerToDelimiter == NULL)
  770. {
  771. iLength = _tcslen(tszStartOfPathElement);
  772. #ifdef DEBUG
  773. _tprintf(TEXT("DEBUG: Path provided = %s\n"), tszStartOfPathElement);
  774. _tprintf(TEXT("DEBUG: Path length = %d\n"), iLength);
  775. #endif
  776. return ( iLength <= MAX_PATH_ELEMENT_LENGTH );
  777. }
  778. while (tszPointerToDelimiter)
  779. {
  780. // Okay, we found a delimiter
  781. chTemp = *tszPointerToDelimiter; // Save the char away...
  782. *tszPointerToDelimiter = '\0'; // Null terminate the path element
  783. iLength = _tcslen(tszStartOfPathElement);
  784. #ifdef DEBUG
  785. _tprintf(TEXT("DEBUG: Path provided = %s\n"), tszStartOfPathElement);
  786. _tprintf(TEXT("DEBUG: Path length = %d\n"), iLength);
  787. #endif
  788. if( iLength > MAX_PATH_ELEMENT_LENGTH )
  789. {
  790. _tprintf(TEXT("Path is too long for element [%s]\n"), tszStartOfPathElement);
  791. *tszPointerToDelimiter = chTemp;
  792. return false;
  793. }
  794. *tszPointerToDelimiter = chTemp; // Restore the char...
  795. tszStartOfPathElement = CharNext(tszPointerToDelimiter); // Set new start of path element
  796. tszPointerToDelimiter = _tcschr(tszStartOfPathElement, ';'); // Look for next delimiter
  797. }
  798. // We will always have some part left to look at...
  799. iLength = _tcslen(tszStartOfPathElement);
  800. #ifdef DEBUG
  801. _tprintf(TEXT("DEBUG: Path provided = %s\n"), tszStartOfPathElement);
  802. _tprintf(TEXT("DEBUG: Path length = %d\n"), iLength);
  803. #endif
  804. return ( iLength <= MAX_PATH_ELEMENT_LENGTH );
  805. }
  806. bool CProgramOptions::fDoesModuleMatchOurSearch(LPCTSTR tszModulePathToTest)
  807. {
  808. // If "-MATCH" was specified, look to see if this filename meets our criteria
  809. if (!GetMode(MatchModuleMode))
  810. return true;
  811. TCHAR tszTestBuffer[_MAX_PATH];
  812. // Before we copy to our string
  813. if (_tcslen(tszModulePathToTest) > _MAX_PATH)
  814. return false;
  815. // Copy to a read/write buffer...
  816. _tcscpy(tszTestBuffer, tszModulePathToTest);
  817. // Upper case for our test...
  818. _tcsupr(tszTestBuffer);
  819. return (_tcsstr(tszTestBuffer, GetModuleToMatch()) != NULL);
  820. }
  821. bool CProgramOptions::DisplayProgramArguments()
  822. {
  823. if (GetMode(QuietMode) || GetMode(PrintTaskListMode))
  824. return false;
  825. CUtilityFunctions::OutputLineOfStars();
  826. #ifdef _UNICODE
  827. _tprintf(TEXT("CHECKSYM V%S - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  828. #else
  829. _tprintf(TEXT("CHECKSYM V%s - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  830. #endif
  831. CUtilityFunctions::OutputLineOfStars();
  832. _tprintf(TEXT("\n***** COLLECTION OPTIONS *****\n"));
  833. // INPUT - FIRST, IF WE'RE LOOKING FOR LOCAL PROCESS DATA ON THIS MACHINE!
  834. if (GetMode(InputProcessesFromLiveSystemMode))
  835. {
  836. _tprintf(TEXT("\nCollect Information From Running Processes\n"));
  837. if (!GetMode(InputProcessesWithMatchingNameOrPID))
  838. {
  839. _tprintf(TEXT("\t-P *\t\t(Query all local processes)\n"));
  840. } else if (m_tszProcessName)
  841. {
  842. _tprintf(TEXT("\t-P %s\t\t(Query for specific process by name)\n"), m_tszProcessName);
  843. } else
  844. {
  845. _tprintf(TEXT("\t-P %d\t\t(Query for specific process ID)\n"), GetProcessID());
  846. }
  847. }
  848. if (GetMode(InputDriversFromLiveSystemMode))
  849. {
  850. _tprintf(TEXT("\t-D\t\t(Query all local device drivers)\n"));
  851. }
  852. // INPUT - SECOND, IF WE'RE SCAVENGING ON THE LOCAL FILE SYSTEM...
  853. if (GetMode(InputModulesDataFromFileSystemMode))
  854. {
  855. _tprintf(TEXT("\nCollect Information From File(s) Specified by the User\n"));
  856. _tprintf(TEXT("\t-F %s\n"), m_tszInputModulesDataFromFileSystemPath);
  857. }
  858. // INPUT - THIRD, CSV FILE
  859. if (GetMode(InputCSVFileMode))
  860. {
  861. _tprintf(TEXT("\nCollect Information from a Saved Checksym Generated CSV File\n"));
  862. _tprintf(TEXT("\t-I %s\n"), m_tszInputCSVFilePath);
  863. }
  864. // INPUT - FOURTH, DMP FILE
  865. if (GetMode(InputDmpFileMode))
  866. {
  867. _tprintf(TEXT("\nCollect Information from a User.Dmp or Memory.Dmp File\n"));
  868. _tprintf(TEXT("\t-Z %s\n"), m_tszInputDmpFilePath);
  869. }
  870. // MATCH - OPTIONS?
  871. if (GetMode(MatchModuleMode))
  872. {
  873. _tprintf(TEXT("\n***** MATCHING OPTIONS *****\n"));
  874. _tprintf(TEXT("\n"));
  875. _tprintf(TEXT("\nLook for Modules that Match the Provided Text\n"));
  876. _tprintf(TEXT("\t-MATCH %s\n"), m_tszModuleToMatch);
  877. }
  878. _tprintf(TEXT("\n***** INFORMATION CHECKING OPTIONS *****\n"));
  879. // INFO - FIRST, SYMBOL INFO
  880. if (GetMode(OutputSymbolInformationMode))
  881. {
  882. _tprintf(TEXT("\nOutput Symbol Information From Modules\n"));
  883. _tprintf(TEXT("\t-S\n"));
  884. }
  885. // INFO - FIRST, SYMBOL INFO
  886. if (GetMode(VerifySymbolsMode))
  887. {
  888. _tprintf(TEXT("\nVerify Symbols Locally Using Collected Symbol Information\n"));
  889. _tprintf(TEXT("\t-V\n"));
  890. }
  891. // INFO - SECOND, VERSION INFO
  892. if (GetMode(CollectVersionInfoMode))
  893. {
  894. _tprintf(TEXT("\nCollect Version and File-System Information From Modules\n"));
  895. _tprintf(TEXT("\t-R\n"));
  896. }
  897. // INFO - THIRD, VERIFY MODE (WITH SYMBOL PATH AND/OR SQL SERVER)
  898. if (GetMode(VerifySymbolsMode))
  899. {
  900. if (GetMode(VerifySymbolsModeWithSymbolPath))
  901. {
  902. _tprintf(TEXT("\nVerify Symbols for Modules Using Symbol Path\n"));
  903. _tprintf(TEXT("\t-Y %s\n"), m_tszSymbolPath);
  904. }
  905. if (GetMode(VerifySymbolsModeWithSQLServer))
  906. {
  907. _tprintf(TEXT("\nVerify Symbols for Modules Using SQL Server\n"));
  908. _tprintf(TEXT("\t-SQL %s\n"), m_tszSQLServer);
  909. }
  910. if (GetMode(VerifySymbolsModeWithSQLServer2))
  911. {
  912. _tprintf(TEXT("\nVerify Symbols for Modules Using SQL Server\n"));
  913. _tprintf(TEXT("\t-SQL2 %s\n"), m_tszSQLServer2);
  914. }
  915. }
  916. if (!GetMode(OutputSymbolInformationMode) &&
  917. !GetMode(CollectVersionInfoMode) &&
  918. !GetMode(VerifySymbolsMode)
  919. )
  920. {
  921. _tprintf(TEXT("\nDump Module Paths\n"));
  922. }
  923. _tprintf(TEXT("\n***** OUTPUT OPTIONS *****\n"));
  924. if (!GetMode(QuietMode))
  925. {
  926. _tprintf(TEXT("\nOutput Results to STDOUT\n"));
  927. }
  928. if (GetMode(BuildSymbolTreeMode))
  929. {
  930. _tprintf(TEXT("\nBuild a Symbol Tree of Matching Symbols\n"));
  931. _tprintf(TEXT("\t-B %s\n"), m_tszSymbolTreeToBuild);
  932. }
  933. if (GetMode(OutputCSVFileMode))
  934. {
  935. if (GetMode(ExceptionMonitorMode))
  936. {
  937. _tprintf(TEXT("\nOutput Collected Module Information To a CSV File In Exception Monitor Format\n"));
  938. } else
  939. {
  940. _tprintf(TEXT("\nOutput Collected Module Information To a CSV File\n"));
  941. }
  942. _tprintf(TEXT("\t-O %s\n"), m_tszOutputCSVFilePath);
  943. }
  944. CUtilityFunctions::OutputLineOfDashes();
  945. return true;
  946. }
  947. void CProgramOptions::DisplayHelp()
  948. {
  949. CUtilityFunctions::OutputLineOfStars();
  950. #ifdef _UNICODE
  951. _tprintf(TEXT("CHECKSYM V%S - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  952. #else
  953. _tprintf(TEXT("CHECKSYM V%s - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  954. #endif
  955. CUtilityFunctions::OutputLineOfStars();
  956. _tprintf(TEXT("\n"));
  957. #ifdef _UNICODE
  958. _tprintf(TEXT("This version is supported for Windows NT 4.0 and Windows 2000\n"));
  959. #else
  960. _tprintf(TEXT("This version is supported for Windows 98, Windows NT 4.0 and Windows 2000\n"));
  961. #endif
  962. _tprintf(TEXT("\n"));
  963. _tprintf(TEXT("DESCRIPTION:\n"));
  964. _tprintf(TEXT("\n"));
  965. _tprintf(TEXT("This program can be used to verify that you have proper symbol files\n"));
  966. _tprintf(TEXT("(*.DBG and/or *.PDB) on your system for the processes you have running, and\n"));
  967. _tprintf(TEXT("for symbol files on your filesystem. This program can also be used to\n"));
  968. _tprintf(TEXT("collect information regarding these modules and output this to a file.\n"));
  969. _tprintf(TEXT("The output file can then be given to another party (Microsoft Product\n"));
  970. _tprintf(TEXT("Support Services) where they can use the file to verify that they have\n"));
  971. _tprintf(TEXT("proper symbols for debugging your environment.\n"));
  972. _tprintf(TEXT("\n"));
  973. _tprintf(TEXT("Obtaining online help:\n"));
  974. _tprintf(TEXT("\n"));
  975. _tprintf(TEXT("CHECKSYM -? : Simple help usage\n"));
  976. _tprintf(TEXT("CHECKSYM -??? : Complete help usage (this screen)\n"));
  977. _tprintf(TEXT("\n"));
  978. _tprintf(TEXT("Usage:\n"));
  979. _tprintf(TEXT("\n"));
  980. _tprintf(TEXT("CHECKSYM [COLLECTION OPTIONS] [INFORMATION CHECKING OPTIONS] [OUTPUT OPTIONS]\n"));
  981. _tprintf(TEXT("\n"));
  982. _tprintf(TEXT("***** COLLECTION OPTIONS *****\n"));
  983. _tprintf(TEXT("\n"));
  984. _tprintf(TEXT("At least one collection option must be specified. The following options are\n"));
  985. _tprintf(TEXT("currently supported.\n"));
  986. _tprintf(TEXT("\n"));
  987. _tprintf(TEXT(" -P <Argument> : Collect Information From Running Processes\n"));
  988. _tprintf(TEXT("\n"));
  989. _tprintf(TEXT(" When used in conjunction with -O the output file will\n"));
  990. _tprintf(TEXT(" contain information about your running system. This\n"));
  991. _tprintf(TEXT(" operation should not interfere with the operation of\n"));
  992. _tprintf(TEXT(" running processes.\n"));
  993. _tprintf(TEXT("\n"));
  994. _tprintf(TEXT(" <Argument> = [ * | Process ID (pid) | Process Name ]\n"));
  995. _tprintf(TEXT("\n"));
  996. _tprintf(TEXT(" To query all running processes, specify the wildcard\n"));
  997. _tprintf(TEXT(" character '*'. To specify a specific process, you can\n"));
  998. _tprintf(TEXT(" provide the Process ID (as a decimal value), or the Process\n"));
  999. _tprintf(TEXT(" Name (eg. notepad.exe). If you use the Process Name as the\n"));
  1000. _tprintf(TEXT(" argument, and multiple instances of that process are\n"));
  1001. _tprintf(TEXT(" running they will all be inspected.\n"));
  1002. _tprintf(TEXT("\n"));
  1003. _tprintf(TEXT(" -D : Collect Information from Running Device Drivers\n"));
  1004. _tprintf(TEXT("\n"));
  1005. _tprintf(TEXT(" This option will obtain information for all device drivers\n"));
  1006. _tprintf(TEXT(" (*.SYS files) running on the current system.\n"));
  1007. _tprintf(TEXT("\n"));
  1008. _tprintf(TEXT("-F <File/Dir Path>:Collect Information From File(s) Specified by the User\n"));
  1009. _tprintf(TEXT("\n"));
  1010. _tprintf(TEXT(" This option will allow you to obtain module information\n"));
  1011. _tprintf(TEXT(" for modules on the specified path. Multiple paths may be\n"));
  1012. _tprintf(TEXT(" provided, separated by semicolons. If the path provided is\n"));
  1013. _tprintf(TEXT(" a directory, then a recursive scan of files from that\n"));
  1014. _tprintf(TEXT(" directory will be used to obtain module information. This\n"));
  1015. _tprintf(TEXT(" input method is useful for situations where the module(s) is\n"));
  1016. _tprintf(TEXT(" not loaded by an active process. (Eg. Perhaps a process is\n"));
  1017. _tprintf(TEXT(" unable to start.)\n"));
  1018. _tprintf(TEXT("\n"));
  1019. _tprintf(TEXT(" -I <File Path> : Collect Information from a Saved Checksym Generated CSV File\n"));
  1020. _tprintf(TEXT("\n"));
  1021. _tprintf(TEXT(" This input method is useful when you want to evaluate\n"));
  1022. _tprintf(TEXT(" whether you have proper symbols for modules on a different\n"));
  1023. _tprintf(TEXT(" system. Most commonly this is useful for preparing to do a\n"));
  1024. _tprintf(TEXT(" remote debug of a remote system. The use of -I prohibits\n"));
  1025. _tprintf(TEXT(" the use of other collection options.\n"));
  1026. _tprintf(TEXT("\n"));
  1027. _tprintf(TEXT(" -Z <File Path> : Collect Information from a DMP File\n"));
  1028. _tprintf(TEXT("\n"));
  1029. _tprintf(TEXT(" This input method is useful when you have a DMP file and\n"));
  1030. _tprintf(TEXT(" to ensure that you have matching symbols for it. Checksym\n"));
  1031. _tprintf(TEXT(" tries to determine as much information as possible to\n"));
  1032. _tprintf(TEXT(" in finding good symbols. If a module name can not be\n"));
  1033. _tprintf(TEXT(" determined (mostly with modules that only use PDB files),\n"));
  1034. _tprintf(TEXT(" the module will be listed as \"IMAGE<Virtual Address>\".\n"));
  1035. _tprintf(TEXT("\n"));
  1036. _tprintf(TEXT(" -MATCH <Text> : Collect Modules that match text only\n"));
  1037. _tprintf(TEXT("\n"));
  1038. _tprintf(TEXT(" This option allows you to restrict searching/collection to\n"));
  1039. _tprintf(TEXT(" include only those modules that match the provided text.\n"));
  1040. _tprintf(TEXT("\n"));
  1041. _tprintf(TEXT("***** INFORMATION CHECKING OPTIONS *****\n"));
  1042. _tprintf(TEXT("\n"));
  1043. _tprintf(TEXT(" -S : Collect/Display Symbol Information From Modules\n"));
  1044. _tprintf(TEXT("\n"));
  1045. _tprintf(TEXT(" This option is used to indicate that symbol information\n"));
  1046. _tprintf(TEXT(" should be collected and displayed from every module analyzed.\n"));
  1047. _tprintf(TEXT(" In order to verify proper symbols, symbol information must\n"));
  1048. _tprintf(TEXT(" be gathered. It is possible to collect symbol information without\n"));
  1049. _tprintf(TEXT(" verifying it. This case is usually used with the -O option\n"));
  1050. _tprintf(TEXT(" to produce a saved CheckSym generated CSV file. Omitting\n"));
  1051. _tprintf(TEXT(" -S and -V could direct CheckSym to collect only version\n"));
  1052. _tprintf(TEXT(" information (if -R is specified), or no information (if\n"));
  1053. _tprintf(TEXT(" no information checking options are specified.\n"));
  1054. _tprintf(TEXT("\n"));
  1055. _tprintf(TEXT(" -R : Collect Version and File-System Information From Modules\n"));
  1056. _tprintf(TEXT("\n"));
  1057. _tprintf(TEXT(" This option requests checksym to collect the following\n"));
  1058. _tprintf(TEXT(" information from the file-system and version information\n"));
  1059. _tprintf(TEXT(" structure (if any):\n"));
  1060. _tprintf(TEXT("\n"));
  1061. _tprintf(TEXT(" File Version\n"));
  1062. _tprintf(TEXT(" Company Name\n"));
  1063. _tprintf(TEXT(" File Description\n"));
  1064. _tprintf(TEXT(" File Size (bytes)\n"));
  1065. _tprintf(TEXT(" File Date/Time\n"));
  1066. _tprintf(TEXT("\n"));
  1067. _tprintf(TEXT(" -V[<blank>|1|2] : Verify Symbols for Modules\n"));
  1068. _tprintf(TEXT("\n"));
  1069. _tprintf(TEXT(" This option uses the symbol information gathered (-S option)\n"));
  1070. _tprintf(TEXT(" to verify that proper symbols exist (as found along the\n"));
  1071. _tprintf(TEXT(" symbol path. Use of -V implies -S when module collection is\n"));
  1072. _tprintf(TEXT(" initiated. There are different levels of symbol\n"));
  1073. _tprintf(TEXT(" verification:\n"));
  1074. _tprintf(TEXT("\n"));
  1075. _tprintf(TEXT(" -V or -V1 : (Default) This treats symbol files that match\n"));
  1076. _tprintf(TEXT(" the module's time/date stamp, but have an wrong\n"));
  1077. _tprintf(TEXT(" checksum as valid symbols. This is the default\n"));
  1078. _tprintf(TEXT(" behavior and these symbols are typically valid.\n"));
  1079. _tprintf(TEXT("\n"));
  1080. _tprintf(TEXT(" -V2 : Only if both checksum and time/date stamp match\n"));
  1081. _tprintf(TEXT(" is the symbol considered valid.\n"));
  1082. _tprintf(TEXT("\n"));
  1083. _tprintf(TEXT("-Y[<blank>|1|2] <Symbol Path> : Verify Symbols Using This Symbol Path\n"));
  1084. _tprintf(TEXT("\n"));
  1085. _tprintf(TEXT(" This is a semi-colon separated search path for looking for\n"));
  1086. _tprintf(TEXT(" symbols. This path is searched with the -V option. -Y now\n"));
  1087. _tprintf(TEXT(" supports the use of SYMSRV DLLs for symbol searching. An\n"));
  1088. _tprintf(TEXT(" example usage would be a symbol path that resembles:\n"));
  1089. _tprintf(TEXT(" -Y SYMSRV*SYMSRV.DLL*\\\\SERVER\\SYMBOLS\n"));
  1090. _tprintf(TEXT("\n"));
  1091. _tprintf(TEXT(" The default value is %%systemroot%%\\symbols\n"));
  1092. _tprintf(TEXT("\n"));
  1093. _tprintf(TEXT(" -Y or -Y1 : (Default) This searches for symbols in the\n"));
  1094. _tprintf(TEXT(" symbol paths using the behavior typical of the\n"));
  1095. _tprintf(TEXT(" debuggers.\n"));
  1096. _tprintf(TEXT("\n"));
  1097. _tprintf(TEXT(" -Y2 : This searches for symbols in the symbol paths\n"));
  1098. _tprintf(TEXT(" provided using a recursive search algorithm.\n"));
  1099. _tprintf(TEXT(" This option is most useful when used with -B to\n"));
  1100. _tprintf(TEXT(" build a symbol tree.\n"));
  1101. _tprintf(TEXT("\n"));
  1102. /*
  1103. // We're going to hide this option in the help text since this may go out to the public...
  1104. _tprintf(TEXT("-SQL <servername>: Collect symbol file location from the provided SQL\n"));
  1105. _tprintf(TEXT(" servername. A hardcoded username/password is currently\n"));
  1106. _tprintf(TEXT(" being used. A SQL server you can point to is \"BPSYMBOLS\"\n"));
  1107. _tprintf(TEXT(" though this can change at anytime.\n"));
  1108. _tprintf(TEXT("\n"));
  1109. */
  1110. _tprintf(TEXT("***** OUTPUT OPTIONS *****\n"));
  1111. _tprintf(TEXT("\n"));
  1112. _tprintf(TEXT(" -B <Symbol Dir> : Build a Symbol Tree of Matching Symbols\n"));
  1113. _tprintf(TEXT("\n"));
  1114. _tprintf(TEXT(" This option will create a new symbol tree for ALL matching\n"));
  1115. _tprintf(TEXT(" symbols that are found through the verification process\n"));
  1116. _tprintf(TEXT(" (-v option). This option is particularly useful when used\n"));
  1117. _tprintf(TEXT(" with the -Y option when many symbol paths are specified\n"));
  1118. _tprintf(TEXT(" and you want to build a single tree for a debug.\n"));
  1119. /*
  1120. _tprintf(TEXT(" with the -SQL option, or -Y option when many symbol paths\n"));
  1121. _tprintf(TEXT(" are specified and you want to build a single tree for a\n"));
  1122. _tprintf(TEXT(" debug.\n"));
  1123. */
  1124. _tprintf(TEXT("\n"));
  1125. _tprintf(TEXT(" -Q[<blank>|2] : Quiet modes (no screen output, or minimal screen output)\n"));
  1126. _tprintf(TEXT("\n"));
  1127. _tprintf(TEXT(" The default behavior is to print out the data to the\n"));
  1128. _tprintf(TEXT(" console window (stdout). If the process terminates with an\n"));
  1129. _tprintf(TEXT(" error, it will print out these (overriding -Q).\n"));
  1130. _tprintf(TEXT("\n"));
  1131. _tprintf(TEXT(" -Q2 : This option prints out a module ONLY if a symbol\n"));
  1132. _tprintf(TEXT(" problem exists. (Not completely quiet mode!)\n"));
  1133. /*
  1134. // We're going to hide this option in the help text since this may go out to the public...
  1135. _tprintf(TEXT("\n"));
  1136. _tprintf(TEXT(" -E : This modifier abreviates the output from this program\n"));
  1137. _tprintf(TEXT(" for the -O option. It does the following:\n"));
  1138. _tprintf(TEXT(" * Removes the Checksym header\n"));
  1139. _tprintf(TEXT(" * Removes the first three columns of data\n"));
  1140. _tprintf(TEXT(" * Only prints out a module if there is a symbol verification problem\n"));
  1141. */
  1142. _tprintf(TEXT("\n"));
  1143. _tprintf(TEXT("-O[<blank>|1|2] <File Path> : Output Collected Module Information To a CSV File\n"));
  1144. _tprintf(TEXT("\n"));
  1145. _tprintf(TEXT(" For this file to to be used as input (-I) to verify good\n"));
  1146. _tprintf(TEXT(" symbols for this system, the -S option should also be used.\n"));
  1147. _tprintf(TEXT("\n"));
  1148. _tprintf(TEXT(" -O or -O1 : (Default) This output mode requires that the\n"));
  1149. _tprintf(TEXT(" file does not exist.\n"));
  1150. _tprintf(TEXT("\n"));
  1151. _tprintf(TEXT(" -O2 : Specifying a -O2 will allow the output file\n"));
  1152. _tprintf(TEXT(" to be OVERWRITTEN if it exists.\n"));
  1153. _tprintf(TEXT("\n"));
  1154. _tprintf(TEXT(" -T : Task List Output\n"));
  1155. _tprintf(TEXT("\n"));
  1156. _tprintf(TEXT(" Prints out a task list on the local machine (similar to the\n"));
  1157. _tprintf(TEXT(" TLIST utility). This option implies the use of -P (querying\n"));
  1158. _tprintf(TEXT(" the local system for active processes. You can provide the\n"));
  1159. _tprintf(TEXT(" -P command explicitly (if you want to provide an argument,\n"));
  1160. _tprintf(TEXT(" for instance). If -P is not specified explicitly, then it\n"));
  1161. _tprintf(TEXT(" defaults to -P *. Also, -T overrides -Q since TLIST\n"));
  1162. _tprintf(TEXT(" behavior is to print to the console window.\n"));
  1163. _tprintf(TEXT("\n"));
  1164. _tprintf(TEXT("***** TYPICAL USAGE EXAMPLES *****\n"));
  1165. _tprintf(TEXT("\n"));
  1166. _tprintf(TEXT("You want to verify the symbols for files in a directory (%%SYSTEMROOT%%\\SYSTEM32)\n"));
  1167. _tprintf(TEXT("in the default symbol directory (%%SYSTEMROOT%%\\SYMBOLS)\n"));
  1168. _tprintf(TEXT("\n"));
  1169. _tprintf(TEXT(" CHECKSYM -F %%SYSTEMROOT%%\\SYSTEM32 -V\n"));
  1170. _tprintf(TEXT("\n"));
  1171. _tprintf(TEXT("You want to do the same search, but for only executables...\n"));
  1172. _tprintf(TEXT("\n"));
  1173. _tprintf(TEXT(" CHECKSYM -F %%SYSTEMROOT%%\\SYSTEM32\\*.EXE -V\n"));
  1174. _tprintf(TEXT("\n"));
  1175. _tprintf(TEXT("You want to search a directory using multiple symbol paths...\n"));
  1176. _tprintf(TEXT("\n"));
  1177. _tprintf(TEXT(" CHECKSYM -F %%SYSTEMROOT%%\\SYSTEM32\\ -V -Y V:\\nt40sp4;V:\\nt40rtm\n"));
  1178. _tprintf(TEXT("\n"));
  1179. _tprintf(TEXT("You want to know what modules are loaded for a process (and the path to each)\n"));
  1180. _tprintf(TEXT("Start NOTEPAD.EXE, and then type:\n"));
  1181. _tprintf(TEXT("\n"));
  1182. _tprintf(TEXT(" CHECKSYM -P NOTEPAD.EXE\n"));
  1183. _tprintf(TEXT("\n"));
  1184. _tprintf(TEXT("You want to know if you have good symbols for a process (notepad.exe).\n"));
  1185. _tprintf(TEXT("\n"));
  1186. _tprintf(TEXT(" CHECKSYM -P NOTEPAD.EXE -V\n"));
  1187. _tprintf(TEXT("\n"));
  1188. _tprintf(TEXT("You want to know the file version for every module loaded by a process.\n"));
  1189. _tprintf(TEXT("\n"));
  1190. _tprintf(TEXT(" CHECKSYM -P NOTEPAD.EXE -R\n"));
  1191. _tprintf(TEXT("\n"));
  1192. _tprintf(TEXT("You want to know if you have good symbols for ALL processes on your machine.\n"));
  1193. _tprintf(TEXT("\n"));
  1194. _tprintf(TEXT(" CHECKSYM -P * -V\n"));
  1195. _tprintf(TEXT("\n"));
  1196. _tprintf(TEXT("***** ADVANCED USAGE EXAMPLES *****\n"));
  1197. _tprintf(TEXT("\n"));
  1198. _tprintf(TEXT("You are going to prepare to debug a remote system, and you want to ensure\n"));
  1199. _tprintf(TEXT("that you have good symbols locally for debugging the remote system. You want\n"));
  1200. _tprintf(TEXT("to verify this prior to initiating the debug session.\n"));
  1201. _tprintf(TEXT("\n"));
  1202. _tprintf(TEXT("Use checksym twice, once on the remote system to gather information and create\n"));
  1203. _tprintf(TEXT("an output file, and then once on your system using the output file created\n"));
  1204. _tprintf(TEXT("as an input argument.\n"));
  1205. _tprintf(TEXT("\n"));
  1206. _tprintf(TEXT("For example, run this on the remote system\n"));
  1207. _tprintf(TEXT("\n"));
  1208. _tprintf(TEXT(" CHECKSYM -P * -S -R -O C:\\TEMP\\PROCESSES.CSV\n"));
  1209. _tprintf(TEXT("\n"));
  1210. _tprintf(TEXT("The C:\\TEMP\\PROCESSES.CSV file will contain a wealth of information about\n"));
  1211. _tprintf(TEXT("the processes that were running, and the modules loaded by every process.\n"));
  1212. _tprintf(TEXT("\n"));
  1213. _tprintf(TEXT("Now, get the output file from the remote system, and copy it locally. Then\n\n"));
  1214. _tprintf(TEXT("run CHECKSYM again, using the file as an input argument...\n"));
  1215. _tprintf(TEXT("\n"));
  1216. _tprintf(TEXT(" CHECKSYM -I C:\\TEMP\\PROCESSES.CSV -V\n"));
  1217. _tprintf(TEXT("\n"));
  1218. _tprintf(TEXT("Another useful option is -B (build a symbol tree). It allows you to update\n"));
  1219. _tprintf(TEXT("or create a symbol tree that contains matching symbols. If you have to use\n"));
  1220. _tprintf(TEXT("many symbol paths in order to have correct symbols available to a debugger,\n"));
  1221. _tprintf(TEXT("can use the -B option to build a single symbol tree to simplify debugging.\n"));
  1222. _tprintf(TEXT("\n"));
  1223. _tprintf(TEXT(" CHECKSYM -P * -B C:\\MySymbols -V -Y V:\\Nt4;V:\\Nt4Sp6a;V:\\NtHotfixes\n"));
  1224. _tprintf(TEXT("\n"));
  1225. _tprintf(TEXT("***** DEFAULT BEHAVIOR *****\n"));
  1226. _tprintf(TEXT("\n"));
  1227. _tprintf(TEXT("The default behavior of CHECKSYM when no arguments are provided is:\n"));
  1228. _tprintf(TEXT("\n"));
  1229. _tprintf(TEXT("CHECKSYM -P * -R -V -Y %%SYSTEMROOT%%\\SYMBOLS\n"));
  1230. }
  1231. void CProgramOptions::DisplaySimpleHelp()
  1232. {
  1233. CUtilityFunctions::OutputLineOfStars();
  1234. #ifdef _UNICODE
  1235. _tprintf(TEXT("CHECKSYM V%S - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  1236. #else
  1237. _tprintf(TEXT("CHECKSYM V%s - Symbol Verification Program \n"), VERSION_FILEVERSIONSTRING);
  1238. #endif
  1239. CUtilityFunctions::OutputLineOfStars();
  1240. _tprintf(TEXT("\n"));
  1241. #ifdef _UNICODE
  1242. _tprintf(TEXT("This version supports Windows NT 4.0 and Windows 2000\n"));
  1243. #else
  1244. _tprintf(TEXT("This version supports Windows 98, Windows NT 4.0 and Windows 2000\n"));
  1245. #endif
  1246. _tprintf(TEXT("\n"));
  1247. _tprintf(TEXT("Obtaining online help:\n"));
  1248. _tprintf(TEXT("\n"));
  1249. _tprintf(TEXT("CHECKSYM -? : Simple help usage (this screen)\n"));
  1250. _tprintf(TEXT("CHECKSYM -??? : Complete help usage\n"));
  1251. _tprintf(TEXT("\n"));
  1252. _tprintf(TEXT("Usage:\n"));
  1253. _tprintf(TEXT("\n"));
  1254. _tprintf(TEXT("CHECKSYM [COLLECTION OPTIONS] [INFORMATION CHECKING OPTIONS] [OUTPUT OPTIONS]\n"));
  1255. _tprintf(TEXT("\n"));
  1256. _tprintf(TEXT("***** COLLECTION OPTIONS *****\n"));
  1257. _tprintf(TEXT("\n"));
  1258. _tprintf(TEXT("At least one collection option must be specified. The following options are\n"));
  1259. _tprintf(TEXT("currently supported.\n"));
  1260. _tprintf(TEXT("\n"));
  1261. _tprintf(TEXT(" -P <Argument> : Collect Information From Running Processes\n"));
  1262. _tprintf(TEXT(" -D : Collect Information from Running Device Drivers\n"));
  1263. _tprintf(TEXT("-F <File/Dir Path>:Collect Information From File(s) Specified by the User\n"));
  1264. _tprintf(TEXT(" -I <File Path> : Collect Information from a Saved Checksym Generated CSV File\n"));
  1265. _tprintf(TEXT(" -Z <File Path> : Collect Information from a DMP File\n"));
  1266. _tprintf(TEXT(" -MATCH <Text> : Collect Modules that match text only\n"));
  1267. _tprintf(TEXT("\n"));
  1268. _tprintf(TEXT("***** INFORMATION CHECKING OPTIONS *****\n"));
  1269. _tprintf(TEXT("\n"));
  1270. _tprintf(TEXT(" -S : Collect Symbol Information From Modules\n"));
  1271. _tprintf(TEXT(" -R : Collect Version and File-System Information From Modules\n"));
  1272. _tprintf(TEXT(" -V[<blank>|1|2] : Verify Symbols for Modules\n"));
  1273. _tprintf(TEXT(" -Y[<blank>|1|2] <Symbol Path> : Verify Symbols Using This Symbol Path\n"));
  1274. _tprintf(TEXT("\n"));
  1275. /*
  1276. // We're going to hide this option in the help text since this may go out to the public...
  1277. _tprintf(TEXT("-SQL <servername>: Collect symbol file location from the provided SQL\n"));
  1278. _tprintf(TEXT("\n"));
  1279. */
  1280. _tprintf(TEXT("***** OUTPUT OPTIONS *****\n"));
  1281. _tprintf(TEXT("\n"));
  1282. _tprintf(TEXT(" -B <Symbol Dir> : Build a Symbol Tree of Matching Symbols\n"));
  1283. _tprintf(TEXT(" -Q[<blank>|2] : Quiet modes (no screen output, or minimal screen output)\n"));
  1284. /*
  1285. // We're going to hide this option in the help text since this may go out to the public...
  1286. _tprintf(TEXT("\n"));
  1287. _tprintf(TEXT(" -E : This modifier abreviates the output from this program\n"));
  1288. */
  1289. _tprintf(TEXT("-O[<blank>|1|2] <File Path> : Output Collected Module Information To a CSV File\n"));
  1290. _tprintf(TEXT(" -T : Task List Output\n"));
  1291. _tprintf(TEXT("\n"));
  1292. _tprintf(TEXT("***** DEFAULT BEHAVIOR *****\n"));
  1293. _tprintf(TEXT("\n"));
  1294. _tprintf(TEXT("The default behavior of CHECKSYM when no arguments are provided is:\n"));
  1295. _tprintf(TEXT("\n"));
  1296. _tprintf(TEXT("CHECKSYM -P * -R -V -Y %%SYSTEMROOT%%\\SYMBOLS\n"));
  1297. _tprintf(TEXT("\n"));
  1298. _tprintf(TEXT("For more usage information run CHECKSYM -???\n"));
  1299. }