Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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