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.

780 lines
26 KiB

  1. //
  2. // VERIFY.C
  3. //
  4. #include "sigverif.h"
  5. //
  6. // Find the file extension and place it in the lpFileNode->lpTypeName field
  7. //
  8. void MyGetFileTypeName(LPFILENODE lpFileInfo)
  9. {
  10. TCHAR szBuffer[MAX_PATH];
  11. TCHAR szBuffer2[MAX_PATH];
  12. TCHAR szExt[MAX_PATH];
  13. LPTSTR lpExtension;
  14. // Initialize szBuffer to be an empty string.
  15. szBuffer[0] = 0;
  16. // Walk to the end of lpFileName
  17. for (lpExtension = lpFileInfo->lpFileName; *lpExtension; lpExtension++);
  18. // Walk backwards until we hit a '.' and we'll use that as our extension
  19. for (lpExtension--; *lpExtension && lpExtension >= lpFileInfo->lpFileName; lpExtension--) {
  20. if (lpExtension[0] == TEXT('.')) {
  21. lstrcpy(szExt, lpExtension + 1);
  22. CharUpperBuff(szExt, lstrlen(szExt));
  23. MyLoadString(szBuffer2, IDS_FILETYPE);
  24. wsprintf(szBuffer, szBuffer2, szExt);
  25. }
  26. }
  27. // If there's no extension, then just call this a "File".
  28. if (szBuffer[0] == 0) {
  29. MyLoadString(szBuffer, IDS_FILE);
  30. }
  31. lpFileInfo->lpTypeName = MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  32. if (lpFileInfo->lpTypeName) {
  33. lstrcpy(lpFileInfo->lpTypeName, szBuffer);
  34. }
  35. }
  36. //
  37. // Use SHGetFileInfo to get the icon index for the specified file.
  38. //
  39. void MyGetFileInfo(LPFILENODE lpFileInfo)
  40. {
  41. SHFILEINFO sfi;
  42. ZeroMemory(&sfi, sizeof(SHFILEINFO));
  43. SHGetFileInfo( lpFileInfo->lpFileName,
  44. 0,
  45. &sfi,
  46. sizeof(SHFILEINFO),
  47. SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_TYPENAME);
  48. lpFileInfo->iIcon = sfi.iIcon;
  49. if (*sfi.szTypeName) {
  50. lpFileInfo->lpTypeName = MALLOC((lstrlen(sfi.szTypeName) + 1) * sizeof(TCHAR));
  51. if (lpFileInfo->lpTypeName) {
  52. lstrcpy(lpFileInfo->lpTypeName, sfi.szTypeName);
  53. }
  54. } else {
  55. MyGetFileTypeName(lpFileInfo);
  56. }
  57. }
  58. void GetFileVersion(LPFILENODE lpFileInfo)
  59. {
  60. DWORD dwHandle, dwRet, dwLength;
  61. BOOL bRet;
  62. LPVOID lpData = NULL;
  63. LPVOID lpBuffer;
  64. VS_FIXEDFILEINFO *lpInfo;
  65. TCHAR szBuffer[MAX_PATH];
  66. TCHAR szBuffer2[MAX_PATH];
  67. dwRet = GetFileVersionInfoSize(lpFileInfo->lpFileName, &dwHandle);
  68. if (dwRet) {
  69. lpData = MALLOC(dwRet + 1);
  70. if (lpData) {
  71. bRet = GetFileVersionInfo(lpFileInfo->lpFileName, dwHandle, dwRet, lpData);
  72. if (bRet) {
  73. lpBuffer = NULL;
  74. dwLength = 0;
  75. bRet = VerQueryValue(lpData, TEXT("\\"), &lpBuffer, &dwLength);
  76. if (bRet) {
  77. lpInfo = (VS_FIXEDFILEINFO *) lpBuffer;
  78. MyLoadString(szBuffer2, IDS_VERSION);
  79. wsprintf(szBuffer, szBuffer2, HIWORD(lpInfo->dwFileVersionMS), LOWORD(lpInfo->dwFileVersionMS),
  80. HIWORD(lpInfo->dwFileVersionLS), LOWORD(lpInfo->dwFileVersionLS));
  81. lpFileInfo->lpVersion = MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  82. if (lpFileInfo->lpVersion) {
  83. lstrcpy(lpFileInfo->lpVersion, szBuffer);
  84. }
  85. }
  86. }
  87. FREE(lpData);
  88. }
  89. }
  90. if (!lpFileInfo->lpVersion) {
  91. MyLoadString(szBuffer, IDS_NOVERSION);
  92. lpFileInfo->lpVersion = MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  93. if (lpFileInfo->lpVersion) {
  94. lstrcpy(lpFileInfo->lpVersion, szBuffer);
  95. }
  96. }
  97. }
  98. /*************************************************************************
  99. * Function : VerifyIsFileSigned
  100. * Purpose : Calls WinVerifyTrust with Policy Provider GUID to
  101. * verify if an individual file is signed.
  102. **************************************************************************/
  103. BOOL VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo)
  104. {
  105. INT iRet;
  106. HRESULT hRes;
  107. WINTRUST_DATA WinTrustData;
  108. WINTRUST_FILE_INFO WinTrustFile;
  109. GUID gOSVerCheck = DRIVER_ACTION_VERIFY;
  110. GUID gPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  111. #ifndef UNICODE
  112. WCHAR wszFileName[MAX_PATH];
  113. #endif
  114. ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
  115. WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
  116. WinTrustData.dwUIChoice = WTD_UI_NONE;
  117. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  118. WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
  119. WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  120. WinTrustData.pFile = &WinTrustFile;
  121. WinTrustData.pPolicyCallbackData = (LPVOID)lpVerInfo;
  122. ZeroMemory(lpVerInfo, sizeof(DRIVER_VER_INFO));
  123. lpVerInfo->cbStruct = sizeof(DRIVER_VER_INFO);
  124. ZeroMemory(&WinTrustFile, sizeof(WINTRUST_FILE_INFO));
  125. WinTrustFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
  126. #ifndef UNICODE
  127. iRet = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcszMatchFile, -1, (LPWSTR)&wszFileName, cA(wszFileName));
  128. WinTrustFile.pcwszFilePath = wszFileName;
  129. #else
  130. WinTrustFile.pcwszFilePath = pcszMatchFile;
  131. #endif
  132. hRes = WinVerifyTrust(g_App.hDlg, &gOSVerCheck, &WinTrustData);
  133. if (hRes != ERROR_SUCCESS) {
  134. hRes = WinVerifyTrust(g_App.hDlg, &gPublishedSoftware, &WinTrustData);
  135. }
  136. //
  137. // Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
  138. // that was allocated in our call to WinVerifyTrust.
  139. //
  140. if (lpVerInfo && lpVerInfo->pcSignerCertContext) {
  141. CertFreeCertificateContext(lpVerInfo->pcSignerCertContext);
  142. lpVerInfo->pcSignerCertContext = NULL;
  143. }
  144. return(hRes == ERROR_SUCCESS);
  145. }
  146. //
  147. // Given a specific LPFILENODE, verify that the file is signed or unsigned.
  148. // Fill in all the necessary structures so the listview control can display properly.
  149. //
  150. BOOL VerifyFileNode(LPFILENODE lpFileNode)
  151. {
  152. HANDLE hFile;
  153. BOOL bRet;
  154. HCATINFO hCatInfo = NULL;
  155. HCATINFO PrevCat;
  156. WINTRUST_DATA WinTrustData;
  157. WINTRUST_CATALOG_INFO WinTrustCatalogInfo;
  158. DRIVER_VER_INFO VerInfo;
  159. GUID gSubSystemDriver = DRIVER_ACTION_VERIFY;
  160. HRESULT hRes;
  161. DWORD cbHash = HASH_SIZE;
  162. BYTE szHash[HASH_SIZE];
  163. LPBYTE lpHash = szHash;
  164. CATALOG_INFO CatInfo;
  165. LPTSTR lpFilePart;
  166. TCHAR szBuffer[MAX_PATH];
  167. static TCHAR szCurrentDirectory[MAX_PATH];
  168. OSVERSIONINFO OsVersionInfo;
  169. #ifndef UNICODE
  170. WCHAR UnicodeKey[MAX_PATH];
  171. #endif
  172. // If this is the first item we are verifying, then initialize the static buffer.
  173. if (lpFileNode == g_App.lpFileList) {
  174. ZeroMemory(szCurrentDirectory, sizeof(szCurrentDirectory));
  175. }
  176. //
  177. // Check the current directory against the one in the lpFileNode.
  178. // We only want to call SetCurrentDirectory if the path is different.
  179. //
  180. if (lstrcmp(szCurrentDirectory, lpFileNode->lpDirName)) {
  181. if (!SetCurrentDirectory(lpFileNode->lpDirName)) {
  182. return FALSE;
  183. }
  184. lstrcpy(szCurrentDirectory, lpFileNode->lpDirName);
  185. }
  186. //
  187. // Get the handle to the file, so we can call CryptCATAdminCalcHashFromFileHandle
  188. //
  189. hFile = CreateFile( lpFileNode->lpFileName,
  190. GENERIC_READ,
  191. FILE_SHARE_READ | FILE_SHARE_WRITE,
  192. NULL,
  193. OPEN_EXISTING,
  194. FILE_ATTRIBUTE_NORMAL,
  195. NULL);
  196. if (hFile == INVALID_HANDLE_VALUE) {
  197. lpFileNode->LastError = GetLastError();
  198. return FALSE;
  199. }
  200. // Initialize the hash buffer
  201. ZeroMemory(lpHash, HASH_SIZE);
  202. // Generate the hash from the file handle and store it in lpHash
  203. if (!CryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, lpHash, 0)) {
  204. //
  205. // If we couldn't generate a hash, it might be an individually signed catalog.
  206. // If it's a catalog, zero out lpHash and cbHash so we know there's no hash to check.
  207. //
  208. if (IsCatalogFile(hFile, NULL)) {
  209. lpHash = NULL;
  210. cbHash = 0;
  211. } else { // If it wasn't a catalog, we'll bail and this file will show up as unscanned.
  212. CloseHandle(hFile);
  213. return FALSE;
  214. }
  215. }
  216. // Close the file handle
  217. CloseHandle(hFile);
  218. //
  219. // Now we have the file's hash. Initialize the structures that
  220. // will be used later on in calls to WinVerifyTrust.
  221. //
  222. ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
  223. WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
  224. WinTrustData.dwUIChoice = WTD_UI_NONE;
  225. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  226. WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
  227. WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  228. WinTrustData.pPolicyCallbackData = (LPVOID)&VerInfo;
  229. ZeroMemory(&VerInfo, sizeof(DRIVER_VER_INFO));
  230. VerInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  231. //
  232. // Only validate against the current OS Version, unless the bValidateAgainstAnyOs
  233. // parameter was TRUE. In that case we will just leave the sOSVersionXxx fields
  234. // 0 which tells WinVerifyTrust to validate against any OS.
  235. //
  236. if (!lpFileNode->bValidateAgainstAnyOs) {
  237. OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo);
  238. if (GetVersionEx(&OsVersionInfo)) {
  239. VerInfo.sOSVersionLow.dwMajor = OsVersionInfo.dwMajorVersion;
  240. VerInfo.sOSVersionLow.dwMinor = OsVersionInfo.dwMinorVersion;
  241. VerInfo.sOSVersionHigh.dwMajor = OsVersionInfo.dwMajorVersion;
  242. VerInfo.sOSVersionHigh.dwMinor = OsVersionInfo.dwMinorVersion;
  243. }
  244. }
  245. WinTrustData.pCatalog = &WinTrustCatalogInfo;
  246. ZeroMemory(&WinTrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
  247. WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
  248. WinTrustCatalogInfo.pbCalculatedFileHash = lpHash;
  249. WinTrustCatalogInfo.cbCalculatedFileHash = cbHash;
  250. #ifdef UNICODE
  251. WinTrustCatalogInfo.pcwszMemberTag = lpFileNode->lpFileName;
  252. #else
  253. MultiByteToWideChar(CP_ACP, 0, lpFileNode->lpFileName, -1, UnicodeKey, cA(UnicodeKey));
  254. WinTrustCatalogInfo.pcwszMemberTag = UnicodeKey;
  255. #endif
  256. //
  257. // Now we try to find the file hash in the catalog list, via CryptCATAdminEnumCatalogFromHash
  258. //
  259. PrevCat = NULL;
  260. if (g_App.hCatAdmin) {
  261. hCatInfo = CryptCATAdminEnumCatalogFromHash(g_App.hCatAdmin, lpHash, cbHash, 0, &PrevCat);
  262. } else {
  263. hCatInfo = NULL;
  264. }
  265. //
  266. // We want to cycle through the matching catalogs until we find one that matches both hash and member tag
  267. //
  268. bRet = FALSE;
  269. while (hCatInfo && !bRet) {
  270. ZeroMemory(&CatInfo, sizeof(CATALOG_INFO));
  271. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  272. if (CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)) {
  273. WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  274. // Now verify that the file is an actual member of the catalog.
  275. hRes = WinVerifyTrust(g_App.hDlg, &gSubSystemDriver, &WinTrustData);
  276. if (hRes == ERROR_SUCCESS) {
  277. #ifdef UNICODE
  278. GetFullPathName(CatInfo.wszCatalogFile, MAX_PATH, szBuffer, &lpFilePart);
  279. #else
  280. WideCharToMultiByte(CP_ACP, 0, CatInfo.wszCatalogFile, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  281. GetFullPathName(szBuffer, MAX_PATH, szBuffer, &lpFilePart);
  282. #endif
  283. lpFileNode->lpCatalog = MALLOC((lstrlen(lpFilePart) + 1) * sizeof(TCHAR));
  284. if (lpFileNode->lpCatalog) {
  285. lstrcpy(lpFileNode->lpCatalog, lpFilePart);
  286. }
  287. bRet = TRUE;
  288. }
  289. //
  290. // Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
  291. // that was allocated in our call to WinVerifyTrust.
  292. //
  293. if (VerInfo.pcSignerCertContext != NULL) {
  294. CertFreeCertificateContext(VerInfo.pcSignerCertContext);
  295. VerInfo.pcSignerCertContext = NULL;
  296. }
  297. }
  298. if (!bRet) {
  299. // The hash was in this catalog, but the file wasn't a member... so off to the next catalog
  300. PrevCat = hCatInfo;
  301. hCatInfo = CryptCATAdminEnumCatalogFromHash(g_App.hCatAdmin, lpHash, cbHash, 0, &PrevCat);
  302. }
  303. }
  304. // Mark this file as having been scanned.
  305. lpFileNode->bScanned = TRUE;
  306. if (!hCatInfo) {
  307. //
  308. // If it wasn't found in the catalogs, check if the file is individually signed.
  309. //
  310. bRet = VerifyIsFileSigned(lpFileNode->lpFileName, (PDRIVER_VER_INFO)&VerInfo);
  311. if (bRet) {
  312. // If so, mark the file as being signed.
  313. lpFileNode->bSigned = TRUE;
  314. }
  315. } else {
  316. // The file was verified in the catalogs, so mark it as signed and free the catalog context.
  317. lpFileNode->bSigned = TRUE;
  318. CryptCATAdminReleaseCatalogContext(g_App.hCatAdmin, hCatInfo, 0);
  319. }
  320. if (lpFileNode->bSigned) {
  321. #ifdef UNICODE
  322. lpFileNode->lpVersion = MALLOC((lstrlen(VerInfo.wszVersion) + 1) * sizeof(TCHAR));
  323. if (lpFileNode->lpVersion) {
  324. lstrcpy(lpFileNode->lpVersion, VerInfo.wszVersion);
  325. }
  326. lpFileNode->lpSignedBy = MALLOC((lstrlen(VerInfo.wszSignedBy) + 1) * sizeof(TCHAR));
  327. if (lpFileNode->lpSignedBy) {
  328. lstrcpy(lpFileNode->lpSignedBy, VerInfo.wszSignedBy);
  329. }
  330. #else
  331. WideCharToMultiByte(CP_ACP, 0, VerInfo.wszVersion, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  332. lpFileNode->lpVersion = MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  333. if (lpFileNode->lpVersion) {
  334. lstrcpy(lpFileNode->lpVersion, szBuffer);
  335. }
  336. WideCharToMultiByte(CP_ACP, 0, VerInfo.wszSignedBy, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  337. lpFileNode->lpSignedBy = MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  338. if (lpFileNode->lpSignedBy) {
  339. lstrcpy(lpFileNode->lpSignedBy, szBuffer);
  340. }
  341. #endif
  342. } else {
  343. //
  344. // Get the icon (if the file isn't signed) so we can display it in the listview faster.
  345. //
  346. MyGetFileInfo(lpFileNode);
  347. }
  348. return lpFileNode->bSigned;
  349. }
  350. //
  351. // This function loops through g_App.lpFileList to verify each file. We want to make this loop as tight
  352. // as possible and keep the progress bar updating as we go. When we are done, we want to pop up a
  353. // dialog that allows the user to choose "Details" which will give them the listview control.
  354. //
  355. BOOL VerifyFileList(void)
  356. {
  357. LPFILENODE lpFileNode;
  358. DWORD dwCount = 0;
  359. DWORD dwPercent = 0;
  360. DWORD dwCurrent = 0;
  361. TCHAR szBuffer[MAX_PATH];
  362. TCHAR szBuffer2[MAX_PATH];
  363. DWORD dwBytesWritten;
  364. HANDLE hSigverif = INVALID_HANDLE_VALUE;
  365. HANDLE hTotals = INVALID_HANDLE_VALUE;
  366. HANDLE hFileSigned = INVALID_HANDLE_VALUE;
  367. HANDLE hFileUnsigned = INVALID_HANDLE_VALUE;
  368. HANDLE hFileUnscanned = INVALID_HANDLE_VALUE;
  369. // Initialize the signed and unsigned counts
  370. g_App.dwSigned = 0;
  371. g_App.dwUnsigned = 0;
  372. // If we don't already have an g_App.hCatAdmin handle, acquire one.
  373. if (!g_App.hCatAdmin) {
  374. CryptCATAdminAcquireContext(&g_App.hCatAdmin, NULL, 0);
  375. }
  376. //
  377. // If the user specified test switches, then we want to open log files to record
  378. // the scanning results as they happen. SIGVERIF.TXT has every file before it is
  379. // scanned (in case of a fault), SIGNED.TXT gets signed files, UNSIGNED.TXT gets
  380. // unsigned files, UNSCANNED.TXT gets everything else. TOTALS.TXT was added last
  381. // and gets the text from the status window on the results dialog.
  382. //
  383. if (g_App.bLogToRoot) {
  384. MyGetWindowsDirectory(szBuffer, MAX_PATH);
  385. szBuffer[3] = 0;
  386. lstrcat(szBuffer, TEXT("SIGVERIF.TXT"));
  387. hSigverif = CreateFile( szBuffer,
  388. GENERIC_READ | GENERIC_WRITE,
  389. FILE_SHARE_READ,
  390. NULL,
  391. CREATE_ALWAYS,
  392. FILE_ATTRIBUTE_NORMAL,
  393. NULL);
  394. if (hSigverif != INVALID_HANDLE_VALUE) {
  395. SetFilePointer(hSigverif, 0, NULL, FILE_BEGIN);
  396. SetEndOfFile(hSigverif);
  397. }
  398. MyGetWindowsDirectory(szBuffer, MAX_PATH);
  399. szBuffer[3] = 0;
  400. lstrcat(szBuffer, TEXT("TOTALS.TXT"));
  401. hTotals = CreateFile( szBuffer,
  402. GENERIC_READ | GENERIC_WRITE,
  403. FILE_SHARE_READ,
  404. NULL,
  405. CREATE_ALWAYS,
  406. FILE_ATTRIBUTE_NORMAL,
  407. NULL);
  408. if (hTotals != INVALID_HANDLE_VALUE) {
  409. SetFilePointer(hTotals, 0, NULL, FILE_BEGIN);
  410. SetEndOfFile(hTotals);
  411. }
  412. MyGetWindowsDirectory(szBuffer, MAX_PATH);
  413. szBuffer[3] = 0;
  414. lstrcat(szBuffer, TEXT("SIGNED.TXT"));
  415. hFileSigned = CreateFile( szBuffer,
  416. GENERIC_READ | GENERIC_WRITE,
  417. FILE_SHARE_READ,
  418. NULL,
  419. CREATE_ALWAYS,
  420. FILE_ATTRIBUTE_NORMAL,
  421. NULL);
  422. if (hFileSigned != INVALID_HANDLE_VALUE) {
  423. SetFilePointer(hFileSigned, 0, NULL, FILE_BEGIN);
  424. SetEndOfFile(hFileSigned);
  425. }
  426. MyGetWindowsDirectory(szBuffer, MAX_PATH);
  427. szBuffer[3] = 0;
  428. lstrcat(szBuffer, TEXT("UNSIGNED.TXT"));
  429. hFileUnsigned = CreateFile( szBuffer,
  430. GENERIC_READ | GENERIC_WRITE,
  431. FILE_SHARE_READ,
  432. NULL,
  433. CREATE_ALWAYS,
  434. FILE_ATTRIBUTE_NORMAL,
  435. NULL);
  436. if (hFileUnsigned != INVALID_HANDLE_VALUE) {
  437. SetFilePointer(hFileUnsigned, 0, NULL, FILE_BEGIN);
  438. SetEndOfFile(hFileUnsigned);
  439. }
  440. MyGetWindowsDirectory(szBuffer, MAX_PATH);
  441. szBuffer[3] = 0;
  442. lstrcat(szBuffer, TEXT("UNSCANNED.TXT"));
  443. hFileUnscanned = CreateFile( szBuffer,
  444. GENERIC_READ | GENERIC_WRITE,
  445. FILE_SHARE_READ,
  446. NULL,
  447. CREATE_ALWAYS,
  448. FILE_ATTRIBUTE_NORMAL,
  449. NULL);
  450. if (hFileUnscanned != INVALID_HANDLE_VALUE) {
  451. SetFilePointer(hFileUnscanned, 0, NULL, FILE_BEGIN);
  452. SetEndOfFile(hFileUnscanned);
  453. }
  454. #ifdef UNICODE
  455. // If we are using UNICODE, then write the 0xFF and 0xFE bytes at the beginning of the file.
  456. ZeroMemory(szBuffer, sizeof(szBuffer));
  457. szBuffer[0] = 0xFEFF;
  458. if (hSigverif != INVALID_HANDLE_VALUE) {
  459. WriteFile(hSigverif, szBuffer, sizeof(TCHAR), &dwBytesWritten, NULL);
  460. }
  461. if (hTotals != INVALID_HANDLE_VALUE) {
  462. WriteFile(hTotals, szBuffer, sizeof(TCHAR), &dwBytesWritten, NULL);
  463. }
  464. if (hFileSigned != INVALID_HANDLE_VALUE) {
  465. WriteFile(hFileSigned, szBuffer, sizeof(TCHAR), &dwBytesWritten, NULL);
  466. }
  467. if (hFileUnsigned != INVALID_HANDLE_VALUE) {
  468. WriteFile(hFileUnsigned, szBuffer, sizeof(TCHAR), &dwBytesWritten, NULL);
  469. }
  470. if (hFileUnscanned != INVALID_HANDLE_VALUE) {
  471. WriteFile(hFileUnscanned, szBuffer, sizeof(TCHAR), &dwBytesWritten, NULL);
  472. }
  473. #endif
  474. }
  475. //
  476. // Start looping through each file and update the progress bar if we cross a percentage boundary.
  477. //
  478. for (lpFileNode=g_App.lpFileList;lpFileNode && !g_App.bStopScan;lpFileNode=lpFileNode->next,dwCount++) {
  479. // Figure out the current percentage and update if it has increased.
  480. dwPercent = (dwCount * 100) / g_App.dwFiles;
  481. if (dwPercent > dwCurrent) {
  482. dwCurrent = dwPercent;
  483. SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) dwCurrent, (LPARAM) 0);
  484. }
  485. // Log the current file to hSigverif, in case something bad happens.
  486. if (g_App.bLogToRoot && hSigverif != INVALID_HANDLE_VALUE) {
  487. MyLoadString(szBuffer2, IDS_STRING_LINEFEED);
  488. wsprintf(szBuffer, szBuffer2, lpFileNode->lpFileName);
  489. WriteFile(hSigverif, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  490. FlushFileBuffers(hSigverif);
  491. }
  492. //
  493. // Verify the file node if it hasn't already been scanned.
  494. //
  495. if (!lpFileNode->bScanned) {
  496. VerifyFileNode(lpFileNode);
  497. }
  498. // In case something went wrong, make sure the version information gets filled in.
  499. if (!lpFileNode->lpVersion) {
  500. GetFileVersion(lpFileNode);
  501. }
  502. if (lpFileNode->bScanned) {
  503. // If the file was signed, increment the g_App.dwSigned or g_App.dwUnsigned counter.
  504. if (lpFileNode->bSigned) {
  505. g_App.dwSigned++;
  506. if (g_App.bLogToRoot && hFileSigned != INVALID_HANDLE_VALUE) {
  507. MyLoadString(szBuffer2, IDS_STRING_LINEFEED);
  508. wsprintf(szBuffer, szBuffer2, lpFileNode->lpFileName);
  509. WriteFile(hFileSigned, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  510. }
  511. } else {
  512. g_App.dwUnsigned++;
  513. if (g_App.bLogToRoot && hFileUnsigned != INVALID_HANDLE_VALUE) {
  514. if (g_App.bFullSystemScan) {
  515. lstrcpy(szBuffer, lpFileNode->lpDirName);
  516. if (*(szBuffer + lstrlen(szBuffer) - 1) != TEXT('\\'))
  517. lstrcat(szBuffer, TEXT("\\"));
  518. lstrcat(szBuffer, lpFileNode->lpFileName);
  519. WriteFile(hFileUnsigned, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  520. MyLoadString(szBuffer, IDS_LINEFEED);
  521. WriteFile(hFileUnsigned, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  522. } else {
  523. MyLoadString(szBuffer2, IDS_STRING_LINEFEED);
  524. wsprintf(szBuffer, szBuffer2, lpFileNode->lpFileName);
  525. WriteFile(hFileUnsigned, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  526. }
  527. }
  528. }
  529. } else {
  530. if (g_App.bLogToRoot && hFileUnscanned != INVALID_HANDLE_VALUE) {
  531. MyLoadString(szBuffer2, IDS_STRING_LINEFEED);
  532. wsprintf(szBuffer, szBuffer2, lpFileNode->lpFileName);
  533. WriteFile(hFileUnscanned, szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &dwBytesWritten, NULL);
  534. }
  535. }
  536. }
  537. if (g_App.bLogToRoot) {
  538. // Load the status string and fill it in with the correct values.
  539. MyLoadString(szBuffer, IDS_NUMFILES);
  540. wsprintf(szBuffer2, szBuffer, g_App.dwFiles, g_App.dwSigned, g_App.dwUnsigned,
  541. g_App.dwFiles - g_App.dwSigned - g_App.dwUnsigned);
  542. if (hTotals != INVALID_HANDLE_VALUE) {
  543. WriteFile(hTotals, szBuffer2, lstrlen(szBuffer2) * sizeof(TCHAR), &dwBytesWritten, NULL);
  544. }
  545. if (hTotals != INVALID_HANDLE_VALUE) {
  546. CloseHandle(hTotals);
  547. }
  548. if (hSigverif != INVALID_HANDLE_VALUE) {
  549. CloseHandle(hSigverif);
  550. }
  551. if (hFileSigned != INVALID_HANDLE_VALUE) {
  552. CloseHandle(hFileSigned);
  553. }
  554. if (hFileUnsigned != INVALID_HANDLE_VALUE) {
  555. CloseHandle(hFileUnsigned);
  556. }
  557. if (hFileUnsigned != INVALID_HANDLE_VALUE) {
  558. CloseHandle(hFileUnscanned);
  559. }
  560. }
  561. // If we had an g_App.hCatAdmin, free it and set it to zero so we can acquire a new one in the future.
  562. if (g_App.hCatAdmin) {
  563. CryptCATAdminReleaseContext(g_App.hCatAdmin,0);
  564. g_App.hCatAdmin = NULL;
  565. }
  566. if (!g_App.bStopScan && !g_App.bFullSystemScan) {
  567. // If the user never clicked STOP, then make sure the progress bar hits 100%
  568. if (!g_App.bStopScan) {
  569. SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) 100, (LPARAM) 0);
  570. }
  571. if (!g_App.dwUnsigned) {
  572. // If there weren't any unsigned files, then we want to tell the user that everything is dandy!
  573. if (g_App.dwSigned) {
  574. MyMessageBoxId(IDS_ALLSIGNED);
  575. } else {
  576. MyMessageBoxId(IDS_NOPROBLEMS);
  577. }
  578. } else {
  579. // Show the user the results by going directly to IDD_RESULTS
  580. DialogBox(g_App.hInstance, MAKEINTRESOURCE(IDD_RESULTS), g_App.hDlg, ListView_DlgProc);
  581. }
  582. }
  583. return TRUE;
  584. }