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.

595 lines
18 KiB

  1. //
  2. // SIGVERIF.C
  3. //
  4. #define SIGVERIF_DOT_C
  5. #include "sigverif.h"
  6. // Allocate our global data structure
  7. GAPPDATA g_App;
  8. //
  9. // Load a resource string into a buffer that is assumed to be MAX_PATH bytes.
  10. //
  11. void MyLoadString(LPTSTR lpString, UINT uId)
  12. {
  13. LoadString(g_App.hInstance, uId, lpString, MAX_PATH);
  14. }
  15. //
  16. // Pop an OK messagebox with a specific string
  17. //
  18. void MyMessageBox(LPTSTR lpString)
  19. {
  20. TCHAR szBuffer[MAX_PATH];
  21. LPTSTR lpBuffer = szBuffer;
  22. MyLoadString(lpBuffer, IDS_MSGBOX);
  23. MessageBox(g_App.hDlg, lpString, lpBuffer, MB_OK);
  24. }
  25. //
  26. // Pop an OK messagebox with a resource string ID
  27. //
  28. void MyMessageBoxId(UINT uId)
  29. {
  30. TCHAR szBuffer[MAX_PATH];
  31. LPTSTR lpBuffer = szBuffer;
  32. MyLoadString(lpBuffer, uId);
  33. MyMessageBox(lpBuffer);
  34. }
  35. //
  36. // Pop an error messagebox with a specific string
  37. //
  38. void MyErrorBox(LPTSTR lpString)
  39. {
  40. TCHAR szBuffer[MAX_PATH];
  41. LPTSTR lpBuffer = szBuffer;
  42. MyLoadString(lpBuffer, IDS_ERRORBOX);
  43. MessageBox(g_App.hDlg, lpString, lpBuffer, MB_OK);
  44. }
  45. //
  46. // Pop an error messagebox with a resource string ID
  47. //
  48. void MyErrorBoxId(UINT uId)
  49. {
  50. TCHAR szBuffer[MAX_PATH];
  51. LPTSTR lpBuffer = szBuffer;
  52. MyLoadString(lpBuffer, uId);
  53. MyErrorBox(lpBuffer);
  54. }
  55. //
  56. // Since Multi-User Windows will give me back a Profile directory, I need to get the real Windows directory
  57. // Dlg_OnInitDialog initializes g_App.szWinDir with the real Windows directory, so I just use that.
  58. //
  59. UINT MyGetWindowsDirectory(LPTSTR lpDirName, UINT uSize)
  60. {
  61. UINT uRet = 0;
  62. if (lpDirName)
  63. {
  64. lstrcpy(lpDirName, g_App.szWinDir);
  65. uRet = lstrlen(lpDirName);
  66. }
  67. return uRet;
  68. }
  69. //
  70. // Initialization of main dialog.
  71. //
  72. BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  73. {
  74. HKEY hKey;
  75. LONG lRes;
  76. DWORD dwDisp, dwType, dwFlags, cbData;
  77. TCHAR szBuffer[MAX_PATH];
  78. // Initialize global hDlg to current hwnd.
  79. g_App.hDlg = hwnd;
  80. // Set the window class to have the icon in the resource file
  81. if (g_App.hIcon)
  82. {
  83. SetClassLongPtr(hwnd, GCLP_HICON, (LONG_PTR) g_App.hIcon);
  84. }
  85. // Make sure the IDC_STATUS control is hidden until something happens.
  86. ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_HIDE);
  87. // Set the range for the custom progress bar to 0-100.
  88. SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETRANGE, (WPARAM) 0, (LPARAM) MAKELPARAM(0, 100));
  89. // Set the global lpLogName to the one that's given in the resource file
  90. MyLoadString(g_App.szLogFile, IDS_LOGNAME);
  91. //
  92. // Figure out what the real Windows directory is and store it in g_App.szWinDir
  93. // This is required because Hydra makes GetWindowsDirectory return a PROFILE directory
  94. //
  95. // We store the original CurrentDirectory in szBuffer so we can restore it after this hack.
  96. // Next we switch into the SYSTEM/SYSTEM32 directory and then into its parent directory.
  97. // This is what we want to store in g_App.szWinDir.
  98. //
  99. GetCurrentDirectory(MAX_PATH, szBuffer);
  100. GetSystemDirectory(g_App.szWinDir, MAX_PATH);
  101. SetCurrentDirectory(g_App.szWinDir);
  102. SetCurrentDirectory(TEXT(".."));
  103. GetCurrentDirectory(MAX_PATH, g_App.szWinDir);
  104. SetCurrentDirectory(szBuffer);
  105. // Set the global search folder to %WinDir%
  106. MyGetWindowsDirectory(g_App.szScanPath, MAX_PATH);
  107. // Set the global search pattern to "*.*"
  108. MyLoadString(g_App.szScanPattern, IDS_ALL);
  109. // Reset the progress bar back to zero percent
  110. SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) 0, (LPARAM) 0);
  111. // By default, we want to turn logging and set the logging mode to OVERWRITE
  112. g_App.bLoggingEnabled = TRUE;
  113. g_App.bOverwrite = TRUE;
  114. //
  115. // Look in the registry for any settings from the last SigVerif session
  116. //
  117. lRes = RegCreateKeyEx( SIGVERIF_HKEY,
  118. SIGVERIF_KEY,
  119. 0,
  120. NULL,
  121. 0,
  122. KEY_ALL_ACCESS,
  123. NULL,
  124. &hKey,
  125. &dwDisp);
  126. if (lRes == ERROR_SUCCESS)
  127. {
  128. // If all we did was create a new key, then there must not be any data. Just close the key.
  129. if (dwDisp == REG_CREATED_NEW_KEY)
  130. {
  131. RegCloseKey(hKey);
  132. }
  133. else // Otherwise, query the values and set any values that we found.
  134. {
  135. cbData = sizeof(DWORD);
  136. lRes = RegQueryValueEx( hKey,
  137. SIGVERIF_FLAGS,
  138. NULL,
  139. &dwType,
  140. (LPBYTE) &dwFlags,
  141. &cbData);
  142. if (lRes == ERROR_SUCCESS)
  143. {
  144. g_App.bLoggingEnabled = (dwFlags & 0x1);
  145. g_App.bOverwrite = (dwFlags & 0x2);
  146. }
  147. cbData = MAX_PATH;
  148. lRes = RegQueryValueEx( hKey,
  149. SIGVERIF_LOGNAME,
  150. NULL,
  151. &dwType,
  152. (LPBYTE) szBuffer,
  153. &cbData);
  154. if (lRes == ERROR_SUCCESS && dwType == REG_SZ)
  155. {
  156. lstrcpy(g_App.szLogFile, szBuffer);
  157. }
  158. RegCloseKey(hKey);
  159. }
  160. }
  161. // Get the startup directory of SigVerif
  162. GetCurrentDirectory(MAX_PATH, g_App.szAppDir);
  163. //
  164. // Check if the user specified /NOBVT, /NODEV, or /NOPRN
  165. //
  166. MyLoadString(szBuffer, IDS_NOBVT);
  167. if (MyStrStr(GetCommandLine(), szBuffer))
  168. g_App.bNoBVT = TRUE;
  169. MyLoadString(szBuffer, IDS_NODEV);
  170. if (MyStrStr(GetCommandLine(), szBuffer))
  171. g_App.bNoDev = TRUE;
  172. MyLoadString(szBuffer, IDS_NOPRN);
  173. if (MyStrStr(GetCommandLine(), szBuffer))
  174. g_App.bNoPRN = TRUE;
  175. //
  176. // If the user specified the "BlySak" flag, we want to log the signed and unsigned filenames to the root.
  177. //
  178. MyLoadString(szBuffer, IDS_BLYSAK);
  179. if (MyStrStr(GetCommandLine(), szBuffer))
  180. g_App.bLogToRoot = TRUE;
  181. //
  182. // If the user specified the FullSystemScan flag, we want to scan the entire system drive and log the results.
  183. //
  184. MyLoadString(szBuffer, IDS_FULLSCAN);
  185. lstrcat(szBuffer, TEXT(":"));
  186. if (MyStrStr(GetCommandLine(), szBuffer))
  187. {
  188. g_App.bFullSystemScan = TRUE;
  189. g_App.bLoggingEnabled = TRUE;
  190. g_App.bLogToRoot = TRUE;
  191. g_App.bUserScan = TRUE;
  192. g_App.bSubFolders = TRUE;
  193. lstrcpy(g_App.szScanPath, MyStrStr(GetCommandLine(), szBuffer) + lstrlen(szBuffer));
  194. if (g_App.szScanPath[0] == TEXT('\0')) {
  195. MyGetWindowsDirectory(g_App.szScanPath, MAX_PATH);
  196. }
  197. // Now that everything is set up, simulate a click to the START button...
  198. PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(ID_START, 0), (LPARAM) 0);
  199. }
  200. //
  201. // If the user specified the DefaultSystemScan flag, we want to scan the entire system drive and log the results.
  202. //
  203. MyLoadString(szBuffer, IDS_DEFSCAN);
  204. if (MyStrStr(GetCommandLine(), szBuffer))
  205. {
  206. g_App.bFullSystemScan = TRUE;
  207. g_App.bLoggingEnabled = TRUE;
  208. g_App.bLogToRoot = TRUE;
  209. // Now that everything is set up, simulate a click to the START button...
  210. PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(ID_START, 0), (LPARAM) 0);
  211. }
  212. return TRUE;
  213. }
  214. //
  215. // Build file list according to dialog settings, then verify the files in the list
  216. //
  217. void WINAPI ProcessFileList(void)
  218. {
  219. DWORD dwCount = 0;
  220. TCHAR szBuffer[MAX_PATH];
  221. // Set the scanning flag to TRUE, so we don't double-scan
  222. g_App.bScanning = TRUE;
  223. // Assume a successful install.
  224. g_App.LastError = ERROR_SUCCESS;
  225. // Change the "Start" to "Stop"
  226. MyLoadString(szBuffer, IDS_STOP);
  227. SetDlgItemText(g_App.hDlg, ID_START, szBuffer);
  228. EnableWindow(GetDlgItem(g_App.hDlg, ID_ADVANCED), FALSE);
  229. EnableWindow(GetDlgItem(g_App.hDlg, IDCANCEL), FALSE);
  230. // Display the text that says "Building file list..."
  231. MyLoadString(szBuffer, IDS_STATUS_BUILD);
  232. SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
  233. // Hide the IDC_INFOTEXT text item so it doesn't cover IDC_STATUS
  234. //ShowWindow(GetDlgItem(g_App.hDlg, IDC_INFOTEXT), SW_HIDE);
  235. // Make sure the IDC_STATUS text item visible
  236. ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_SHOW);
  237. // Free any memory that we may have allocated for the g_App.lpFileList
  238. DestroyFileList(TRUE);
  239. // Now actually build the g_App.lpFileList list given the dialog settings
  240. if (g_App.bUserScan)
  241. {
  242. BuildFileList(g_App.szScanPath);
  243. }
  244. else
  245. {
  246. if (!g_App.bNoDev && !g_App.bStopScan) {
  247. BuildDriverFileList();
  248. }
  249. if (!g_App.bNoPRN && !g_App.bStopScan) {
  250. BuildPrinterFileList();
  251. }
  252. if (!g_App.bNoBVT && !g_App.bStopScan) {
  253. BuildCoreFileList();
  254. }
  255. }
  256. // Check if there is even a file list to verify.
  257. if (g_App.lpFileList)
  258. {
  259. if (!g_App.bStopScan)
  260. {
  261. // Display the "Scanning File List..." text
  262. MyLoadString(szBuffer, IDS_STATUS_SCAN);
  263. SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
  264. // Reset the progress bar back to zero percent while it's invisible.
  265. SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) 0, (LPARAM) 0);
  266. //
  267. // WooHoo! Let's display the progress bar and start cranking on the file list!
  268. //
  269. ShowWindow(GetDlgItem(g_App.hDlg, IDC_PROGRESS), SW_SHOW);
  270. VerifyFileList();
  271. ShowWindow(GetDlgItem(g_App.hDlg, IDC_PROGRESS), SW_HIDE);
  272. }
  273. }
  274. else
  275. {
  276. //
  277. // The IDC_NOTMS code displays it's own error message, so only display
  278. // an error dialog if we are doing a System Integrity Scan
  279. //
  280. if (!g_App.bStopScan && !g_App.bUserScan)
  281. {
  282. MyMessageBoxId(IDS_NOSYSTEMFILES);
  283. }
  284. }
  285. // Disable the start button while we clean up the g_App.lpFileList
  286. EnableWindow(GetDlgItem(g_App.hDlg, ID_START), FALSE);
  287. if (!g_App.bStopScan)
  288. {
  289. // Display the text that says "Writing Log File..."
  290. MyLoadString(szBuffer, IDS_STATUS_LOG);
  291. SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
  292. // Write the results to the log file
  293. PrintFileList();
  294. }
  295. else
  296. {
  297. // If the user clicked STOP, let them know about it.
  298. MyMessageBoxId(IDS_SCANSTOPPED);
  299. }
  300. // Display the text that says "Freeing File List..."
  301. MyLoadString(szBuffer, IDS_STATUS_FREE);
  302. SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
  303. // Free all the memory that we allocated for the g_App.lpFileList
  304. DestroyFileList(FALSE);
  305. // Hide the IDC_STATUS text item so it doesn't cover IDC_STATUS
  306. ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_HIDE);
  307. // Change the "Stop" button back to "Start"
  308. MyLoadString(szBuffer, IDS_START);
  309. SetDlgItemText(g_App.hDlg, ID_START, szBuffer);
  310. EnableWindow(GetDlgItem(g_App.hDlg, ID_START), TRUE);
  311. EnableWindow(GetDlgItem(g_App.hDlg, ID_ADVANCED), TRUE);
  312. EnableWindow(GetDlgItem(g_App.hDlg, IDCANCEL), TRUE);
  313. // Clear the scanning flag
  314. g_App.bScanning = FALSE;
  315. g_App.bStopScan = FALSE;
  316. //
  317. // If the user started SigVerif with the FullSystemScan flag, then we exit.
  318. //
  319. if (g_App.bFullSystemScan)
  320. {
  321. PostMessage(g_App.hDlg, WM_CLOSE, (WPARAM) 0, (LPARAM) 0);
  322. }
  323. }
  324. // Spawns a thread to do the scan so the GUI remains responsive.
  325. void Dlg_OnPushStartButton(HWND hwnd)
  326. {
  327. HANDLE hThread;
  328. DWORD dwThreadId;
  329. // Check if we are already scanning... if so, bail.
  330. if (g_App.bScanning)
  331. return;
  332. // Create a thread where Search_ProcessFileList can go without tying up the GUI thread.
  333. hThread = CreateThread(NULL,
  334. 0,
  335. (LPTHREAD_START_ROUTINE) ProcessFileList,
  336. 0,
  337. 0,
  338. &dwThreadId);
  339. }
  340. // Handle any WM_COMMAND messages sent to the search dialog
  341. void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  342. {
  343. switch(id)
  344. {
  345. //
  346. // The user clicked ID_START, so if we aren't scanning start scanning.
  347. // If we are scanning, then stop the tests because the button actually says "Stop"
  348. //
  349. case ID_START:
  350. if (!g_App.bScanning)
  351. {
  352. Dlg_OnPushStartButton(hwnd);
  353. }
  354. else if (!g_App.bStopScan)
  355. {
  356. g_App.bStopScan = TRUE;
  357. g_App.LastError = ERROR_CANCELLED;
  358. }
  359. break;
  360. //
  361. // The user clicked IDCANCEL, so if the tests are running try to stop them before exiting.
  362. //
  363. case IDCANCEL:
  364. if (g_App.bScanning)
  365. {
  366. g_App.bStopScan = TRUE;
  367. g_App.LastError = ERROR_CANCELLED;
  368. } else SendMessage(hwnd, WM_CLOSE, 0, 0);
  369. break;
  370. // Pop up the IDD_SETTINGS dialog so the user can change their log settings.
  371. case ID_ADVANCED:
  372. if (!g_App.bScanning)
  373. {
  374. AdvancedPropertySheet(hwnd);
  375. }
  376. break;
  377. }
  378. }
  379. void SigVerif_Help(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bContext)
  380. {
  381. static DWORD SigVerif_HelpIDs[] =
  382. {
  383. IDC_SCAN, IDH_SIGVERIF_SEARCH_CHECK_SYSTEM,
  384. IDC_NOTMS, IDH_SIGVERIF_SEARCH_LOOK_FOR,
  385. IDC_TYPE, IDH_SIGVERIF_SEARCH_SCAN_FILES,
  386. IDC_FOLDER, IDH_SIGVERIF_SEARCH_LOOK_IN_FOLDER,
  387. IDC_SUBFOLDERS, IDH_SIGVERIF_SEARCH_INCLUDE_SUBFOLDERS,
  388. IDC_ENABLELOG, IDH_SIGVERIF_LOGGING_ENABLE_LOGGING,
  389. IDC_APPEND, IDH_SIGVERIF_LOGGING_APPEND,
  390. IDC_OVERWRITE, IDH_SIGVERIF_LOGGING_OVERWRITE,
  391. IDC_LOGNAME, IDH_SIGVERIF_LOGGING_FILENAME,
  392. IDC_VIEWLOG, IDH_SIGVERIF_LOGGING_VIEW_LOG,
  393. 0,0
  394. };
  395. static DWORD Windows_HelpIDs[] =
  396. {
  397. ID_BROWSE, IDH_BROWSE,
  398. 0,0
  399. };
  400. HWND hItem = NULL;
  401. LPHELPINFO lphi = NULL;
  402. POINT point;
  403. switch (uMsg)
  404. {
  405. case WM_HELP:
  406. lphi = (LPHELPINFO) lParam;
  407. if (lphi && (lphi->iContextType == HELPINFO_WINDOW)) // must be for a control
  408. hItem = (HWND) lphi->hItemHandle;
  409. break;
  410. case WM_CONTEXTMENU:
  411. hItem = (HWND) wParam;
  412. point.x = GET_X_LPARAM(lParam);
  413. point.y = GET_Y_LPARAM(lParam);
  414. if (ScreenToClient(hwnd, &point))
  415. {
  416. hItem = ChildWindowFromPoint(hwnd, point);
  417. }
  418. break;
  419. }
  420. if (hItem)
  421. {
  422. if (GetWindowLong(hItem, GWL_ID) == ID_BROWSE)
  423. {
  424. WinHelp(hItem,
  425. (LPCTSTR) WINDOWS_HELPFILE,
  426. (bContext ? HELP_CONTEXTMENU : HELP_WM_HELP),
  427. (ULONG_PTR) Windows_HelpIDs);
  428. }
  429. else
  430. {
  431. WinHelp(hItem,
  432. (LPCTSTR) SIGVERIF_HELPFILE,
  433. (bContext ? HELP_CONTEXTMENU : HELP_WM_HELP),
  434. (ULONG_PTR) SigVerif_HelpIDs);
  435. }
  436. }
  437. }
  438. //
  439. // The main dialog procedure. Needs to handle WM_INITDIALOG, WM_COMMAND, and WM_CLOSE/WM_DESTROY.
  440. //
  441. INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg,
  442. WPARAM wParam, LPARAM lParam)
  443. {
  444. BOOL fProcessed = TRUE;
  445. switch (uMsg)
  446. {
  447. HANDLE_MSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
  448. HANDLE_MSG(hwnd, WM_COMMAND, Dlg_OnCommand);
  449. case WM_CLOSE:
  450. if (g_App.bScanning)
  451. g_App.bStopScan = TRUE;
  452. else
  453. EndDialog(hwnd, IDCANCEL);
  454. break;
  455. default: fProcessed = FALSE;
  456. }
  457. return fProcessed;
  458. }
  459. //
  460. // Program entry point. Set up for creation of IDD_DIALOG.
  461. //
  462. WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  463. LPSTR lpszCmdParam, int nCmdShow)
  464. {
  465. HWND hwnd;
  466. TCHAR szAppName[MAX_PATH];
  467. // Zero-Initialize our global data structure
  468. ZeroMemory(&g_App, sizeof(GAPPDATA));
  469. // Initialize global hInstance variable
  470. g_App.hInstance = hInstance;
  471. // Look for any existing instances of SigVerif...
  472. MyLoadString(szAppName, IDS_SIGVERIF);
  473. hwnd = FindWindow(NULL, szAppName);
  474. if (!hwnd)
  475. {
  476. // We definitely need this for the progress bar, and maybe other stuff too.
  477. InitCommonControls();
  478. // Register the custom control we use for the progress bar
  479. Progress_InitRegisterClass();
  480. // Load the icon from the resource file that we will use everywhere
  481. g_App.hIcon = LoadIcon(g_App.hInstance, MAKEINTRESOURCE(IDI_ICON1));
  482. // Create the IDD_DIALOG and use DlgProc as the main procedure
  483. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
  484. // Free the icon
  485. if (g_App.hIcon) {
  486. DestroyIcon(g_App.hIcon);
  487. g_App.hIcon = NULL;
  488. }
  489. }
  490. else
  491. {
  492. // If there is already an instance of SigVerif running, make that one foreground and we exit.
  493. SetForegroundWindow(hwnd);
  494. }
  495. //
  496. // If we encountered any errors during our scan, then return the error code,
  497. // otherwise return 0 if all the files are signed or 1 if we found any
  498. // unsigned files.
  499. //
  500. if (g_App.LastError != ERROR_SUCCESS) {
  501. return g_App.LastError;
  502. } else {
  503. return ((g_App.dwUnsigned > 0) ? 1 : 0);
  504. }
  505. }