/**************************************************************************** * * File: fileinfo.cpp * Project: DxDiag (DirectX Diagnostic Tool) * Author: Mike Anderson (manders@microsoft.com) * Purpose: Gather information about files on this machine * * (C) Copyright 1998 Microsoft Corp. All rights reserved. * ****************************************************************************/ #include #include #include #include #include #include #include #include "sysinfo.h" // for BIsPlatformNT #include "fileinfo.h" #include "resource.h" // MsCat32.dll function prototypes typedef BOOL (WINAPI* PfnCryptCATAdminAcquireContext)(OUT HCATADMIN *phCatAdmin, IN const GUID *pgSubsystem, IN DWORD dwFlags); typedef BOOL (WINAPI* PfnCryptCATAdminReleaseContext)(IN HCATADMIN hCatAdmin, IN DWORD dwFlags); typedef BOOL (WINAPI* PfnCryptCATAdminReleaseCatalogContext)(IN HCATADMIN hCatAdmin, IN HCATINFO hCatInfo, IN DWORD dwFlags); typedef BOOL (WINAPI* PfnCryptCATCatalogInfoFromContext)(IN HCATINFO hCatInfo, IN OUT CATALOG_INFO *psCatInfo, IN DWORD dwFlags); typedef HCATINFO (WINAPI* PfnCryptCATAdminEnumCatalogFromHash)(IN HCATADMIN hCatAdmin, IN BYTE *pbHash, IN DWORD cbHash, IN DWORD dwFlags, IN OUT HCATINFO *phPrevCatInfo); typedef BOOL (WINAPI* PfnIsCatalogFile)(IN OPTIONAL HANDLE hFile, IN OPTIONAL WCHAR *pwszFileName); typedef BOOL (WINAPI* PfnCryptCATAdminCalcHashFromFileHandle)(IN HANDLE hFile, IN OUT DWORD *pcbHash, OUT OPTIONAL BYTE *pbHash, IN DWORD dwFlags); // WinTrust.dll function prototypes typedef HRESULT (WINAPI* PfnWinVerifyTrust)(HWND hWnd, GUID *pgActionID, WINTRUST_DATA *pWinTrustData); // Crypt32.dll function prototypes typedef BOOL (WINAPI* PfnCertFreeCertificateContext)(IN PCCERT_CONTEXT pCertContext); struct DigiSignData { BOOL bInitialized; BOOL bFailed; // Need to LoadLibrary/GetProcAddress for mscat32 APIs since they // don't exist on Win95 HINSTANCE hInstMsCat32; PfnCryptCATAdminAcquireContext CryptCATAdminAcquireContext; PfnCryptCATAdminReleaseContext CryptCATAdminReleaseContext; PfnCryptCATAdminReleaseCatalogContext CryptCATAdminReleaseCatalogContext; PfnCryptCATCatalogInfoFromContext CryptCATCatalogInfoFromContext; PfnCryptCATAdminEnumCatalogFromHash CryptCATAdminEnumCatalogFromHash; PfnIsCatalogFile IsCatalogFile; PfnCryptCATAdminCalcHashFromFileHandle CryptCATAdminCalcHashFromFileHandle; // Ditto for wintrust.dll APIs HINSTANCE hInstWinTrust; PfnWinVerifyTrust WinVerifyTrust; // Ditto for cypt32.dll APIs HINSTANCE hInstCrypt32; PfnCertFreeCertificateContext CertFreeCertificateContext; HCATADMIN hCatAdmin; }; static DigiSignData s_dsd; static BOOL GetMediaPlayerFolder(TCHAR* pszPath); static BOOL VerifyFileNode(TCHAR* lpFileName, TCHAR* lpDirName); static BOOL VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo); static BOOL InitDigiSignData(VOID); static BOOL IsFileDigitallySigned(TCHAR* pszFile); static BOOL IsBadWin95Winsock( FileInfo* pFileInfo ); /**************************************************************************** * * GetProgramFilesFolder * ****************************************************************************/ VOID InitFileInfo() { ZeroMemory(&s_dsd, sizeof(s_dsd)); s_dsd.bFailed = FALSE; s_dsd.bInitialized = FALSE; } /**************************************************************************** * * GetProgramFilesFolder * ****************************************************************************/ BOOL GetProgramFilesFolder(TCHAR* pszPath) { HKEY hkey; DWORD dwType; DWORD cb; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion"), 0, KEY_READ, &hkey)) { return FALSE; } cb = MAX_PATH; RegQueryValueEx(hkey, TEXT("ProgramFilesDir"), NULL, &dwType, (LPBYTE)pszPath, &cb); RegCloseKey(hkey); if (cb == 0) return FALSE; return TRUE; } /**************************************************************************** * * FormatFileTime * ****************************************************************************/ VOID FormatFileTime(FILETIME* pUTCFileTime, TCHAR* pszDateLocal, TCHAR* pszDateEnglish) { FILETIME fileTimeLocal; SYSTEMTIME systemTime; TCHAR szTime[100]; FileTimeToLocalFileTime(pUTCFileTime, &fileTimeLocal); FileTimeToSystemTime(&fileTimeLocal, &systemTime); wsprintf(pszDateEnglish, TEXT("%d/%d/%04d %02d:%02d:%02d"), systemTime.wMonth, systemTime.wDay, systemTime.wYear, systemTime.wHour, systemTime.wMinute, systemTime.wSecond); GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, NULL, pszDateLocal, 30); wsprintf(szTime, TEXT(" %02d:%02d:%02d"), systemTime.wHour, systemTime.wMinute, systemTime.wSecond); lstrcat(pszDateLocal, szTime); } /**************************************************************************** * * GetMediaPlayerFolder * ****************************************************************************/ BOOL GetMediaPlayerFolder(TCHAR* pszPath) { HKEY hkey; DWORD dwType; DWORD cb; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\MediaPlayer"), 0, KEY_READ, &hkey)) { return FALSE; } cb = MAX_PATH; RegQueryValueEx(hkey, TEXT("Installation Directory"), NULL, &dwType, (LPBYTE)pszPath, &cb); RegCloseKey(hkey); if (cb == 0) return FALSE; return TRUE; } /**************************************************************************** * * GetDxSetupFolder * ****************************************************************************/ BOOL GetDxSetupFolder(TCHAR* pszPath) { if (!GetProgramFilesFolder(pszPath)) return FALSE; lstrcat(pszPath, TEXT("\\DirectX\\Setup")); return TRUE; } /**************************************************************************** * * GetComponentFiles * ****************************************************************************/ HRESULT GetComponentFiles(TCHAR* pszFolder, FileInfo** ppFileInfoFirst, BOOL bSkipMissingFiles, LONG ids) { LONG cch; FileInfo* pFileInfo; FileInfo* pFileInfoNew; LONG iFile; TCHAR szFile[50]; TCHAR szPath[MAX_PATH]; TCHAR szComponentFiles[2048]; TCHAR* pszFilePos; TCHAR* pszFilePos2; TCHAR* pszFirstParen; FLOAT fStartShipAt; FLOAT fStopShipAt; BOOL bDriversDir; BOOL bNTDriversDir; BOOL bIgnoreVersionInfo; BOOL bIgnoreDebug; BOOL bIgnoreBeta; BOOL bBDA; BOOL bNotIA64; BOOL bOptional; BOOL bOptionalOnNT; BOOL bOptionalOnWOW64; BOOL bIsNT = BIsPlatformNT(); BOOL bIs95 = BIsWin95(); cch = LoadString(NULL, ids, szComponentFiles, 2048); if (cch == 0 || cch >= 2047) return E_FAIL; pszFilePos = szComponentFiles; for (iFile = 0; ; iFile++) { // Stop if we've gone through the whole list if (pszFilePos == NULL) break; // Pull the next file out of the list pszFilePos2 = _tcsstr(pszFilePos, TEXT(",")); if (pszFilePos2 == NULL) { _tcsncpy(szFile, pszFilePos, 50); szFile[49]=0; pszFilePos = NULL; } else { _tcsncpy(szFile, pszFilePos, (DWORD)(pszFilePos2 - pszFilePos)); szFile[pszFilePos2 - pszFilePos] = '\0'; pszFilePos = pszFilePos2 + 1; } // Clear file flags fStartShipAt = 0.0f; fStopShipAt = 10000.0f; bDriversDir = FALSE; bNTDriversDir = FALSE; bIgnoreVersionInfo = FALSE; bIgnoreDebug = FALSE; bIgnoreBeta = FALSE; bBDA = FALSE; bNotIA64 = FALSE; bOptional = FALSE; bOptionalOnNT = FALSE; bOptionalOnWOW64 = FALSE; // Look at file flags, if any pszFirstParen = _tcsstr(szFile, TEXT("(")); if (pszFirstParen != NULL) { // If this file does not exist on NT, and we are running NT, skip it. if (_tcsstr(pszFirstParen, TEXT("notNT")) != NULL && bIsNT) continue; // If this file does not exist on W95, and we are running W95, skip it. if (_tcsstr(pszFirstParen, TEXT("not95")) != NULL && bIs95) continue; // If this file only exists on W95, and we are not running W95, skip it. // Note: files like vjoyd.vxd may exist on Win98, but DX setup does not // install them or update them, so we ignore them. // Note: can't call this "95only" because it would clash with "5only" if (_tcsstr(pszFirstParen, TEXT("9fiveonly")) != NULL && !bIs95) continue; // Check for other flags if (_tcsstr(pszFirstParen, TEXT("+")) != NULL) { if (_tcsstr(pszFirstParen, TEXT("+5")) != NULL) fStartShipAt = 5.0f; else if (_tcsstr(pszFirstParen, TEXT("+61")) != NULL) fStartShipAt = 6.1f; else if (_tcsstr(pszFirstParen, TEXT("+6")) != NULL) fStartShipAt = 6.0f; else if (_tcsstr(pszFirstParen, TEXT("+71")) != NULL) fStartShipAt = 7.1f; else if (_tcsstr(pszFirstParen, TEXT("+7")) != NULL) fStartShipAt = 7.0f; else if (_tcsstr(pszFirstParen, TEXT("+81")) != NULL) fStartShipAt = 8.1f; else if (_tcsstr(pszFirstParen, TEXT("+8")) != NULL) fStartShipAt = 8.0f; } if (_tcsstr(pszFirstParen, TEXT("-")) != NULL) { if (_tcsstr(pszFirstParen, TEXT("-5")) != NULL) fStopShipAt = 5.0f; else if (_tcsstr(pszFirstParen, TEXT("-61")) != NULL) fStopShipAt = 6.1f; else if (_tcsstr(pszFirstParen, TEXT("-6")) != NULL) fStopShipAt = 6.0f; else if (_tcsstr(pszFirstParen, TEXT("-71")) != NULL) fStopShipAt = 7.1f; else if (_tcsstr(pszFirstParen, TEXT("-7")) != NULL) fStopShipAt = 7.0f; else if (_tcsstr(pszFirstParen, TEXT("-81")) != NULL) fStopShipAt = 8.1f; else if (_tcsstr(pszFirstParen, TEXT("-8")) != NULL) fStopShipAt = 8.0f; } // Note: can't call this "DriversDir" because it would clash with "NTDriversDir" if (_tcsstr(pszFirstParen, TEXT("DrivDir")) != NULL) bDriversDir = TRUE; if (_tcsstr(pszFirstParen, TEXT("NTDriversDir")) != NULL) bNTDriversDir = TRUE; if (_tcsstr(pszFirstParen, TEXT("SkipVer")) != NULL) bIgnoreVersionInfo = TRUE; if (_tcsstr(pszFirstParen, TEXT("SkipDebug")) != NULL) bIgnoreDebug = TRUE; if (_tcsstr(pszFirstParen, TEXT("SkipBeta")) != NULL) bIgnoreBeta = TRUE; if (_tcsstr(pszFirstParen, TEXT("notia64")) != NULL) bNotIA64 = TRUE; if (_tcsstr(pszFirstParen, TEXT("optnt")) != NULL) bOptionalOnNT = TRUE; else if (_tcsstr(pszFirstParen, TEXT("optwow")) != NULL) bOptionalOnWOW64 = TRUE; else if (_tcsstr(pszFirstParen, TEXT("opt")) != NULL) bOptional = TRUE; if (_tcsstr(pszFirstParen, TEXT("bda")) != NULL) { bBDA = TRUE; bOptional = TRUE; bIgnoreVersionInfo = TRUE; } // End file name at open parenthesis, if any: *pszFirstParen = TEXT('\0'); } pFileInfoNew = new FileInfo; if (pFileInfoNew == NULL) return E_OUTOFMEMORY; ZeroMemory(pFileInfoNew, sizeof(FileInfo)); pFileInfoNew->m_fStartShipAt = fStartShipAt; pFileInfoNew->m_fStopShipAt = fStopShipAt; pFileInfoNew->m_bIgnoreVersionInfo = bIgnoreVersionInfo; pFileInfoNew->m_bIgnoreDebug = bIgnoreDebug; pFileInfoNew->m_bIgnoreBeta = bIgnoreBeta; pFileInfoNew->m_bBDA = bBDA; pFileInfoNew->m_bNotIA64 = bNotIA64; pFileInfoNew->m_bOptional = bOptional; pFileInfoNew->m_bOptionalOnNT = bOptionalOnNT; pFileInfoNew->m_bOptionalOnWOW64 = bOptionalOnWOW64; lstrcpy(pFileInfoNew->m_szName, szFile); _tcsncpy(szPath, pszFolder,MAX_PATH); szPath[MAX_PATH-1]=0; lstrcat(szPath, TEXT("\\")); if (bNTDriversDir && bIsNT) lstrcat(szPath, TEXT("Drivers\\")); else if (bDriversDir) lstrcat(szPath, TEXT("..\\System32\\Drivers\\")); lstrcat(szPath, szFile); WIN32_FIND_DATA findFileData; HANDLE hFind = FindFirstFile(szPath, &findFileData); if (hFind == INVALID_HANDLE_VALUE) { if (bSkipMissingFiles) { delete pFileInfoNew; continue; } } else { pFileInfoNew->m_bExists = TRUE; FindClose(hFind); } if (pFileInfoNew->m_bExists) { pFileInfoNew->m_numBytes = findFileData.nFileSizeLow; pFileInfoNew->m_FileTime = findFileData.ftLastWriteTime; FormatFileTime(&findFileData.ftLastWriteTime, pFileInfoNew->m_szDatestampLocal, pFileInfoNew->m_szDatestamp); GetFileVersion(szPath, pFileInfoNew->m_szVersion, pFileInfoNew->m_szAttributes, pFileInfoNew->m_szLanguageLocal, pFileInfoNew->m_szLanguage, &pFileInfoNew->m_bBeta, &pFileInfoNew->m_bDebug); } if (*ppFileInfoFirst == NULL) *ppFileInfoFirst = pFileInfoNew; else { for (pFileInfo = *ppFileInfoFirst; pFileInfo->m_pFileInfoNext != NULL; pFileInfo = pFileInfo->m_pFileInfoNext) { } pFileInfo->m_pFileInfoNext = pFileInfoNew; } } return S_OK; } /**************************************************************************** * * DestroyFileList * ****************************************************************************/ VOID DestroyFileList(FileInfo* pFileInfoFirst) { FileInfo* pFileInfo; FileInfo* pFileInfoNext; for (pFileInfo = pFileInfoFirst; pFileInfo != NULL; pFileInfo = pFileInfoNext) { pFileInfoNext = pFileInfo->m_pFileInfoNext; delete pFileInfo; } } /**************************************************************************** * * GetFileDateAndSize * ****************************************************************************/ BOOL GetFileDateAndSize(TCHAR* pszFile, TCHAR* pszDateLocal, TCHAR* pszDateEnglish, LONG* pnumBytes) { WIN32_FIND_DATA findFileData; HANDLE hFind; pszDateLocal[0] = '\0'; pszDateEnglish[0] = '\0'; *pnumBytes = 0; hFind = FindFirstFile(pszFile, &findFileData); if (hFind == INVALID_HANDLE_VALUE) return FALSE; // file not found FindClose(hFind); *pnumBytes = findFileData.nFileSizeLow; FormatFileTime(&findFileData.ftLastWriteTime, pszDateLocal, pszDateEnglish); return TRUE; } /**************************************************************************** * * GetFileVersion * ****************************************************************************/ HRESULT GetFileVersion(TCHAR* pszFile, TCHAR* pszVersion, TCHAR* pszAttributes, TCHAR* pszLanguageLocal, TCHAR* pszLanguage, BOOL* pbBeta, BOOL* pbDebug) { UINT cb; DWORD dwHandle; BYTE FileVersionBuffer[4096]; VS_FIXEDFILEINFO* pVersion = NULL; DWORD dwVersionAttribs = 0; // DEBUG, RETAIL, etc. DWORD* pdwCharSet = NULL; WORD wLanguage; LCID lcid; TCHAR szDebug[100]; TCHAR szRetail[100]; TCHAR szBeta[100]; TCHAR szFinal[100]; TCHAR szCombineFmt[100]; LoadString(NULL, IDS_DEBUG, szDebug, 100); LoadString(NULL, IDS_RETAIL, szRetail, 100); LoadString(NULL, IDS_BETA, szBeta, 100); LoadString(NULL, IDS_FINAL, szFinal, 100); LoadString(NULL, IDS_ATTRIBCOMBINE, szCombineFmt, 100); cb = GetFileVersionInfoSize(pszFile, &dwHandle/*ignored*/); if (cb > 0) { if (cb > sizeof(FileVersionBuffer)) cb = sizeof(FileVersionBuffer); if (GetFileVersionInfo(pszFile, 0, cb, FileVersionBuffer)) { pVersion = NULL; if (VerQueryValue(FileVersionBuffer, TEXT("\\"), (VOID**)&pVersion, &cb) && pVersion != NULL) { if (pszVersion != NULL) { wsprintf(pszVersion, TEXT("%d.%02d.%02d.%04d"), HIWORD(pVersion->dwFileVersionMS), LOWORD(pVersion->dwFileVersionMS), HIWORD(pVersion->dwFileVersionLS), LOWORD(pVersion->dwFileVersionLS)); } if (pszAttributes != NULL) { dwVersionAttribs = pVersion->dwFileFlags; // Bug 18892: work around DPlay 6.0a if (pVersion->dwFileVersionMS == 0x00040006 && (pVersion->dwFileVersionLS == 0x0002016b || // 4.06.02.0363 pVersion->dwFileVersionLS == 0x00020164)) // 4.06.02.0356 { dwVersionAttribs &= ~VS_FF_PRERELEASE; } if (pszVersion != NULL) { TCHAR* pszLeaf = _tcsrchr(pszFile, TEXT('\\')); if( pszLeaf ) { pszLeaf++; // Work around several DXMedia files which are incorrectly marked as beta if (lstrcmp(pszLeaf, TEXT("oleaut32.dll")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("quartz.dll")) == 0 && lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("quartz.vxd")) == 0 && lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("mciqtz.drv")) == 0 && lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("mciqtz32.dll")) == 0 && lstrcmp(pszVersion, TEXT("4.00.96.0729")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("actmovie.exe")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("strmdll.dll")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("unam4ie.exe")) == 0 && lstrcmp(pszVersion, TEXT("6.00.02.0902")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("unam4ie.exe")) == 0 && lstrcmp(pszVersion, TEXT("5.01.18.1024")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 && lstrcmp(pszVersion, TEXT("2.00.05.0050")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 && lstrcmp(pszVersion, TEXT("2.00.05.0052")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("tm20dec.ax")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("tm20dec.ax")) == 0 && lstrcmp(pszVersion, TEXT("1.00.00.0000")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("msdxm.ocx")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("dxmasf.dll")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; } else if (lstrcmp(pszLeaf, TEXT("iac25_32.ax")) == 0 && lstrcmp(pszVersion, TEXT("2.00.05.0053")) == 0) { dwVersionAttribs &= ~VS_FF_PRERELEASE; // Since 350883 got punted } } } wsprintf(pszAttributes, szCombineFmt, (dwVersionAttribs & VS_FF_PRERELEASE ? szBeta : szFinal), (dwVersionAttribs & VS_FF_DEBUG ? szDebug : szRetail)); if (pbBeta != NULL) *pbBeta = (dwVersionAttribs & VS_FF_PRERELEASE) ? TRUE : FALSE; if (pbDebug != NULL) *pbDebug = (dwVersionAttribs & VS_FF_DEBUG) ? TRUE : FALSE; } } if (pszLanguage != NULL) { if (VerQueryValue(FileVersionBuffer, TEXT("\\VarFileInfo\\Translation"), (VOID**)&pdwCharSet, &cb) && pdwCharSet && cb) { wLanguage = LOWORD(*pdwCharSet); lcid = MAKELCID(wLanguage, SORT_DEFAULT); GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, pszLanguage, 100); if (pszLanguageLocal != NULL) { GetLocaleInfo(lcid, LOCALE_SLANGUAGE, pszLanguageLocal, 100); // Show "English", not "English (United States)". I can't // find a better way to do this (such that it localizes properly) TCHAR* pszSublanguage; pszSublanguage = _tcsstr(pszLanguageLocal, TEXT(" (")); if (pszSublanguage != NULL) *pszSublanguage = '\0'; } } } } } else { TCHAR* pszLeaf = _tcsrchr(pszFile, TEXT('\\')); if( pszLeaf ) { pszLeaf++; if (DXUtil_strcmpi(pszLeaf, TEXT("vidx16.dll")) == 0) { if (pszVersion != NULL) lstrcpy(pszVersion, TEXT("0.00.00.0000")); if (pszAttributes != NULL) { _sntprintf(pszAttributes, 50, TEXT("%s %s"), szFinal, szRetail); pszAttributes[49] = 0; } if (pszLanguage != NULL) { wLanguage = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); lcid = MAKELCID(wLanguage, SORT_DEFAULT); GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, pszLanguage, 100); if (pszLanguageLocal != NULL) { GetLocaleInfo(lcid, LOCALE_SLANGUAGE, pszLanguageLocal, 100); // Show "English", not "English (United States)". I can't // find a better way to do this (such that it localizes properly) TCHAR* pszSublanguage; pszSublanguage = _tcsstr(pszLanguageLocal, TEXT(" (")); if (pszSublanguage != NULL) *pszSublanguage = '\0'; } } } } } return S_OK; } /**************************************************************************** * * GetLanguageFromFile * ****************************************************************************/ WORD GetLanguageFromFile(const TCHAR* pszFileName, const TCHAR* pszPath) { BYTE FileVersionBuffer[4096]; DWORD *pdwCharSet; UINT cb; DWORD dwHandle; TCHAR szFileAndPath[MAX_PATH]; WORD wLanguage; _tcsncpy(szFileAndPath, pszPath, MAX_PATH); szFileAndPath[MAX_PATH-1] = 0; lstrcat(szFileAndPath, TEXT("\\")); if( lstrlen(szFileAndPath) + lstrlen(pszFileName) < MAX_PATH ) lstrcat(szFileAndPath, pszFileName); memset(FileVersionBuffer, 0, sizeof FileVersionBuffer); wLanguage = 0; if (cb = GetFileVersionInfoSize(szFileAndPath, &dwHandle/*ignored*/)) { cb = (cb <= sizeof FileVersionBuffer ? cb : sizeof FileVersionBuffer); if (GetFileVersionInfo(szFileAndPath, 0, cb, FileVersionBuffer)) { pdwCharSet = 0; if (VerQueryValue(FileVersionBuffer, TEXT("\\VarFileInfo\\Translation"), (void**)&pdwCharSet, &cb) && pdwCharSet && cb) { wLanguage = LOWORD(*pdwCharSet); } } } return wLanguage; } struct DLSVERSION { DWORD dwVersionMS; DWORD dwVersionLS; }; #define FOURCC_VERS mmioFOURCC('v','e','r','s') /**************************************************************************** * * GetRiffFileVersion * ****************************************************************************/ HRESULT GetRiffFileVersion(TCHAR* pszFile, TCHAR* pszVersion) { MMIOINFO mmio; MMCKINFO mmck1; MMCKINFO mmck2; DLSVERSION dlsver; HMMIO hDLS; // DLS file has different version scheme since it's a riff file. // So retrieve version info from 'vers' chunk. ZeroMemory(&mmio, sizeof(MMIOINFO)); hDLS = mmioOpen(pszFile,&mmio,MMIO_READ); if (hDLS == NULL) { return E_FAIL; } // read riff chunk ZeroMemory(&mmck1,sizeof(MMCKINFO)); if (mmioDescend(hDLS, &mmck1, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR) { mmioClose(hDLS,0); return E_FAIL; } ZeroMemory(&mmck2,sizeof(MMCKINFO)); mmck2.ckid = FOURCC_VERS; if (mmioDescend(hDLS, &mmck2, &mmck1, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) { mmioClose(hDLS,0); return E_FAIL; } if (mmioRead(hDLS, (HPSTR)&dlsver, sizeof(DLSVERSION)) != sizeof(DLSVERSION)) { mmioClose(hDLS,0); return E_FAIL; } wsprintf(pszVersion, TEXT("%d.%02d.%02d.%04d"), HIWORD(dlsver.dwVersionMS), LOWORD(dlsver.dwVersionMS), HIWORD(dlsver.dwVersionLS), LOWORD(dlsver.dwVersionLS)); mmioClose(hDLS,0); return S_OK; } /**************************************************************************** * * FileIsSigned - use digital signature on all OSs * ****************************************************************************/ VOID FileIsSigned(LPTSTR lpszFile, BOOL* pbSigned, BOOL* pbIsValid) { // Look for digital sig if( !InitDigiSignData() ) { if( pbSigned ) *pbSigned = FALSE; if( pbIsValid ) *pbIsValid = FALSE; return; } if( pbSigned ) *pbSigned = IsFileDigitallySigned(lpszFile); if( pbIsValid ) *pbIsValid = TRUE; } /**************************************************************************** * * InitDigiSignData * ****************************************************************************/ BOOL InitDigiSignData(VOID) { TCHAR szPath[MAX_PATH]; if( s_dsd.bInitialized ) return TRUE; if( s_dsd.bFailed ) return FALSE; ZeroMemory(&s_dsd, sizeof(s_dsd)); GetSystemDirectory(szPath, MAX_PATH); lstrcat(szPath, TEXT("\\mscat32.dll")); s_dsd.hInstMsCat32 = LoadLibrary(szPath); if (s_dsd.hInstMsCat32 == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATAdminAcquireContext = (PfnCryptCATAdminAcquireContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminAcquireContext"); if (s_dsd.CryptCATAdminAcquireContext == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATAdminReleaseContext = (PfnCryptCATAdminReleaseContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminReleaseContext"); if (s_dsd.CryptCATAdminReleaseContext == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATAdminReleaseCatalogContext = (PfnCryptCATAdminReleaseCatalogContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminReleaseCatalogContext"); if (s_dsd.CryptCATAdminReleaseCatalogContext == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATCatalogInfoFromContext = (PfnCryptCATCatalogInfoFromContext)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATCatalogInfoFromContext"); if (s_dsd.CryptCATCatalogInfoFromContext == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATAdminEnumCatalogFromHash = (PfnCryptCATAdminEnumCatalogFromHash)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminEnumCatalogFromHash"); if (s_dsd.CryptCATAdminEnumCatalogFromHash == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.IsCatalogFile = (PfnIsCatalogFile)GetProcAddress(s_dsd.hInstMsCat32, "IsCatalogFile"); if (s_dsd.IsCatalogFile == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CryptCATAdminCalcHashFromFileHandle = (PfnCryptCATAdminCalcHashFromFileHandle)GetProcAddress(s_dsd.hInstMsCat32, "CryptCATAdminCalcHashFromFileHandle"); if (s_dsd.CryptCATAdminCalcHashFromFileHandle == NULL) { s_dsd.bFailed = TRUE; return FALSE; } if (!s_dsd.CryptCATAdminAcquireContext(&s_dsd.hCatAdmin, NULL, 0)) { s_dsd.bFailed = TRUE; return FALSE; } GetSystemDirectory(szPath, MAX_PATH); lstrcat(szPath, TEXT("\\wintrust.dll")); s_dsd.hInstWinTrust = LoadLibrary(szPath); if (s_dsd.hInstWinTrust == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.WinVerifyTrust = (PfnWinVerifyTrust)GetProcAddress(s_dsd.hInstWinTrust, "WinVerifyTrust"); if (s_dsd.WinVerifyTrust == NULL) { s_dsd.bFailed = TRUE; return FALSE; } GetSystemDirectory(szPath, MAX_PATH); lstrcat(szPath, TEXT("\\crypt32.dll")); s_dsd.hInstCrypt32 = LoadLibrary(szPath); if (s_dsd.hInstCrypt32 == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.CertFreeCertificateContext = (PfnCertFreeCertificateContext)GetProcAddress(s_dsd.hInstCrypt32, "CertFreeCertificateContext"); if (s_dsd.CertFreeCertificateContext == NULL) { s_dsd.bFailed = TRUE; return FALSE; } s_dsd.bFailed = FALSE; s_dsd.bInitialized = TRUE; return TRUE; } /**************************************************************************** * * ReleaseDigiSignData * ****************************************************************************/ VOID ReleaseDigiSignData(VOID) { if( s_dsd.CryptCATAdminReleaseContext && s_dsd.hCatAdmin ) s_dsd.CryptCATAdminReleaseContext(s_dsd.hCatAdmin,0); if (s_dsd.hInstMsCat32 != NULL) FreeLibrary(s_dsd.hInstMsCat32); if (s_dsd.hInstWinTrust != NULL) FreeLibrary(s_dsd.hInstWinTrust); if (s_dsd.hInstCrypt32 != NULL) FreeLibrary(s_dsd.hInstCrypt32); ZeroMemory(&s_dsd, sizeof(s_dsd)); } /**************************************************************************** * * IsFileDigitallySigned * ****************************************************************************/ BOOL IsFileDigitallySigned(TCHAR* pszFile) { if (!s_dsd.bInitialized) return FALSE; TCHAR lpFileName[MAX_PATH]; TCHAR lpDirName[MAX_PATH]; TCHAR* pch; if( lstrlen(lpDirName) + lstrlen(pszFile) < MAX_PATH ) lstrcpy(lpDirName, pszFile); CharLowerBuff(lpDirName, lstrlen(lpDirName)); pch = _tcsrchr(lpDirName, TEXT('\\')); // 22670: There *should* be a backslash in pszFile, but cope if it isn't if (pch == NULL) { lstrcpyn(lpFileName, pszFile,MAX_PATH); GetCurrentDirectory(MAX_PATH, lpDirName); } else { lstrcpy(lpFileName, pch + 1); *pch = TEXT('\0'); } if (_tcsstr(lpDirName, TEXT("\\")) == NULL) lstrcat(lpDirName, TEXT("\\")); return VerifyFileNode(lpFileName, lpDirName); } /**************************************************************************** * * VerifyFileNode * ****************************************************************************/ BOOL VerifyFileNode(TCHAR* lpFileName, TCHAR* lpDirName) { const DWORD HASH_SIZE = 100; HANDLE hFile; BOOL bRet; HCATINFO hCatInfo = NULL; HCATINFO PrevCat; WINTRUST_DATA WinTrustData; WINTRUST_CATALOG_INFO WinTrustCatalogInfo; DRIVER_VER_INFO VerInfo; GUID guidSubSystemDriver = DRIVER_ACTION_VERIFY; HRESULT hRes; DWORD cbHash = HASH_SIZE; BYTE szHash[HASH_SIZE]; LPBYTE lpHash = szHash; CATALOG_INFO CatInfo; #ifndef UNICODE WCHAR UnicodeKey[MAX_PATH]; #endif BOOL bSigned = FALSE; TCHAR szFullPath[MAX_PATH]; wsprintf(szFullPath, TEXT("%s\\%s"), lpDirName, lpFileName); // // Get the handle to the file, so we can call CryptCATAdminCalcHashFromFileHandle // hFile = CreateFile( szFullPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } // Initialize the hash buffer ZeroMemory(lpHash, HASH_SIZE); // Generate the hash from the file handle and store it in lpHash if (!s_dsd.CryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, lpHash, 0)) { // // If we couldn't generate a hash, it might be an individually signed catalog. // If it's a catalog, zero out lpHash and cbHash so we know there's no hash to check. // if (s_dsd.IsCatalogFile(hFile, NULL)) { lpHash = NULL; cbHash = 0; } else // If it wasn't a catalog, we'll bail and this file will show up as unscanned. { CloseHandle(hFile); return FALSE; } } // Close the file handle CloseHandle(hFile); // // Now we have the file's hash. Initialize the structures that // will be used later on in calls to WinVerifyTrust. // ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA)); WinTrustData.cbStruct = sizeof(WINTRUST_DATA); WinTrustData.dwUIChoice = WTD_UI_NONE; WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE; WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG; WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE; WinTrustData.pPolicyCallbackData = (LPVOID)&VerInfo; ZeroMemory(&VerInfo, sizeof(DRIVER_VER_INFO)); VerInfo.cbStruct = sizeof(DRIVER_VER_INFO); OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); if (GetVersionEx(&osvi)) { VerInfo.dwPlatform = osvi.dwPlatformId; VerInfo.dwVersion = osvi.dwMajorVersion; VerInfo.sOSVersionLow.dwMajor = osvi.dwMajorVersion; VerInfo.sOSVersionLow.dwMinor = osvi.dwMinorVersion; VerInfo.sOSVersionHigh.dwMajor = osvi.dwMajorVersion; VerInfo.sOSVersionHigh.dwMinor = osvi.dwMinorVersion; } WinTrustData.pCatalog = &WinTrustCatalogInfo; ZeroMemory(&WinTrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO)); WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO); WinTrustCatalogInfo.pbCalculatedFileHash = lpHash; WinTrustCatalogInfo.cbCalculatedFileHash = cbHash; #ifdef UNICODE WinTrustCatalogInfo.pcwszMemberTag = lpFileName; #else MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, UnicodeKey, MAX_PATH); WinTrustCatalogInfo.pcwszMemberTag = UnicodeKey; #endif // // Now we try to find the file hash in the catalog list, via CryptCATAdminEnumCatalogFromHash // PrevCat = NULL; hCatInfo = s_dsd.CryptCATAdminEnumCatalogFromHash(s_dsd.hCatAdmin, lpHash, cbHash, 0, &PrevCat); // // We want to cycle through the matching catalogs until we find one that matches both hash and member tag // bRet = FALSE; while(hCatInfo && !bRet) { ZeroMemory(&CatInfo, sizeof(CATALOG_INFO)); CatInfo.cbStruct = sizeof(CATALOG_INFO); if(s_dsd.CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)) { WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile; // Now verify that the file is an actual member of the catalog. hRes = s_dsd.WinVerifyTrust(NULL, &guidSubSystemDriver, &WinTrustData); if (hRes == ERROR_SUCCESS) { /* #ifdef UNICODE GetFullPathName(CatInfo.wszCatalogFile, MAX_PATH, szBuffer, &lpFilePart); #else WideCharToMultiByte(CP_ACP, 0, CatInfo.wszCatalogFile, -1, szBuffer, sizeof(szBuffer), NULL, NULL); GetFullPathName(szBuffer, MAX_PATH, szBuffer, &lpFilePart); #endif lpFileNode->lpCatalog = (LPTSTR)MALLOC((lstrlen(lpFilePart) + 1) * sizeof(TCHAR)); lstrcpy(lpFileNode->lpCatalog, lpFilePart); */ if (VerInfo.pcSignerCertContext != NULL) { s_dsd.CertFreeCertificateContext(VerInfo.pcSignerCertContext); VerInfo.pcSignerCertContext = NULL; } bRet = TRUE; } } if (!bRet) { // The hash was in this catalog, but the file wasn't a member... so off to the next catalog PrevCat = hCatInfo; hCatInfo = s_dsd.CryptCATAdminEnumCatalogFromHash(s_dsd.hCatAdmin, lpHash, cbHash, 0, &PrevCat); } } if (!hCatInfo) { // // If it wasn't found in the catalogs, check if the file is individually signed. // bRet = VerifyIsFileSigned(lpFileName, (PDRIVER_VER_INFO) &VerInfo); if (bRet) { // If so, mark the file as being signed. bSigned = TRUE; } } else { // The file was verified in the catalogs, so mark it as signed and free the catalog context. bSigned = TRUE; s_dsd.CryptCATAdminReleaseCatalogContext(s_dsd.hCatAdmin, hCatInfo, 0); } /* if (lpFileNode->bSigned) { #ifdef UNICODE lpFileNode->lpVersion = MALLOC((lstrlen(VerInfo.wszVersion) + 1) * sizeof(TCHAR)); lstrcpy(lpFileNode->lpVersion, VerInfo.wszVersion); lpFileNode->lpSignedBy = MALLOC((lstrlen(VerInfo.wszSignedBy) + 1) * sizeof(TCHAR)); lstrcpy(lpFileNode->lpSignedBy, VerInfo.wszSignedBy); #else WideCharToMultiByte(CP_ACP, 0, VerInfo.wszVersion, -1, szBuffer, sizeof(szBuffer), NULL, NULL); lpFileNode->lpVersion = (LPTSTR)MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR)); lstrcpy(lpFileNode->lpVersion, szBuffer); WideCharToMultiByte(CP_ACP, 0, VerInfo.wszSignedBy, -1, szBuffer, sizeof(szBuffer), NULL, NULL); lpFileNode->lpSignedBy = (LPTSTR)MALLOC((lstrlen(szBuffer) + 1) * sizeof(TCHAR)); lstrcpy(lpFileNode->lpSignedBy, szBuffer); #endif } */ return bSigned; } /**************************************************************************** * * VerifyIsFileSigned * ****************************************************************************/ BOOL VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo) { HRESULT hRes; WINTRUST_DATA WinTrustData; WINTRUST_FILE_INFO WinTrustFile; GUID guidOSVerCheck = DRIVER_ACTION_VERIFY; GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2; ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA)); WinTrustData.cbStruct = sizeof(WINTRUST_DATA); WinTrustData.dwUIChoice = WTD_UI_NONE; WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE; WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE; WinTrustData.pFile = &WinTrustFile; WinTrustData.pPolicyCallbackData = (LPVOID)lpVerInfo; ZeroMemory(lpVerInfo, sizeof(DRIVER_VER_INFO)); lpVerInfo->cbStruct = sizeof(DRIVER_VER_INFO); ZeroMemory(&WinTrustFile, sizeof(WINTRUST_FILE_INFO)); WinTrustFile.cbStruct = sizeof(WINTRUST_FILE_INFO); #ifndef UNICODE WCHAR wszFileName[MAX_PATH]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcszMatchFile, -1, (LPWSTR)wszFileName, MAX_PATH); wszFileName[MAX_PATH-1] = 0; WinTrustFile.pcwszFilePath = wszFileName; #else WinTrustFile.pcwszFilePath = pcszMatchFile; #endif hRes = s_dsd.WinVerifyTrust(NULL, &guidOSVerCheck, &WinTrustData); if (hRes != ERROR_SUCCESS) hRes = s_dsd.WinVerifyTrust(NULL, &guidPublishedSoftware, &WinTrustData); if (lpVerInfo->pcSignerCertContext != NULL) { s_dsd.CertFreeCertificateContext(lpVerInfo->pcSignerCertContext); lpVerInfo->pcSignerCertContext = NULL; } return (hRes == ERROR_SUCCESS); } /**************************************************************************** * * DiagnoseDxFiles * ****************************************************************************/ VOID DiagnoseDxFiles(SysInfo* pSysInfo, FileInfo* pDxComponentsFileInfoFirst, FileInfo* pDxWinComponentsFileInfoFirst) { FileInfo* pFileInfo; TCHAR szHighest[100]; TCHAR szDXVersion[100]; BOOL bNT = BIsPlatformNT(); BOOL bWin2k = BIsWin2k(); BOOL bIA64 = BIsIA64(); FLOAT fDXVersion = 0.0f; BOOL bDX5 = FALSE; BOOL bDX6 = FALSE; // 6.x BOOL bDX60 = FALSE; // 6.0 BOOL bDX61 = FALSE; // 6.1 BOOL bDX7 = FALSE; // 7.x BOOL bDX70 = FALSE; // 7.0 BOOL bDX71 = FALSE; // 7.1 BOOL bDX8 = FALSE; // 8.x BOOL bDX80 = FALSE; // 8.0 BOOL bDX81 = FALSE; // 8.1 BOOL b64BitDxDiag = BIsDxDiag64Bit(); TCHAR szMissing[200]; TCHAR szInWindows[200]; TCHAR szOld[200]; TCHAR szDebug[200]; TCHAR szBeta[200]; TCHAR szFmt[300]; TCHAR szMessage[300]; LONG lwNumInWindows; LONG lwNumMissing; LONG lwNumOld; LONG lwNumDebug; LONG lwNumBeta; TCHAR szListContinuer[30]; TCHAR szListEtc[30]; BOOL bVersionWarnings = TRUE; BOOL bWinsockWarning = FALSE; // Find highest version number in list szHighest[0] = '\0'; for (pFileInfo = pDxComponentsFileInfoFirst; pFileInfo != NULL; pFileInfo = pFileInfo->m_pFileInfoNext) { if (pFileInfo->m_bIgnoreVersionInfo) continue; // ddrawex.dll and dxapi.sys have wacky version numbers, so ignore them if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dxapi.sys")) == 0) { continue; } // Bug 18892: dplayx.dll and dpmodemx.dll can have wacky version numbers if // DPlay 6.0a is installed over DX 6.0 if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0) { continue; } if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0356")) == 0) { continue; } // DPlay 6.1a: dplay files can have higher version numbers if // DPlay 6.1a is installed over DX 6.0 (or DX 6.1) if (DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0)) { continue; } if (lstrcmp(pFileInfo->m_szVersion, pSysInfo->m_szDxDiagVersion) > 0) { // Bug 21291: Do not complain about file version newer than DxDiag itself continue; } if (lstrcmp(szHighest, pFileInfo->m_szVersion) < 0) lstrcpy(szHighest, pFileInfo->m_szVersion); } if (bNT) lstrcpy(szDXVersion, pSysInfo->m_szDirectXVersion); else lstrcpy(szDXVersion, szHighest); // Determine DX version DWORD dwMajor; DWORD dwMinor; DWORD dwRevision; DWORD dwBuild; if( _stscanf(szDXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild) != 4 ) { dwMajor = 0; dwMinor = 0; dwRevision = 0; dwBuild = 0; } if (dwMinor < 6) bDX5 = TRUE; else if (dwMinor < 7 && dwRevision < 2) bDX60 = TRUE; else if (dwMinor < 7) bDX61 = TRUE; else if (dwMinor < 8 && dwRevision < 1) bDX70 = TRUE; else if (dwMinor < 8) bDX71 = TRUE; else if (dwMinor == 8 && dwRevision < 1) bDX80 = TRUE; else if (dwMinor >= 8) bDX81 = TRUE; // Calc DX ver fDXVersion = (float) dwMinor + (float) (dwRevision/10.0f); // Is this DX6? bDX6 = bDX60 || bDX61; // Is this DX7? bDX7 = bDX70 || bDX71; // Is this DX8? bDX8 = bDX80 || bDX81; lwNumInWindows = 0; lwNumMissing = 0; lwNumOld = 0; lwNumDebug = 0; lwNumBeta = 0; LoadString(NULL, IDS_LISTCONTINUER, szListContinuer, 30); LoadString(NULL, IDS_LISTETC, szListEtc, 30); for (pFileInfo = pDxWinComponentsFileInfoFirst; pFileInfo != NULL; pFileInfo = pFileInfo->m_pFileInfoNext) { pFileInfo->m_bProblem = TRUE; lwNumInWindows++; if (lwNumInWindows == 1) { lstrcpy(szInWindows, pFileInfo->m_szName); } else if (lwNumInWindows < 4) { lstrcat(szInWindows, szListContinuer); lstrcat(szInWindows, pFileInfo->m_szName); } else if (lwNumInWindows < 5) { lstrcat(szInWindows, szListEtc); } } for (pFileInfo = pDxComponentsFileInfoFirst; pFileInfo != NULL; pFileInfo = pFileInfo->m_pFileInfoNext) { if (!pFileInfo->m_bExists && !pFileInfo->m_bOptional) { // A missing file is a problem unless it's optional, OR... // (on NT): it's optional on NT // (on IA64): it's not on IA64 // (on IA64): we're running 32-bit dxdiag and its optional on WOW // if file hasn't shipped yet on this DX version // if file stopped shipping on or after this DX version if (bNT && pFileInfo->m_bOptionalOnNT) { } else if (bIA64 && pFileInfo->m_bNotIA64) { } else if (bIA64 && !b64BitDxDiag && pFileInfo->m_bOptionalOnWOW64) { } else if (fDXVersion+0.05f < pFileInfo->m_fStartShipAt) { } else if (fDXVersion+0.05f >= pFileInfo->m_fStopShipAt) { } else { pFileInfo->m_bProblem = TRUE; LoadString(NULL, IDS_FILEMISSING, pFileInfo->m_szVersion, 50); lwNumMissing++; if (lwNumMissing == 1) { lstrcpy(szMissing, pFileInfo->m_szName); } else if (lwNumMissing < 4) { lstrcat(szMissing, szListContinuer); lstrcat(szMissing, pFileInfo->m_szName); } else if (lwNumMissing < 5) { lstrcat(szMissing, szListEtc); } } } if (!pFileInfo->m_bExists) continue; if( BIsWin95() ) { if( DXUtil_strcmpi(pFileInfo->m_szName, TEXT("wsock32.dll")) ) { if( IsBadWin95Winsock( pFileInfo ) ) bWinsockWarning = TRUE; } } // If DX6 or later, flag any dx5 only files as // obsolete (needing to be deleted) // manbugs 16765: don't complain about these files, just don't list them if (!bDX5 && (pFileInfo->m_fStopShipAt == 6.0f)) { pFileInfo->m_bProblem = TRUE; pFileInfo->m_bObsolete = TRUE; continue; // don't complain about these files for any other reason } if (bVersionWarnings && lstrcmp(szHighest, pFileInfo->m_szVersion) != 0) { if( pFileInfo->m_bIgnoreVersionInfo ) { // Don't warn on files that have m_bIgnoreVersionInfo set } else if( bDX81 && ( _tcsstr(pFileInfo->m_szVersion, TEXT("4.08.00.0400")) != NULL || _tcsstr(pFileInfo->m_szVersion, TEXT("5.01.2258.0400")) != NULL ) ) { // Bug 48732: If szHighest is 4.08.00.05xx and // pFileInfo->m_szVersion is 4.08.00.0400 its OK } else if( bWin2k && ( (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("5.00.2134.0001")) == 0) || (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("5.00.2135.0001")) == 0) || (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("5.00.2134.0001")) == 0) ) ) { } else if( bDX71 && _tcsstr(pFileInfo->m_szVersion, TEXT("4.07.00.07")) != NULL ) { // Bug 114753: If szHighest is 4.07.01.xxxx and // pFileInfo->m_szVersion is 4.07.00.0700 its OK (for now). } else if (!bNT && (bDX60 || bDX61) && CompareString(LOCALE_SYSTEM_DEFAULT, 0, pFileInfo->m_szVersion, 4, TEXT("4.05"), 4) == CSTR_EQUAL && ( DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dsound.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dsound.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("msanalog.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("gchand.dll")) == 0)) { // If Win9x DX6.x, dsound and dinput are allowed to be 4.05.xx.xxxx // CompareString is used rather than lstrcmp only because we // only want to look at the first four characters of the string // Don't report these as version problems } else if (!bNT && bDX7 && CompareString(LOCALE_SYSTEM_DEFAULT, 0, pFileInfo->m_szVersion, 4, TEXT("4.05"), 4) == CSTR_EQUAL && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("gchand.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("msanalog.vxd")) == 0)) { // 21470: On DX7, these input files still exist on Win95, // and they stay at DX5 level. } else if ( !bNT && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("msjstick.drv")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.00.00.0950")) == 0) || (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.05.00.0155")) == 0) ) { // 34687: These stays at the dx5 level. } else if (!bNT && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dxapi.sys")) == 0)) { // Ignore ddrawex.dll and dxapi.sys on Win9x because they have weird version numbers: } else if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0) { // Bug 18892: work around DPlay 6.0a } else if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0356")) == 0) { // Bug 18892: work around DPlay 6.0a } else if (DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0)) { // DPlay 6.1a: dplay files can have higher version numbers if // DPlay 6.1a is installed over DX 6.0 (or DX 6.1) } else if (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dxsetup.exe")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dsetup.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dsetup16.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dsetup32.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("directx.cpl")) == 0) { // Bug 18540: Don't complain if dsetup/cpl files are out of date because // some updates (OSR) don't update the setup/cpl files which may exist from // another (SDK) installation } else if (!bNT && DXUtil_strcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0436")) == 0 && (DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 || DXUtil_strcmpi(pFileInfo->m_szName, TEXT("dplaysvr.exe")) == 0)) { // On DX 6.1a, the RM and DPlay files stay at 4.06.02.0436. No problemo. } else if (lstrcmp(pFileInfo->m_szVersion, pSysInfo->m_szDxDiagVersion) > 0) { // Bug 21291: Do not complain about file version newer than DxDiag itself } else { pFileInfo->m_bProblem = TRUE; lwNumOld++; if (lwNumOld == 1) { lstrcpy(szOld, pFileInfo->m_szName); } else if (lwNumOld < 4) { lstrcat(szOld, szListContinuer); lstrcat(szOld, pFileInfo->m_szName); } else if (lwNumOld < 5) { lstrcat(szOld, szListEtc); } } } // end if (bVersionWarnings && lstrcmp(szHighest, pFileInfo->m_szVersion) != 0) if (pFileInfo->m_bBeta && !pFileInfo->m_bIgnoreBeta) { pFileInfo->m_bProblem = TRUE; lwNumBeta++; if (lwNumBeta == 1) { lstrcpy(szBeta, pFileInfo->m_szName); } else if (lwNumBeta < 4) { lstrcat(szBeta, szListContinuer); lstrcat(szBeta, pFileInfo->m_szName); } else if (lwNumBeta < 5) { lstrcat(szBeta, szListEtc); } } if (pFileInfo->m_bDebug && !pFileInfo->m_bIgnoreDebug) { pFileInfo->m_bProblem = TRUE; lwNumDebug++; if (lwNumDebug == 1) { lstrcpy(szDebug, pFileInfo->m_szName); } else if (lwNumDebug < 4) { lstrcat(szDebug, szListContinuer); lstrcat(szDebug, pFileInfo->m_szName); } else if (lwNumDebug < 5) { lstrcat(szDebug, szListEtc); } } } BOOL bShouldReinstall = FALSE; _tcscpy(pSysInfo->m_szDXFileNotes, TEXT("") ); _tcscpy(pSysInfo->m_szDXFileNotesEnglish, TEXT("") ); if (lwNumInWindows > 0) { if (lwNumInWindows == 1) LoadString(NULL, IDS_INWINDOWSFMT1, szFmt, 300); else LoadString(NULL, IDS_INWINDOWSFMT2, szFmt, 300); wsprintf(szMessage, szFmt, szInWindows); _tcscat(pSysInfo->m_szDXFileNotes, szMessage); if (lwNumInWindows == 1) LoadString(NULL, IDS_INWINDOWSFMT1_ENGLISH, szFmt, 300); else LoadString(NULL, IDS_INWINDOWSFMT2_ENGLISH, szFmt, 300); wsprintf(szMessage, szFmt, szInWindows); _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage); } if (lwNumMissing > 0) { if (lwNumMissing == 1) LoadString(NULL, IDS_MISSINGFMT1, szFmt, 300); else LoadString(NULL, IDS_MISSINGFMT2, szFmt, 300); wsprintf(szMessage, szFmt, szMissing); _tcscat(pSysInfo->m_szDXFileNotes, szMessage); if (lwNumMissing == 1) LoadString(NULL, IDS_MISSINGFMT1_ENGLISH, szFmt, 300); else LoadString(NULL, IDS_MISSINGFMT2_ENGLISH, szFmt, 300); wsprintf(szMessage, szFmt, szMissing); _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage); bShouldReinstall = TRUE; } if (lwNumOld > 0) { if (lwNumOld == 1) LoadString(NULL, IDS_OLDFMT1, szFmt, 300); else LoadString(NULL, IDS_OLDFMT2, szFmt, 300); wsprintf(szMessage, szFmt, szOld); _tcscat(pSysInfo->m_szDXFileNotes, szMessage); if (lwNumOld == 1) LoadString(NULL, IDS_OLDFMT1_ENGLISH, szFmt, 300); else LoadString(NULL, IDS_OLDFMT2_ENGLISH, szFmt, 300); wsprintf(szMessage, szFmt, szOld); _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage); bShouldReinstall = TRUE; } if (lwNumBeta > 0) { if (lwNumBeta == 1) LoadString(NULL, IDS_BETAFMT1, szFmt, 300); else LoadString(NULL, IDS_BETAFMT2, szFmt, 300); wsprintf(szMessage, szFmt, szBeta); _tcscat(pSysInfo->m_szDXFileNotes, szMessage); if (lwNumBeta == 1) LoadString(NULL, IDS_BETAFMT1_ENGLISH, szFmt, 300); else LoadString(NULL, IDS_BETAFMT2_ENGLISH, szFmt, 300); wsprintf(szMessage, szFmt, szBeta); _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage); bShouldReinstall = TRUE; } if (lwNumDebug > 0) { if (lwNumDebug == 1) LoadString(NULL, IDS_DEBUGFMT1, szFmt, 300); else LoadString(NULL, IDS_DEBUGFMT2, szFmt, 300); wsprintf(szMessage, szFmt, szDebug); _tcscat( pSysInfo->m_szDXFileNotes, szMessage); if (lwNumDebug == 1) LoadString(NULL, IDS_DEBUGFMT1_ENGLISH, szFmt, 300); else LoadString(NULL, IDS_DEBUGFMT2_ENGLISH, szFmt, 300); wsprintf(szMessage, szFmt, szDebug); _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage); //bShouldReinstall = TRUE; } if( bWinsockWarning ) { LoadString(NULL, IDS_WINSOCK_WARN, szMessage, 300); _tcscat( pSysInfo->m_szDXFileNotes, szMessage); LoadString(NULL, IDS_WINSOCK_WARN_ENGLISH, szMessage, 300); _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage); } if( bShouldReinstall ) { BOOL bTellUser = FALSE; // Figure out if the user can install DirectX if( BIsPlatform9x() ) bTellUser = TRUE; else if( BIsWin2k() && bDX8 ) bTellUser = TRUE; if( bTellUser ) { LoadString(NULL, IDS_REINSTALL_DX, szMessage, 300); _tcscat( pSysInfo->m_szDXFileNotes, szMessage); LoadString(NULL, IDS_REINSTALL_DX_ENGLISH, szMessage, 300); _tcscat( pSysInfo->m_szDXFileNotesEnglish, szMessage); } } if (lwNumMissing == 0 && lwNumOld == 0 && lwNumBeta == 0 && lwNumDebug == 0 && lwNumInWindows == 0) { LoadString(NULL, IDS_NOPROBLEM, szMessage, 300); _tcscat(pSysInfo->m_szDXFileNotes, szMessage); LoadString(NULL, IDS_NOPROBLEM_ENGLISH, szMessage, 300); _tcscat(pSysInfo->m_szDXFileNotesEnglish, szMessage); } } /**************************************************************************** * * IsBadWin95Winsock * ****************************************************************************/ BOOL IsBadWin95Winsock( FileInfo* pFileInfo ) { typedef int (PASCAL* LPWSASTARTUP)(IN WORD wVersionRequired, OUT LPWSADATA lpWSAData); typedef int (PASCAL* LPWSACLEANUP)(void); BOOL bReturn = FALSE; TCHAR szPath[MAX_PATH]; HINSTANCE hInstWSock; LPWSASTARTUP pWSAStartup = NULL; LPWSACLEANUP pWSACleanup = NULL; GetSystemDirectory(szPath, MAX_PATH); lstrcat(szPath, TEXT("\\wsock32.dll")); hInstWSock = LoadLibrary(szPath); if (hInstWSock != NULL) { pWSAStartup = (LPWSASTARTUP)GetProcAddress(hInstWSock, "WSAStartup"); pWSACleanup = (LPWSACLEANUP)GetProcAddress(hInstWSock, "WSACleanup"); if (pWSAStartup != NULL && pWSACleanup != NULL) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = pWSAStartup( wVersionRequested, &wsaData ); if ( err == 0 ) { if ( LOBYTE( wsaData.wVersion ) == 2 && HIBYTE( wsaData.wVersion ) == 2 ) { FILETIME fileTimeGoodWinsock; SYSTEMTIME systemTimeGoodWinsock; ULARGE_INTEGER ulGoodWinsock; ULARGE_INTEGER ulCurrentWinsock; ZeroMemory( &systemTimeGoodWinsock, sizeof(SYSTEMTIME) ); systemTimeGoodWinsock.wYear = 1998; systemTimeGoodWinsock.wMonth = 2; systemTimeGoodWinsock.wDay = 6; systemTimeGoodWinsock.wHour = 14; systemTimeGoodWinsock.wMinute = 18; systemTimeGoodWinsock.wSecond = 00; SystemTimeToFileTime( &systemTimeGoodWinsock, &fileTimeGoodWinsock ); ulCurrentWinsock.LowPart = pFileInfo->m_FileTime.dwLowDateTime; ulCurrentWinsock.HighPart = pFileInfo->m_FileTime.dwHighDateTime; ulGoodWinsock.LowPart = fileTimeGoodWinsock.dwLowDateTime; ulGoodWinsock.HighPart = fileTimeGoodWinsock.dwHighDateTime; if( ulCurrentWinsock.QuadPart < ulGoodWinsock.QuadPart ) { bReturn = TRUE; } } pWSACleanup(); } } } FreeLibrary(hInstWSock); return bReturn; }