You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1285 lines
42 KiB
1285 lines
42 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: drvinfo.c
|
|
* Content: DirectDraw driver info implementation
|
|
*@@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 17-jun-98 jeffno initial implementation, after michael lyons and toddla
|
|
* 14-jun-99 mregen return WHQL certification level -- postponed
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "ddrawpr.h"
|
|
|
|
#include <tchar.h>
|
|
#include <stdio.h>
|
|
#include <wincrypt.h>
|
|
#include <wintrust.h>
|
|
#include <softpub.h>
|
|
#include <mscat.h>
|
|
|
|
|
|
|
|
//========================================================================
|
|
//
|
|
// just some handy forward declarations
|
|
//
|
|
DWORD GetWHQLLevel(LPTSTR lpszDriver, LPSTR lpszWin9xDriver);
|
|
DWORD IsFileDigitallySigned(LPTSTR lpszDriver);
|
|
BOOL FileIsSignedOld(LPTSTR lpszFile);
|
|
|
|
//
|
|
// These functions are defined in mscat.h. They are not available on win95,
|
|
// so we have to use LoadLibrary to load mscat32.dll and wincrypt.dll
|
|
//
|
|
typedef HCATINFO WINAPI funcCryptCATAdminEnumCatalogFromHash(HCATADMIN hCatAdmin,
|
|
BYTE *pbHash,
|
|
DWORD cbHash,
|
|
DWORD dwFlags,
|
|
HCATINFO *phPrevCatInfo);
|
|
typedef BOOL WINAPI funcCryptCATAdminCalcHashFromFileHandle(HANDLE hFile,
|
|
DWORD *pcbHash,
|
|
BYTE *pbHash,
|
|
DWORD dwFlags);
|
|
typedef HANDLE WINAPI funcCryptCATOpen( LPWSTR pwszFileName,
|
|
DWORD fdwOpenFlags,
|
|
HCRYPTPROV hProv,
|
|
DWORD dwPublicVersion,
|
|
DWORD dwEncodingType);
|
|
typedef BOOL WINAPI funcCryptCATClose(IN HANDLE hCatalog);
|
|
typedef CRYPTCATATTRIBUTE * WINAPI funcCryptCATGetCatAttrInfo( HANDLE hCatalog,
|
|
LPWSTR pwszReferenceTag);
|
|
typedef BOOL WINAPI funcCryptCATAdminAcquireContext(HCATADMIN *phCatAdmin,
|
|
GUID *pgSubsystem,
|
|
DWORD dwFlags);
|
|
typedef BOOL WINAPI funcCryptCATAdminReleaseContext(HCATADMIN hCatAdmin,
|
|
DWORD dwFlags);
|
|
typedef BOOL WINAPI funcCryptCATAdminReleaseCatalogContext(HCATADMIN hCatAdmin,
|
|
HCATINFO hCatInfo,
|
|
DWORD dwFlags);
|
|
typedef BOOL WINAPI funcCryptCATCatalogInfoFromContext(HCATINFO hCatInfo,
|
|
CATALOG_INFO *psCatInfo,
|
|
DWORD dwFlags);
|
|
|
|
typedef CRYPTCATATTRIBUTE * WINAPI funcCryptCATEnumerateCatAttr(HCATINFO hCatalog,
|
|
CRYPTCATATTRIBUTE *lpCat);
|
|
|
|
|
|
//
|
|
// function defined in wincrypt.dll
|
|
//
|
|
typedef LONG WINAPI funcWinVerifyTrust(HWND hwnd, GUID *pgActionID,
|
|
LPVOID pWVTData);
|
|
|
|
//
|
|
// our storage for the mscat32/wincrypt dll loader
|
|
//
|
|
typedef struct tagCatApi {
|
|
BOOL bInitialized;
|
|
HINSTANCE hLibMSCat;
|
|
HINSTANCE hLibWinTrust;
|
|
HCATADMIN hCatAdmin;
|
|
funcCryptCATClose *pCryptCATClose;
|
|
funcCryptCATGetCatAttrInfo *pCryptCATGetCatAttrInfo;
|
|
funcCryptCATOpen *pCryptCATOpen;
|
|
funcCryptCATAdminEnumCatalogFromHash *pCryptCATAdminEnumCatalogFromHash;
|
|
funcCryptCATAdminCalcHashFromFileHandle *pCryptCATAdminCalcHashFromFileHandle;
|
|
funcCryptCATAdminAcquireContext *pCryptCATAdminAcquireContext;
|
|
funcCryptCATAdminReleaseContext *pCryptCATAdminReleaseContext;
|
|
funcCryptCATAdminReleaseCatalogContext *pCryptCATAdminReleaseCatalogContext;
|
|
funcCryptCATCatalogInfoFromContext *pCryptCATCatalogInfoFromContext;
|
|
funcCryptCATEnumerateCatAttr *pCryptCATEnumerateCatAttr;
|
|
funcWinVerifyTrust *pWinVerifyTrust;
|
|
} CATAPI,* LPCATAPI;
|
|
|
|
//========================================================================
|
|
//
|
|
// some helper functions to open/close crypt API
|
|
//
|
|
|
|
BOOL InitCATAPI(LPCATAPI lpCatApi)
|
|
{
|
|
UINT uiOldErrorMode;
|
|
HINSTANCE hLibMSCat;
|
|
HINSTANCE hLibWinTrust;
|
|
|
|
DDASSERT(lpCatApi!=NULL);
|
|
ZeroMemory( lpCatApi, sizeof(CATAPI));
|
|
|
|
// already initialized by ZeroMemory
|
|
// lpCatApi->bInitialized=FALSE:
|
|
|
|
uiOldErrorMode=SetErrorMode(SEM_NOOPENFILEERRORBOX);
|
|
hLibMSCat=LoadLibrary("mscat32.dll");
|
|
hLibWinTrust=LoadLibrary("wintrust.dll");
|
|
|
|
if (hLibMSCat!=NULL &&
|
|
hLibWinTrust!=NULL)
|
|
{
|
|
lpCatApi->pCryptCATOpen=(funcCryptCATOpen *)
|
|
GetProcAddress ( hLibMSCat, "CryptCATOpen");
|
|
lpCatApi->pCryptCATClose=(funcCryptCATClose *)
|
|
GetProcAddress ( hLibMSCat, "CryptCATClose");
|
|
lpCatApi->pCryptCATGetCatAttrInfo=(funcCryptCATGetCatAttrInfo *)
|
|
GetProcAddress ( hLibMSCat, "CryptCATGetCatAttrInfo");
|
|
lpCatApi->pCryptCATAdminCalcHashFromFileHandle=(funcCryptCATAdminCalcHashFromFileHandle*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATAdminCalcHashFromFileHandle");
|
|
lpCatApi->pCryptCATAdminEnumCatalogFromHash=(funcCryptCATAdminEnumCatalogFromHash*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATAdminEnumCatalogFromHash");
|
|
lpCatApi->pCryptCATAdminAcquireContext=(funcCryptCATAdminAcquireContext*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATAdminAcquireContext");
|
|
lpCatApi->pCryptCATAdminReleaseContext=(funcCryptCATAdminReleaseContext*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATAdminReleaseContext");
|
|
lpCatApi->pCryptCATAdminReleaseCatalogContext=(funcCryptCATAdminReleaseCatalogContext*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATAdminReleaseCatalogContext");
|
|
lpCatApi->pCryptCATCatalogInfoFromContext=(funcCryptCATCatalogInfoFromContext*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATCatalogInfoFromContext");
|
|
lpCatApi->pCryptCATEnumerateCatAttr=(funcCryptCATEnumerateCatAttr*)
|
|
GetProcAddress ( hLibMSCat, "CryptCATEnumerateCatAttr");
|
|
lpCatApi->pWinVerifyTrust=(funcWinVerifyTrust*)
|
|
GetProcAddress ( hLibWinTrust,"WinVerifyTrust");
|
|
|
|
if (lpCatApi->pCryptCATOpen!=NULL &&
|
|
lpCatApi->pCryptCATClose!=NULL &&
|
|
lpCatApi->pCryptCATGetCatAttrInfo!=NULL &&
|
|
lpCatApi->pCryptCATAdminCalcHashFromFileHandle!=NULL &&
|
|
lpCatApi->pCryptCATAdminEnumCatalogFromHash!=NULL &&
|
|
lpCatApi->pCryptCATAdminAcquireContext!=NULL &&
|
|
lpCatApi->pCryptCATAdminReleaseContext!=NULL &&
|
|
lpCatApi->pCryptCATAdminReleaseCatalogContext!=NULL &&
|
|
lpCatApi->pCryptCATCatalogInfoFromContext!=NULL &&
|
|
lpCatApi->pCryptCATEnumerateCatAttr !=NULL &&
|
|
lpCatApi->pWinVerifyTrust!=NULL
|
|
)
|
|
{
|
|
if ((*lpCatApi->pCryptCATAdminAcquireContext)(&lpCatApi->hCatAdmin,NULL,0))
|
|
{
|
|
lpCatApi->hLibMSCat=hLibMSCat;
|
|
lpCatApi->hLibWinTrust=hLibWinTrust;
|
|
lpCatApi->bInitialized=TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!lpCatApi->bInitialized)
|
|
{
|
|
FreeLibrary(hLibMSCat);
|
|
FreeLibrary(hLibWinTrust);
|
|
}
|
|
|
|
SetErrorMode(uiOldErrorMode);
|
|
|
|
return lpCatApi->bInitialized;
|
|
}
|
|
|
|
BOOL ReleaseCATAPI(LPCATAPI lpCatApi)
|
|
{
|
|
DDASSERT(lpCatApi!=NULL);
|
|
|
|
if (lpCatApi->bInitialized)
|
|
{
|
|
(*lpCatApi->pCryptCATAdminReleaseContext)( lpCatApi->hCatAdmin, 0);
|
|
|
|
FreeLibrary(lpCatApi->hLibMSCat);
|
|
FreeLibrary(lpCatApi->hLibWinTrust);
|
|
ZeroMemory( lpCatApi, sizeof(CATAPI));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//========================================================================
|
|
//
|
|
// _strstr
|
|
//
|
|
// String-in-string function, written to avoid RTL inclusion necessity.
|
|
//
|
|
//========================================================================
|
|
char *_strstr(char *s1, char *s2)
|
|
{
|
|
if (s1 && s2)
|
|
{
|
|
while (*s1)
|
|
{
|
|
char *p1=s1;
|
|
char *p2=s2;
|
|
|
|
while (*p2 && (*p1==*p2))
|
|
{
|
|
p1++;
|
|
p2++;
|
|
}
|
|
if (*p2==0)
|
|
return s1;
|
|
|
|
s1++;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
//***&&*%**!!ing c runtime
|
|
|
|
DWORD _atoi(char * p)
|
|
{
|
|
DWORD dw=0;
|
|
while ( (*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'F') || (*p >= 'A' && *p <= 'F') )
|
|
{
|
|
dw = dw*16;
|
|
if (*p >= 'a')
|
|
dw += *p-'a' + 10;
|
|
else if (*p >= 'A')
|
|
dw += *p-'A' + 10;
|
|
else
|
|
dw += *p-'0';
|
|
|
|
p++;
|
|
}
|
|
return dw;
|
|
}
|
|
|
|
char *FindLast(char * s, char c)
|
|
{
|
|
char * pFound=0;
|
|
if (s)
|
|
{
|
|
while (*s)
|
|
{
|
|
if (*s == c)
|
|
pFound = s;
|
|
s++;
|
|
}
|
|
}
|
|
return pFound;
|
|
}
|
|
|
|
//========================================================================
|
|
// hard-coded vendor IDs
|
|
//========================================================================
|
|
#define VEN_3DFX "VEN_121A"
|
|
#define VEN_3DFXVOODOO1 "VEN_121A&DEV_0001"
|
|
#define VEN_POWERVR "VEN_1033"
|
|
|
|
#ifdef WIN95
|
|
|
|
void GetFileVersionData(
|
|
LPDDDRIVERINFOEX pDI)
|
|
{
|
|
void * buffer;
|
|
VS_FIXEDFILEINFO * verinfo;
|
|
DWORD dwSize;
|
|
DWORD dwHi,dwLo;
|
|
|
|
//Failure means 0 returned
|
|
pDI->di.liDriverVersion.HighPart = 0;
|
|
pDI->di.liDriverVersion.LowPart = 0;
|
|
|
|
|
|
dwSize=GetFileVersionInfoSize(pDI->di.szDriver, 0);
|
|
|
|
if (!dwSize)
|
|
return;
|
|
|
|
buffer=LocalAlloc(LPTR, dwSize);
|
|
if (!buffer)
|
|
return;
|
|
|
|
if (!GetFileVersionInfo(pDI->di.szDriver, 0, dwSize, buffer))
|
|
{
|
|
LocalFree(buffer);
|
|
return;
|
|
}
|
|
|
|
if (!VerQueryValue(buffer, "\\", (void **)&verinfo, (UINT *)&dwSize))
|
|
{
|
|
LocalFree(buffer);
|
|
return;
|
|
}
|
|
|
|
pDI->di.liDriverVersion.HighPart = verinfo->dwFileVersionMS;
|
|
pDI->di.liDriverVersion.LowPart = verinfo->dwFileVersionLS;
|
|
|
|
LocalFree(buffer);
|
|
}
|
|
|
|
|
|
extern HRESULT _GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, LPDDDRIVERINFOEX pDI);
|
|
|
|
/*
|
|
* following are all the 9x-specific version functions
|
|
*/
|
|
void GetHALName(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
LPDDDRIVERINFOEX pDI)
|
|
{
|
|
pDI->di.szDriver[0] = 0;
|
|
lstrcpyn(pDI->di.szDriver, pdrv->dd32BitDriverData.szName, sizeof(pDI->di.szDriver) );
|
|
}
|
|
|
|
|
|
BOOL CheckPowerVR(LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDDRIVERINFOEX pDI)
|
|
{
|
|
BOOL bFound=FALSE;
|
|
HKEY hKey;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
if (pdrv->dwFlags & DDRAWI_SECONDARYDRIVERLOADED)
|
|
{
|
|
/*
|
|
* Any secondary driver information in the registry at all? (assert this is true)
|
|
*/
|
|
if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
|
|
REGSTR_PATH_SECONDARY,
|
|
&hKey ) )
|
|
{
|
|
/*
|
|
* Extract the name of the secondary driver's DLL. (assert this works)
|
|
*/
|
|
dwSize = sizeof( pDI->di.szDriver ) - 1;
|
|
if( ERROR_SUCCESS == RegQueryValueEx( hKey,
|
|
REGSTR_VALUE_SECONDARY_DRIVERNAME,
|
|
NULL,
|
|
&dwType,
|
|
pDI->di.szDriver,
|
|
&dwSize ) )
|
|
{
|
|
if( REG_SZ == dwType )
|
|
{
|
|
GetFileVersionData(pDI);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (SUCCEEDED(_GetDriverInfoFromRegistry(NULL, "Display", VEN_POWERVR, pDI)))
|
|
{
|
|
//got PVR data...
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
HRESULT Check3Dfx(LPDDDRIVERINFOEX pDI)
|
|
{
|
|
HRESULT hr = DD_OK;
|
|
|
|
if (FAILED(_GetDriverInfoFromRegistry(NULL, "Display", VEN_3DFX, pDI)))
|
|
{
|
|
DPF_ERR("Couldn't get registry data for this device");
|
|
hr = DDERR_NOTFOUND;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, LPDDDRIVERINFOEX pDI)
|
|
{
|
|
return _GetDriverInfoFromRegistry(szClass, szClassNot, szVendor, pDI);
|
|
}
|
|
|
|
/*
|
|
* Given a DISPLAY_DEVICE, get driver name
|
|
* NOTE::: THIS FUNCTION NUKES THE DISPLAY_DEVICE.DeviceKey STRING!!!!
|
|
*/
|
|
void GetWin9XDriverName(DISPLAY_DEVICEA * pdd, LPSTR pDrvName)
|
|
{
|
|
HKEY hKey;
|
|
|
|
lstrcat( pdd->DeviceKey, "\\DEFAULT" );
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
pdd->DeviceKey,
|
|
0,
|
|
KEY_QUERY_VALUE ,
|
|
&hKey ) )
|
|
{
|
|
DWORD dwSize = MAX_DDDEVICEID_STRING;
|
|
DWORD dwType = 0;
|
|
|
|
RegQueryValueEx( hKey,
|
|
TEXT("drv"),
|
|
NULL,
|
|
&dwType,
|
|
pDrvName,
|
|
&dwSize );
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
#else //win95
|
|
|
|
/*
|
|
* following are all the NT-specific version functions
|
|
*/
|
|
void GetFileVersionData(
|
|
LPDDDRIVERINFOEX pDI)
|
|
{
|
|
//Failure means 0 returned
|
|
pDI->di.liDriverVersion.HighPart = 0;
|
|
pDI->di.liDriverVersion.LowPart = 0;
|
|
}
|
|
|
|
void GetHALName(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
LPDDDRIVERINFOEX pDI)
|
|
{
|
|
pDI->di.szDriver[0] = 0;
|
|
}
|
|
|
|
BOOL CheckPowerVR(LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDDRIVERINFOEX pdi)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT Check3Dfx(LPDDDRIVERINFOEX pDI)
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, LPDDDRIVERINFOEX pDI)
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
/*
|
|
* Given a DISPLAY_DEVICE, get driver name, assuming winnt5
|
|
* NOTE::: THIS FUNCTION NUKES THE DISPLAY_DEVICE.DeviceKey STRING!!!!
|
|
*/
|
|
void GetNTDriverNameAndVersion(DISPLAY_DEVICEA * pdd, LPDDDRIVERINFOEX pDI)
|
|
{
|
|
HKEY hKey;
|
|
|
|
//
|
|
// old style to determine display driver...returns name of miniport!
|
|
//
|
|
|
|
char * pTemp;
|
|
|
|
// The device key has the form blah\blah\services\<devicekey>\DeviceN
|
|
// So we back up one node:
|
|
if ( (pTemp = FindLast(pdd->DeviceKey,'\\')) )
|
|
{
|
|
char * pTempX;
|
|
char cOld=*pTemp;
|
|
*pTemp = 0;
|
|
|
|
//If we back up one node, we'll have the registry key under which the driver is stored. Let's use that!
|
|
if ( (pTempX = FindLast(pdd->DeviceKey,'\\')) )
|
|
{
|
|
lstrcpyn(pDI->di.szDriver, pTemp+1, sizeof(pDI->di.szDriver));
|
|
//ATTENTION No point getting version data without a filname:
|
|
//We need a new service or something to get the used display driver name
|
|
//GetFileVersionData(pDI);
|
|
}
|
|
|
|
*pTemp=cOld;
|
|
}
|
|
|
|
//
|
|
// we can find the display driver in a registry key
|
|
//
|
|
// note: InstalledDisplayDrivers can contain several entries
|
|
// to display drivers Since there is no way to find out which
|
|
// one is the active one, we always return the first as being
|
|
// the display driver!
|
|
//
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
pdd->DeviceKey+18,
|
|
0,
|
|
KEY_QUERY_VALUE ,
|
|
&hKey ) )
|
|
{
|
|
DWORD dwSize=sizeof(pDI->di.szDriver), dwType=0;
|
|
if( ERROR_SUCCESS == RegQueryValueEx( hKey,
|
|
TEXT("InstalledDisplayDrivers"),
|
|
NULL,
|
|
&dwType,
|
|
pDI->di.szDriver,
|
|
&dwSize ) )
|
|
{
|
|
lstrcat(pDI->di.szDriver, TEXT(".dll"));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
#endif //win95
|
|
|
|
|
|
|
|
void GenerateIdentifier(LPDDDRIVERINFOEX pDI)
|
|
{
|
|
LPDWORD pdw;
|
|
|
|
CopyMemory(&pDI->di.guidDeviceIdentifier, &CLSID_DirectDraw, sizeof(pDI->di.guidDeviceIdentifier));
|
|
|
|
//The device IDs get XORed into the whole GUID with the vendor and device ID in the
|
|
//first two DWORDs so they don't get XORed with anything else. This makes it
|
|
DDASSERT(sizeof(GUID) >= 4*sizeof(DWORD));
|
|
pdw = (LPDWORD) &pDI->di.guidDeviceIdentifier;
|
|
pdw[0] ^= pDI->di.dwVendorId;
|
|
pdw[1] ^= pDI->di.dwDeviceId;
|
|
pdw[2] ^= pDI->di.dwSubSysId;
|
|
pdw[3] ^= pDI->di.dwRevision;
|
|
|
|
// The driver version gets XORed into the last two DWORDs of the GUID:
|
|
pdw[2] ^= pDI->di.liDriverVersion.LowPart;
|
|
pdw[3] ^= pDI->di.liDriverVersion.HighPart;
|
|
}
|
|
|
|
|
|
void ParseDeviceId(LPDDDRIVERINFOEX pDI)
|
|
{
|
|
char * p;
|
|
|
|
DPF(5,"Parsing %s",pDI->szDeviceID);
|
|
|
|
pDI->di.dwVendorId = 0;
|
|
pDI->di.dwDeviceId = 0;
|
|
pDI->di.dwSubSysId = 0;
|
|
pDI->di.dwRevision = 0;
|
|
|
|
if(p =_strstr(pDI->szDeviceID, "VEN_"))
|
|
pDI->di.dwVendorId = _atoi( p + 4);
|
|
|
|
if(p = _strstr(pDI->szDeviceID, "DEV_"))
|
|
pDI->di.dwDeviceId = _atoi( p + 4);
|
|
|
|
if(p = _strstr(pDI->szDeviceID, "SUBSYS_"))
|
|
pDI->di.dwSubSysId = _atoi( p + 7);
|
|
|
|
if(p = _strstr(pDI->szDeviceID, "REV_"))
|
|
pDI->di.dwRevision = _atoi( p + 4);
|
|
}
|
|
|
|
|
|
HRESULT DDAPI DD_GetDeviceIdentifier( LPDIRECTDRAW lpDD, LPDDDEVICEIDENTIFIER pDI, DWORD dwFlags)
|
|
{
|
|
DDDEVICEIDENTIFIER2 ddi2;
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
HRESULT hr;
|
|
|
|
ZeroMemory(&ddi2, sizeof(ddi2));
|
|
|
|
hr = DD_GetDeviceIdentifier7(lpDD, &ddi2, dwFlags);
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
|
|
if( VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
if (VALIDEX_DDDEVICEIDENTIFIER_PTR( pDI ))
|
|
{
|
|
CopyMemory(pDI,&ddi2,sizeof(*pDI));
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid version struct passed" );
|
|
hr = DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid driver object passed" );
|
|
hr = DDERR_INVALIDOBJECT;
|
|
}
|
|
}
|
|
EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DPF_ERR("Exception encountered querying device info");
|
|
hr = DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT InternalGetDeviceIdentifier7( LPDIRECTDRAW lpDD, LPDDDEVICEIDENTIFIER2 pDI, DWORD dwFlags, BOOL bWHQL)
|
|
{
|
|
HRESULT hr=DD_OK;
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
int n;
|
|
DISPLAY_DEVICEA dd;
|
|
DDDRIVERINFOEX di;
|
|
BOOL bFound;
|
|
#ifndef WINNT
|
|
static char szWin9xName[MAX_DDDEVICEID_STRING];
|
|
#endif
|
|
|
|
ENTER_DDRAW();
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
|
|
if( VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
this_lcl = this_int->lpLcl;
|
|
pdrv = this_lcl->lpGbl;
|
|
|
|
if (VALIDEX_DDDEVICEIDENTIFIER2_PTR( pDI ))
|
|
{
|
|
/*
|
|
* Reset to something sensible
|
|
*/
|
|
ZeroMemory(&di,sizeof(di));
|
|
#ifndef WINNT
|
|
szWin9xName[0] = '\0';
|
|
#endif
|
|
|
|
if (0 == (dwFlags & ~DDGDI_VALID) )
|
|
{
|
|
/*
|
|
* First step: version info and name for the ddraw HAL driver (on 9x), and format it into a string
|
|
*/
|
|
GetHALName(pdrv, &di);
|
|
GetFileVersionData(&di);
|
|
|
|
/*
|
|
* If it's a 3dfx, it's easy
|
|
*/
|
|
if ( 0 == (pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
|
|
{
|
|
hr = Check3Dfx(&di);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Not a 3dfx.
|
|
*/
|
|
|
|
/*
|
|
* Next step: Figure out which display device we really are and get description string for it
|
|
*/
|
|
ZeroMemory(&dd, sizeof(dd));
|
|
dd.cb = sizeof(dd);
|
|
|
|
bFound=FALSE;
|
|
|
|
for( n=0; xxxEnumDisplayDevicesA( NULL, n, &dd, 0 ); n++ )
|
|
{
|
|
char * pDeviceName = pdrv->cDriverName;
|
|
|
|
//DDraw has this convention that the primary device is always DISPLAY.
|
|
|
|
if (0 == _stricmp(dd.DeviceName, pdrv->cDriverName ) ||
|
|
((dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) &&
|
|
(0 == _stricmp(pdrv->cDriverName , "DISPLAY")) ) )
|
|
{
|
|
/*
|
|
* Found the device. Now we can get some data for it.
|
|
*/
|
|
lstrcpyn(di.di.szDescription, dd.DeviceString, sizeof(di.di.szDescription));
|
|
lstrcpyn(di.szDeviceID, dd.DeviceID, sizeof(di.szDeviceID) );
|
|
|
|
bFound = TRUE;
|
|
|
|
#ifdef WINNT
|
|
GetNTDriverNameAndVersion(&dd,&di);
|
|
#else
|
|
|
|
GetWin9XDriverName(&dd, szWin9xName);
|
|
if( di.di.szDriver[0] == '\0' )
|
|
{
|
|
lstrcpyn( di.di.szDriver, szWin9xName, sizeof(di.di.szDriver) );
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory(&dd, sizeof(dd));
|
|
dd.cb = sizeof(dd);
|
|
}
|
|
|
|
/*
|
|
* Final step: Go get the pnp id of the chipset
|
|
*/
|
|
if (!bFound)
|
|
{
|
|
/*
|
|
* Didn't find it: xxxEnumDisplayDevices failed, i.e. we're on 9x or NT4,
|
|
*/
|
|
if (FAILED(GetDriverInfoFromRegistry("Display", NULL, NULL, &di)))
|
|
{
|
|
DPF_ERR("Couldn't get registry data for display");
|
|
hr = DDERR_NOTFOUND;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ParseDeviceId(&di);
|
|
|
|
/*
|
|
* Finally, for the primary only, check if a PowerVR is in and functioning
|
|
*/
|
|
if (0 == (dwFlags & DDGDI_GETHOSTIDENTIFIER) )
|
|
{
|
|
if (IsVGADevice(pdrv->cDriverName) && CheckPowerVR(pdrv, &di))
|
|
{
|
|
ParseDeviceId(&di);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Munge driver version and ID into the identifier GUID.
|
|
*/
|
|
GenerateIdentifier(&di);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid flags passed" );
|
|
hr = DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Finally copy the struct, or 0s if failed, to the app's buffer
|
|
*/
|
|
CopyMemory(pDI,&di.di,offsetof(DDDEVICEIDENTIFIER2,dwWHQLLevel) + sizeof(DWORD));
|
|
|
|
/*
|
|
* Our compiler packs structs to 8 byte boundaries, but this struct is only 4 byte aligned.
|
|
* In short, sizeof(*pDI) == 1072, but the actual size is 1068, so we cannot copy the
|
|
* buffer using sizeof, so we instead do the above wackiness. We need to assert, however,
|
|
* so we can fix this if this structure ever grows.
|
|
*/
|
|
DDASSERT((sizeof(*pDI) - (offsetof(DDDEVICEIDENTIFIER2,dwWHQLLevel) + sizeof(DWORD))) <= 4);
|
|
|
|
if (bWHQL)
|
|
{
|
|
#ifdef WINNT
|
|
pDI->dwWHQLLevel=GetWHQLLevel((LPTSTR)&di.di.szDriver, NULL);
|
|
#else
|
|
pDI->dwWHQLLevel=GetWHQLLevel((LPTSTR)&di.di.szDriver, szWin9xName);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
pDI->dwWHQLLevel = 0;
|
|
}
|
|
|
|
/*
|
|
* lets find out here if driver is WHQL certified
|
|
*/
|
|
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid version struct passed" );
|
|
hr = DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid driver object passed" );
|
|
hr = DDERR_INVALIDOBJECT;
|
|
}
|
|
}
|
|
EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DPF_ERR("Exception encountered querying device info");
|
|
hr = DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT DDAPI DD_GetDeviceIdentifier7( LPDIRECTDRAW lpDD, LPDDDEVICEIDENTIFIER2 pDI, DWORD dwFlags)
|
|
{
|
|
return InternalGetDeviceIdentifier7 (lpDD, pDI, dwFlags, TRUE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Voodoo1GoodToGo
|
|
*
|
|
* The Voodoo 1 driver will succeed the CreateDC call on Voodoo 2, Voodoo 3,
|
|
* or Banshee hardware, but if we use the driver beyond that it will hang
|
|
* the hardware. This is a work around to not enumerate a Voodoo 1
|
|
* driver if the hardware isn't there.
|
|
*
|
|
* To our knowledge, only two guids were ever used to enumerate Voodoo1
|
|
* hardware, so we will look for those guids and assume that anything else
|
|
* doesn't need to be checked.
|
|
*/
|
|
BOOL Voodoo1GoodToGo( GUID * pGuid )
|
|
{
|
|
DDDRIVERINFOEX DI;
|
|
|
|
if (IsEqualIID(pGuid, &guidVoodoo1A) || IsEqualIID(pGuid, &guidVoodoo1B) )
|
|
{
|
|
#ifdef WIN95
|
|
/*
|
|
* Now search the hardware enum key to see if Voodoo 1 hardware exists
|
|
*/
|
|
if (FAILED(_GetDriverInfoFromRegistry(NULL, "Display", VEN_3DFXVOODOO1, &DI)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifndef WINNT
|
|
/****************************************************************************
|
|
*
|
|
* FileIsSignedOld
|
|
*
|
|
* find win95 style of signature
|
|
*
|
|
****************************************************************************/
|
|
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;
|
|
|
|
|
|
FILEINFO fi;
|
|
int nRC;
|
|
LPIMAGE_DOS_HEADER lpmz;
|
|
LPIMAGE_OS2_HEADER lpne;
|
|
BYTE cbInfo[9+32+2];
|
|
BOOL IsSigned = FALSE;
|
|
OFSTRUCT OpenStruct;
|
|
HFILE hFile;
|
|
|
|
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,
|
|
}
|
|
};
|
|
|
|
OpenStruct.cBytes = sizeof( OpenStruct );
|
|
lstrcpyn( OpenStruct.szPathName, lpszFile, OFS_MAXPATHNAME );
|
|
hFile = OpenFile(lpszFile, &OpenStruct, OF_READ);
|
|
if (hFile == HFILE_ERROR )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
nRC = 0;
|
|
ReadFile( (HANDLE) hFile, (LPVOID)&fi, sizeof(FILEINFO), &nRC, NULL);
|
|
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;
|
|
}
|
|
|
|
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:
|
|
|
|
_lclose( hFile );
|
|
|
|
return IsSigned;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* GetWHQLLevel - On Win95, look for old stamp only. On Win2000, use digital
|
|
* signature only. On Win98, look for old stamp first, then digital signature
|
|
* if no old stamp.
|
|
*
|
|
* return 0 -- unsigned or uncertified
|
|
* return 1 -- driver certified
|
|
* return 1997 -- driver certified, PC97 compliant...
|
|
* return 1998...
|
|
*
|
|
*
|
|
* arguments:
|
|
*
|
|
* lpszDriver----Path of driver file
|
|
*
|
|
*/
|
|
|
|
DWORD GetWHQLLevel(LPTSTR lpszDriver, LPSTR lpszWin9xDriver)
|
|
{
|
|
TCHAR szTmp[MAX_PATH];
|
|
DWORD dwWhqlLevel = 0;
|
|
|
|
// here we should rather call
|
|
if (GetSystemDirectory( szTmp, MAX_PATH-lstrlen(lpszDriver)-2)==0)
|
|
return 0;
|
|
|
|
lstrcat( szTmp, TEXT("\\"));
|
|
lstrcat( szTmp, lpszDriver);
|
|
_tcslwr( szTmp);
|
|
|
|
//
|
|
// Look for a digital signature
|
|
//
|
|
dwWhqlLevel = IsFileDigitallySigned(szTmp);
|
|
if( dwWhqlLevel != 0 )
|
|
{
|
|
return dwWhqlLevel;
|
|
}
|
|
|
|
|
|
#ifndef WINNT
|
|
|
|
// It wasn't digitally signed, but it may still have been signed
|
|
// the old way. On Win9X, however, lpszDriver actually contains the
|
|
// 32 bit HAL name rather than the display driver, but we typically only
|
|
// signed the display driver, so we should use lpszWin9xDriver.
|
|
|
|
if( lpszWin9xDriver[0] != '\0' )
|
|
{
|
|
GetSystemDirectory( szTmp, MAX_PATH-lstrlen(lpszWin9xDriver)-2);
|
|
lstrcat( szTmp, TEXT("\\"));
|
|
lstrcat( szTmp, lpszWin9xDriver);
|
|
}
|
|
else
|
|
{
|
|
GetSystemDirectory( szTmp, MAX_PATH-lstrlen(lpszDriver)-2);
|
|
lstrcat( szTmp, TEXT("\\"));
|
|
lstrcat( szTmp, lpszDriver);
|
|
}
|
|
|
|
if (FileIsSignedOld(szTmp))
|
|
{
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
DWORD IsFileDigitallySigned(LPTSTR lpszDriver)
|
|
{
|
|
DWORD dwWHQLLevel=0; // default, driver not certified
|
|
CATAPI catapi;
|
|
WCHAR *lpFileName;
|
|
DRIVER_VER_INFO VerInfo;
|
|
TCHAR szBuffer[50];
|
|
LPSTR lpAttr;
|
|
#ifndef UNICODE
|
|
WCHAR wszDriver[MAX_PATH];
|
|
MultiByteToWideChar(CP_ACP, 0, lpszDriver, -1, wszDriver, MAX_PATH);
|
|
lpFileName = wcsrchr(wszDriver, TEXT('\\'));
|
|
if (lpFileName==NULL)
|
|
{
|
|
lpFileName = wszDriver;
|
|
}
|
|
else
|
|
{
|
|
lpFileName++;
|
|
}
|
|
#else
|
|
lpFileName = _tcsrchr(lpszDriver, TEXT('\\'));
|
|
if (lpFileName==NULL) lpFileName = lpszDriver;
|
|
#endif
|
|
|
|
|
|
//
|
|
// try to load and initialize the mscat32.dll and wintrust.dll
|
|
// these dlls are not available on win95
|
|
//
|
|
if (InitCATAPI(&catapi))
|
|
{
|
|
HANDLE hFile;
|
|
DWORD cbHashSize=0;
|
|
BYTE *pbHash;
|
|
BOOL bResult;
|
|
|
|
//
|
|
// create a handle to our driver, because cat api wants handle to file
|
|
//
|
|
hFile = CreateFile( lpszDriver,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0
|
|
);
|
|
|
|
if (hFile!=INVALID_HANDLE_VALUE)
|
|
{
|
|
// first query hash size...
|
|
bResult=(*catapi.pCryptCATAdminCalcHashFromFileHandle)(hFile,
|
|
&cbHashSize,
|
|
NULL,
|
|
0);
|
|
pbHash=NULL;
|
|
if (bResult)
|
|
{
|
|
// allocate hash
|
|
pbHash = LocalAlloc( LPTR, cbHashSize);
|
|
}
|
|
|
|
if (pbHash!=NULL)
|
|
{
|
|
HCATINFO hPrevCat=NULL;
|
|
HANDLE hCatalog=NULL;
|
|
WINTRUST_DATA WinTrustData;
|
|
WINTRUST_CATALOG_INFO WinTrustCatalogInfo;
|
|
GUID guidSubSystemDriver = DRIVER_ACTION_VERIFY;
|
|
CRYPTCATATTRIBUTE *lpCat = NULL;
|
|
|
|
//
|
|
// Now get the hash for our file
|
|
//
|
|
|
|
bResult=(*catapi.pCryptCATAdminCalcHashFromFileHandle)(hFile,
|
|
&cbHashSize,
|
|
pbHash,
|
|
0);
|
|
|
|
if (bResult)
|
|
{
|
|
hCatalog=(*catapi.pCryptCATAdminEnumCatalogFromHash)(
|
|
catapi.hCatAdmin,
|
|
pbHash,
|
|
cbHashSize,
|
|
0,
|
|
&hPrevCat);
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
WinTrustData.pCatalog = &WinTrustCatalogInfo;
|
|
|
|
ZeroMemory(&WinTrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
|
|
WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
|
|
WinTrustCatalogInfo.pbCalculatedFileHash = pbHash;
|
|
WinTrustCatalogInfo.cbCalculatedFileHash = cbHashSize;
|
|
WinTrustCatalogInfo.pcwszMemberTag = lpFileName;
|
|
|
|
while (hCatalog)
|
|
{
|
|
CATALOG_INFO CatInfo;
|
|
|
|
ZeroMemory(&CatInfo, sizeof(CATALOG_INFO));
|
|
CatInfo.cbStruct = sizeof(CATALOG_INFO);
|
|
if((*catapi.pCryptCATCatalogInfoFromContext)(hCatalog, &CatInfo, 0))
|
|
{
|
|
HRESULT hRes;
|
|
|
|
WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
|
|
|
|
// Now verify that the file is an actual member of the catalog.
|
|
hRes = (*catapi.pWinVerifyTrust)
|
|
(NULL, &guidSubSystemDriver, &WinTrustData);
|
|
|
|
if (hRes == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Our driver is certified! Now see if the cat
|
|
// info contains the WHQL level
|
|
//
|
|
CRYPTCATATTRIBUTE *lpCat = NULL;
|
|
HANDLE hCat;
|
|
|
|
dwWHQLLevel=1; // return "certified"
|
|
|
|
hCat = (*catapi.pCryptCATOpen)(CatInfo.wszCatalogFile, (DWORD)CRYPTCAT_OPEN_EXISTING, (HCRYPTPROV)NULL, 0, 0);
|
|
lpCat = (*catapi.pCryptCATGetCatAttrInfo) (hCat, L"KV_DISPLAY");
|
|
if( lpCat != NULL )
|
|
{
|
|
WideCharToMultiByte(CP_ACP, 0, (PUSHORT)lpCat->pbValue, -1, szBuffer, 50, NULL, NULL);
|
|
|
|
// The value looks like "1:yyyy-mm-dd".
|
|
|
|
lpAttr = _strstr( szBuffer, ":");
|
|
lpAttr++;
|
|
lpAttr[4] = '\0';
|
|
dwWHQLLevel = atoi( lpAttr ) * 0x10000;
|
|
lpAttr[7] = '\0';
|
|
dwWHQLLevel |= atoi( &lpAttr[5]) * 0x100;
|
|
dwWHQLLevel |= atoi( &lpAttr[8]);
|
|
}
|
|
|
|
(*catapi.pCryptCATClose)(hCat);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// iterate through catalogs...
|
|
//
|
|
hPrevCat=hCatalog;
|
|
hCatalog=(*catapi.pCryptCATAdminEnumCatalogFromHash)(
|
|
catapi.hCatAdmin,
|
|
pbHash,
|
|
cbHashSize,
|
|
0,
|
|
&hPrevCat);
|
|
}
|
|
|
|
//
|
|
// we might have to free a catalog context!
|
|
//
|
|
if (hCatalog)
|
|
{
|
|
(*catapi.pCryptCATAdminReleaseCatalogContext)
|
|
(catapi.hCatAdmin, hCatalog, 0);
|
|
}
|
|
|
|
//
|
|
// free hash
|
|
//
|
|
LocalFree(pbHash);
|
|
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
}
|
|
|
|
ReleaseCATAPI(&catapi);
|
|
|
|
return dwWHQLLevel;
|
|
}
|