|
|
/*==========================================================================;
* * 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
//
#undef DPF_MODNAME
#define DPF_MODNAME "InitCATAPI"
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 (D3DADAPTER_IDENTIFIER8* pDI) { void * buffer; VS_FIXEDFILEINFO * verinfo; DWORD dwSize; DWORD dwHi,dwLo;
//Failure means 0 returned
pDI->DriverVersion.HighPart = 0; pDI->DriverVersion.LowPart = 0;
dwSize = GetFileVersionInfoSize (pDI->Driver, 0);
if (!dwSize) { return; }
buffer=MemAlloc(dwSize); if (!buffer) { return; }
if (!GetFileVersionInfo(pDI->Driver, 0, dwSize, buffer)) { MemFree(buffer); return; }
if (!VerQueryValue(buffer, "\\", (void **)&verinfo, (UINT *)&dwSize)) { MemFree(buffer); return; }
pDI->DriverVersion.HighPart = verinfo->dwFileVersionMS; pDI->DriverVersion.LowPart = verinfo->dwFileVersionLS;
MemFree(buffer); }
extern HRESULT _GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, D3DADAPTER_IDENTIFIER8* pDI, char *szDeviceID);
/*
* following are all the 9x-specific version functions */ void GetHALName(char* pDriverName, D3DADAPTER_IDENTIFIER8* pDI) { pDI->Driver[0] = '\0'; D3D8GetHALName(pDriverName, pDI->Driver); }
BOOL CheckPowerVR(D3DADAPTER_IDENTIFIER8* pDI) { #if 0
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; #endif
return TRUE; }
HRESULT Check3Dfx (D3DADAPTER_IDENTIFIER8* pDI) { HRESULT hr = S_OK; char szDeviceID[MAX_DDDEVICEID_STRING];
if (FAILED(_GetDriverInfoFromRegistry(NULL, "Display", VEN_3DFX, pDI, szDeviceID))) { DPF_ERR("Couldn't get registry data for this device"); hr = E_FAIL; }
return hr; }
HRESULT GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, D3DADAPTER_IDENTIFIER8* pDI, char *szDeviceID) { return _GetDriverInfoFromRegistry(szClass, szClassNot, szVendor, pDI, szDeviceID); }
/*
* 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
HRESULT Check3Dfx(D3DADAPTER_IDENTIFIER8* pDI) { return E_FAIL; }
HRESULT GetDriverInfoFromRegistry(char *szClass, char *szClassNot, char *szVendor, D3DADAPTER_IDENTIFIER8* pDI, char *szDeviceID) { return E_FAIL; }
/*
* Given a DISPLAY_DEVICE, get driver name, assuming winnt5 * NOTE::: THIS FUNCTION NUKES THE DISPLAY_DEVICE.DeviceKey STRING!!!! */ void GetNTDriverNameAndVersion(DISPLAY_DEVICEA * pdd, D3DADAPTER_IDENTIFIER8* pDI) { HKEY hKey; void* buffer; DWORD dwSize; VS_FIXEDFILEINFO* verinfo;
//
// 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->Driver, pTemp+1, sizeof(pDI->Driver)); //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->Driver); DWORD dwType = 0; if (ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("InstalledDisplayDrivers"), NULL, &dwType, pDI->Driver, &dwSize)) { lstrcat(pDI->Driver, TEXT(".dll")); }
RegCloseKey(hKey); }
// We have the name, now get the version
pDI->DriverVersion.HighPart = 0; pDI->DriverVersion.LowPart = 0;
dwSize=GetFileVersionInfoSize(pDI->Driver, 0); if (dwSize == 0) return;
buffer = MemAlloc(dwSize); if (buffer == NULL) return;
if (!GetFileVersionInfo(pDI->Driver, 0, dwSize, buffer)) { MemFree(buffer); return; }
if (!VerQueryValue(buffer, "\\", (void **)&verinfo, (UINT *)&dwSize)) { MemFree(buffer); return; }
pDI->DriverVersion.HighPart = verinfo->dwFileVersionMS; pDI->DriverVersion.LowPart = verinfo->dwFileVersionLS;
MemFree(buffer); } #endif //win95
void GenerateIdentifier(D3DADAPTER_IDENTIFIER8* pDI) { LPDWORD pdw;
CopyMemory(&pDI->DeviceIdentifier, &CLSID_DirectDraw, sizeof(pDI->DeviceIdentifier));
//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->DeviceIdentifier; pdw[0] ^= pDI->VendorId; pdw[1] ^= pDI->DeviceId; pdw[2] ^= pDI->SubSysId; pdw[3] ^= pDI->Revision;
// The driver version gets XORed into the last two DWORDs of the GUID:
pdw[2] ^= pDI->DriverVersion.LowPart; pdw[3] ^= pDI->DriverVersion.HighPart; }
void ParseDeviceId(D3DADAPTER_IDENTIFIER8* pDI, char *szDeviceID) { char * p;
DPF(5,"Parsing %s",szDeviceID);
pDI->VendorId = 0; pDI->DeviceId = 0; pDI->SubSysId = 0; pDI->Revision = 0;
if (p =_strstr(szDeviceID, "VEN_")) pDI->VendorId = _atoi(p + 4);
if (p = _strstr(szDeviceID, "DEV_")) pDI->DeviceId = _atoi(p + 4);
if (p = _strstr(szDeviceID, "SUBSYS_")) pDI->SubSysId = _atoi(p + 7);
if (p = _strstr(szDeviceID, "REV_")) pDI->Revision = _atoi(p + 4); }
void GetAdapterInfo(char* pDriverName, D3DADAPTER_IDENTIFIER8* pDI, BOOL bDisplayDriver, BOOL bGuidOnly, BOOL bDriverName) { HRESULT hr = S_OK; int n; DISPLAY_DEVICEA dd; BOOL bFound; char szDeviceID[MAX_DDDEVICEID_STRING]; #ifndef WINNT
static char szWin9xName[MAX_DDDEVICEID_STRING]; #endif
memset(pDI, 0, sizeof(*pDI)); szDeviceID[0] = 0; #ifndef WINNT
// On Win9X, it's pretty expensive to get the driver name, so we
// only want to get it when we really need it
szWin9xName[0] = '\0'; if (bDriverName) { GetHALName(pDriverName, pDI); GetFileVersionData(pDI); } #endif
// If it's a 3dfx, it's easy
if (!bDisplayDriver) { hr = Check3Dfx(pDI); } 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++) { if (0 == _stricmp(dd.DeviceName, pDriverName)) { // Found the device. Now we can get some data for it.
lstrcpyn(pDI->Description, dd.DeviceString, sizeof(pDI->Description)); lstrcpyn(szDeviceID, dd.DeviceID, sizeof(szDeviceID));
bFound = TRUE;
#ifdef WINNT
GetNTDriverNameAndVersion(&dd,pDI); #else
GetWin9XDriverName(&dd, szWin9xName); if (pDI->Driver[0] == '\0') { lstrcpyn(pDI->Driver, szWin9xName, sizeof(pDI->Driver)); } #endif
break; }
ZeroMemory(&dd, sizeof(dd)); dd.cb = sizeof(dd); }
if (!bFound) { // Didn't find it: xxxEnumDisplayDevices failed, i.e. we're on 9x or NT4,
if (FAILED(GetDriverInfoFromRegistry("Display", NULL, NULL, pDI, szDeviceID))) { return; } } }
if (SUCCEEDED(hr)) { ParseDeviceId(pDI, szDeviceID);
// Finally, for the primary only, check if a PowerVR is in and functioning
#if 0
if (0 == (dwFlags & DDGDI_GETHOSTIDENTIFIER)) { if (IsVGADevice(pdrv->cDriverName) && CheckPowerVR(pDI)) { ParseDeviceId(pDI, szDeviceID); } } #endif
// Munge driver version and ID into the identifier GUID.
GenerateIdentifier(pDI);
// Now get the WHQL level
if (!bGuidOnly) { #ifdef WINNT
pDI->WHQLLevel = GetWHQLLevel((LPTSTR)pDI->Driver, NULL); #else
pDI->WHQLLevel = GetWHQLLevel((LPTSTR)pDI->Driver, szWin9xName); #endif
} else { pDI->WHQLLevel = 0; } } }
/*
* 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) { D3DADAPTER_IDENTIFIER8 DI;
if (IsEqualIID(pGuid, &guidVoodoo1A) || IsEqualIID(pGuid, &guidVoodoo1B)) { #ifdef WIN95
char szDeviceID[MAX_DDDEVICEID_STRING];
/*
* Now search the hardware enum key to see if Voodoo 1 hardware exists */ if (FAILED(_GetDriverInfoFromRegistry(NULL, "Display", VEN_3DFXVOODOO1, &DI, szDeviceID))) { 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 = MemAlloc(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
//
MemFree(pbHash);
}
CloseHandle(hFile); } }
ReleaseCATAPI(&catapi);
return dwWHQLLevel; }
|