windows-nt/Source/XPSP1/NT/multimedia/directx/dxdiag/fileinfo.cpp
2020-09-26 16:20:57 +08:00

2020 lines
72 KiB
C++

/****************************************************************************
*
* 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 <tchar.h>
#include <Windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <capi.h>
#include <softpub.h>
#include <winsock.h>
#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 FileIsSignedOld(LPTSTR lpszFile);
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 != RegOpenKey(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion"), &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 != RegOpenKey(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\MediaPlayer"), &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)
{
lstrcpy(szFile, pszFilePos);
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);
lstrcpy(szPath, pszFolder);
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 (lstrcmpi(pszLeaf, TEXT("vidx16.dll")) == 0)
{
if (pszVersion != NULL)
lstrcpy(pszVersion, TEXT("0.00.00.0000"));
if (pszAttributes != NULL)
wsprintf(pszAttributes, TEXT("%s %s"), szFinal, szRetail);
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;
lstrcpy(szFileAndPath, pszPath);
lstrcat(szFileAndPath, TEXT("\\"));
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;
}
// 5/12/97(RichGr): From Eric's dsetup16.c.
// * 14-sep-95 ericeng directdraw signed tests, drivers failing dll tests are removed from list
/****************************************************************************
*
* FileIsSignedOld
*
****************************************************************************/
BOOL FileIsSignedOld(LPTSTR lpszFile)
{
typedef struct tagIMAGE_DOS_HEADER // DOS .EXE header
{
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER, FAR* LPIMAGE_DOS_HEADER;
typedef struct tagIMAGE_OS2_HEADER // OS/2 .EXE header
{
WORD ne_magic; // Magic number
CHAR ne_ver; // Version number
CHAR ne_rev; // Revision number
WORD ne_enttab; // Offset of Entry Table
WORD ne_cbenttab; // Number of bytes in Entry Table
LONG ne_crc; // Checksum of whole file
WORD ne_flags; // Flag word
WORD ne_autodata; // Automatic data segment number
WORD ne_heap; // Initial heap allocation
WORD ne_stack; // Initial stack allocation
LONG ne_csip; // Initial CS:IP setting
LONG ne_sssp; // Initial SS:SP setting
WORD ne_cseg; // Count of file segments
WORD ne_cmod; // Entries in Module Reference Table
WORD ne_cbnrestab; // Size of non-resident name table
WORD ne_segtab; // Offset of Segment Table
WORD ne_rsrctab; // Offset of Resource Table
WORD ne_restab; // Offset of resident name table
WORD ne_modtab; // Offset of Module Reference Table
WORD ne_imptab; // Offset of Imported Names Table
LONG ne_nrestab; // Offset of Non-resident Names Table
WORD ne_cmovent; // Count of movable entries
WORD ne_align; // Segment alignment shift count
WORD ne_cres; // Count of resource segments
BYTE ne_exetyp; // Target Operating system
BYTE ne_flagsothers; // Other .EXE flags
WORD ne_pretthunks; // offset to return thunks
WORD ne_psegrefbytes; // offset to segment ref. bytes
WORD ne_swaparea; // Minimum code swap area size
WORD ne_expver; // Expected Windows version number
} IMAGE_OS2_HEADER, * PIMAGE_OS2_HEADER, FAR* LPIMAGE_OS2_HEADER;
typedef struct tagWINSTUB
{
IMAGE_DOS_HEADER idh;
BYTE rgb[14];
} WINSTUB, * PWINSTUB, FAR* LPWINSTUB;
typedef struct tagFILEINFO
{
BYTE cbInfo[0x120];
} FILEINFO, * PFILEINFO, FAR* LPFILEINFO;
FILE * pf;
int nRC;
FILEINFO fi;
LPIMAGE_DOS_HEADER lpmz;
// LPIMAGE_OS2_HEADER lpne;
BYTE cbInfo[9+32+2];
BOOL IsSigned = FALSE;
static WINSTUB winstub = {
{
IMAGE_DOS_SIGNATURE, /* magic */
0, /* bytes on last page - varies */
0, /* pages in file - varies */
0, /* relocations */
4, /* paragraphs in header */
1, /* min allocation */
0xFFFF, /* max allocation */
0, /* initial SS */
0xB8, /* initial SP */
0, /* checksum (ha!) */
0, /* initial IP */
0, /* initial CS */
0x40, /* lfarlc */
0, /* overlay number */
{ 0, 0, 0, 0}, /* reserved */
0, /* oem id */
0, /* oem info */
0, /* compiler bug */
{ 0}, /* reserved */
0x80, /* lfanew */
},
{
0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21,
}
};
pf = _tfopen(lpszFile, TEXT("rb"));
if (pf==0)
{
return FALSE;
}
nRC = fread(&fi, sizeof(BYTE), sizeof(FILEINFO), pf);
if (nRC != sizeof(FILEINFO))
{
goto FileIsSigned_exit;
}
lpmz = (LPIMAGE_DOS_HEADER)(&fi);
// lpne = (LPIMAGE_OS2_HEADER)((WORD)&fi + 0x80);
winstub.idh.e_cblp = lpmz->e_cblp;
winstub.idh.e_cp = lpmz->e_cp;
if (memcmp(&fi, &winstub, sizeof(winstub)) == 0)
{
goto FileIsSigned_exit;
}
// if (lpne->ne_magic == IMAGE_OS2_SIGNATURE ||
// lpne->ne_magic == IMAGE_VXD_SIGNATURE ||
// lpne->ne_magic == IMAGE_NT_SIGNATURE)
// {
// DPF(0, "Found a match in the OS2 header");
// }
// else
// {
// DPF(0, "Didn't meet second criteria!!!");
// goto FileIsSigned_exit;
// }
memcpy(cbInfo, &((PWINSTUB)(&fi)->cbInfo)->rgb[14], sizeof(cbInfo));
if ( (cbInfo[4] != ' ' ) || // space
(cbInfo[8] != ' ' ) || // space
(cbInfo[9+32] != '\n') || // return
(cbInfo[9+32+1] != '$' ) ) // Dollar Sign
{
goto FileIsSigned_exit;
}
cbInfo[4] = 0;
cbInfo[8] = 0;
if ( (strcmp((const char*)&cbInfo[0], "Cert") != 0) ||
(strcmp((const char*)&cbInfo[5], "DX2") != 0) )
{
goto FileIsSigned_exit;
}
IsSigned=TRUE;
FileIsSigned_exit:
fclose(pf);
return IsSigned;
}
/****************************************************************************
*
* 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;
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)
{
lstrcpy(lpFileName, pszFile);
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);
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[50];
TCHAR szDXVersion[50];
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 (lstrcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 ||
lstrcmpi(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 (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 &&
lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0)
{
continue;
}
if (lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 &&
lstrcmpi(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 (lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 &&
(lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
lstrcmpi(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;
_stscanf(szDXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
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( lstrcmpi(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( _tcsstr(pFileInfo->m_szVersion, TEXT("5.01.2600.0000")) != NULL )
{
// Allow 5.01.2600.0000 in SP1
}
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 && (
(lstrcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("5.00.2134.0001")) == 0) ||
(lstrcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("5.00.2135.0001")) == 0) ||
(lstrcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 && lstrcmpi(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 &&
( lstrcmpi(pFileInfo->m_szName, TEXT("dsound.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dsound.vxd")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("msanalog.vxd")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 ||
lstrcmpi(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 &&
(lstrcmpi(pFileInfo->m_szName, TEXT("dinput.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dinput.vxd")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("joy.cpl")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("gchand.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("gcdef.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 ||
lstrcmpi(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 &&
(lstrcmpi(pFileInfo->m_szName, TEXT("msjstick.drv")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.00.00.0950")) == 0) ||
(lstrcmpi(pFileInfo->m_szName, TEXT("vjoyd.vxd")) == 0 && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.05.00.0155")) == 0)
)
{
// 34687: These stays at the dx5 level.
}
else if (!bNT && (lstrcmpi(pFileInfo->m_szName, TEXT("ddrawex.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dxapi.sys")) == 0))
{
// Ignore ddrawex.dll and dxapi.sys on Win9x because they have weird version numbers:
}
else if (lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 &&
lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0363")) == 0)
{
// Bug 18892: work around DPlay 6.0a
}
else if (lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 &&
lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0356")) == 0)
{
// Bug 18892: work around DPlay 6.0a
}
else if (lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.03.0518")) == 0 &&
(lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
lstrcmpi(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 (lstrcmpi(pFileInfo->m_szName, TEXT("dxsetup.exe")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dsetup.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dsetup16.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dsetup32.dll")) == 0 ||
lstrcmpi(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 && lstrcmpi(pFileInfo->m_szVersion, TEXT("4.06.02.0436")) == 0 &&
(lstrcmpi(pFileInfo->m_szName, TEXT("d3drm.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("d3dxof.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("d3dpmesh.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dplayx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpmodemx.dll")) == 0 ||
lstrcmpi(pFileInfo->m_szName, TEXT("dpwsockx.dll")) == 0 ||
lstrcmpi(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;
}