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.

2019 lines
72 KiB

  1. /****************************************************************************
  2. *
  3. * File: fileinfo.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * Purpose: Gather information about files on this machine
  7. *
  8. * (C) Copyright 1998 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #include <tchar.h>
  12. #include <Windows.h>
  13. #include <mmsystem.h>
  14. #include <stdio.h>
  15. #include <capi.h>
  16. #include <softpub.h>
  17. #include <winsock.h>
  18. #include "sysinfo.h" // for BIsPlatformNT
  19. #include "fileinfo.h"
  20. #include "resource.h"
  21. // MsCat32.dll function prototypes
  22. typedef BOOL (WINAPI* PfnCryptCATAdminAcquireContext)(OUT HCATADMIN *phCatAdmin,
  23. IN const GUID *pgSubsystem,
  24. IN DWORD dwFlags);
  25. typedef BOOL (WINAPI* PfnCryptCATAdminReleaseContext)(IN HCATADMIN hCatAdmin,
  26. IN DWORD dwFlags);
  27. typedef BOOL (WINAPI* PfnCryptCATAdminReleaseCatalogContext)(IN HCATADMIN hCatAdmin,
  28. IN HCATINFO hCatInfo,
  29. IN DWORD dwFlags);
  30. typedef BOOL (WINAPI* PfnCryptCATCatalogInfoFromContext)(IN HCATINFO hCatInfo,
  31. IN OUT CATALOG_INFO *psCatInfo,
  32. IN DWORD dwFlags);
  33. typedef HCATINFO (WINAPI* PfnCryptCATAdminEnumCatalogFromHash)(IN HCATADMIN hCatAdmin,
  34. IN BYTE *pbHash,
  35. IN DWORD cbHash,
  36. IN DWORD dwFlags,
  37. IN OUT HCATINFO *phPrevCatInfo);
  38. typedef BOOL (WINAPI* PfnIsCatalogFile)(IN OPTIONAL HANDLE hFile,
  39. IN OPTIONAL WCHAR *pwszFileName);
  40. typedef BOOL (WINAPI* PfnCryptCATAdminCalcHashFromFileHandle)(IN HANDLE hFile,
  41. IN OUT DWORD *pcbHash,
  42. OUT OPTIONAL BYTE *pbHash,
  43. IN DWORD dwFlags);
  44. // WinTrust.dll function prototypes
  45. typedef HRESULT (WINAPI* PfnWinVerifyTrust)(HWND hWnd,
  46. GUID *pgActionID,
  47. WINTRUST_DATA *pWinTrustData);
  48. // Crypt32.dll function prototypes
  49. typedef BOOL (WINAPI* PfnCertFreeCertificateContext)(IN PCCERT_CONTEXT pCertContext);
  50. struct DigiSignData
  51. {
  52. BOOL bInitialized;
  53. BOOL bFailed;
  54. // Need to LoadLibrary/GetProcAddress for mscat32 APIs since they
  55. // don't exist on Win95
  56. HINSTANCE hInstMsCat32;
  57. PfnCryptCATAdminAcquireContext CryptCATAdminAcquireContext;
  58. PfnCryptCATAdminReleaseContext CryptCATAdminReleaseContext;
  59. PfnCryptCATAdminReleaseCatalogContext CryptCATAdminReleaseCatalogContext;
  60. PfnCryptCATCatalogInfoFromContext CryptCATCatalogInfoFromContext;
  61. PfnCryptCATAdminEnumCatalogFromHash CryptCATAdminEnumCatalogFromHash;
  62. PfnIsCatalogFile IsCatalogFile;
  63. PfnCryptCATAdminCalcHashFromFileHandle CryptCATAdminCalcHashFromFileHandle;
  64. // Ditto for wintrust.dll APIs
  65. HINSTANCE hInstWinTrust;
  66. PfnWinVerifyTrust WinVerifyTrust;
  67. // Ditto for cypt32.dll APIs
  68. HINSTANCE hInstCrypt32;
  69. PfnCertFreeCertificateContext CertFreeCertificateContext;
  70. HCATADMIN hCatAdmin;
  71. };
  72. static DigiSignData s_dsd;
  73. static BOOL GetMediaPlayerFolder(TCHAR* pszPath);
  74. static BOOL FileIsSignedOld(LPTSTR lpszFile);
  75. static BOOL VerifyFileNode(TCHAR* lpFileName, TCHAR* lpDirName);
  76. static BOOL VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo);
  77. static BOOL InitDigiSignData(VOID);
  78. static BOOL IsFileDigitallySigned(TCHAR* pszFile);
  79. static BOOL IsBadWin95Winsock( FileInfo* pFileInfo );
  80. /****************************************************************************
  81. *
  82. * GetProgramFilesFolder
  83. *
  84. ****************************************************************************/
  85. VOID InitFileInfo()
  86. {
  87. ZeroMemory(&s_dsd, sizeof(s_dsd));
  88. s_dsd.bFailed = FALSE;
  89. s_dsd.bInitialized = FALSE;
  90. }
  91. /****************************************************************************
  92. *
  93. * GetProgramFilesFolder
  94. *
  95. ****************************************************************************/
  96. BOOL GetProgramFilesFolder(TCHAR* pszPath)
  97. {
  98. HKEY hkey;
  99. DWORD dwType;
  100. DWORD cb;
  101. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  102. TEXT("Software\\Microsoft\\Windows\\CurrentVersion"), &hkey))
  103. {
  104. return FALSE;
  105. }
  106. cb = MAX_PATH;
  107. RegQueryValueEx(hkey, TEXT("ProgramFilesDir"), NULL, &dwType, (LPBYTE)pszPath, &cb);
  108. RegCloseKey(hkey);
  109. if (cb == 0)
  110. return FALSE;
  111. return TRUE;
  112. }
  113. /****************************************************************************
  114. *
  115. * FormatFileTime
  116. *
  117. ****************************************************************************/
  118. VOID FormatFileTime(FILETIME* pUTCFileTime, TCHAR* pszDateLocal, TCHAR* pszDateEnglish)
  119. {
  120. FILETIME fileTimeLocal;
  121. SYSTEMTIME systemTime;
  122. TCHAR szTime[100];
  123. FileTimeToLocalFileTime(pUTCFileTime, &fileTimeLocal);
  124. FileTimeToSystemTime(&fileTimeLocal, &systemTime);
  125. wsprintf(pszDateEnglish, TEXT("%d/%d/%04d %02d:%02d:%02d"),
  126. systemTime.wMonth, systemTime.wDay, systemTime.wYear,
  127. systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
  128. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, NULL, pszDateLocal, 30);
  129. wsprintf(szTime, TEXT(" %02d:%02d:%02d"), systemTime.wHour,
  130. systemTime.wMinute, systemTime.wSecond);
  131. lstrcat(pszDateLocal, szTime);
  132. }
  133. /****************************************************************************
  134. *
  135. * GetMediaPlayerFolder
  136. *
  137. ****************************************************************************/
  138. BOOL GetMediaPlayerFolder(TCHAR* pszPath)
  139. {
  140. HKEY hkey;
  141. DWORD dwType;
  142. DWORD cb;
  143. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  144. TEXT("Software\\Microsoft\\MediaPlayer"), &hkey))
  145. {
  146. return FALSE;
  147. }
  148. cb = MAX_PATH;
  149. RegQueryValueEx(hkey, TEXT("Installation Directory"), NULL, &dwType, (LPBYTE)pszPath, &cb);
  150. RegCloseKey(hkey);
  151. if (cb == 0)
  152. return FALSE;
  153. return TRUE;
  154. }
  155. /****************************************************************************
  156. *
  157. * GetDxSetupFolder
  158. *
  159. ****************************************************************************/
  160. BOOL GetDxSetupFolder(TCHAR* pszPath)
  161. {
  162. if (!GetProgramFilesFolder(pszPath))
  163. return FALSE;
  164. lstrcat(pszPath, TEXT("\\DirectX\\Setup"));
  165. return TRUE;
  166. }
  167. /****************************************************************************
  168. *
  169. * GetComponentFiles
  170. *
  171. ****************************************************************************/
  172. HRESULT GetComponentFiles(TCHAR* pszFolder, FileInfo** ppFileInfoFirst,
  173. BOOL bSkipMissingFiles, LONG ids)
  174. {
  175. LONG cch;
  176. FileInfo* pFileInfo;
  177. FileInfo* pFileInfoNew;
  178. LONG iFile;
  179. TCHAR szFile[50];
  180. TCHAR szPath[MAX_PATH];
  181. TCHAR szComponentFiles[2048];
  182. TCHAR* pszFilePos;
  183. TCHAR* pszFilePos2;
  184. TCHAR* pszFirstParen;
  185. FLOAT fStartShipAt;
  186. FLOAT fStopShipAt;
  187. BOOL bDriversDir;
  188. BOOL bNTDriversDir;
  189. BOOL bIgnoreVersionInfo;
  190. BOOL bIgnoreDebug;
  191. BOOL bIgnoreBeta;
  192. BOOL bBDA;
  193. BOOL bNotIA64;
  194. BOOL bOptional;
  195. BOOL bOptionalOnNT;
  196. BOOL bOptionalOnWOW64;
  197. BOOL bIsNT = BIsPlatformNT();
  198. BOOL bIs95 = BIsWin95();
  199. cch = LoadString(NULL, ids, szComponentFiles, 2048);
  200. if (cch == 0 || cch >= 2047)
  201. return E_FAIL;
  202. pszFilePos = szComponentFiles;
  203. for (iFile = 0; ; iFile++)
  204. {
  205. // Stop if we've gone through the whole list
  206. if (pszFilePos == NULL)
  207. break;
  208. // Pull the next file out of the list
  209. pszFilePos2 = _tcsstr(pszFilePos, TEXT(","));
  210. if (pszFilePos2 == NULL)
  211. {
  212. lstrcpy(szFile, pszFilePos);
  213. pszFilePos = NULL;
  214. }
  215. else
  216. {
  217. _tcsncpy(szFile, pszFilePos, (DWORD)(pszFilePos2 - pszFilePos));
  218. szFile[pszFilePos2 - pszFilePos] = '\0';
  219. pszFilePos = pszFilePos2 + 1;
  220. }
  221. // Clear file flags
  222. fStartShipAt = 0.0f;
  223. fStopShipAt = 10000.0f;
  224. bDriversDir = FALSE;
  225. bNTDriversDir = FALSE;
  226. bIgnoreVersionInfo = FALSE;
  227. bIgnoreDebug = FALSE;
  228. bIgnoreBeta = FALSE;
  229. bBDA = FALSE;
  230. bNotIA64 = FALSE;
  231. bOptional = FALSE;
  232. bOptionalOnNT = FALSE;
  233. bOptionalOnWOW64 = FALSE;
  234. // Look at file flags, if any
  235. pszFirstParen = _tcsstr(szFile, TEXT("("));
  236. if (pszFirstParen != NULL)
  237. {
  238. // If this file does not exist on NT, and we are running NT, skip it.
  239. if (_tcsstr(pszFirstParen, TEXT("notNT")) != NULL && bIsNT)
  240. continue;
  241. // If this file does not exist on W95, and we are running W95, skip it.
  242. if (_tcsstr(pszFirstParen, TEXT("not95")) != NULL && bIs95)
  243. continue;
  244. // If this file only exists on W95, and we are not running W95, skip it.
  245. // Note: files like vjoyd.vxd may exist on Win98, but DX setup does not
  246. // install them or update them, so we ignore them.
  247. // Note: can't call this "95only" because it would clash with "5only"
  248. if (_tcsstr(pszFirstParen, TEXT("9fiveonly")) != NULL && !bIs95)
  249. continue;
  250. // Check for other flags
  251. if (_tcsstr(pszFirstParen, TEXT("+")) != NULL)
  252. {
  253. if (_tcsstr(pszFirstParen, TEXT("+5")) != NULL)
  254. fStartShipAt = 5.0f;
  255. else if (_tcsstr(pszFirstParen, TEXT("+61")) != NULL)
  256. fStartShipAt = 6.1f;
  257. else if (_tcsstr(pszFirstParen, TEXT("+6")) != NULL)
  258. fStartShipAt = 6.0f;
  259. else if (_tcsstr(pszFirstParen, TEXT("+71")) != NULL)
  260. fStartShipAt = 7.1f;
  261. else if (_tcsstr(pszFirstParen, TEXT("+7")) != NULL)
  262. fStartShipAt = 7.0f;
  263. else if (_tcsstr(pszFirstParen, TEXT("+81")) != NULL)
  264. fStartShipAt = 8.1f;
  265. else if (_tcsstr(pszFirstParen, TEXT("+8")) != NULL)
  266. fStartShipAt = 8.0f;
  267. }
  268. if (_tcsstr(pszFirstParen, TEXT("-")) != NULL)
  269. {
  270. if (_tcsstr(pszFirstParen, TEXT("-5")) != NULL)
  271. fStopShipAt = 5.0f;
  272. else if (_tcsstr(pszFirstParen, TEXT("-61")) != NULL)
  273. fStopShipAt = 6.1f;
  274. else if (_tcsstr(pszFirstParen, TEXT("-6")) != NULL)
  275. fStopShipAt = 6.0f;
  276. else if (_tcsstr(pszFirstParen, TEXT("-71")) != NULL)
  277. fStopShipAt = 7.1f;
  278. else if (_tcsstr(pszFirstParen, TEXT("-7")) != NULL)
  279. fStopShipAt = 7.0f;
  280. else if (_tcsstr(pszFirstParen, TEXT("-81")) != NULL)
  281. fStopShipAt = 8.1f;
  282. else if (_tcsstr(pszFirstParen, TEXT("-8")) != NULL)
  283. fStopShipAt = 8.0f;
  284. }
  285. // Note: can't call this "DriversDir" because it would clash with "NTDriversDir"
  286. if (_tcsstr(pszFirstParen, TEXT("DrivDir")) != NULL)
  287. bDriversDir = TRUE;
  288. if (_tcsstr(pszFirstParen, TEXT("NTDriversDir")) != NULL)
  289. bNTDriversDir = TRUE;
  290. if (_tcsstr(pszFirstParen, TEXT("SkipVer")) != NULL)
  291. bIgnoreVersionInfo = TRUE;
  292. if (_tcsstr(pszFirstParen, TEXT("SkipDebug")) != NULL)
  293. bIgnoreDebug = TRUE;
  294. if (_tcsstr(pszFirstParen, TEXT("SkipBeta")) != NULL)
  295. bIgnoreBeta = TRUE;
  296. if (_tcsstr(pszFirstParen, TEXT("notia64")) != NULL)
  297. bNotIA64 = TRUE;
  298. if (_tcsstr(pszFirstParen, TEXT("optnt")) != NULL)
  299. bOptionalOnNT = TRUE;
  300. else if (_tcsstr(pszFirstParen, TEXT("optwow")) != NULL)
  301. bOptionalOnWOW64 = TRUE;
  302. else if (_tcsstr(pszFirstParen, TEXT("opt")) != NULL)
  303. bOptional = TRUE;
  304. if (_tcsstr(pszFirstParen, TEXT("bda")) != NULL)
  305. {
  306. bBDA = TRUE;
  307. bOptional = TRUE;
  308. bIgnoreVersionInfo = TRUE;
  309. }
  310. // End file name at open parenthesis, if any:
  311. *pszFirstParen = TEXT('\0');
  312. }
  313. pFileInfoNew = new FileInfo;
  314. if (pFileInfoNew == NULL)
  315. return E_OUTOFMEMORY;
  316. ZeroMemory(pFileInfoNew, sizeof(FileInfo));
  317. pFileInfoNew->m_fStartShipAt = fStartShipAt;
  318. pFileInfoNew->m_fStopShipAt = fStopShipAt;
  319. pFileInfoNew->m_bIgnoreVersionInfo = bIgnoreVersionInfo;
  320. pFileInfoNew->m_bIgnoreDebug = bIgnoreDebug;
  321. pFileInfoNew->m_bIgnoreBeta = bIgnoreBeta;
  322. pFileInfoNew->m_bBDA = bBDA;
  323. pFileInfoNew->m_bNotIA64 = bNotIA64;
  324. pFileInfoNew->m_bOptional = bOptional;
  325. pFileInfoNew->m_bOptionalOnNT = bOptionalOnNT;
  326. pFileInfoNew->m_bOptionalOnWOW64 = bOptionalOnWOW64;
  327. lstrcpy(pFileInfoNew->m_szName, szFile);
  328. lstrcpy(szPath, pszFolder);
  329. lstrcat(szPath, TEXT("\\"));
  330. if (bNTDriversDir && bIsNT)
  331. lstrcat(szPath, TEXT("Drivers\\"));
  332. else if (bDriversDir)
  333. lstrcat(szPath, TEXT("..\\System32\\Drivers\\"));
  334. lstrcat(szPath, szFile);
  335. WIN32_FIND_DATA findFileData;
  336. HANDLE hFind = FindFirstFile(szPath, &findFileData);
  337. if (hFind == INVALID_HANDLE_VALUE)
  338. {
  339. if (bSkipMissingFiles)
  340. {
  341. delete pFileInfoNew;
  342. continue;
  343. }
  344. }
  345. else
  346. {
  347. pFileInfoNew->m_bExists = TRUE;
  348. FindClose(hFind);
  349. }
  350. if (pFileInfoNew->m_bExists)
  351. {
  352. pFileInfoNew->m_numBytes = findFileData.nFileSizeLow;
  353. pFileInfoNew->m_FileTime = findFileData.ftLastWriteTime;
  354. FormatFileTime(&findFileData.ftLastWriteTime, pFileInfoNew->m_szDatestampLocal,
  355. pFileInfoNew->m_szDatestamp);
  356. GetFileVersion(szPath, pFileInfoNew->m_szVersion, pFileInfoNew->m_szAttributes,
  357. pFileInfoNew->m_szLanguageLocal, pFileInfoNew->m_szLanguage, &pFileInfoNew->m_bBeta, &pFileInfoNew->m_bDebug);
  358. }
  359. if (*ppFileInfoFirst == NULL)
  360. *ppFileInfoFirst = pFileInfoNew;
  361. else
  362. {
  363. for (pFileInfo = *ppFileInfoFirst;
  364. pFileInfo->m_pFileInfoNext != NULL;
  365. pFileInfo = pFileInfo->m_pFileInfoNext)
  366. {
  367. }
  368. pFileInfo->m_pFileInfoNext = pFileInfoNew;
  369. }
  370. }
  371. return S_OK;
  372. }
  373. /****************************************************************************
  374. *
  375. * DestroyFileList
  376. *
  377. ****************************************************************************/
  378. VOID DestroyFileList(FileInfo* pFileInfoFirst)
  379. {
  380. FileInfo* pFileInfo;
  381. FileInfo* pFileInfoNext;
  382. for (pFileInfo = pFileInfoFirst; pFileInfo != NULL; pFileInfo = pFileInfoNext)
  383. {
  384. pFileInfoNext = pFileInfo->m_pFileInfoNext;
  385. delete pFileInfo;
  386. }
  387. }
  388. /****************************************************************************
  389. *
  390. * GetFileDateAndSize
  391. *
  392. ****************************************************************************/
  393. BOOL GetFileDateAndSize(TCHAR* pszFile, TCHAR* pszDateLocal, TCHAR* pszDateEnglish,
  394. LONG* pnumBytes)
  395. {
  396. WIN32_FIND_DATA findFileData;
  397. HANDLE hFind;
  398. pszDateLocal[0] = '\0';
  399. pszDateEnglish[0] = '\0';
  400. *pnumBytes = 0;
  401. hFind = FindFirstFile(pszFile, &findFileData);
  402. if (hFind == INVALID_HANDLE_VALUE)
  403. return FALSE; // file not found
  404. FindClose(hFind);
  405. *pnumBytes = findFileData.nFileSizeLow;
  406. FormatFileTime(&findFileData.ftLastWriteTime, pszDateLocal, pszDateEnglish);
  407. return TRUE;
  408. }
  409. /****************************************************************************
  410. *
  411. * GetFileVersion
  412. *
  413. ****************************************************************************/
  414. HRESULT GetFileVersion(TCHAR* pszFile, TCHAR* pszVersion, TCHAR* pszAttributes,
  415. TCHAR* pszLanguageLocal, TCHAR* pszLanguage, BOOL* pbBeta, BOOL* pbDebug)
  416. {
  417. UINT cb;
  418. DWORD dwHandle;
  419. BYTE FileVersionBuffer[4096];
  420. VS_FIXEDFILEINFO* pVersion = NULL;
  421. DWORD dwVersionAttribs = 0; // DEBUG, RETAIL, etc.
  422. DWORD* pdwCharSet = NULL;
  423. WORD wLanguage;
  424. LCID lcid;
  425. TCHAR szDebug[100];
  426. TCHAR szRetail[100];
  427. TCHAR szBeta[100];
  428. TCHAR szFinal[100];
  429. TCHAR szCombineFmt[100];
  430. LoadString(NULL, IDS_DEBUG, szDebug, 100);
  431. LoadString(NULL, IDS_RETAIL, szRetail, 100);
  432. LoadString(NULL, IDS_BETA, szBeta, 100);
  433. LoadString(NULL, IDS_FINAL, szFinal, 100);
  434. LoadString(NULL, IDS_ATTRIBCOMBINE, szCombineFmt, 100);
  435. cb = GetFileVersionInfoSize(pszFile, &dwHandle/*ignored*/);
  436. if (cb > 0)
  437. {
  438. if (cb > sizeof(FileVersionBuffer))
  439. cb = sizeof(FileVersionBuffer);
  440. if (GetFileVersionInfo(pszFile, 0, cb, &FileVersionBuffer))
  441. {
  442. pVersion = NULL;
  443. if (VerQueryValue(&FileVersionBuffer, TEXT("\\"), (VOID**)&pVersion, &cb)
  444. && pVersion != NULL)
  445. {
  446. if (pszVersion != NULL)
  447. {
  448. wsprintf(pszVersion, TEXT("%d.%02d.%02d.%04d"),
  449. HIWORD(pVersion->dwFileVersionMS),
  450. LOWORD(pVersion->dwFileVersionMS),
  451. HIWORD(pVersion->dwFileVersionLS),
  452. LOWORD(pVersion->dwFileVersionLS));
  453. }
  454. if (pszAttributes != NULL)
  455. {
  456. dwVersionAttribs = pVersion->dwFileFlags;
  457. // Bug 18892: work around DPlay 6.0a
  458. if (pVersion->dwFileVersionMS == 0x00040006 &&
  459. (pVersion->dwFileVersionLS == 0x0002016b || // 4.06.02.0363
  460. pVersion->dwFileVersionLS == 0x00020164)) // 4.06.02.0356
  461. {
  462. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  463. }
  464. if (pszVersion != NULL)
  465. {
  466. TCHAR* pszLeaf = _tcsrchr(pszFile, TEXT('\\'));
  467. if( pszLeaf )
  468. {
  469. pszLeaf++;
  470. // Work around several DXMedia files which are incorrectly marked as beta
  471. if (lstrcmp(pszLeaf, TEXT("oleaut32.dll")) == 0)
  472. {
  473. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  474. }
  475. else if (lstrcmp(pszLeaf, TEXT("quartz.dll")) == 0 &&
  476. lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0)
  477. {
  478. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  479. }
  480. else if (lstrcmp(pszLeaf, TEXT("quartz.vxd")) == 0 &&
  481. lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0)
  482. {
  483. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  484. }
  485. else if (lstrcmp(pszLeaf, TEXT("mciqtz.drv")) == 0 &&
  486. lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0)
  487. {
  488. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  489. }
  490. else if (lstrcmp(pszLeaf, TEXT("mciqtz32.dll")) == 0 &&
  491. lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0)
  492. {
  493. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  494. }
  495. else if (lstrcmp(pszLeaf, TEXT("actmovie.exe")) == 0)
  496. {
  497. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  498. }
  499. else if (lstrcmp(pszLeaf, TEXT("strmdll.dll")) == 0)
  500. {
  501. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  502. }
  503. else if (lstrcmp(pszLeaf, TEXT("unam4ie.exe")) == 0 &&
  504. lstrcmp(pszVersion, TEXT("6.00.02.0902")) == 0)
  505. {
  506. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  507. }
  508. else if (lstrcmp(pszLeaf, TEXT("unam4ie.exe")) == 0 &&
  509. lstrcmp(pszVersion, TEXT("5.01.18.1024")) == 0)
  510. {
  511. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  512. }
  513. else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 &&
  514. lstrcmp(pszVersion, TEXT("2.00.05.0050")) == 0)
  515. {
  516. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  517. }
  518. else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 &&
  519. lstrcmp(pszVersion, TEXT("2.00.05.0052")) == 0)
  520. {
  521. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  522. }
  523. else if (lstrcmp(pszLeaf, TEXT("tm20dec.ax")) == 0)
  524. {
  525. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  526. }
  527. else if (lstrcmp(pszLeaf, TEXT("tm20dec.ax")) == 0 &&
  528. lstrcmp(pszVersion, TEXT("1.00.00.0000")) == 0)
  529. {
  530. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  531. }
  532. else if (lstrcmp(pszLeaf, TEXT("msdxm.ocx")) == 0)
  533. {
  534. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  535. }
  536. else if (lstrcmp(pszLeaf, TEXT("dxmasf.dll")) == 0)
  537. {
  538. dwVersionAttribs &= ~VS_FF_PRERELEASE;
  539. }
  540. else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 &&
  541. lstrcmp(pszVersion, TEXT("2.00.05.0053")) == 0)
  542. {
  543. dwVersionAttribs &= ~VS_FF_PRERELEASE; // Since 350883 got punted
  544. }
  545. }
  546. wsprintf(pszAttributes, szCombineFmt,
  547. (dwVersionAttribs & VS_FF_PRERELEASE ? szBeta : szFinal),
  548. (dwVersionAttribs & VS_FF_DEBUG ? szDebug : szRetail));
  549. if (pbBeta != NULL)
  550. *pbBeta = (dwVersionAttribs & VS_FF_PRERELEASE) ? TRUE : FALSE;
  551. if (pbDebug != NULL)
  552. *pbDebug = (dwVersionAttribs & VS_FF_DEBUG) ? TRUE : FALSE;
  553. }
  554. }
  555. }
  556. if (pszLanguage != NULL)
  557. {
  558. if (VerQueryValue(&FileVersionBuffer, TEXT("\\VarFileInfo\\Translation"), (VOID**)&pdwCharSet, &cb)
  559. && pdwCharSet && cb)
  560. {
  561. wLanguage = LOWORD(*pdwCharSet);
  562. lcid = MAKELCID(wLanguage, SORT_DEFAULT);
  563. GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, pszLanguage, 100);
  564. if (pszLanguageLocal != NULL)
  565. {
  566. GetLocaleInfo(lcid, LOCALE_SLANGUAGE, pszLanguageLocal, 100);
  567. // Show "English", not "English (United States)". I can't
  568. // find a better way to do this (such that it localizes properly)
  569. TCHAR* pszSublanguage;
  570. pszSublanguage = _tcsstr(pszLanguageLocal, TEXT(" ("));
  571. if (pszSublanguage != NULL)
  572. *pszSublanguage = '\0';
  573. }
  574. }
  575. }
  576. }
  577. }
  578. else
  579. {
  580. TCHAR* pszLeaf = _tcsrchr(pszFile, TEXT('\\'));
  581. if( pszLeaf )
  582. {
  583. pszLeaf++;
  584. if (lstrcmpi(pszLeaf, TEXT("vidx16.dll")) == 0)
  585. {
  586. if (pszVersion != NULL)
  587. lstrcpy(pszVersion, TEXT("0.00.00.0000"));
  588. if (pszAttributes != NULL)
  589. wsprintf(pszAttributes, TEXT("%s %s"), szFinal, szRetail);
  590. if (pszLanguage != NULL)
  591. {
  592. wLanguage = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  593. lcid = MAKELCID(wLanguage, SORT_DEFAULT);
  594. GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, pszLanguage, 100);
  595. if (pszLanguageLocal != NULL)
  596. {
  597. GetLocaleInfo(lcid, LOCALE_SLANGUAGE, pszLanguageLocal, 100);
  598. // Show "English", not "English (United States)". I can't
  599. // find a better way to do this (such that it localizes properly)
  600. TCHAR* pszSublanguage;
  601. pszSublanguage = _tcsstr(pszLanguageLocal, TEXT(" ("));
  602. if (pszSublanguage != NULL)
  603. *pszSublanguage = '\0';
  604. }
  605. }
  606. }
  607. }
  608. }
  609. return S_OK;
  610. }
  611. /****************************************************************************
  612. *
  613. * GetLanguageFromFile
  614. *
  615. ****************************************************************************/
  616. WORD GetLanguageFromFile(const TCHAR* pszFileName, const TCHAR* pszPath)
  617. {
  618. BYTE FileVersionBuffer[4096];
  619. DWORD *pdwCharSet;
  620. UINT cb;
  621. DWORD dwHandle;
  622. TCHAR szFileAndPath[MAX_PATH];
  623. WORD wLanguage;
  624. lstrcpy(szFileAndPath, pszPath);
  625. lstrcat(szFileAndPath, TEXT("\\"));
  626. lstrcat(szFileAndPath, pszFileName);
  627. memset(&FileVersionBuffer, 0, sizeof FileVersionBuffer);
  628. wLanguage = 0;
  629. if (cb = GetFileVersionInfoSize(szFileAndPath, &dwHandle/*ignored*/))
  630. {
  631. cb = (cb <= sizeof FileVersionBuffer ? cb : sizeof FileVersionBuffer);
  632. if (GetFileVersionInfo(szFileAndPath, 0, cb, &FileVersionBuffer))
  633. {
  634. pdwCharSet = 0;
  635. if (VerQueryValue(&FileVersionBuffer, TEXT("\\VarFileInfo\\Translation"), (void**)&pdwCharSet, &cb)
  636. && pdwCharSet && cb)
  637. {
  638. wLanguage = LOWORD(*pdwCharSet);
  639. }
  640. }
  641. }
  642. return wLanguage;
  643. }
  644. struct DLSVERSION
  645. {
  646. DWORD dwVersionMS;
  647. DWORD dwVersionLS;
  648. };
  649. #define FOURCC_VERS mmioFOURCC('v','e','r','s')
  650. /****************************************************************************
  651. *
  652. * GetRiffFileVersion
  653. *
  654. ****************************************************************************/
  655. HRESULT GetRiffFileVersion(TCHAR* pszFile, TCHAR* pszVersion)
  656. {
  657. MMIOINFO mmio;
  658. MMCKINFO mmck1;
  659. MMCKINFO mmck2;
  660. DLSVERSION dlsver;
  661. HMMIO hDLS;
  662. // DLS file has different version scheme since it's a riff file.
  663. // So retrieve version info from 'vers' chunk.
  664. ZeroMemory(&mmio, sizeof(MMIOINFO));
  665. hDLS = mmioOpen(pszFile,&mmio,MMIO_READ);
  666. if (hDLS == NULL)
  667. {
  668. return E_FAIL;
  669. }
  670. // read riff chunk
  671. ZeroMemory(&mmck1,sizeof(MMCKINFO));
  672. if (mmioDescend(hDLS,
  673. &mmck1,
  674. NULL,
  675. MMIO_FINDRIFF) != MMSYSERR_NOERROR)
  676. {
  677. mmioClose(hDLS,0);
  678. return E_FAIL;
  679. }
  680. ZeroMemory(&mmck2,sizeof(MMCKINFO));
  681. mmck2.ckid = FOURCC_VERS;
  682. if (mmioDescend(hDLS,
  683. &mmck2,
  684. &mmck1,
  685. MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
  686. {
  687. mmioClose(hDLS,0);
  688. return E_FAIL;
  689. }
  690. if (mmioRead(hDLS,
  691. (HPSTR)&dlsver,
  692. sizeof(DLSVERSION)) != sizeof(DLSVERSION))
  693. {
  694. mmioClose(hDLS,0);
  695. return E_FAIL;
  696. }
  697. wsprintf(pszVersion, TEXT("%d.%02d.%02d.%04d"),
  698. HIWORD(dlsver.dwVersionMS),
  699. LOWORD(dlsver.dwVersionMS),
  700. HIWORD(dlsver.dwVersionLS),
  701. LOWORD(dlsver.dwVersionLS));
  702. mmioClose(hDLS,0);
  703. return S_OK;
  704. }
  705. /****************************************************************************
  706. *
  707. * FileIsSigned - use digital signature on all OSs
  708. *
  709. ****************************************************************************/
  710. VOID FileIsSigned(LPTSTR lpszFile, BOOL* pbSigned, BOOL* pbIsValid)
  711. {
  712. // Look for digital sig
  713. if( !InitDigiSignData() )
  714. {
  715. if( pbSigned )
  716. *pbSigned = FALSE;
  717. if( pbIsValid )
  718. *pbIsValid = FALSE;
  719. return;
  720. }
  721. if( pbSigned )
  722. *pbSigned = IsFileDigitallySigned(lpszFile);
  723. if( pbIsValid )
  724. *pbIsValid = TRUE;
  725. }
  726. // 5/12/97(RichGr): From Eric's dsetup16.c.
  727. // * 14-sep-95 ericeng directdraw signed tests, drivers failing dll tests are removed from list
  728. /****************************************************************************
  729. *
  730. * FileIsSignedOld
  731. *
  732. ****************************************************************************/
  733. BOOL FileIsSignedOld(LPTSTR lpszFile)
  734. {
  735. typedef struct tagIMAGE_DOS_HEADER // DOS .EXE header
  736. {
  737. WORD e_magic; // Magic number
  738. WORD e_cblp; // Bytes on last page of file
  739. WORD e_cp; // Pages in file
  740. WORD e_crlc; // Relocations
  741. WORD e_cparhdr; // Size of header in paragraphs
  742. WORD e_minalloc; // Minimum extra paragraphs needed
  743. WORD e_maxalloc; // Maximum extra paragraphs needed
  744. WORD e_ss; // Initial (relative) SS value
  745. WORD e_sp; // Initial SP value
  746. WORD e_csum; // Checksum
  747. WORD e_ip; // Initial IP value
  748. WORD e_cs; // Initial (relative) CS value
  749. WORD e_lfarlc; // File address of relocation table
  750. WORD e_ovno; // Overlay number
  751. WORD e_res[4]; // Reserved words
  752. WORD e_oemid; // OEM identifier (for e_oeminfo)
  753. WORD e_oeminfo; // OEM information; e_oemid specific
  754. WORD e_res2[10]; // Reserved words
  755. LONG e_lfanew; // File address of new exe header
  756. } IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER, FAR* LPIMAGE_DOS_HEADER;
  757. typedef struct tagIMAGE_OS2_HEADER // OS/2 .EXE header
  758. {
  759. WORD ne_magic; // Magic number
  760. CHAR ne_ver; // Version number
  761. CHAR ne_rev; // Revision number
  762. WORD ne_enttab; // Offset of Entry Table
  763. WORD ne_cbenttab; // Number of bytes in Entry Table
  764. LONG ne_crc; // Checksum of whole file
  765. WORD ne_flags; // Flag word
  766. WORD ne_autodata; // Automatic data segment number
  767. WORD ne_heap; // Initial heap allocation
  768. WORD ne_stack; // Initial stack allocation
  769. LONG ne_csip; // Initial CS:IP setting
  770. LONG ne_sssp; // Initial SS:SP setting
  771. WORD ne_cseg; // Count of file segments
  772. WORD ne_cmod; // Entries in Module Reference Table
  773. WORD ne_cbnrestab; // Size of non-resident name table
  774. WORD ne_segtab; // Offset of Segment Table
  775. WORD ne_rsrctab; // Offset of Resource Table
  776. WORD ne_restab; // Offset of resident name table
  777. WORD ne_modtab; // Offset of Module Reference Table
  778. WORD ne_imptab; // Offset of Imported Names Table
  779. LONG ne_nrestab; // Offset of Non-resident Names Table
  780. WORD ne_cmovent; // Count of movable entries
  781. WORD ne_align; // Segment alignment shift count
  782. WORD ne_cres; // Count of resource segments
  783. BYTE ne_exetyp; // Target Operating system
  784. BYTE ne_flagsothers; // Other .EXE flags
  785. WORD ne_pretthunks; // offset to return thunks
  786. WORD ne_psegrefbytes; // offset to segment ref. bytes
  787. WORD ne_swaparea; // Minimum code swap area size
  788. WORD ne_expver; // Expected Windows version number
  789. } IMAGE_OS2_HEADER, * PIMAGE_OS2_HEADER, FAR* LPIMAGE_OS2_HEADER;
  790. typedef struct tagWINSTUB
  791. {
  792. IMAGE_DOS_HEADER idh;
  793. BYTE rgb[14];
  794. } WINSTUB, * PWINSTUB, FAR* LPWINSTUB;
  795. typedef struct tagFILEINFO
  796. {
  797. BYTE cbInfo[0x120];
  798. } FILEINFO, * PFILEINFO, FAR* LPFILEINFO;
  799. FILE * pf;
  800. int nRC;
  801. FILEINFO fi;
  802. LPIMAGE_DOS_HEADER lpmz;
  803. // LPIMAGE_OS2_HEADER lpne;
  804. BYTE cbInfo[9+32+2];
  805. BOOL IsSigned = FALSE;
  806. static WINSTUB winstub = {
  807. {
  808. IMAGE_DOS_SIGNATURE, /* magic */
  809. 0, /* bytes on last page - varies */
  810. 0, /* pages in file - varies */
  811. 0, /* relocations */
  812. 4, /* paragraphs in header */
  813. 1, /* min allocation */
  814. 0xFFFF, /* max allocation */
  815. 0, /* initial SS */
  816. 0xB8, /* initial SP */
  817. 0, /* checksum (ha!) */
  818. 0, /* initial IP */
  819. 0, /* initial CS */
  820. 0x40, /* lfarlc */
  821. 0, /* overlay number */
  822. { 0, 0, 0, 0}, /* reserved */
  823. 0, /* oem id */
  824. 0, /* oem info */
  825. 0, /* compiler bug */
  826. { 0}, /* reserved */
  827. 0x80, /* lfanew */
  828. },
  829. {
  830. 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
  831. 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21,
  832. }
  833. };
  834. pf = _tfopen(lpszFile, TEXT("rb"));
  835. if (pf==0)
  836. {
  837. return FALSE;
  838. }
  839. nRC = fread(&fi, sizeof(BYTE), sizeof(FILEINFO), pf);
  840. if (nRC != sizeof(FILEINFO))
  841. {
  842. goto FileIsSigned_exit;
  843. }
  844. lpmz = (LPIMAGE_DOS_HEADER)(&fi);
  845. // lpne = (LPIMAGE_OS2_HEADER)((WORD)&fi + 0x80);
  846. winstub.idh.e_cblp = lpmz->e_cblp;
  847. winstub.idh.e_cp = lpmz->e_cp;
  848. if (memcmp(&fi, &winstub, sizeof(winstub)) == 0)
  849. {
  850. goto FileIsSigned_exit;
  851. }
  852. // if (lpne->ne_magic == IMAGE_OS2_SIGNATURE ||
  853. // lpne->ne_magic == IMAGE_VXD_SIGNATURE ||
  854. // lpne->ne_magic == IMAGE_NT_SIGNATURE)
  855. // {
  856. // DPF(0, "Found a match in the OS2 header");
  857. // }
  858. // else
  859. // {
  860. // DPF(0, "Didn't meet second criteria!!!");
  861. // goto FileIsSigned_exit;
  862. // }
  863. memcpy(cbInfo, &((PWINSTUB)(&fi)->cbInfo)->rgb[14], sizeof(cbInfo));
  864. if ( (cbInfo[4] != ' ' ) || // space
  865. (cbInfo[8] != ' ' ) || // space
  866. (cbInfo[9+32] != '\n') || // return
  867. (cbInfo[9+32+1] != '$' ) ) // Dollar Sign
  868. {
  869. goto FileIsSigned_exit;
  870. }
  871. cbInfo[4] = 0;
  872. cbInfo[8] = 0;
  873. if ( (strcmp((const char*)&cbInfo[0], "Cert") != 0) ||
  874. (strcmp((const char*)&cbInfo[5], "DX2") != 0) )
  875. {
  876. goto FileIsSigned_exit;
  877. }
  878. IsSigned=TRUE;
  879. FileIsSigned_exit:
  880. fclose(pf);
  881. return IsSigned;
  882. }
  883. /****************************************************************************
  884. *
  885. * InitDigiSignData
  886. *
  887. ****************************************************************************/
  888. BOOL InitDigiSignData(VOID)
  889. {
  890. TCHAR szPath[MAX_PATH];
  891. if( s_dsd.bInitialized )
  892. return TRUE;
  893. if( s_dsd.bFailed )
  894. return FALSE;
  895. ZeroMemory(&s_dsd, sizeof(s_dsd));
  896. GetSystemDirectory(szPath, MAX_PATH);
  897. lstrcat(szPath, TEXT("\\mscat32.dll"));
  898. s_dsd.hInstMsCat32 = LoadLibrary(szPath);
  899. if (s_dsd.hInstMsCat32 == NULL)
  900. {
  901. s_dsd.bFailed = TRUE;
  902. return FALSE;
  903. }
  904. s_dsd.CryptCATAdminAcquireContext = (PfnCryptCATAdminAcquireContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminAcquireContext");
  905. if (s_dsd.CryptCATAdminAcquireContext == NULL)
  906. {
  907. s_dsd.bFailed = TRUE;
  908. return FALSE;
  909. }
  910. s_dsd.CryptCATAdminReleaseContext = (PfnCryptCATAdminReleaseContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminReleaseContext");
  911. if (s_dsd.CryptCATAdminReleaseContext == NULL)
  912. {
  913. s_dsd.bFailed = TRUE;
  914. return FALSE;
  915. }
  916. s_dsd.CryptCATAdminReleaseCatalogContext = (PfnCryptCATAdminReleaseCatalogContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminReleaseCatalogContext");
  917. if (s_dsd.CryptCATAdminReleaseCatalogContext == NULL)
  918. {
  919. s_dsd.bFailed = TRUE;
  920. return FALSE;
  921. }
  922. s_dsd.CryptCATCatalogInfoFromContext = (PfnCryptCATCatalogInfoFromContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATCatalogInfoFromContext");
  923. if (s_dsd.CryptCATCatalogInfoFromContext == NULL)
  924. {
  925. s_dsd.bFailed = TRUE;
  926. return FALSE;
  927. }
  928. s_dsd.CryptCATAdminEnumCatalogFromHash = (PfnCryptCATAdminEnumCatalogFromHash)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminEnumCatalogFromHash");
  929. if (s_dsd.CryptCATAdminEnumCatalogFromHash == NULL)
  930. {
  931. s_dsd.bFailed = TRUE;
  932. return FALSE;
  933. }
  934. s_dsd.IsCatalogFile = (PfnIsCatalogFile)GetProcAddress(s_dsd.hInstMsCat32, "IsCatalogFile");
  935. if (s_dsd.IsCatalogFile == NULL)
  936. {
  937. s_dsd.bFailed = TRUE;
  938. return FALSE;
  939. }
  940. s_dsd.CryptCATAdminCalcHashFromFileHandle = (PfnCryptCATAdminCalcHashFromFileHandle)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminCalcHashFromFileHandle");
  941. if (s_dsd.CryptCATAdminCalcHashFromFileHandle == NULL)
  942. {
  943. s_dsd.bFailed = TRUE;
  944. return FALSE;
  945. }
  946. if (!s_dsd.CryptCATAdminAcquireContext(&s_dsd.hCatAdmin, NULL, 0))
  947. {
  948. s_dsd.bFailed = TRUE;
  949. return FALSE;
  950. }
  951. GetSystemDirectory(szPath, MAX_PATH);
  952. lstrcat(szPath, TEXT("\\wintrust.dll"));
  953. s_dsd.hInstWinTrust = LoadLibrary(szPath);
  954. if (s_dsd.hInstWinTrust == NULL)
  955. {
  956. s_dsd.bFailed = TRUE;
  957. return FALSE;
  958. }
  959. s_dsd.WinVerifyTrust = (PfnWinVerifyTrust)GetProcAddress(s_dsd.hInstWinTrust, "WinVerifyTrust");
  960. if (s_dsd.WinVerifyTrust == NULL)
  961. {
  962. s_dsd.bFailed = TRUE;
  963. return FALSE;
  964. }
  965. GetSystemDirectory(szPath, MAX_PATH);
  966. lstrcat(szPath, TEXT("\\crypt32.dll"));
  967. s_dsd.hInstCrypt32 = LoadLibrary(szPath);
  968. if (s_dsd.hInstCrypt32 == NULL)
  969. {
  970. s_dsd.bFailed = TRUE;
  971. return FALSE;
  972. }
  973. s_dsd.CertFreeCertificateContext = (PfnCertFreeCertificateContext)GetProcAddress(s_dsd.hInstCrypt32, "CertFreeCertificateContext");
  974. if (s_dsd.CertFreeCertificateContext == NULL)
  975. {
  976. s_dsd.bFailed = TRUE;
  977. return FALSE;
  978. }
  979. s_dsd.bFailed = FALSE;
  980. s_dsd.bInitialized = TRUE;
  981. return TRUE;
  982. }
  983. /****************************************************************************
  984. *
  985. * ReleaseDigiSignData
  986. *
  987. ****************************************************************************/
  988. VOID ReleaseDigiSignData(VOID)
  989. {
  990. if( s_dsd.CryptCATAdminReleaseContext && s_dsd.hCatAdmin )
  991. s_dsd.CryptCATAdminReleaseContext(s_dsd.hCatAdmin,0);
  992. if (s_dsd.hInstMsCat32 != NULL)
  993. FreeLibrary(s_dsd.hInstMsCat32);
  994. if (s_dsd.hInstWinTrust != NULL)
  995. FreeLibrary(s_dsd.hInstWinTrust);
  996. if (s_dsd.hInstCrypt32 != NULL)
  997. FreeLibrary(s_dsd.hInstCrypt32);
  998. ZeroMemory(&s_dsd, sizeof(s_dsd));
  999. }
  1000. /****************************************************************************
  1001. *
  1002. * IsFileDigitallySigned
  1003. *
  1004. ****************************************************************************/
  1005. BOOL IsFileDigitallySigned(TCHAR* pszFile)
  1006. {
  1007. if (!s_dsd.bInitialized)
  1008. return FALSE;
  1009. TCHAR lpFileName[MAX_PATH];
  1010. TCHAR lpDirName[MAX_PATH];
  1011. TCHAR* pch;
  1012. lstrcpy(lpDirName, pszFile);
  1013. CharLowerBuff(lpDirName, lstrlen(lpDirName));
  1014. pch = _tcsrchr(lpDirName, TEXT('\\'));
  1015. // 22670: There *should* be a backslash in pszFile, but cope if it isn't
  1016. if (pch == NULL)
  1017. {
  1018. lstrcpy(lpFileName, pszFile);
  1019. GetCurrentDirectory(MAX_PATH, lpDirName);
  1020. }
  1021. else
  1022. {
  1023. lstrcpy(lpFileName, pch + 1);
  1024. *pch = TEXT('\0');
  1025. }
  1026. if (_tcsstr(lpDirName, TEXT("\\")) == NULL)
  1027. lstrcat(lpDirName, TEXT("\\"));
  1028. return VerifyFileNode(lpFileName, lpDirName);
  1029. }
  1030. /****************************************************************************
  1031. *
  1032. * VerifyFileNode
  1033. *
  1034. ****************************************************************************/
  1035. BOOL VerifyFileNode(TCHAR* lpFileName, TCHAR* lpDirName)
  1036. {
  1037. const DWORD HASH_SIZE = 100;
  1038. HANDLE hFile;
  1039. BOOL bRet;
  1040. HCATINFO hCatInfo = NULL;
  1041. HCATINFO PrevCat;
  1042. WINTRUST_DATA WinTrustData;
  1043. WINTRUST_CATALOG_INFO WinTrustCatalogInfo;
  1044. DRIVER_VER_INFO VerInfo;
  1045. GUID guidSubSystemDriver = DRIVER_ACTION_VERIFY;
  1046. HRESULT hRes;
  1047. DWORD cbHash = HASH_SIZE;
  1048. BYTE szHash[HASH_SIZE];
  1049. LPBYTE lpHash = szHash;
  1050. CATALOG_INFO CatInfo;
  1051. #ifndef UNICODE
  1052. WCHAR UnicodeKey[MAX_PATH];
  1053. #endif
  1054. BOOL bSigned = FALSE;
  1055. TCHAR szFullPath[MAX_PATH];
  1056. wsprintf(szFullPath, TEXT("%s\\%s"), lpDirName, lpFileName);
  1057. //
  1058. // Get the handle to the file, so we can call CryptCATAdminCalcHashFromFileHandle
  1059. //
  1060. hFile = CreateFile( szFullPath,
  1061. GENERIC_READ,
  1062. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1063. NULL,
  1064. OPEN_EXISTING,
  1065. FILE_ATTRIBUTE_NORMAL,
  1066. NULL);
  1067. if (hFile == INVALID_HANDLE_VALUE)
  1068. {
  1069. return FALSE;
  1070. }
  1071. // Initialize the hash buffer
  1072. ZeroMemory(lpHash, HASH_SIZE);
  1073. // Generate the hash from the file handle and store it in lpHash
  1074. if (!s_dsd.CryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, lpHash, 0))
  1075. {
  1076. //
  1077. // If we couldn't generate a hash, it might be an individually signed catalog.
  1078. // If it's a catalog, zero out lpHash and cbHash so we know there's no hash to check.
  1079. //
  1080. if (s_dsd.IsCatalogFile(hFile, NULL))
  1081. {
  1082. lpHash = NULL;
  1083. cbHash = 0;
  1084. }
  1085. else // If it wasn't a catalog, we'll bail and this file will show up as unscanned.
  1086. {
  1087. CloseHandle(hFile);
  1088. return FALSE;
  1089. }
  1090. }
  1091. // Close the file handle
  1092. CloseHandle(hFile);
  1093. //
  1094. // Now we have the file's hash. Initialize the structures that
  1095. // will be used later on in calls to WinVerifyTrust.
  1096. //
  1097. ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
  1098. WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
  1099. WinTrustData.dwUIChoice = WTD_UI_NONE;
  1100. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  1101. WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
  1102. WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  1103. WinTrustData.pPolicyCallbackData = (LPVOID)&VerInfo;
  1104. ZeroMemory(&VerInfo, sizeof(DRIVER_VER_INFO));
  1105. VerInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  1106. OSVERSIONINFO osvi;
  1107. ZeroMemory(&osvi, sizeof(osvi));
  1108. osvi.dwOSVersionInfoSize = sizeof(osvi);
  1109. if (GetVersionEx(&osvi))
  1110. {
  1111. VerInfo.dwPlatform = osvi.dwPlatformId;
  1112. VerInfo.dwVersion = osvi.dwMajorVersion;
  1113. VerInfo.sOSVersionLow.dwMajor = osvi.dwMajorVersion;
  1114. VerInfo.sOSVersionLow.dwMinor = osvi.dwMinorVersion;
  1115. VerInfo.sOSVersionHigh.dwMajor = osvi.dwMajorVersion;
  1116. VerInfo.sOSVersionHigh.dwMinor = osvi.dwMinorVersion;
  1117. }
  1118. WinTrustData.pCatalog = &WinTrustCatalogInfo;
  1119. ZeroMemory(&WinTrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
  1120. WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
  1121. WinTrustCatalogInfo.pbCalculatedFileHash = lpHash;
  1122. WinTrustCatalogInfo.cbCalculatedFileHash = cbHash;
  1123. #ifdef UNICODE
  1124. WinTrustCatalogInfo.pcwszMemberTag = lpFileName;
  1125. #else
  1126. MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, UnicodeKey, MAX_PATH);
  1127. WinTrustCatalogInfo.pcwszMemberTag = UnicodeKey;
  1128. #endif
  1129. //
  1130. // Now we try to find the file hash in the catalog list, via CryptCATAdminEnumCatalogFromHash
  1131. //
  1132. PrevCat = NULL;
  1133. hCatInfo = s_dsd.CryptCATAdminEnumCatalogFromHash(s_dsd.hCatAdmin, lpHash, cbHash, 0, &PrevCat);
  1134. //
  1135. // We want to cycle through the matching catalogs until we find one that matches both hash and member tag
  1136. //
  1137. bRet = FALSE;
  1138. while(hCatInfo && !bRet)
  1139. {
  1140. ZeroMemory(&CatInfo, sizeof(CATALOG_INFO));
  1141. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  1142. if(s_dsd.CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0))
  1143. {
  1144. WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  1145. // Now verify that the file is an actual member of the catalog.
  1146. hRes = s_dsd.WinVerifyTrust(NULL, &guidSubSystemDriver, &WinTrustData);
  1147. if (hRes == ERROR_SUCCESS)
  1148. {
  1149. /*
  1150. #ifdef UNICODE
  1151. GetFullPathName(CatInfo.wszCatalogFile, MAX_PATH, szBuffer, &lpFilePart);
  1152. #else
  1153. WideCharToMultiByte(CP_ACP, 0, CatInfo.wszCatalogFile, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  1154. GetFullPathName(szBuffer, MAX_PATH, szBuffer, &lpFilePart);
  1155. #endif
  1156. lpFileNode->lpCatalog = (LPTSTR)MALLOC((lstrlen(lpFilePart) + 1) * sizeof(TCHAR));
  1157. lstrcpy(lpFileNode->lpCatalog, lpFilePart);
  1158. */
  1159. if (VerInfo.pcSignerCertContext != NULL)
  1160. {
  1161. s_dsd.CertFreeCertificateContext(VerInfo.pcSignerCertContext);
  1162. VerInfo.pcSignerCertContext = NULL;
  1163. }
  1164. bRet = TRUE;
  1165. }
  1166. }
  1167. if (!bRet)
  1168. {
  1169. // The hash was in this catalog, but the file wasn't a member... so off to the next catalog
  1170. PrevCat = hCatInfo;
  1171. hCatInfo = s_dsd.CryptCATAdminEnumCatalogFromHash(s_dsd.hCatAdmin, lpHash, cbHash, 0, &PrevCat);
  1172. }
  1173. }
  1174. if (!hCatInfo)
  1175. {
  1176. //
  1177. // If it wasn't found in the catalogs, check if the file is individually signed.
  1178. //
  1179. bRet = VerifyIsFileSigned(lpFileName, (PDRIVER_VER_INFO) &VerInfo);
  1180. if (bRet)
  1181. {
  1182. // If so, mark the file as being signed.
  1183. bSigned = TRUE;
  1184. }
  1185. }
  1186. else
  1187. {
  1188. // The file was verified in the catalogs, so mark it as signed and free the catalog context.
  1189. bSigned = TRUE;
  1190. s_dsd.CryptCATAdminReleaseCatalogContext(s_dsd.hCatAdmin, hCatInfo, 0);
  1191. }
  1192. /*
  1193. if (lpFileNode->bSigned)
  1194. {
  1195. #ifdef UNICODE
  1196. lpFileNode->lpVersion = MALLOC((lstrlen(VerInfo.wszVersion) + 1) * sizeof(TCHAR));
  1197. lstrcpy(lpFileNode->lpVersion, VerInfo.wszVersion);
  1198. lpFileNode->lpSignedBy = MALLOC((lstrlen(VerInfo.wszSignedBy) + 1) * sizeof(TCHAR));
  1199. lstrcpy(lpFileNode->lpSignedBy, VerInfo.wszSignedBy);
  1200. #else
  1201. WideCharToMultiByte(CP_ACP, 0, VerInfo.wszVersion, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  1202. lpFileNode->lpVersion = (LPTSTR)MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  1203. lstrcpy(lpFileNode->lpVersion, szBuffer);
  1204. WideCharToMultiByte(CP_ACP, 0, VerInfo.wszSignedBy, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  1205. lpFileNode->lpSignedBy = (LPTSTR)MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  1206. lstrcpy(lpFileNode->lpSignedBy, szBuffer);
  1207. #endif
  1208. }
  1209. */
  1210. return bSigned;
  1211. }
  1212. /****************************************************************************
  1213. *
  1214. * VerifyIsFileSigned
  1215. *
  1216. ****************************************************************************/
  1217. BOOL VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo)
  1218. {
  1219. HRESULT hRes;
  1220. WINTRUST_DATA WinTrustData;
  1221. WINTRUST_FILE_INFO WinTrustFile;
  1222. GUID guidOSVerCheck = DRIVER_ACTION_VERIFY;
  1223. GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  1224. ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
  1225. WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
  1226. WinTrustData.dwUIChoice = WTD_UI_NONE;
  1227. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  1228. WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
  1229. WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  1230. WinTrustData.pFile = &WinTrustFile;
  1231. WinTrustData.pPolicyCallbackData = (LPVOID)lpVerInfo;
  1232. ZeroMemory(lpVerInfo, sizeof(DRIVER_VER_INFO));
  1233. lpVerInfo->cbStruct = sizeof(DRIVER_VER_INFO);
  1234. ZeroMemory(&WinTrustFile, sizeof(WINTRUST_FILE_INFO));
  1235. WinTrustFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
  1236. #ifndef UNICODE
  1237. WCHAR wszFileName[MAX_PATH];
  1238. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcszMatchFile, -1, (LPWSTR)&wszFileName, MAX_PATH);
  1239. WinTrustFile.pcwszFilePath = wszFileName;
  1240. #else
  1241. WinTrustFile.pcwszFilePath = pcszMatchFile;
  1242. #endif
  1243. hRes = s_dsd.WinVerifyTrust(NULL, &guidOSVerCheck, &WinTrustData);
  1244. if (hRes != ERROR_SUCCESS)
  1245. hRes = s_dsd.WinVerifyTrust(NULL, &guidPublishedSoftware, &WinTrustData);
  1246. if (lpVerInfo->pcSignerCertContext != NULL)
  1247. {
  1248. s_dsd.CertFreeCertificateContext(lpVerInfo->pcSignerCertContext);
  1249. lpVerInfo->pcSignerCertContext = NULL;
  1250. }
  1251. return (hRes == ERROR_SUCCESS);
  1252. }
  1253. /****************************************************************************
  1254. *
  1255. * DiagnoseDxFiles
  1256. *
  1257. ****************************************************************************/
  1258. VOID DiagnoseDxFiles(SysInfo* pSysInfo, FileInfo* pDxComponentsFileInfoFirst,
  1259. FileInfo* pDxWinComponentsFileInfoFirst)
  1260. {
  1261. FileInfo* pFileInfo;
  1262. TCHAR szHighest[50];
  1263. TCHAR szDXVersion[50];
  1264. BOOL bNT = BIsPlatformNT();
  1265. BOOL bWin2k = BIsWin2k();
  1266. BOOL bIA64 = BIsIA64();
  1267. FLOAT fDXVersion = 0.0f;
  1268. BOOL bDX5 = FALSE;
  1269. BOOL bDX6 = FALSE; // 6.x
  1270. BOOL bDX60 = FALSE; // 6.0
  1271. BOOL bDX61 = FALSE; // 6.1
  1272. BOOL bDX7 = FALSE; // 7.x
  1273. BOOL bDX70 = FALSE; // 7.0
  1274. BOOL bDX71 = FALSE; // 7.1
  1275. BOOL bDX8 = FALSE; // 8.x
  1276. BOOL bDX80 = FALSE; // 8.0
  1277. BOOL bDX81 = FALSE; // 8.1
  1278. BOOL b64BitDxDiag = BIsDxDiag64Bit();
  1279. TCHAR szMissing[200];
  1280. TCHAR szInWindows[200];
  1281. TCHAR szOld[200];
  1282. TCHAR szDebug[200];
  1283. TCHAR szBeta[200];
  1284. TCHAR szFmt[300];
  1285. TCHAR szMessage[300];
  1286. LONG lwNumInWindows;
  1287. LONG lwNumMissing;
  1288. LONG lwNumOld;
  1289. LONG lwNumDebug;
  1290. LONG lwNumBeta;
  1291. TCHAR szListContinuer[30];
  1292. TCHAR szListEtc[30];
  1293. BOOL bVersionWarnings = TRUE;
  1294. BOOL bWinsockWarning = FALSE;
  1295. // Find highest version number in list
  1296. szHighest[0] = '\0';
  1297. for (pFileInfo = pDxComponentsFileInfoFirst; pFileInfo != NULL;
  1298. pFileInfo = pFileInfo->m_pFileInfoNext)
  1299. {
  1300. if (pFileInfo->m_bIgnoreVersionInfo)
  1301. continue;
  1302. // ddrawex.dll and dxapi.sys have wacky version numbers, so ignore them
  1303. if (lstrcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 ||
  1304. lstrcmpi(pFileInfo->m_szName, TEXT("dxapi.sys")) == 0)
  1305. {
  1306. continue;
  1307. }
  1308. // Bug 18892: dplayx.dll and dpmodemx.dll can have wacky version numbers if
  1309. // DPlay 6.0a is installed over DX 6.0
  1310. if (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 &&
  1311. lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0)
  1312. {
  1313. continue;
  1314. }
  1315. if (lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 &&
  1316. lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0356")) == 0)
  1317. {
  1318. continue;
  1319. }
  1320. // DPlay 6.1a: dplay files can have higher version numbers if
  1321. // DPlay 6.1a is installed over DX 6.0 (or DX 6.1)
  1322. if (lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 &&
  1323. (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
  1324. lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
  1325. lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
  1326. lstrcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0))
  1327. {
  1328. continue;
  1329. }
  1330. if (lstrcmp(pFileInfo->m_szVersion, pSysInfo->m_szDxDiagVersion) > 0)
  1331. {
  1332. // Bug 21291: Do not complain about file version newer than DxDiag itself
  1333. continue;
  1334. }
  1335. if (lstrcmp(szHighest, pFileInfo->m_szVersion) < 0)
  1336. lstrcpy(szHighest, pFileInfo->m_szVersion);
  1337. }
  1338. if (bNT)
  1339. lstrcpy(szDXVersion, pSysInfo->m_szDirectXVersion);
  1340. else
  1341. lstrcpy(szDXVersion, szHighest);
  1342. // Determine DX version
  1343. DWORD dwMajor;
  1344. DWORD dwMinor;
  1345. DWORD dwRevision;
  1346. DWORD dwBuild;
  1347. _stscanf(szDXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
  1348. if (dwMinor < 6)
  1349. bDX5 = TRUE;
  1350. else if (dwMinor < 7 && dwRevision < 2)
  1351. bDX60 = TRUE;
  1352. else if (dwMinor < 7)
  1353. bDX61 = TRUE;
  1354. else if (dwMinor < 8 && dwRevision < 1)
  1355. bDX70 = TRUE;
  1356. else if (dwMinor < 8)
  1357. bDX71 = TRUE;
  1358. else if (dwMinor == 8 && dwRevision < 1)
  1359. bDX80 = TRUE;
  1360. else if (dwMinor >= 8)
  1361. bDX81 = TRUE;
  1362. // Calc DX ver
  1363. fDXVersion = (float) dwMinor + (float) (dwRevision/10.0f);
  1364. // Is this DX6?
  1365. bDX6 = bDX60 || bDX61;
  1366. // Is this DX7?
  1367. bDX7 = bDX70 || bDX71;
  1368. // Is this DX8?
  1369. bDX8 = bDX80 || bDX81;
  1370. lwNumInWindows = 0;
  1371. lwNumMissing = 0;
  1372. lwNumOld = 0;
  1373. lwNumDebug = 0;
  1374. lwNumBeta = 0;
  1375. LoadString(NULL, IDS_LISTCONTINUER, szListContinuer, 30);
  1376. LoadString(NULL, IDS_LISTETC, szListEtc, 30);
  1377. for (pFileInfo = pDxWinComponentsFileInfoFirst; pFileInfo != NULL;
  1378. pFileInfo = pFileInfo->m_pFileInfoNext)
  1379. {
  1380. pFileInfo->m_bProblem = TRUE;
  1381. lwNumInWindows++;
  1382. if (lwNumInWindows == 1)
  1383. {
  1384. lstrcpy(szInWindows, pFileInfo->m_szName);
  1385. }
  1386. else if (lwNumInWindows < 4)
  1387. {
  1388. lstrcat(szInWindows, szListContinuer);
  1389. lstrcat(szInWindows, pFileInfo->m_szName);
  1390. }
  1391. else if (lwNumInWindows < 5)
  1392. {
  1393. lstrcat(szInWindows, szListEtc);
  1394. }
  1395. }
  1396. for (pFileInfo = pDxComponentsFileInfoFirst; pFileInfo != NULL;
  1397. pFileInfo = pFileInfo->m_pFileInfoNext)
  1398. {
  1399. if (!pFileInfo->m_bExists && !pFileInfo->m_bOptional)
  1400. {
  1401. // A missing file is a problem unless it's optional, OR...
  1402. // (on NT): it's optional on NT
  1403. // (on IA64): it's not on IA64
  1404. // (on IA64): we're running 32-bit dxdiag and its optional on WOW
  1405. // if file hasn't shipped yet on this DX version
  1406. // if file stopped shipping on or after this DX version
  1407. if (bNT && pFileInfo->m_bOptionalOnNT)
  1408. {
  1409. }
  1410. else if (bIA64 && pFileInfo->m_bNotIA64)
  1411. {
  1412. }
  1413. else if (bIA64 && !b64BitDxDiag && pFileInfo->m_bOptionalOnWOW64)
  1414. {
  1415. }
  1416. else if (fDXVersion+0.05f < pFileInfo->m_fStartShipAt)
  1417. {
  1418. }
  1419. else if (fDXVersion+0.05f >= pFileInfo->m_fStopShipAt)
  1420. {
  1421. }
  1422. else
  1423. {
  1424. pFileInfo->m_bProblem = TRUE;
  1425. LoadString(NULL, IDS_FILEMISSING, pFileInfo->m_szVersion, 50);
  1426. lwNumMissing++;
  1427. if (lwNumMissing == 1)
  1428. {
  1429. lstrcpy(szMissing, pFileInfo->m_szName);
  1430. }
  1431. else if (lwNumMissing < 4)
  1432. {
  1433. lstrcat(szMissing, szListContinuer);
  1434. lstrcat(szMissing, pFileInfo->m_szName);
  1435. }
  1436. else if (lwNumMissing < 5)
  1437. {
  1438. lstrcat(szMissing, szListEtc);
  1439. }
  1440. }
  1441. }
  1442. if (!pFileInfo->m_bExists)
  1443. continue;
  1444. if( BIsWin95() )
  1445. {
  1446. if( lstrcmpi(pFileInfo->m_szName, TEXT("wsock32.dll")) )
  1447. {
  1448. if( IsBadWin95Winsock( pFileInfo ) )
  1449. bWinsockWarning = TRUE;
  1450. }
  1451. }
  1452. // If DX6 or later, flag any dx5 only files as
  1453. // obsolete (needing to be deleted)
  1454. // manbugs 16765: don't complain about these files, just don't list them
  1455. if (!bDX5 && (pFileInfo->m_fStopShipAt == 6.0f))
  1456. {
  1457. pFileInfo->m_bProblem = TRUE;
  1458. pFileInfo->m_bObsolete = TRUE;
  1459. continue; // don't complain about these files for any other reason
  1460. }
  1461. if (bVersionWarnings && lstrcmp(szHighest, pFileInfo->m_szVersion) != 0)
  1462. {
  1463. if( pFileInfo->m_bIgnoreVersionInfo )
  1464. {
  1465. // Don't warn on files that have m_bIgnoreVersionInfo set
  1466. }
  1467. else if( _tcsstr(pFileInfo->m_szVersion, TEXT("5.01.2600.0000")) != NULL )
  1468. {
  1469. // Allow 5.01.2600.0000 in SP1
  1470. }
  1471. else if( bDX81 && ( _tcsstr(pFileInfo->m_szVersion, TEXT("4.08.00.0400")) != NULL ||
  1472. _tcsstr(pFileInfo->m_szVersion, TEXT("5.01.2258.0400")) != NULL ) )
  1473. {
  1474. // Bug 48732: If szHighest is 4.08.00.05xx and
  1475. // pFileInfo->m_szVersion is 4.08.00.0400 its OK
  1476. }
  1477. else if( bWin2k && (
  1478. (lstrcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("5.00.2134.0001")) == 0) ||
  1479. (lstrcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("5.00.2135.0001")) == 0) ||
  1480. (lstrcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("5.00.2134.0001")) == 0)
  1481. )
  1482. )
  1483. {
  1484. }
  1485. else if( bDX71 && _tcsstr(pFileInfo->m_szVersion, TEXT("4.07.00.07")) != NULL )
  1486. {
  1487. // Bug 114753: If szHighest is 4.07.01.xxxx and
  1488. // pFileInfo->m_szVersion is 4.07.00.0700 its OK (for now).
  1489. }
  1490. else if (!bNT && (bDX60 || bDX61) && CompareString(LOCALE_SYSTEM_DEFAULT, 0,
  1491. pFileInfo->m_szVersion, 4, TEXT("4.05"), 4) == CSTR_EQUAL &&
  1492. ( lstrcmpi(pFileInfo->m_szName, TEXT("dsound.dll")) == 0 ||
  1493. lstrcmpi(pFileInfo->m_szName, TEXT("dsound.vxd")) == 0 ||
  1494. lstrcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 ||
  1495. lstrcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 ||
  1496. lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 ||
  1497. lstrcmpi(pFileInfo->m_szName, TEXT("msanalog.vxd")) == 0 ||
  1498. lstrcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 ||
  1499. lstrcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 ||
  1500. lstrcmpi(pFileInfo->m_szName, TEXT("gchand.dll")) == 0))
  1501. {
  1502. // If Win9x DX6.x, dsound and dinput are allowed to be 4.05.xx.xxxx
  1503. // CompareString is used rather than lstrcmp only because we
  1504. // only want to look at the first four characters of the string
  1505. // Don't report these as version problems
  1506. }
  1507. else if (!bNT && bDX7 && CompareString(LOCALE_SYSTEM_DEFAULT, 0,
  1508. pFileInfo->m_szVersion, 4, TEXT("4.05"), 4) == CSTR_EQUAL &&
  1509. (lstrcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 ||
  1510. lstrcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 ||
  1511. lstrcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 ||
  1512. lstrcmpi(pFileInfo->m_szName, TEXT("gchand.dll")) == 0 ||
  1513. lstrcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 ||
  1514. lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 ||
  1515. lstrcmpi(pFileInfo->m_szName, TEXT("msanalog.vxd")) == 0))
  1516. {
  1517. // 21470: On DX7, these input files still exist on Win95,
  1518. // and they stay at DX5 level.
  1519. }
  1520. else if ( !bNT &&
  1521. (lstrcmpi(pFileInfo->m_szName, TEXT("msjstick.drv")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.00.00.0950")) == 0) ||
  1522. (lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.05.00.0155")) == 0)
  1523. )
  1524. {
  1525. // 34687: These stays at the dx5 level.
  1526. }
  1527. else if (!bNT && (lstrcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 ||
  1528. lstrcmpi(pFileInfo->m_szName, TEXT("dxapi.sys")) == 0))
  1529. {
  1530. // Ignore ddrawex.dll and dxapi.sys on Win9x because they have weird version numbers:
  1531. }
  1532. else if (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 &&
  1533. lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0)
  1534. {
  1535. // Bug 18892: work around DPlay 6.0a
  1536. }
  1537. else if (lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 &&
  1538. lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0356")) == 0)
  1539. {
  1540. // Bug 18892: work around DPlay 6.0a
  1541. }
  1542. else if (lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 &&
  1543. (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
  1544. lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
  1545. lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
  1546. lstrcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0))
  1547. {
  1548. // DPlay 6.1a: dplay files can have higher version numbers if
  1549. // DPlay 6.1a is installed over DX 6.0 (or DX 6.1)
  1550. }
  1551. else if (lstrcmpi(pFileInfo->m_szName, TEXT("dxsetup.exe")) == 0 ||
  1552. lstrcmpi(pFileInfo->m_szName, TEXT("dsetup.dll")) == 0 ||
  1553. lstrcmpi(pFileInfo->m_szName, TEXT("dsetup16.dll")) == 0 ||
  1554. lstrcmpi(pFileInfo->m_szName, TEXT("dsetup32.dll")) == 0 ||
  1555. lstrcmpi(pFileInfo->m_szName, TEXT("directx.cpl")) == 0)
  1556. {
  1557. // Bug 18540: Don't complain if dsetup/cpl files are out of date because
  1558. // some updates (OSR) don't update the setup/cpl files which may exist from
  1559. // another (SDK) installation
  1560. }
  1561. else if (!bNT && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0436")) == 0 &&
  1562. (lstrcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 ||
  1563. lstrcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 ||
  1564. lstrcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 ||
  1565. lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
  1566. lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
  1567. lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
  1568. lstrcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0))
  1569. {
  1570. // On DX 6.1a, the RM and DPlay files stay at 4.06.02.0436. No problemo.
  1571. }
  1572. else if (lstrcmp(pFileInfo->m_szVersion, pSysInfo->m_szDxDiagVersion) > 0)
  1573. {
  1574. // Bug 21291: Do not complain about file version newer than DxDiag itself
  1575. }
  1576. else
  1577. {
  1578. pFileInfo->m_bProblem = TRUE;
  1579. lwNumOld++;
  1580. if (lwNumOld == 1)
  1581. {
  1582. lstrcpy(szOld, pFileInfo->m_szName);
  1583. }
  1584. else if (lwNumOld < 4)
  1585. {
  1586. lstrcat(szOld, szListContinuer);
  1587. lstrcat(szOld, pFileInfo->m_szName);
  1588. }
  1589. else if (lwNumOld < 5)
  1590. {
  1591. lstrcat(szOld, szListEtc);
  1592. }
  1593. }
  1594. } // end if (bVersionWarnings && lstrcmp(szHighest, pFileInfo->m_szVersion) != 0)
  1595. if (pFileInfo->m_bBeta && !pFileInfo->m_bIgnoreBeta)
  1596. {
  1597. pFileInfo->m_bProblem = TRUE;
  1598. lwNumBeta++;
  1599. if (lwNumBeta == 1)
  1600. {
  1601. lstrcpy(szBeta, pFileInfo->m_szName);
  1602. }
  1603. else if (lwNumBeta < 4)
  1604. {
  1605. lstrcat(szBeta, szListContinuer);
  1606. lstrcat(szBeta, pFileInfo->m_szName);
  1607. }
  1608. else if (lwNumBeta < 5)
  1609. {
  1610. lstrcat(szBeta, szListEtc);
  1611. }
  1612. }
  1613. if (pFileInfo->m_bDebug && !pFileInfo->m_bIgnoreDebug)
  1614. {
  1615. pFileInfo->m_bProblem = TRUE;
  1616. lwNumDebug++;
  1617. if (lwNumDebug == 1)
  1618. {
  1619. lstrcpy(szDebug, pFileInfo->m_szName);
  1620. }
  1621. else if (lwNumDebug < 4)
  1622. {
  1623. lstrcat(szDebug, szListContinuer);
  1624. lstrcat(szDebug, pFileInfo->m_szName);
  1625. }
  1626. else if (lwNumDebug < 5)
  1627. {
  1628. lstrcat(szDebug, szListEtc);
  1629. }
  1630. }
  1631. }
  1632. BOOL bShouldReinstall = FALSE;
  1633. _tcscpy(pSysInfo->m_szDXFileNotes, TEXT("") );
  1634. _tcscpy(pSysInfo->m_szDXFileNotesEnglish, TEXT("") );
  1635. if (lwNumInWindows > 0)
  1636. {
  1637. if (lwNumInWindows == 1)
  1638. LoadString(NULL, IDS_INWINDOWSFMT1, szFmt, 300);
  1639. else
  1640. LoadString(NULL, IDS_INWINDOWSFMT2, szFmt, 300);
  1641. wsprintf(szMessage, szFmt, szInWindows);
  1642. _tcscat(pSysInfo->m_szDXFileNotes, szMessage);
  1643. if (lwNumInWindows == 1)
  1644. LoadString(NULL, IDS_INWINDOWSFMT1_ENGLISH, szFmt, 300);
  1645. else
  1646. LoadString(NULL, IDS_INWINDOWSFMT2_ENGLISH, szFmt, 300);
  1647. wsprintf(szMessage, szFmt, szInWindows);
  1648. _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1649. }
  1650. if (lwNumMissing > 0)
  1651. {
  1652. if (lwNumMissing == 1)
  1653. LoadString(NULL, IDS_MISSINGFMT1, szFmt, 300);
  1654. else
  1655. LoadString(NULL, IDS_MISSINGFMT2, szFmt, 300);
  1656. wsprintf(szMessage, szFmt, szMissing);
  1657. _tcscat(pSysInfo->m_szDXFileNotes, szMessage);
  1658. if (lwNumMissing == 1)
  1659. LoadString(NULL, IDS_MISSINGFMT1_ENGLISH, szFmt, 300);
  1660. else
  1661. LoadString(NULL, IDS_MISSINGFMT2_ENGLISH, szFmt, 300);
  1662. wsprintf(szMessage, szFmt, szMissing);
  1663. _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1664. bShouldReinstall = TRUE;
  1665. }
  1666. if (lwNumOld > 0)
  1667. {
  1668. if (lwNumOld == 1)
  1669. LoadString(NULL, IDS_OLDFMT1, szFmt, 300);
  1670. else
  1671. LoadString(NULL, IDS_OLDFMT2, szFmt, 300);
  1672. wsprintf(szMessage, szFmt, szOld);
  1673. _tcscat(pSysInfo->m_szDXFileNotes, szMessage);
  1674. if (lwNumOld == 1)
  1675. LoadString(NULL, IDS_OLDFMT1_ENGLISH, szFmt, 300);
  1676. else
  1677. LoadString(NULL, IDS_OLDFMT2_ENGLISH, szFmt, 300);
  1678. wsprintf(szMessage, szFmt, szOld);
  1679. _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1680. bShouldReinstall = TRUE;
  1681. }
  1682. if (lwNumBeta > 0)
  1683. {
  1684. if (lwNumBeta == 1)
  1685. LoadString(NULL, IDS_BETAFMT1, szFmt, 300);
  1686. else
  1687. LoadString(NULL, IDS_BETAFMT2, szFmt, 300);
  1688. wsprintf(szMessage, szFmt, szBeta);
  1689. _tcscat(pSysInfo->m_szDXFileNotes, szMessage);
  1690. if (lwNumBeta == 1)
  1691. LoadString(NULL, IDS_BETAFMT1_ENGLISH, szFmt, 300);
  1692. else
  1693. LoadString(NULL, IDS_BETAFMT2_ENGLISH, szFmt, 300);
  1694. wsprintf(szMessage, szFmt, szBeta);
  1695. _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1696. bShouldReinstall = TRUE;
  1697. }
  1698. if (lwNumDebug > 0)
  1699. {
  1700. if (lwNumDebug == 1)
  1701. LoadString(NULL, IDS_DEBUGFMT1, szFmt, 300);
  1702. else
  1703. LoadString(NULL, IDS_DEBUGFMT2, szFmt, 300);
  1704. wsprintf(szMessage, szFmt, szDebug);
  1705. _tcscat( pSysInfo->m_szDXFileNotes, szMessage);
  1706. if (lwNumDebug == 1)
  1707. LoadString(NULL, IDS_DEBUGFMT1_ENGLISH, szFmt, 300);
  1708. else
  1709. LoadString(NULL, IDS_DEBUGFMT2_ENGLISH, szFmt, 300);
  1710. wsprintf(szMessage, szFmt, szDebug);
  1711. _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1712. //bShouldReinstall = TRUE;
  1713. }
  1714. if( bWinsockWarning )
  1715. {
  1716. LoadString(NULL, IDS_WINSOCK_WARN, szMessage, 300);
  1717. _tcscat( pSysInfo->m_szDXFileNotes, szMessage);
  1718. LoadString(NULL, IDS_WINSOCK_WARN_ENGLISH, szMessage, 300);
  1719. _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1720. }
  1721. if( bShouldReinstall )
  1722. {
  1723. BOOL bTellUser = FALSE;
  1724. // Figure out if the user can install DirectX
  1725. if( BIsPlatform9x() )
  1726. bTellUser = TRUE;
  1727. else if( BIsWin2k() && bDX8 )
  1728. bTellUser = TRUE;
  1729. if( bTellUser )
  1730. {
  1731. LoadString(NULL, IDS_REINSTALL_DX, szMessage, 300);
  1732. _tcscat( pSysInfo->m_szDXFileNotes, szMessage);
  1733. LoadString(NULL, IDS_REINSTALL_DX_ENGLISH, szMessage, 300);
  1734. _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1735. }
  1736. }
  1737. if (lwNumMissing == 0 && lwNumOld == 0 &&
  1738. lwNumBeta == 0 && lwNumDebug == 0 && lwNumInWindows == 0)
  1739. {
  1740. LoadString(NULL, IDS_NOPROBLEM, szMessage, 300);
  1741. _tcscat(pSysInfo->m_szDXFileNotes, szMessage);
  1742. LoadString(NULL, IDS_NOPROBLEM_ENGLISH, szMessage, 300);
  1743. _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage);
  1744. }
  1745. }
  1746. /****************************************************************************
  1747. *
  1748. * IsBadWin95Winsock
  1749. *
  1750. ****************************************************************************/
  1751. BOOL IsBadWin95Winsock( FileInfo* pFileInfo )
  1752. {
  1753. typedef int (PASCAL* LPWSASTARTUP)(IN WORD wVersionRequired, OUT LPWSADATA lpWSAData);
  1754. typedef int (PASCAL* LPWSACLEANUP)(void);
  1755. BOOL bReturn = FALSE;
  1756. TCHAR szPath[MAX_PATH];
  1757. HINSTANCE hInstWSock;
  1758. LPWSASTARTUP pWSAStartup = NULL;
  1759. LPWSACLEANUP pWSACleanup = NULL;
  1760. GetSystemDirectory(szPath, MAX_PATH);
  1761. lstrcat(szPath, TEXT("\\wsock32.dll"));
  1762. hInstWSock = LoadLibrary(szPath);
  1763. if (hInstWSock != NULL)
  1764. {
  1765. pWSAStartup = (LPWSASTARTUP)GetProcAddress(hInstWSock, "WSAStartup");
  1766. pWSACleanup = (LPWSACLEANUP)GetProcAddress(hInstWSock, "WSACleanup");
  1767. if (pWSAStartup != NULL && pWSACleanup != NULL)
  1768. {
  1769. WORD wVersionRequested;
  1770. WSADATA wsaData;
  1771. int err;
  1772. wVersionRequested = MAKEWORD( 2, 2 );
  1773. err = pWSAStartup( wVersionRequested, &wsaData );
  1774. if ( err == 0 )
  1775. {
  1776. if ( LOBYTE( wsaData.wVersion ) == 2 &&
  1777. HIBYTE( wsaData.wVersion ) == 2 )
  1778. {
  1779. FILETIME fileTimeGoodWinsock;
  1780. SYSTEMTIME systemTimeGoodWinsock;
  1781. ULARGE_INTEGER ulGoodWinsock;
  1782. ULARGE_INTEGER ulCurrentWinsock;
  1783. ZeroMemory( &systemTimeGoodWinsock, sizeof(SYSTEMTIME) );
  1784. systemTimeGoodWinsock.wYear = 1998;
  1785. systemTimeGoodWinsock.wMonth = 2;
  1786. systemTimeGoodWinsock.wDay = 6;
  1787. systemTimeGoodWinsock.wHour = 14;
  1788. systemTimeGoodWinsock.wMinute = 18;
  1789. systemTimeGoodWinsock.wSecond = 00;
  1790. SystemTimeToFileTime( &systemTimeGoodWinsock, &fileTimeGoodWinsock );
  1791. ulCurrentWinsock.LowPart = pFileInfo->m_FileTime.dwLowDateTime;
  1792. ulCurrentWinsock.HighPart = pFileInfo->m_FileTime.dwHighDateTime;
  1793. ulGoodWinsock.LowPart = fileTimeGoodWinsock.dwLowDateTime;
  1794. ulGoodWinsock.HighPart = fileTimeGoodWinsock.dwHighDateTime;
  1795. if( ulCurrentWinsock.QuadPart < ulGoodWinsock.QuadPart )
  1796. {
  1797. bReturn = TRUE;
  1798. }
  1799. }
  1800. pWSACleanup();
  1801. }
  1802. }
  1803. }
  1804. FreeLibrary(hInstWSock);
  1805. return bReturn;
  1806. }