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.

894 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 2000
  6. //
  7. // File: main.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef NO_STRICT
  11. #ifndef STRICT
  12. #define STRICT 1
  13. #endif
  14. #endif /* NO_STRICT */
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <tchar.h>
  18. #include "Globals.h"
  19. #include "DelayLoad.h"
  20. #include "ProgramOptions.h"
  21. #include "Processes.h"
  22. #include "ProcessInfo.h"
  23. #include "SymbolVerification.h"
  24. #include "ModuleInfoCache.h"
  25. #include "FileData.h"
  26. #include "Modules.h"
  27. #include "UtilityFunctions.h"
  28. #include "DmpFile.h"
  29. //#if ( _MSC_VER < 1200 )
  30. //extern "C"
  31. //{
  32. //#endif
  33. #ifdef CHECKSYM_TEST
  34. #include "CheckSym_test.h"
  35. #endif
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. //#ifdef _UNICODE
  40. // Adding support for Unicode on Ansi systems (Win9x)
  41. //#include "CheckSym_UAPI.h"
  42. //#endif
  43. #ifndef CHECKSYM_TEST
  44. // Normal startup!
  45. int _cdecl _tmain(int argc, TCHAR *argv[])
  46. {
  47. int iReturnCode = EXIT_FAILURE;
  48. #else
  49. // Startup for testing... no command-line is interpreted...
  50. int _tmain()
  51. {
  52. // We'll populate this below for every test run...
  53. int argc = 0;
  54. TCHAR ** argv = NULL;
  55. LPTSTR tszPointerToCurrentArgument = NULL;
  56. int iArgvIndex;
  57. LPTSTR tszCopyOfTestString = NULL;
  58. bool fFoundNextArgument, fQuoteMode;
  59. int iReturnCode = EXIT_FAILURE;
  60. int iTotalNumberOfTests = sizeof(g_TestArguments) / sizeof(g_TestArguments[0]);
  61. _tprintf(TEXT("\n\n"));
  62. CUtilityFunctions::OutputLineOfStars();
  63. _tprintf(TEXT("ABOUT TO BEGIN %d TESTS!\n"), iTotalNumberOfTests);
  64. CUtilityFunctions::OutputLineOfStars();
  65. for (int iTestNumber = 0; iTestNumber < iTotalNumberOfTests; iTestNumber++)
  66. {
  67. _tprintf(TEXT("\n\n\n"));
  68. CUtilityFunctions::OutputLineOfStars();
  69. CUtilityFunctions::OutputLineOfStars();
  70. _tprintf(TEXT("TESTING [%3d]: %s\n"), iTestNumber, g_TestArguments[iTestNumber].tszTestDescription );
  71. CUtilityFunctions::OutputLineOfStars();
  72. CUtilityFunctions::OutputLineOfStars();
  73. _tprintf(TEXT("\n\n"));
  74. #endif
  75. // Initialize our object pointers...
  76. CSymbolVerification * lpSymbolVerification = NULL;
  77. // Processes/Modules data collected on this machine
  78. CProcesses * lpLocalSystemProcesses = NULL; // -P Option
  79. CModules * lpLocalFileSystemModules = NULL; // -F Option
  80. CModules * lpKernelModeDrivers = NULL; // -D Option
  81. // CSV File Support
  82. CFileData * lpCSVInputFile = NULL; // -I Option
  83. CFileData * lpCSVOutputFile = NULL; // -O Option
  84. CProcesses * lpCSVProcesses = NULL; // [PROCESSES]
  85. CProcessInfo * lpCSVProcess = NULL; // [PROCESS]
  86. CModules * lpCSVModulesFromFileSystem = NULL; // [FILESYSTEM MODULES]
  87. CModules * lpCSVKernelModeDrivers = NULL; // [KERNEL-MODE DRIVERS]
  88. //
  89. // Module Caches (these implement separate name spaces for the modules collected)
  90. //
  91. // It is important that we separate the modules in these caches because a module
  92. // from a CSV file should not be assumed to be the same module if you also happen
  93. // to collect it from a DMP file... or your local system...
  94. CModuleInfoCache * lpLocalSystemModuleInfoCache = NULL; // Contains Local System modules
  95. CModuleInfoCache * lpCSVModuleInfoCache = NULL; // Contains CSV modules
  96. CModuleInfoCache * lpDmpModuleInfoCache = NULL; // Contains user.dmp & kernel.dmp modules
  97. long lTotalNumberOfModulesVerified = 0;
  98. long lTotalNumberOfVerifyErrors = 0;
  99. // Support for Dmp Files...
  100. CDmpFile * lpDmpFile = NULL; // This object allows a Dump file (user/kernel) to be manipulated
  101. CProcessInfo * lpDmpFileUserModeProcess = NULL; // User.dmp files use this object to contain modules
  102. CModules * lpDmpFileKernelModeDrivers = NULL; // Memory.dmp files use this object to contain modules
  103. // Allocate local values
  104. bool fQuietMode = false;
  105. //#ifdef _UNICODE
  106. // First, we need to enable the Unicode APIs (if this is a Win9x machine)...
  107. // if (!InitUnicodeAPI())
  108. // {
  109. // goto cleanup;
  110. // }
  111. //#endif
  112. // Let's populate our Globals!
  113. g_lpDelayLoad = new CDelayLoad();
  114. g_lpProgramOptions = new CProgramOptions();
  115. if (!g_lpDelayLoad && !g_lpProgramOptions)
  116. goto cleanup;
  117. // Initialize Options to their defaults...
  118. if (!g_lpProgramOptions->Initialize())
  119. {
  120. _tprintf(TEXT("Unable to initialize Program Options!\n"));
  121. goto cleanup;
  122. }
  123. #ifdef CHECKSYM_TEST
  124. // Okay, we need to create the appearance of a true argc, and argv (argc is easy)...
  125. argc = g_TestArguments[iTestNumber].nArguments;
  126. argv = new LPTSTR[argc];
  127. if (!argv)
  128. goto cleanup;
  129. // Okay, we need to populate the argv with pointers...
  130. tszCopyOfTestString = CUtilityFunctions::CopyString(g_TestArguments[iTestNumber].tszCommandLineArguments);
  131. if (!tszCopyOfTestString)
  132. goto cleanup;
  133. tszPointerToCurrentArgument = tszCopyOfTestString;
  134. for (iArgvIndex = 0; iArgvIndex < argc; iArgvIndex++)
  135. {
  136. // Hey... if the first character is a quote skip it and enter quote mode...
  137. if (*tszPointerToCurrentArgument == '\"')
  138. {
  139. // Advance to next character..
  140. tszPointerToCurrentArgument = _tcsinc(tszPointerToCurrentArgument);
  141. fQuoteMode = true;
  142. } else
  143. {
  144. fQuoteMode = false;
  145. }
  146. // We should be pointing to our next argument...
  147. argv[iArgvIndex] = tszPointerToCurrentArgument;
  148. fFoundNextArgument = false;
  149. // Keep hunting for the next argument and leave our pointer pointing to it...
  150. while (!fFoundNextArgument)
  151. {
  152. // Now, we need to find the next argument... look for either a quote or a space...
  153. tszPointerToCurrentArgument = _tcspbrk( tszPointerToCurrentArgument, TEXT(" \"") );
  154. // If this returns NULL, then we're at the end...
  155. if (!tszPointerToCurrentArgument)
  156. {
  157. break;
  158. }
  159. // If we found a space... then we have our next argument if we're not in quote mode..
  160. if (*tszPointerToCurrentArgument == ' ')
  161. {
  162. if (fQuoteMode == true)
  163. {
  164. // We're in quote mode...
  165. // Advance to next argument..
  166. tszPointerToCurrentArgument = _tcsinc(tszPointerToCurrentArgument);
  167. continue;
  168. } else
  169. {
  170. // Hey, we found our argument!
  171. fFoundNextArgument = true;
  172. // Null terminate our last argument
  173. *tszPointerToCurrentArgument = '\0';
  174. // Advance to next argument..
  175. tszPointerToCurrentArgument = _tcsinc(tszPointerToCurrentArgument);
  176. continue;
  177. }
  178. } else if (*tszPointerToCurrentArgument == '\"')
  179. {
  180. // If the next character happens to be a space... then this is the final
  181. // quote in a quoted argument... go ahead and nuke it and skip to next
  182. // argument...
  183. if (fQuoteMode && *_tcsinc(tszPointerToCurrentArgument) == ' ')
  184. {
  185. *tszPointerToCurrentArgument = NULL;
  186. }
  187. // Reverse the value of our mode...
  188. fQuoteMode = !fQuoteMode;
  189. // Advance to next argument..
  190. tszPointerToCurrentArgument = _tcsinc(tszPointerToCurrentArgument);
  191. }
  192. }
  193. }
  194. #endif
  195. // Take care of the commandline...
  196. if (!g_lpProgramOptions->ProcessCommandLineArguments(argc, argv))
  197. {
  198. // An error occurred, simply comment about how to get more assistance
  199. _tprintf(TEXT("\n"));
  200. _tprintf(TEXT("For simple help, type: CHECKSYM -?\n"));
  201. _tprintf(TEXT("For extended help, type: CHECKSYM -???\n"));
  202. goto cleanup;
  203. }
  204. // Do we need to display help?
  205. if ( g_lpProgramOptions->GetMode(CProgramOptions::HelpMode) )
  206. {
  207. g_lpProgramOptions->DisplayHelp();
  208. goto cleanup;
  209. }
  210. // Do we need to display simple help?
  211. if ( g_lpProgramOptions->GetMode(CProgramOptions::SimpleHelpMode) )
  212. {
  213. g_lpProgramOptions->DisplaySimpleHelp();
  214. goto cleanup;
  215. }
  216. #ifdef _UNICODE
  217. // It's unsupported running the UNICODE version on a Windows Platform
  218. if (g_lpProgramOptions->IsRunningWindows())
  219. {
  220. _tprintf(TEXT("The UNICODE version of CHECKSYM does not work on a Windows platform!\n"));
  221. _tprintf(TEXT("You require the ANSI version.\n"));
  222. goto cleanup;
  223. }
  224. #endif
  225. // Let's suppress nasty critical errors (like... there's no
  226. // disk in the cd-rom drive, etc...)
  227. SetErrorMode(SEM_FAILCRITICALERRORS);
  228. // Let's save this for ease of access...
  229. fQuietMode = g_lpProgramOptions->GetMode(CProgramOptions::QuietMode);
  230. // Dump the program arguments (so it's obvious what we're going to do)
  231. g_lpProgramOptions->DisplayProgramArguments();
  232. // DBGHELP FUNCTIONS?
  233. // Do we need to instantiate a CDBGHelpFunctions Object? We do if we need to call...
  234. // - MakeSureDirectoryPathExists() Used for the -B (build symbol tree) option
  235. if ( g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode) )
  236. {
  237. // Now, we need to build the symbol tree root...
  238. if ( !g_lpDelayLoad->MakeSureDirectoryPathExists(g_lpProgramOptions->GetSymbolTreeToBuild()) )
  239. {
  240. _tprintf(TEXT("ERROR: Unable to create symbol tree root [%s]\n"), g_lpProgramOptions->GetSymbolTreeToBuild() );
  241. CUtilityFunctions::PrintMessageString(GetLastError());
  242. goto cleanup;
  243. }
  244. }
  245. // VERIFICATION OPTION: -V (verification)?
  246. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  247. {
  248. // Allocate a structure for our symbol verification object.
  249. lpSymbolVerification = new CSymbolVerification();
  250. if (!lpSymbolVerification)
  251. {
  252. _tprintf(TEXT("Unable to allocate memory for a verification symbol object!\n"));
  253. goto cleanup;
  254. }
  255. // Initialize Symbol Verification (if necessary)
  256. if (!lpSymbolVerification->Initialize())
  257. {
  258. _tprintf(TEXT("Unable to initialize Symbol Verification object!\n"));
  259. goto cleanup;
  260. }
  261. }
  262. //
  263. // Allocate a structure for our ModuleInfoCache if we're getting anything from the local system
  264. //
  265. if ( g_lpProgramOptions->GetMode(CProgramOptions::InputProcessesFromLiveSystemMode) ||
  266. g_lpProgramOptions->GetMode(CProgramOptions::InputDriversFromLiveSystemMode) ||
  267. g_lpProgramOptions->GetMode(CProgramOptions::InputModulesDataFromFileSystemMode) )
  268. {
  269. lpLocalSystemModuleInfoCache= new CModuleInfoCache();
  270. // Check for out of memory condition...
  271. if ( lpLocalSystemModuleInfoCache == NULL )
  272. {
  273. _tprintf(TEXT("Unable to allocate memory for the ModuleInfoCache object!\n"));
  274. goto cleanup;
  275. }
  276. // Initialize Options to their defaults...
  277. if (!lpLocalSystemModuleInfoCache->Initialize(lpSymbolVerification))
  278. {
  279. _tprintf(TEXT("Unable to initialize ModuleInfoCache!\n"));
  280. goto cleanup;
  281. }
  282. }
  283. //
  284. // Allocate a structure for our CSVModuleInfoCache (if needed)... we need a separate
  285. // ModuleInfoCache space because the location of files on a remote system
  286. // files and we don't want to clash...
  287. //
  288. if (g_lpProgramOptions->GetMode(CProgramOptions::InputCSVFileMode))
  289. {
  290. // We need a Module Info Cache for these CSV data (it all was collected from
  291. // the same system (supposedly)
  292. lpCSVModuleInfoCache= new CModuleInfoCache();
  293. // Check for out of memory condition...
  294. if ( lpCSVModuleInfoCache == NULL )
  295. {
  296. _tprintf(TEXT("Unable to allocate memory for the CSVModuleInfoCache object!\n"));
  297. goto cleanup;
  298. }
  299. // Initialize Options to their defaults...
  300. if (!lpCSVModuleInfoCache->Initialize(lpSymbolVerification))
  301. {
  302. _tprintf(TEXT("Unable to initialize CSVModuleInfoCache!\n"));
  303. goto cleanup;
  304. }
  305. }
  306. //
  307. // Since we're going to read in a file... try and open it now...
  308. // This has the advantage of detecting problems accessing the file
  309. // when we've spent tons of time collecting data...
  310. //
  311. if (g_lpProgramOptions->GetMode(CProgramOptions::InputCSVFileMode))
  312. {
  313. // Create the file object
  314. lpCSVInputFile = new CFileData();
  315. if (!lpCSVInputFile)
  316. {
  317. _tprintf(TEXT("Unable to allocate memory for an input file object!\n"));
  318. goto cleanup;
  319. }
  320. // Set the input file path
  321. if (!lpCSVInputFile->SetFilePath(g_lpProgramOptions->GetInputFilePath()))
  322. {
  323. _tprintf(TEXT("Unable set input file path in the file data object! Out of memory?\n"));
  324. goto cleanup;
  325. }
  326. // If we are going to produce an input file... try to do that now...
  327. if (!lpCSVInputFile->OpenFile(OPEN_EXISTING, true)) // Must exist, read only mode...
  328. {
  329. _tprintf(TEXT("Unable to open the input file %s.\n"), lpCSVInputFile->GetFilePath());
  330. lpCSVInputFile->PrintLastError();
  331. goto cleanup;
  332. }
  333. // Reading is so much easier in memory mapped mode...
  334. if (!lpCSVInputFile->CreateFileMapping())
  335. {
  336. _tprintf(TEXT("Unable to CreateFileMapping of the input file %s.\n"), lpCSVInputFile->GetFilePath());
  337. lpCSVInputFile->PrintLastError();
  338. goto cleanup;
  339. }
  340. // Go ahead and read in the header of the file (validate it).
  341. // Reading is so much easier in memory mapped mode...
  342. if (!lpCSVInputFile->ReadFileHeader())
  343. {
  344. _tprintf(TEXT("Invalid header found on input file %s.\n"), lpCSVInputFile->GetFilePath());
  345. lpCSVInputFile->PrintLastError();
  346. goto cleanup;
  347. }
  348. }
  349. // If we specified an output file, this is where we go ahead and allocate memory
  350. // for the object
  351. if (g_lpProgramOptions->GetMode(CProgramOptions::OutputCSVFileMode))
  352. {
  353. // Allocate a structure for our output fileData Object...
  354. lpCSVOutputFile = new CFileData();
  355. if (!lpCSVOutputFile )
  356. {
  357. _tprintf(TEXT("Unable to allocate memory for an output file object!\n"));
  358. goto cleanup;
  359. }
  360. }
  361. // INPUT METHOD: -Z Option? (Dump files?)
  362. if (g_lpProgramOptions->GetMode(CProgramOptions::InputDmpFileMode))
  363. {
  364. if (!fQuietMode)
  365. _tprintf(TEXT("\nReading Data from DMP File...\n"));
  366. // Create a Module Info Cache namespace to contain any modules found...
  367. lpDmpModuleInfoCache = new CModuleInfoCache();
  368. // Check for out of memory condition...
  369. if ( lpDmpModuleInfoCache == NULL )
  370. {
  371. _tprintf(TEXT("Unable to allocate memory for the DmpModuleInfoCache object!\n"));
  372. goto cleanup;
  373. }
  374. // Initialize Options to their defaults...
  375. if (!lpDmpModuleInfoCache->Initialize(lpSymbolVerification))
  376. {
  377. _tprintf(TEXT("Unable to initialize DmpModuleInfoCache!\n"));
  378. goto cleanup;
  379. }
  380. // Create the DMP File object
  381. lpDmpFile = new CDmpFile();
  382. if (!lpDmpFile)
  383. {
  384. _tprintf(TEXT("Unable to allocate memory for a DMP file object!\n"));
  385. goto cleanup;
  386. }
  387. // Initialize the DMP File
  388. if (!lpDmpFile->Initialize(lpCSVOutputFile))
  389. {
  390. _tprintf(TEXT("ERROR: Unable to initialize DMP file!\n"));
  391. goto cleanup;
  392. }
  393. // Header is good... so let's go ahead and get some data...
  394. if (!lpDmpFile->CollectData(&lpDmpFileUserModeProcess, &lpDmpFileKernelModeDrivers, lpDmpModuleInfoCache) )
  395. {
  396. _tprintf(TEXT("ERROR: Unable to collect data from the DMP file!\n"));
  397. }
  398. }
  399. // INPUT METHOD: -i Option?
  400. if (g_lpProgramOptions->GetMode(CProgramOptions::InputCSVFileMode))
  401. {
  402. if (!fQuietMode)
  403. _tprintf(TEXT("\nReading Data from Input File...\n"));
  404. // Header is good... so let's go ahead and dispatch
  405. if (!lpCSVInputFile->DispatchCollectionObject(&lpCSVProcesses, &lpCSVProcess, &lpCSVModulesFromFileSystem, &lpCSVKernelModeDrivers, lpCSVModuleInfoCache, lpCSVOutputFile))
  406. {
  407. _tprintf(TEXT("Failure reading data collection from input file %s.\n"), lpCSVInputFile->GetFilePath());
  408. lpCSVInputFile->PrintLastError();
  409. goto cleanup;
  410. }
  411. }
  412. // INPUT METHOD: -p Option?
  413. if ( g_lpProgramOptions->GetMode(CProgramOptions::InputProcessesFromLiveSystemMode) )
  414. {
  415. // Allocate a structure for our Processes Object.
  416. lpLocalSystemProcesses = new CProcesses();
  417. if (!lpLocalSystemProcesses)
  418. {
  419. _tprintf(TEXT("Unable to allocate memory for the processes object!\n"));
  420. goto cleanup;
  421. }
  422. // The Processes Object will init differently depending on what
  423. // Command-Line arguments have been provided...
  424. if (!lpLocalSystemProcesses->Initialize(lpLocalSystemModuleInfoCache, NULL, lpCSVOutputFile))
  425. {
  426. _tprintf(TEXT("Unable to initialize Processes Object!\n"));
  427. goto cleanup;
  428. }
  429. // Mention the delay...
  430. if (!( fQuietMode ||
  431. g_lpProgramOptions->GetMode(CProgramOptions::PrintTaskListMode)
  432. ) )
  433. _tprintf(TEXT("\nCollecting Process Data.... (this may take a few minutes)\n"));
  434. // Get the goods from the local system!
  435. lpLocalSystemProcesses->GetProcessesData();
  436. }
  437. // INPUT METHOD: -f OPTION?
  438. if ( g_lpProgramOptions->GetMode(CProgramOptions::InputModulesDataFromFileSystemMode) )
  439. {
  440. // Allocate a structure for our CModules collection (a generic collection of
  441. // files from the filesystem)
  442. // Allocate a structure for our Processes Object.
  443. lpLocalFileSystemModules = new CModules();
  444. if (!lpLocalFileSystemModules)
  445. {
  446. _tprintf(TEXT("Unable to allocate memory for the CModules object!\n"));
  447. goto cleanup;
  448. }
  449. if (!lpLocalFileSystemModules->Initialize(lpLocalSystemModuleInfoCache, NULL, lpCSVOutputFile, NULL))
  450. {
  451. _tprintf(TEXT("Unable to initialize FileSystemModules Object!\n"));
  452. goto cleanup;
  453. }
  454. if (!fQuietMode)
  455. _tprintf(TEXT("\nCollecting Modules Data from file path.... (this may take a few minutes)\n"));
  456. lpLocalFileSystemModules->GetModulesData(CProgramOptions::InputModulesDataFromFileSystemMode);
  457. }
  458. // INPUT METHOD: -d OPTION?
  459. if ( g_lpProgramOptions->GetMode(CProgramOptions::InputDriversFromLiveSystemMode) )
  460. {
  461. // Allocate a structure for our CModules collection (a generic collection of
  462. // files from the filesystem)
  463. // Allocate a structure for our Processes Object.
  464. lpKernelModeDrivers = new CModules();
  465. if (!lpKernelModeDrivers)
  466. {
  467. _tprintf(TEXT("Unable to allocate memory for the CModules object!\n"));
  468. goto cleanup;
  469. }
  470. if (!lpKernelModeDrivers->Initialize(lpLocalSystemModuleInfoCache, NULL, lpCSVOutputFile, NULL))
  471. {
  472. _tprintf(TEXT("Unable to initialize Modules Object!\n"));
  473. goto cleanup;
  474. }
  475. if (!fQuietMode)
  476. _tprintf(TEXT("\nCollecting Device Driver Data.... (this may take a few minutes)\n"));
  477. lpKernelModeDrivers->GetModulesData(CProgramOptions::InputDriversFromLiveSystemMode);
  478. }
  479. // If we specified an output file, this is where we go ahead and allocate memory
  480. // for the object
  481. if (g_lpProgramOptions->GetMode(CProgramOptions::OutputCSVFileMode))
  482. {
  483. // Do we have any data to output? If we have any data in cache... we should...
  484. if ( ( lpLocalSystemModuleInfoCache && lpLocalSystemModuleInfoCache->GetNumberOfModulesInCache() ) ||
  485. ( lpCSVModuleInfoCache && lpCSVModuleInfoCache->GetNumberOfModulesInCache() ) ||
  486. ( lpDmpModuleInfoCache && lpDmpModuleInfoCache->GetNumberOfModulesInCache() )
  487. )
  488. {
  489. // Set the output file path
  490. if (!lpCSVOutputFile->SetFilePath(g_lpProgramOptions->GetOutputFilePath()))
  491. {
  492. _tprintf(TEXT("Unable set output file path in the file data object! Out of memory?\n"));
  493. goto cleanup;
  494. }
  495. // Verify the output file directory...
  496. if (!lpCSVOutputFile ->VerifyFileDirectory())
  497. {
  498. _tprintf(TEXT("Directory provided is invalid!\n"));
  499. lpCSVOutputFile->PrintLastError();
  500. goto cleanup;
  501. }
  502. // If we are going to produce an output file... try to do that now...
  503. if ( !lpCSVOutputFile->OpenFile(g_lpProgramOptions->GetMode(CProgramOptions::OverwriteOutputFileMode) ? CREATE_ALWAYS : CREATE_NEW) )
  504. {
  505. _tprintf(TEXT("Unable to create the output file %s.\n"), lpCSVOutputFile->GetFilePath());
  506. lpCSVOutputFile->PrintLastError();
  507. goto cleanup;
  508. }
  509. // We skip output of the file header if -E was specified...
  510. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  511. {
  512. // Write the file header!
  513. if (!lpCSVOutputFile->WriteFileHeader())
  514. {
  515. _tprintf(TEXT("Unable to write the output file header.\n"));
  516. lpCSVOutputFile->PrintLastError();
  517. goto cleanup;
  518. }
  519. }
  520. } else
  521. {
  522. // Nothing to output... do not enable this mode...
  523. g_lpProgramOptions->SetMode(CProgramOptions::OutputCSVFileMode, false);
  524. }
  525. }
  526. // Do we verify symbols on this machine?
  527. if ( g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode) &&
  528. ( lpLocalSystemModuleInfoCache || lpCSVModuleInfoCache || lpDmpModuleInfoCache) )
  529. {
  530. // If there is any data in any of our caches... we need to verify them...
  531. // Do a Verify on the ModuleCache... (We'll be quiet in QuietMode or when Building a Symbol Tree)
  532. if (lpLocalSystemModuleInfoCache)
  533. {
  534. if (!fQuietMode)
  535. _tprintf(TEXT("\nVerifying %d Modules from this System...\n"), lpLocalSystemModuleInfoCache->GetNumberOfModulesInCache());
  536. lpLocalSystemModuleInfoCache->VerifySymbols( fQuietMode ||
  537. g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode)
  538. );
  539. // Update our stats...
  540. lTotalNumberOfModulesVerified = lTotalNumberOfModulesVerified + lpLocalSystemModuleInfoCache->GetNumberOfModulesVerified();
  541. lTotalNumberOfVerifyErrors = lTotalNumberOfVerifyErrors + lpLocalSystemModuleInfoCache->GetNumberOfVerifyErrors();
  542. }
  543. // Do a Verify on the ModuleCache... (We'll be quiet in QuietMode or when Building a Symbol Tree)
  544. if (lpCSVModuleInfoCache)
  545. {
  546. if (!fQuietMode)
  547. _tprintf(TEXT("\nVerifying %d Modules from the CSV file...\n"), lpCSVModuleInfoCache->GetNumberOfModulesInCache());
  548. lpCSVModuleInfoCache->VerifySymbols( fQuietMode ||
  549. g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode)
  550. );
  551. // Update our stats...
  552. lTotalNumberOfModulesVerified = lTotalNumberOfModulesVerified + lpCSVModuleInfoCache->GetNumberOfModulesVerified();
  553. lTotalNumberOfVerifyErrors = lTotalNumberOfVerifyErrors + lpCSVModuleInfoCache->GetNumberOfVerifyErrors();
  554. }
  555. // Do a Verify on the ModuleCache... (We'll be quiet in QuietMode or when Building a Symbol Tree)
  556. if (lpDmpModuleInfoCache)
  557. {
  558. if (!fQuietMode)
  559. _tprintf(TEXT("\nVerifying %d Modules from the DMP file...\n"), lpDmpModuleInfoCache->GetNumberOfModulesInCache());
  560. lpDmpModuleInfoCache->VerifySymbols( fQuietMode ||
  561. g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode)
  562. );
  563. // Update our stats...
  564. lTotalNumberOfModulesVerified = lTotalNumberOfModulesVerified + lpDmpModuleInfoCache->GetNumberOfModulesVerified();
  565. lTotalNumberOfVerifyErrors = lTotalNumberOfVerifyErrors + lpDmpModuleInfoCache->GetNumberOfVerifyErrors();
  566. }
  567. }
  568. // OUTPUT Phase!
  569. //
  570. // PROCESS COLLECTIONS FIRST!!!!
  571. //
  572. // Let's output local system processes first!
  573. if (lpLocalSystemProcesses)
  574. lpLocalSystemProcesses->OutputProcessesData(Processes, false);
  575. // Let's output CSV Processes next...
  576. if (lpCSVProcesses)
  577. lpCSVProcesses->OutputProcessesData(Processes, true);
  578. // If we're going to Dump to a USER.DMP file... do it...
  579. // Dump the data from a USER.DMP file... if we have one...
  580. if (lpDmpFileUserModeProcess)
  581. lpDmpFileUserModeProcess->OutputProcessData(Process, false, true);
  582. // let's output CSV Process next...
  583. if (lpCSVProcess)
  584. lpCSVProcess->OutputProcessData(Processes, true);
  585. //
  586. // MODULE COLLECTIONS SECOND!!!!
  587. //
  588. // Dump modules we found from our local file system first...
  589. if (lpLocalFileSystemModules)
  590. lpLocalFileSystemModules->OutputModulesData(Modules, false);
  591. // Dump modules from the CSV file second...
  592. if (lpCSVModulesFromFileSystem)
  593. lpCSVModulesFromFileSystem->OutputModulesData(Modules, true);
  594. // Dump device drivers from our local system first
  595. if (lpKernelModeDrivers)
  596. lpKernelModeDrivers->OutputModulesData(KernelModeDrivers, false);
  597. if (lpDmpFileKernelModeDrivers)
  598. lpDmpFileKernelModeDrivers->OutputModulesData(KernelModeDrivers, false);
  599. if (lpCSVKernelModeDrivers)
  600. lpCSVKernelModeDrivers->OutputModulesData(KernelModeDrivers, true);
  601. // Dump device drivers from our CSV file second...
  602. // ISSUE-2000/07/24-GREGWI: Add support for Device Drivers here...
  603. //
  604. // DISPLAY RESULTS (IF VERIFICATION WAS USED)
  605. //
  606. // Dump the verification results...
  607. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode) &&
  608. !fQuietMode)
  609. {
  610. long lPercentageSuccessfullyVerified = 0;
  611. if (lTotalNumberOfModulesVerified)
  612. lPercentageSuccessfullyVerified = (lTotalNumberOfModulesVerified - lTotalNumberOfVerifyErrors) * 100 / lTotalNumberOfModulesVerified;
  613. _tprintf(TEXT("RESULTS: %d Total Files Checked, Total %d Verification Errors Found\n"), lTotalNumberOfModulesVerified , lTotalNumberOfVerifyErrors );
  614. _tprintf(TEXT("RESULTS: Percentage Verified Successfully = %d%%\n"), lPercentageSuccessfullyVerified);
  615. // Return an error level equal to the number of errors found (0 == EXIT_SUCCESS)
  616. iReturnCode = lTotalNumberOfVerifyErrors;
  617. } else
  618. {
  619. // Success!
  620. iReturnCode = EXIT_SUCCESS;
  621. }
  622. cleanup:
  623. // If we specified an output file, this is where we close it...
  624. if (lpCSVOutputFile)
  625. {
  626. // Try and close the file this object is bound to...
  627. lpCSVOutputFile->CloseFile();
  628. // Free the memory...
  629. delete lpCSVOutputFile;
  630. lpCSVOutputFile = NULL;
  631. }
  632. // If we specified an input file, this is where we close it...
  633. if (lpCSVInputFile)
  634. {
  635. // Try and close the file this object is bound to...
  636. lpCSVInputFile->CloseFile();
  637. // Free the memory...
  638. delete lpCSVInputFile;
  639. lpCSVInputFile = NULL;
  640. }
  641. if (g_lpDelayLoad)
  642. {
  643. delete g_lpDelayLoad;
  644. g_lpDelayLoad = NULL;
  645. }
  646. if (g_lpProgramOptions)
  647. {
  648. delete g_lpProgramOptions;
  649. g_lpProgramOptions = NULL;
  650. }
  651. if (lpLocalSystemProcesses)
  652. {
  653. delete lpLocalSystemProcesses;
  654. lpLocalSystemProcesses = NULL;
  655. }
  656. if (lpSymbolVerification)
  657. {
  658. delete lpSymbolVerification;
  659. lpSymbolVerification = NULL;
  660. }
  661. if (lpCSVKernelModeDrivers)
  662. {
  663. delete lpCSVKernelModeDrivers;
  664. lpCSVKernelModeDrivers = NULL;
  665. }
  666. if (lpCSVProcesses)
  667. {
  668. delete lpCSVProcesses;
  669. lpCSVProcesses = NULL;
  670. }
  671. if (lpCSVProcess)
  672. {
  673. delete lpCSVProcess;
  674. lpCSVProcess = NULL;
  675. }
  676. if (lpCSVModulesFromFileSystem)
  677. {
  678. delete lpCSVModulesFromFileSystem;
  679. lpCSVModulesFromFileSystem = NULL;
  680. }
  681. if (lpLocalSystemModuleInfoCache)
  682. {
  683. delete lpLocalSystemModuleInfoCache;
  684. lpLocalSystemModuleInfoCache = NULL;
  685. }
  686. if (lpCSVModuleInfoCache)
  687. {
  688. delete lpCSVModuleInfoCache;
  689. lpCSVModuleInfoCache = NULL;
  690. }
  691. if (lpDmpModuleInfoCache)
  692. {
  693. delete lpDmpModuleInfoCache;
  694. lpDmpModuleInfoCache = NULL;
  695. }
  696. if (lpLocalFileSystemModules)
  697. {
  698. delete lpLocalFileSystemModules;
  699. lpLocalFileSystemModules = NULL;
  700. }
  701. if (lpKernelModeDrivers)
  702. {
  703. delete lpKernelModeDrivers;
  704. lpKernelModeDrivers = NULL;
  705. }
  706. if (lpDmpFile)
  707. {
  708. delete lpDmpFile;
  709. lpDmpFile = NULL;
  710. }
  711. if (lpDmpFileUserModeProcess)
  712. {
  713. delete lpDmpFileUserModeProcess;
  714. lpDmpFileUserModeProcess = NULL;
  715. }
  716. if (lpDmpFileKernelModeDrivers)
  717. {
  718. delete lpDmpFileKernelModeDrivers;
  719. lpDmpFileKernelModeDrivers = NULL;
  720. }
  721. #ifdef CHECKSYM_TEST
  722. if (argv)
  723. {
  724. delete [] argv;
  725. argv = NULL;
  726. }
  727. if (tszCopyOfTestString)
  728. {
  729. delete [] tszCopyOfTestString;
  730. tszCopyOfTestString = NULL;
  731. }
  732. } // Return for more tests?
  733. #endif
  734. return iReturnCode;
  735. }
  736. //#if ( _MSC_VER < 1200 )
  737. #ifdef __cplusplus
  738. }
  739. #endif