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

1722 lines
66 KiB
C++

/****************************************************************************
*
* File: dispinfo.cpp
* Project: DxDiag (DirectX Diagnostic Tool)
* Author: Mike Anderson (manders@microsoft.com)
* Purpose: Gather information about the display(s) on this machine
*
* (C) Copyright 1998-1999 Microsoft Corp. All rights reserved.
*
****************************************************************************/
#include <tchar.h>
#include <Windows.h>
#define COMPILE_MULTIMON_STUBS // for multimon.h
#include <multimon.h>
#define DIRECTDRAW_VERSION 5 // run on DX5 and later versions
#include <ddraw.h>
#include <d3d.h>
#include <stdio.h>
#include "sysinfo.h" // for BIsPlatformNT
#include "reginfo.h"
#include "dispinfo.h"
#include "dispinfo8.h"
#include "fileinfo.h" // for GetFileVersion
#include "sysinfo.h"
#include "resource.h"
// Taken from DirectDraw's ddcreate.c
// This is the first GUID of secondary display devices
static const GUID DisplayGUID =
{0x67685559,0x3106,0x11d0,{0xb9,0x71,0x0,0xaa,0x0,0x34,0x2f,0x9f}};
typedef HRESULT (WINAPI* LPDIRECTDRAWCREATE)(GUID FAR *lpGUID,
LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
static VOID GetRegDisplayInfo9x(DisplayInfo* pDisplayInfo);
static VOID GetRegDisplayInfoNT(DisplayInfo* pDisplayInfo);
static HRESULT GetDirectDrawInfo(LPDIRECTDRAWCREATE pDDCreate, DisplayInfo* pDisplayInfo);
static HRESULT CALLBACK EnumDevicesCallback(GUID* pGuid, LPSTR pszDesc, LPSTR pszName,
D3DDEVICEDESC* pd3ddevdesc1, D3DDEVICEDESC* pd3ddevdesc2, VOID* pvContext);
static BOOL FindDevice(INT iDevice, TCHAR* pszDeviceClass, TCHAR* pszDeviceClassNot, TCHAR* pszHardwareKey);
static BOOL GetDeviceValue(TCHAR* pszHardwareKey, TCHAR* pszKey, TCHAR* pszValue, BYTE *buf, DWORD cbbuf);
static HRESULT CheckRegistry(RegError** ppRegErrorFirst);
static BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData );
static VOID GetRegDisplayInfoWhistler(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage );
static VOID GetRegDisplayInfoWin2k(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage );
/****************************************************************************
*
* GetBasicDisplayInfo - Get minimal info on each display
*
****************************************************************************/
HRESULT GetBasicDisplayInfo(DisplayInfo** ppDisplayInfoFirst)
{
DisplayInfo* pDisplayInfo;
DisplayInfo* pDisplayInfoNew;
TCHAR szHardwareKey[MAX_PATH];
TCHAR szDriver[MAX_PATH];
// Check OS version. Win95 cannot use EnumDisplayDevices; Win98/NT5 can:
if( BIsWinNT() || BIsWin3x() )
return S_OK; // NT4 and earlier and pre-Win95 not supported
if( BIsWin95() )
{
// Win95:
if (!FindDevice(0, TEXT("Display"), NULL, szHardwareKey))
return E_FAIL;
pDisplayInfoNew = new DisplayInfo;
if (pDisplayInfoNew == NULL)
return E_OUTOFMEMORY;
ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
*ppDisplayInfoFirst = pDisplayInfoNew;
pDisplayInfoNew->m_bCanRenderWindow = TRUE;
pDisplayInfoNew->m_hMonitor = NULL; // Win95 doesn't like multimon
lstrcpy(pDisplayInfoNew->m_szKeyDeviceID, szHardwareKey);
if (GetDeviceValue(szHardwareKey, NULL, TEXT("Driver"), (LPBYTE)szDriver, sizeof(szDriver)))
{
lstrcpy(pDisplayInfoNew->m_szKeyDeviceKey, TEXT("System\\CurrentControlSet\\Services\\Class\\"));
lstrcat(pDisplayInfoNew->m_szKeyDeviceKey, szDriver);
}
GetDeviceValue(szHardwareKey, NULL, TEXT("DeviceDesc"), (LPBYTE)pDisplayInfoNew->m_szDescription, sizeof(pDisplayInfoNew->m_szDescription));
HDC hdc;
hdc = GetDC(NULL);
if (hdc != NULL)
{
wsprintf(pDisplayInfoNew->m_szDisplayMode, TEXT("%d x %d (%d bit)"),
GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), GetDeviceCaps(hdc, BITSPIXEL));
lstrcpy( pDisplayInfoNew->m_szDisplayModeEnglish, pDisplayInfoNew->m_szDisplayMode );
ReleaseDC(NULL, hdc);
pDisplayInfoNew->m_dwWidth = GetDeviceCaps(hdc, HORZRES);
pDisplayInfoNew->m_dwHeight = GetDeviceCaps(hdc, VERTRES);
pDisplayInfoNew->m_dwBpp = GetDeviceCaps(hdc, BITSPIXEL);
}
// On Win98 and NT, we get the monitor key through a call to EnumDisplayDevices.
// On Win95, we have to use the registry to get the monitor key.
HKEY hKey = NULL;
DWORD cbData;
TCHAR szKey[200];
ULONG ulType;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Enum\\MONITOR\\DEFAULT_MONITOR\\0001"), 0, KEY_READ, &hKey))
{
cbData = sizeof szKey;
if (ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("Driver"), 0, &ulType, (LPBYTE)szKey, &cbData)
&& szKey[0])
{
lstrcpy(pDisplayInfoNew->m_szMonitorKey, TEXT("System\\CurrentControlSet\\Services\\Class\\"));
lstrcat(pDisplayInfoNew->m_szMonitorKey, szKey);
}
RegCloseKey(hKey);
}
}
else
{
// Win98 / NT5:
LONG iDevice = 0;
DISPLAY_DEVICE dispdev;
DISPLAY_DEVICE dispdev2;
ZeroMemory(&dispdev, sizeof(dispdev));
dispdev.cb = sizeof(dispdev);
ZeroMemory(&dispdev2, sizeof(dispdev2));
dispdev2.cb = sizeof(dispdev2);
while (EnumDisplayDevices(NULL, iDevice, (DISPLAY_DEVICE*)&dispdev, 0))
{
// Mirroring drivers are for monitors that echo another display, so
// they should be ignored. NT5 seems to create a mirroring driver called
// "NetMeeting driver", and we definitely don't want that.
if (dispdev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
{
iDevice++;
continue;
}
// Skip devices that aren't attached since they cause problems
if ( (dispdev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0 )
{
iDevice++;
continue;
}
pDisplayInfoNew = new DisplayInfo;
if (pDisplayInfoNew == NULL)
return E_OUTOFMEMORY;
ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
if (*ppDisplayInfoFirst == NULL)
{
*ppDisplayInfoFirst = pDisplayInfoNew;
}
else
{
for (pDisplayInfo = *ppDisplayInfoFirst;
pDisplayInfo->m_pDisplayInfoNext != NULL;
pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
{
}
pDisplayInfo->m_pDisplayInfoNext = pDisplayInfoNew;
}
pDisplayInfoNew->m_bCanRenderWindow = TRUE;
pDisplayInfoNew->m_guid = DisplayGUID;
pDisplayInfoNew->m_guid.Data1 += iDevice;
lstrcpy(pDisplayInfoNew->m_szDeviceName, dispdev.DeviceName);
lstrcpy(pDisplayInfoNew->m_szDescription, dispdev.DeviceString);
lstrcpy(pDisplayInfoNew->m_szKeyDeviceID, TEXT("Enum\\"));
lstrcat(pDisplayInfoNew->m_szKeyDeviceID, dispdev.DeviceID);
lstrcpy(pDisplayInfoNew->m_szKeyDeviceKey, dispdev.DeviceKey);
DEVMODE devmode;
ZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = sizeof(devmode);
if (EnumDisplaySettings(dispdev.DeviceName, ENUM_CURRENT_SETTINGS, &devmode))
{
pDisplayInfoNew->m_dwWidth = devmode.dmPelsWidth;
pDisplayInfoNew->m_dwHeight = devmode.dmPelsHeight;
pDisplayInfoNew->m_dwBpp = devmode.dmBitsPerPel;
wsprintf(pDisplayInfoNew->m_szDisplayMode, TEXT("%d x %d (%d bit)"),
devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel);
lstrcpy( pDisplayInfoNew->m_szDisplayModeEnglish, pDisplayInfoNew->m_szDisplayMode );
if (devmode.dmDisplayFrequency > 0)
{
TCHAR sz[10];
wsprintf(sz, TEXT(" (%dHz)"), devmode.dmDisplayFrequency);
lstrcat(pDisplayInfoNew->m_szDisplayMode, sz);
lstrcat(pDisplayInfoNew->m_szDisplayModeEnglish, sz);
pDisplayInfoNew->m_dwRefreshRate = devmode.dmDisplayFrequency;
}
}
// Call EnumDisplayDevices a second time to get monitor name and monitor key
if (EnumDisplayDevices(dispdev.DeviceName, 0, &dispdev2, 0))
{
lstrcpy(pDisplayInfoNew->m_szMonitorName, dispdev2.DeviceString);
lstrcpy(pDisplayInfoNew->m_szMonitorKey, dispdev2.DeviceKey);
}
// Try to figure out the m_hMonitor
pDisplayInfoNew->m_hMonitor = NULL;
EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, (LPARAM) pDisplayInfoNew );
iDevice++;
}
}
// Now look for non-display devices (like 3dfx Voodoo):
HKEY hkey;
HKEY hkey2;
DWORD dwIndex;
TCHAR szName[MAX_PATH+1];
DWORD cb;
DWORD dwType;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("Hardware\\DirectDrawDrivers"), &hkey))
{
dwIndex = 0;
while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szName, MAX_PATH+1))
{
BOOL bGoodDevice = FALSE;
TCHAR szDriverName[200];
HDC hdc;
if (lstrcmp(szName, TEXT("3a0cfd01-9320-11cf-ac-a1-00-a0-24-13-c2-e2")) == 0 ||
lstrcmp(szName, TEXT("aba52f41-f744-11cf-b4-52-00-00-1d-1b-41-26")) == 0)
{
// 24940: It's a Voodoo1, which will succeed GetDC (and crash later) if
// no Voodoo1 is present but a Voodoo2 is. So instead of the GetDC test,
// see if a V1 is present in registry's CurrentConfig.
INT i;
for (i=0 ; ; i++)
{
TCHAR szDevice[MAX_DDDEVICEID_STRING];
if (FindDevice(i, NULL, TEXT("Display"), szDevice))
{
if (_tcsstr(szDevice, TEXT("VEN_121A&DEV_0001")) != NULL)
{
bGoodDevice = TRUE;
break;
}
}
else
{
break;
}
}
}
else
{
// To confirm that this is a real active DD device, create a DC with it
if (ERROR_SUCCESS == RegOpenKey(hkey, szName, &hkey2))
{
cb = 200;
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("DriverName"), NULL, &dwType,
(CONST LPBYTE)szDriverName, &cb) && cb > 0)
{
// I think the following "if" will always fail, but we're about to ship so
// I'm being paranoid and doing everything that DDraw does:
if (szDriverName[0] == '\\' && szDriverName[1] == '\\' && szDriverName[2] == '.')
hdc = CreateDC( NULL, szDriverName, NULL, NULL);
else
hdc = CreateDC( szDriverName, NULL, NULL, NULL);
if (hdc != NULL)
{
bGoodDevice = TRUE;
DeleteDC(hdc);
}
}
RegCloseKey(hkey2);
}
}
if (!bGoodDevice)
{
dwIndex++;
continue;
}
pDisplayInfoNew = new DisplayInfo;
if (pDisplayInfoNew == NULL)
return E_OUTOFMEMORY;
ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
if (*ppDisplayInfoFirst == NULL)
{
*ppDisplayInfoFirst = pDisplayInfoNew;
}
else
{
for (pDisplayInfo = *ppDisplayInfoFirst;
pDisplayInfo->m_pDisplayInfoNext != NULL;
pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
{
}
pDisplayInfo->m_pDisplayInfoNext = pDisplayInfoNew;
}
pDisplayInfoNew->m_bCanRenderWindow = FALSE;
pDisplayInfoNew->m_hMonitor = NULL;
_stscanf(szName, TEXT("%08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x"),
&pDisplayInfoNew->m_guid.Data1,
&pDisplayInfoNew->m_guid.Data2,
&pDisplayInfoNew->m_guid.Data3,
&pDisplayInfoNew->m_guid.Data4[0],
&pDisplayInfoNew->m_guid.Data4[1],
&pDisplayInfoNew->m_guid.Data4[2],
&pDisplayInfoNew->m_guid.Data4[3],
&pDisplayInfoNew->m_guid.Data4[4],
&pDisplayInfoNew->m_guid.Data4[5],
&pDisplayInfoNew->m_guid.Data4[6],
&pDisplayInfoNew->m_guid.Data4[7]);
if (ERROR_SUCCESS == RegOpenKey(hkey, szName, &hkey2))
{
cb = sizeof(pDisplayInfoNew->m_szDescription);
RegQueryValueEx(hkey2, TEXT("Description"), NULL, &dwType, (LPBYTE)pDisplayInfoNew->m_szDescription, &cb);
cb = sizeof(pDisplayInfoNew->m_szDriverName);
RegQueryValueEx(hkey2, TEXT("DriverName"), NULL, &dwType, (LPBYTE)pDisplayInfoNew->m_szDriverName, &cb);
RegCloseKey(hkey2);
}
dwIndex++;
}
RegCloseKey(hkey);
}
return S_OK;
}
/****************************************************************************
*
* MonitorEnumProc
*
****************************************************************************/
BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor,
LPRECT lprcMonitor, LPARAM dwData )
{
DisplayInfo* pDisplayInfoNew = (DisplayInfo*) dwData;
// Get the MONITORINFOEX for this HMONITOR
MONITORINFOEX monInfo;
ZeroMemory( &monInfo, sizeof(MONITORINFOEX) );
monInfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo( hMonitor, &monInfo );
// Compare the display device for this HMONITOR and the one
// we just enumed with EnumDisplayDevices
if( lstrcmp( monInfo.szDevice, pDisplayInfoNew->m_szDeviceName ) == 0 )
{
// If they match, then record the HMONITOR
pDisplayInfoNew->m_hMonitor = hMonitor;
return FALSE;
}
// Keep looking...
return TRUE;
}
/****************************************************************************
*
* GetExtraDisplayInfo
*
****************************************************************************/
HRESULT GetExtraDisplayInfo(DisplayInfo* pDisplayInfoFirst)
{
HRESULT hr;
DisplayInfo* pDisplayInfo;
BOOL bDDAccelEnabled;
BOOL bD3DAccelEnabled;
BOOL bAGPEnabled;
BOOL bNT = BIsPlatformNT();
bDDAccelEnabled = IsDDHWAccelEnabled();
bD3DAccelEnabled = IsD3DHWAccelEnabled();
bAGPEnabled = IsAGPEnabled();
for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
{
if (bNT)
GetRegDisplayInfoNT(pDisplayInfo);
else
GetRegDisplayInfo9x(pDisplayInfo);
pDisplayInfo->m_bDDAccelerationEnabled = bDDAccelEnabled;
pDisplayInfo->m_b3DAccelerationEnabled = bD3DAccelEnabled;
pDisplayInfo->m_bAGPEnabled = bAGPEnabled;
if (FAILED(hr = CheckRegistry(&pDisplayInfo->m_pRegErrorFirst)))
return hr;
}
return S_OK;
}
/****************************************************************************
*
* GetDDrawDisplayInfo
*
****************************************************************************/
HRESULT GetDDrawDisplayInfo(DisplayInfo* pDisplayInfoFirst)
{
HRESULT hr;
HRESULT hrRet = S_OK;
DisplayInfo* pDisplayInfo;
TCHAR szPath[MAX_PATH];
HINSTANCE hInstDDraw;
LPDIRECTDRAWCREATE pDDCreate;
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\ddraw.dll"));
hInstDDraw = LoadLibrary(szPath);
if (hInstDDraw == NULL)
return E_FAIL;
pDDCreate = (LPDIRECTDRAWCREATE)GetProcAddress(hInstDDraw, "DirectDrawCreate");
if (pDDCreate == NULL)
{
FreeLibrary(hInstDDraw);
return E_FAIL;
}
// Init D3D8 so we can use GetDX8AdapterInfo()
InitD3D8();
for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
{
pDisplayInfo->m_b3DAccelerationExists = FALSE; // until proven otherwise
if (FAILED(hr = GetDirectDrawInfo(pDDCreate, pDisplayInfo)))
hrRet = hr; // but keep going
}
// Cleanup the D3D8 library
CleanupD3D8();
FreeLibrary(hInstDDraw);
return hrRet;
}
/****************************************************************************
*
* DestroyDisplayInfo
*
****************************************************************************/
VOID DestroyDisplayInfo(DisplayInfo* pDisplayInfoFirst)
{
DisplayInfo* pDisplayInfo;
DisplayInfo* pDisplayInfoNext;
for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
pDisplayInfo = pDisplayInfoNext)
{
DestroyReg( &pDisplayInfo->m_pRegErrorFirst );
pDisplayInfoNext = pDisplayInfo->m_pDisplayInfoNext;
delete pDisplayInfo;
}
}
/****************************************************************************
*
* GetRegDisplayInfo9x - Uses the registry keys to get more info about a
* display adapter.
*
****************************************************************************/
VOID GetRegDisplayInfo9x(DisplayInfo* pDisplayInfo)
{
TCHAR szFullKey[200];
HKEY hkey;
DWORD cbData;
DWORD dwType;
// set to n/a by default
_tcscpy( pDisplayInfo->m_szMiniVddDate, TEXT("n/a") );
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szKeyDeviceID, 0, KEY_READ, &hkey))
{
cbData = sizeof(pDisplayInfo->m_szManufacturer);
RegQueryValueEx(hkey, TEXT("Mfg"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szManufacturer, &cbData);
RegCloseKey(hkey);
}
if (pDisplayInfo->m_dwRefreshRate == 0)
{
wsprintf(szFullKey, TEXT("%s\\Modes\\%d\\%d,%d"), pDisplayInfo->m_szKeyDeviceKey,
pDisplayInfo->m_dwBpp, pDisplayInfo->m_dwWidth, pDisplayInfo->m_dwHeight);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
{
TCHAR szRefresh[100];
TCHAR szRefresh2[100];
TCHAR szRefreshEnglish2[100];
cbData = sizeof(szRefresh);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("RefreshRate"), 0, &dwType, (LPBYTE)szRefresh, &cbData))
{
_stscanf(szRefresh, TEXT("%d"), &pDisplayInfo->m_dwRefreshRate);
if (lstrcmp(szRefresh, TEXT("0")) == 0)
LoadString(NULL, IDS_DEFAULTREFRESH, szRefresh2, 100);
else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
LoadString(NULL, IDS_OPTIMALREFRESH, szRefresh2, 100);
else
wsprintf(szRefresh2, TEXT("(%sHz)"), szRefresh);
lstrcat(pDisplayInfo->m_szDisplayMode, TEXT(" "));
lstrcat(pDisplayInfo->m_szDisplayMode, szRefresh2);
if (lstrcmp(szRefresh, TEXT("0")) == 0)
LoadString(NULL, IDS_DEFAULTREFRESH_ENGLISH, szRefreshEnglish2, 100);
else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
LoadString(NULL, IDS_OPTIMALREFRESH_ENGLISH, szRefreshEnglish2, 100);
else
wsprintf(szRefreshEnglish2, TEXT("(%sHz)"), szRefresh);
lstrcat(pDisplayInfo->m_szDisplayModeEnglish, szRefreshEnglish2);
lstrcat(pDisplayInfo->m_szDisplayModeEnglish, TEXT(" "));
if (pDisplayInfo->m_dwRefreshRate == 0)
pDisplayInfo->m_dwRefreshRate = 1; // 23399: so it doesn't check again
}
RegCloseKey(hkey);
}
}
lstrcpy(szFullKey, pDisplayInfo->m_szKeyDeviceKey);
lstrcat(szFullKey, TEXT("\\DEFAULT"));
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
{
// If no specific refresh rate was listed for the current mode, report the
// default rate.
if (pDisplayInfo->m_dwRefreshRate == 0)
{
TCHAR szRefresh[100];
TCHAR szRefresh2[100];
TCHAR szRefreshEnglish2[100];
cbData = sizeof(szRefresh);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("RefreshRate"), 0, &dwType, (LPBYTE)szRefresh, &cbData))
{
if (lstrcmp(szRefresh, TEXT("0")) == 0)
LoadString(NULL, IDS_DEFAULTREFRESH, szRefresh2, 100);
else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
LoadString(NULL, IDS_OPTIMALREFRESH, szRefresh2, 100);
else
wsprintf(szRefresh2, TEXT("(%sHz)"), szRefresh);
lstrcat(pDisplayInfo->m_szDisplayMode, TEXT(" "));
lstrcat(pDisplayInfo->m_szDisplayMode, szRefresh2);
if (lstrcmp(szRefresh, TEXT("0")) == 0)
LoadString(NULL, IDS_DEFAULTREFRESH_ENGLISH, szRefreshEnglish2, 100);
else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
LoadString(NULL, IDS_OPTIMALREFRESH_ENGLISH, szRefreshEnglish2, 100);
else
wsprintf(szRefreshEnglish2, TEXT("(%sHz)"), szRefresh);
lstrcat(pDisplayInfo->m_szDisplayModeEnglish, szRefreshEnglish2);
lstrcat(pDisplayInfo->m_szDisplayModeEnglish, TEXT(" "));
if (pDisplayInfo->m_dwRefreshRate == 0)
pDisplayInfo->m_dwRefreshRate = 1; // 23399: so it doesn't check again
}
}
cbData = sizeof(pDisplayInfo->m_szDriverName);
RegQueryValueEx(hkey, TEXT("drv"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szDriverName, &cbData);
if (lstrlen(pDisplayInfo->m_szDriverName) > 0)
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, pDisplayInfo->m_szDriverName);
GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage,
&pDisplayInfo->m_bDriverBeta, &pDisplayInfo->m_bDriverDebug);
FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
}
cbData = sizeof(pDisplayInfo->m_szVdd);
RegQueryValueEx(hkey, TEXT("vdd"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szVdd, &cbData);
cbData = sizeof(pDisplayInfo->m_szMiniVdd);
RegQueryValueEx(hkey, TEXT("minivdd"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMiniVdd, &cbData);
if (lstrlen(pDisplayInfo->m_szMiniVdd) > 0)
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\drivers\\"));
lstrcat(szPath, pDisplayInfo->m_szMiniVdd);
TCHAR szDateLocal[100];
GetFileDateAndSize( szPath, szDateLocal, pDisplayInfo->m_szMiniVddDate,
&pDisplayInfo->m_cbMiniVdd );
}
RegCloseKey(hkey);
}
lstrcpy(szFullKey, pDisplayInfo->m_szKeyDeviceKey);
lstrcat(szFullKey, TEXT("\\INFO"));
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
{
cbData = sizeof pDisplayInfo->m_szChipType;
RegQueryValueEx(hkey, TEXT("ChipType"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szChipType, &cbData);
cbData = sizeof pDisplayInfo->m_szDACType;
RegQueryValueEx(hkey, TEXT("DACType"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szDACType, &cbData);
cbData = sizeof pDisplayInfo->m_szRevision;
RegQueryValueEx(hkey, TEXT("Revision"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szRevision, &cbData);
if (cbData > 0)
{
lstrcat(pDisplayInfo->m_szChipType, TEXT(" Rev "));
lstrcat(pDisplayInfo->m_szChipType, pDisplayInfo->m_szRevision);
}
RegCloseKey(hkey);
}
if (lstrlen(pDisplayInfo->m_szDriverVersion) == 0)
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, pDisplayInfo->m_szDriverName);
lstrcat(szPath, TEXT(".drv"));
GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
{
lstrcat(pDisplayInfo->m_szDriverName, TEXT(".drv"));
}
else
{
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, pDisplayInfo->m_szDriverName);
lstrcat(szPath, TEXT("32.dll"));
GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
{
lstrcat(pDisplayInfo->m_szDriverName, TEXT("32.dll"));
}
else
{
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, pDisplayInfo->m_szDriverName);
lstrcat(szPath, TEXT(".dll"));
GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
{
lstrcat(pDisplayInfo->m_szDriverName, TEXT(".dll"));
}
}
}
}
// Use monitor key to get monitor max resolution (and monitor name, if we don't have it yet)
if (lstrlen(pDisplayInfo->m_szMonitorKey) > 0)
{
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szMonitorKey, 0, KEY_READ, &hkey))
{
cbData = sizeof(pDisplayInfo->m_szMonitorMaxRes);
RegQueryValueEx(hkey, TEXT("MaxResolution"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorMaxRes, &cbData);
if (lstrlen(pDisplayInfo->m_szMonitorName) == 0)
{
cbData = sizeof(pDisplayInfo->m_szMonitorName);
RegQueryValueEx(hkey, TEXT("DriverDesc"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorName, &cbData);
}
RegCloseKey(hkey);
}
}
}
/****************************************************************************
*
* GetRegDisplayInfoNT - Uses the registry keys to get more info about a
* display adapter.
*
****************************************************************************/
VOID GetRegDisplayInfoNT(DisplayInfo* pDisplayInfo)
{
TCHAR* pch;
DWORD dwType;
DWORD cbData;
TCHAR szKeyVideo[MAX_PATH+1];
TCHAR szKeyImage[MAX_PATH+1];
TCHAR szKey[MAX_PATH+1];
TCHAR szName[MAX_PATH+1];
HKEY hkey;
HKEY hkeyInfo;
// set to n/a by default
_tcscpy( pDisplayInfo->m_szMiniVddDate, TEXT("n/a") );
// On NT, m_szKeyDeviceID isn't quite as specific as we need--must go
// one level further in the registry.
lstrcpy(szKey, TEXT("System\\CurrentControlSet\\"));
lstrcat(szKey, pDisplayInfo->m_szKeyDeviceID);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkey))
{
if (ERROR_SUCCESS == RegEnumKey(hkey, 0, szName, MAX_PATH+1))
{
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkeyInfo))
{
cbData = sizeof(pDisplayInfo->m_szManufacturer);
RegQueryValueEx(hkeyInfo, TEXT("Mfg"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szManufacturer, &cbData);
RegCloseKey(hkeyInfo);
}
}
RegCloseKey(hkey);
}
// Forked path due to bug 182866: dispinfo.cpp makes an invalid assumption
// about the structure of video key.
// szKey will be filled with where the video info is.
// either "\System\ControlSet001\Services\[Service]\Device0",
// or "\System\ControlSet001\Video\[GUID]\0000" depending on
// pDisplayInfo->m_szKeyDeviceKey
if( _tcsstr( pDisplayInfo->m_szKeyDeviceKey, TEXT("\\Services\\") ) != NULL )
GetRegDisplayInfoWin2k( pDisplayInfo, szKeyVideo, szKeyImage );
else
GetRegDisplayInfoWhistler( pDisplayInfo, szKeyVideo, szKeyImage );
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyVideo, 0, KEY_READ, &hkeyInfo))
{
WCHAR wszChipType[200];
WCHAR wszDACType[200];
TCHAR szDriver[200];
cbData = 200 * sizeof(WCHAR);
if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.ChipType"), 0, &dwType, (LPBYTE)wszChipType, &cbData))
{
#ifdef UNICODE
lstrcpy(pDisplayInfo->m_szChipType, wszChipType);
#else
WideCharToMultiByte(CP_ACP, 0, wszChipType, -1, pDisplayInfo->m_szChipType, 200, NULL, NULL);
#endif
}
cbData = 200 * sizeof(WCHAR);
if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.DacType"), 0, &dwType, (LPBYTE)wszDACType, &cbData))
{
#ifdef UNICODE
lstrcpy(pDisplayInfo->m_szDACType, wszDACType);
#else
WideCharToMultiByte(CP_ACP, 0, wszDACType, -1, pDisplayInfo->m_szDACType, 200, NULL, NULL);
#endif
}
DWORD dwDisplayMemory;
cbData = sizeof(dwDisplayMemory);
if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.MemorySize"), 0, &dwType, (LPBYTE)&dwDisplayMemory, &cbData))
{
// Round to nearest 512K:
dwDisplayMemory = ((dwDisplayMemory + (256 * 1024)) / (512 * 1024));
// So dwDisplayMemory is (number of bytes / 512K), which makes the
// following line easier.
wsprintf(pDisplayInfo->m_szDisplayMemory, TEXT("%d.%d MB"), dwDisplayMemory / 2,
(dwDisplayMemory % 2) * 5);
wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, pDisplayInfo->m_szDisplayMemory );
}
cbData = 200;
if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("InstalledDisplayDrivers"), 0, &dwType, (LPBYTE)szDriver, &cbData))
{
lstrcpy(pDisplayInfo->m_szDriverName, szDriver);
lstrcat(pDisplayInfo->m_szDriverName, TEXT(".dll"));
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, pDisplayInfo->m_szDriverName);
GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage,
&pDisplayInfo->m_bDriverBeta, &pDisplayInfo->m_bDriverDebug);
FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
}
RegCloseKey(hkeyInfo);
}
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyImage, 0, KEY_READ, &hkeyInfo))
{
TCHAR szImagePath[MAX_PATH];
cbData = MAX_PATH;
if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("ImagePath"), 0, &dwType, (LPBYTE)szImagePath, &cbData))
{
pch = _tcsrchr(szImagePath, TEXT('\\'));
lstrcpy(pDisplayInfo->m_szMiniVdd, pch + 1);
if (lstrlen(pDisplayInfo->m_szMiniVdd) > 0)
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\drivers\\"));
lstrcat(szPath, pDisplayInfo->m_szMiniVdd);
TCHAR szDateLocal[100];
GetFileDateAndSize( szPath, szDateLocal, pDisplayInfo->m_szMiniVddDate,
&pDisplayInfo->m_cbMiniVdd );
}
}
RegCloseKey(hkeyInfo);
}
// Use monitor key to get monitor max resolution (and monitor name, if we don't have it yet)
if (lstrlen(pDisplayInfo->m_szMonitorKey) > 0)
{
// Note: Have to skip first 18 characters of string because it's "Registry\Machine\"
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szMonitorKey + 18, 0, KEY_READ, &hkeyInfo))
{
cbData = sizeof(pDisplayInfo->m_szMonitorMaxRes);
RegQueryValueEx(hkeyInfo, TEXT("MaxResolution"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorMaxRes, &cbData);
if (lstrlen(pDisplayInfo->m_szMonitorName) == 0)
{
cbData = sizeof(pDisplayInfo->m_szMonitorName);
RegQueryValueEx(hkeyInfo, TEXT("DriverDesc"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorName, &cbData);
}
RegCloseKey(hkeyInfo);
}
}
}
/****************************************************************************
*
* GetRegDisplayInfoWhistler - Returns string location of video struct and
* ImageInfo info in registry
*
****************************************************************************/
VOID GetRegDisplayInfoWhistler(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage )
{
TCHAR* pch;
TCHAR szKey[MAX_PATH];
DWORD dwType;
DWORD cbData;
HKEY hkeyService;
// m_szKeyDeviceKey will be something like
// "\Registry\Machine\System\ControlSet001\Video\[GUID]\0000",
// The "\Registry\Machine\" part is useless, so we skip past the
// first 18 characters in the string.
lstrcpy(szKey, pDisplayInfo->m_szKeyDeviceKey + 18);
// Slice off the "\0000" and add "\Video" to get the service
pch = _tcsrchr(szKey, TEXT('\\'));
if (pch != NULL)
*pch = 0;
lstrcat(szKey, TEXT("\\Video\\"));
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkeyService))
{
TCHAR szService[MAX_PATH];
cbData = MAX_PATH;
if (ERROR_SUCCESS == RegQueryValueEx(hkeyService, TEXT("Service"), 0, &dwType, (LPBYTE)szService, &cbData))
{
lstrcpy(szKeyImage, TEXT("System\\CurrentControlSet\\Services\\") );
lstrcat(szKeyImage, szService);
}
RegCloseKey(hkeyService);
}
// return something like "\System\ControlSet001\Services\atirage\Device0".
lstrcpy(szKeyVideo, pDisplayInfo->m_szKeyDeviceKey + 18);
}
/****************************************************************************
*
* GetRegDisplayInfoWin2k - Returns string location of video struct and
* ImageInfo info in registry
*
****************************************************************************/
VOID GetRegDisplayInfoWin2k(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage )
{
TCHAR* pch;
// m_szKeyDeviceKey will be something like
// "\Registry\Machine\System\ControlSet001\Services\atirage\Device0".
// The "\Registry\Machine\" part is useless, so we skip past the
// first 18 characters in the string.
lstrcpy(szKeyImage, pDisplayInfo->m_szKeyDeviceKey + 18);
// Slice off the "\Device0" to get the miniport driver path
pch = _tcsrchr(szKeyImage, TEXT('\\'));
if (pch != NULL)
*pch = 0;
// return something like "\System\ControlSet001\Services\atirage\Device0".
lstrcpy(szKeyVideo, pDisplayInfo->m_szKeyDeviceKey + 18);
}
/****************************************************************************
*
* GetDirectDrawInfo
*
****************************************************************************/
HRESULT GetDirectDrawInfo(LPDIRECTDRAWCREATE pDDCreate, DisplayInfo* pDisplayInfo)
{
HRESULT hr;
LPDIRECTDRAW pdd = NULL;
GUID* pGUID;
DDCAPS ddcaps;
DWORD dwDisplayMemory;
if (pDisplayInfo->m_guid == GUID_NULL)
pGUID = NULL;
else
pGUID = &pDisplayInfo->m_guid;
if (FAILED(hr = pDDCreate(pGUID, &pdd, NULL)))
goto LFail;
ddcaps.dwSize = sizeof(ddcaps);
if (FAILED(hr = pdd->GetCaps(&ddcaps, NULL)))
goto LFail;
// If AGP is disabled, we won't be able to tell if AGP is supported because
// the flag will not be set. So in that case, assume that AGP is supported.
// If AGP is not disabled, check the existence of AGP and note that we are
// confident in the knowledge of whether AGP exists or not. I know, it's yucky.
if (pDisplayInfo->m_bAGPEnabled)
{
pDisplayInfo->m_bAGPExistenceValid = TRUE;
if (ddcaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM)
pDisplayInfo->m_bAGPExists = TRUE;
}
if( ddcaps.dwCaps & DDCAPS_NOHARDWARE )
pDisplayInfo->m_bNoHardware = TRUE;
else
pDisplayInfo->m_bNoHardware = FALSE;
// 28873: if( DDCAPS_NOHARDWARE && m_bDDAccelerationEnabled ) then GetAvailableVidMem is wrong.
if( pDisplayInfo->m_bNoHardware && pDisplayInfo->m_bDDAccelerationEnabled )
{
LoadString(NULL, IDS_NA, pDisplayInfo->m_szDisplayMemory, 100);
wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, TEXT("n/a") );
}
else
{
if (lstrlen(pDisplayInfo->m_szDisplayMemory) == 0)
{
// 26678: returns wrong vid mem for 2nd monitor, so ignore non-hardware devices
if( (ddcaps.dwCaps & DDCAPS_NOHARDWARE) == 0 )
{
// 24351: ddcaps.dwVidMemTotal sometimes includes AGP-accessible memory,
// which we don't want. So use GetAvailableVidMem whenever we can, and
// fall back to ddcaps.dwVidMemTotal if that's a problem.
dwDisplayMemory = 0;
LPDIRECTDRAW2 pdd2;
if (SUCCEEDED(pdd->QueryInterface(IID_IDirectDraw2, (VOID**)&pdd2)))
{
DDSCAPS ddscaps;
ddscaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
pdd2->GetAvailableVidMem(&ddscaps, &dwDisplayMemory, NULL);
pdd2->Release();
}
if (dwDisplayMemory == 0)
{
dwDisplayMemory = ddcaps.dwVidMemTotal;
}
// Add GDI memory except on no-GDI cards (Voodoo-type cards)
if (pDisplayInfo->m_bCanRenderWindow)
{
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
if (FAILED(hr = pdd->GetDisplayMode(&ddsd)))
goto LFail;
dwDisplayMemory += ddsd.dwWidth * ddsd.dwHeight *
(ddsd.ddpfPixelFormat.dwRGBBitCount / 8);
}
// Round to nearest 512K:
dwDisplayMemory = ((dwDisplayMemory + (256 * 1024)) / (512 * 1024));
// So dwDisplayMemory is (number of bytes / 512K), which makes the
// following line easier.
wsprintf(pDisplayInfo->m_szDisplayMemory, TEXT("%d.%d MB"), dwDisplayMemory / 2,
(dwDisplayMemory % 2) * 5);
wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, pDisplayInfo->m_szDisplayMemory );
}
}
}
// 24427: Detect driver DDI version
// 24656: Also detect D3D acceleration without DDCAPS_3D, since that flag is
// sometimes sensitive to the current desktop color depth.
// First, see if DD/D3D are disabled, and if so, briefly re-enable them
BOOL bDDDisabled;
BOOL bD3DDisabled;
HKEY hkeyDD;
HKEY hkeyD3D;
DWORD dwSize;
DWORD dwType;
DWORD dwData;
bDDDisabled = FALSE;
bD3DDisabled = FALSE;
hkeyDD = NULL;
hkeyD3D = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkeyDD))
{
dwSize = sizeof(dwData);
dwData = 0;
RegQueryValueEx(hkeyDD, TEXT("EmulationOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize);
if (dwData != 0)
{
bDDDisabled = TRUE;
// Re-enable DD
dwData = 0;
RegSetValueEx(hkeyDD, TEXT("EmulationOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
}
// Note: don't close key yet
}
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Direct3D\\Drivers"), 0, KEY_ALL_ACCESS, &hkeyD3D))
{
dwSize = sizeof(dwData);
dwData = 0;
RegQueryValueEx(hkeyD3D, TEXT("SoftwareOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize);
if (dwData != 0)
{
bD3DDisabled = TRUE;
// Re-enable D3D
dwData = 0;
RegSetValueEx(hkeyD3D, TEXT("SoftwareOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
}
// Note: don't close key yet
}
LPDIRECT3D pd3d;
if (SUCCEEDED(pdd->QueryInterface(IID_IDirect3D, (VOID**)&pd3d)))
{
DWORD dwVersion = 0;
if (SUCCEEDED(pd3d->EnumDevices(EnumDevicesCallback, (VOID*)&dwVersion)))
{
pDisplayInfo->m_dwDDIVersion = dwVersion;
}
pd3d->Release();
}
// While were in this function wrapped with crash protection try to
// get adapter info from D3D8, and match it up with the DisplayInfo list.
// This will also tell us if m_dwDDIVersion==8.
GetDX8AdapterInfo(pDisplayInfo);
switch (pDisplayInfo->m_dwDDIVersion)
{
case 0:
wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("Unknown"));
break;
case 7:
if( IsD3D8Working() )
wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("7"));
else
wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("7 (or higher)"));
break;
case 8:
wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("8 (or higher)"));
break;
default:
wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("%d"), pDisplayInfo->m_dwDDIVersion);
break;
}
if (pDisplayInfo->m_dwDDIVersion != 0)
pDisplayInfo->m_b3DAccelerationExists = TRUE;
// Re-disable DD and D3D, if necessary
dwData = 1;
if (bDDDisabled)
RegSetValueEx(hkeyDD, TEXT("EmulationOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
if (bD3DDisabled)
RegSetValueEx(hkeyD3D, TEXT("SoftwareOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
if (hkeyDD != NULL)
RegCloseKey(hkeyDD);
if (hkeyD3D != NULL)
RegCloseKey(hkeyD3D);
pdd->Release();
return S_OK;
LFail:
if (pdd != NULL)
pdd->Release();
return hr;
}
/****************************************************************************
*
* EnumDevicesCallback
*
****************************************************************************/
HRESULT CALLBACK EnumDevicesCallback(GUID* pGuid, LPSTR pszDesc, LPSTR pszName,
D3DDEVICEDESC* pd3ddevdesc1, D3DDEVICEDESC* pd3ddevdesc2, VOID* pvContext)
{
DWORD* pdwVersion = (DWORD*)pvContext;
DWORD dwDevCaps;
if (pd3ddevdesc1->dcmColorModel == D3DCOLOR_RGB)
{
dwDevCaps = pd3ddevdesc1->dwDevCaps;
if (dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
*pdwVersion = 7;
else if (dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2)
*pdwVersion = 6;
else if (dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX)
*pdwVersion = 5;
else if (dwDevCaps & D3DDEVCAPS_FLOATTLVERTEX)
*pdwVersion = 3;
}
return D3DENUMRET_OK;
}
/****************************************************************************
*
* IsDDHWAccelEnabled
*
****************************************************************************/
BOOL IsDDHWAccelEnabled(VOID)
{
HKEY hkey;
DWORD dwSize;
DWORD dwType;
DWORD dwData;
BOOL bResult = TRUE;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkey))
{
dwSize = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("EmulationOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
{
if (dwData != 0)
bResult = FALSE;
RegCloseKey(hkey);
}
}
return bResult;
}
/****************************************************************************
*
* IsD3DHWAccelEnabled
*
****************************************************************************/
BOOL IsD3DHWAccelEnabled(VOID)
{
HKEY hkey;
DWORD dwSize;
DWORD dwType;
DWORD dwData;
BOOL bIsD3DHWAccelEnabled = TRUE;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Direct3D\\Drivers"), 0, KEY_ALL_ACCESS, &hkey))
{
dwSize = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("SoftwareOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
{
if (dwData != 0)
bIsD3DHWAccelEnabled = FALSE;
RegCloseKey( hkey );
}
}
return bIsD3DHWAccelEnabled;
}
/****************************************************************************
*
* IsAGPEnabled
*
****************************************************************************/
BOOL IsAGPEnabled(VOID)
{
HKEY hkey;
DWORD dwSize;
DWORD dwType;
DWORD dwData;
BOOL bIsAGPEnabled = TRUE;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkey))
{
dwSize = sizeof(dwData);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("DisableAGPSupport"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
{
if (dwData != 0)
bIsAGPEnabled = FALSE;
RegCloseKey( hkey );
}
}
return bIsAGPEnabled;
}
//
// GetDeviceValue
//
// read a value from the HW or SW of a PnP device
//
BOOL GetDeviceValue(TCHAR* pszHardwareKey, TCHAR* pszKey, TCHAR* pszValue, BYTE *buf, DWORD cbbuf)
{
HKEY hkeyHW;
HKEY hkeySW;
BOOL f = FALSE;
DWORD cb;
TCHAR szSoftwareKey[MAX_PATH];
*(DWORD*)buf = 0;
//
// open the HW key
//
if (RegOpenKey(HKEY_LOCAL_MACHINE, pszHardwareKey, &hkeyHW) == ERROR_SUCCESS)
{
//
// try to read the value from the HW key
//
*buf = 0;
cb = cbbuf;
if (RegQueryValueEx(hkeyHW, pszValue, NULL, NULL, buf, &cb) == ERROR_SUCCESS)
{
f = TRUE;
}
else
{
//
// now try the SW key
//
static TCHAR szSW[] = TEXT("System\\CurrentControlSet\\Services\\Class\\");
lstrcpy(szSoftwareKey, szSW);
cb = sizeof(szSoftwareKey) - sizeof(szSW);
RegQueryValueEx(hkeyHW, TEXT("Driver"), NULL, NULL, (LPBYTE)(szSoftwareKey + sizeof(szSW) - 1), &cb);
if (pszKey)
{
lstrcat(szSoftwareKey, TEXT("\\"));
lstrcat(szSoftwareKey, pszKey);
}
if (RegOpenKey(HKEY_LOCAL_MACHINE, szSoftwareKey, &hkeySW) == ERROR_SUCCESS)
{
*buf = 0;
cb = cbbuf;
if (RegQueryValueEx(hkeySW, pszValue, NULL, NULL, buf, &cb) == ERROR_SUCCESS)
{
f = TRUE;
}
RegCloseKey(hkeySW);
}
}
RegCloseKey(hkeyHW);
}
return f;
}
//
// FindDevice
//
// enum the started PnP devices looking for a device of a particular class
//
// iDevice what device to return (0= first device, 1=second et)
// szDeviceClass what class device (ie "Display") NULL will match all
// szDeviceID buffer to return the hardware ID (MAX_PATH bytes)
//
// return TRUE if a device was found.
//
// example:
//
// for (int i=0; FindDevice(i, "Display", DeviceID); i++)
// {
// }
//
BOOL FindDevice(INT iDevice, TCHAR* pszDeviceClass, TCHAR* pszDeviceClassNot, TCHAR* pszHardwareKey)
{
HKEY hkeyPnP;
HKEY hkey;
DWORD n;
DWORD cb;
DWORD dw;
TCHAR ach[MAX_PATH+1];
if (RegOpenKey(HKEY_DYN_DATA, TEXT("Config Manager\\Enum"), &hkeyPnP) != ERROR_SUCCESS)
return FALSE;
for (n=0; RegEnumKey(hkeyPnP, n, ach, MAX_PATH+1) == 0; n++)
{
static TCHAR szHW[] = TEXT("Enum\\");
if (RegOpenKey(hkeyPnP, ach, &hkey) != ERROR_SUCCESS)
continue;
lstrcpy(pszHardwareKey, szHW);
cb = MAX_PATH - sizeof(szHW);
RegQueryValueEx(hkey, TEXT("HardwareKey"), NULL, NULL, (BYTE*)pszHardwareKey + sizeof(szHW) - 1, &cb);
dw = 0;
cb = sizeof(dw);
RegQueryValueEx(hkey, TEXT("Problem"), NULL, NULL, (BYTE*)&dw, &cb);
RegCloseKey(hkey);
if (dw != 0) // if this device has a problem skip it
continue;
if (pszDeviceClass || pszDeviceClassNot)
{
GetDeviceValue(pszHardwareKey, NULL, TEXT("Class"), (BYTE*)ach, sizeof(ach));
if (pszDeviceClass && lstrcmpi(pszDeviceClass, ach) != 0)
continue;
if (pszDeviceClassNot && lstrcmpi(pszDeviceClassNot, ach) == 0)
continue;
}
//
// we found a device, make sure it is the one the caller wants
//
if (iDevice-- == 0)
{
RegCloseKey(hkeyPnP);
return TRUE;
}
}
RegCloseKey(hkeyPnP);
return FALSE;
}
/****************************************************************************
*
* CheckRegistry
*
****************************************************************************/
HRESULT CheckRegistry(RegError** ppRegErrorFirst)
{
HRESULT hr;
HKEY HKLM = HKEY_LOCAL_MACHINE;
HKEY HKCR = HKEY_CLASSES_ROOT;
TCHAR szVersion[100];
HKEY hkey;
DWORD cbData;
ULONG ulType;
DWORD dwMajor = 0;
DWORD dwMinor = 0;
DWORD dwRevision = 0;
DWORD dwBuild = 0;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
0, KEY_READ, &hkey))
{
cbData = 100;
RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)szVersion, &cbData);
RegCloseKey(hkey);
if (lstrlen(szVersion) > 6 &&
lstrlen(szVersion) < 20)
{
_stscanf(szVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
}
}
// No registry checking on DX versions before DX7
if (dwMinor < 7)
return S_OK;
// From ddraw.inf (compatibility hacks not included):
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDraw"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDraw\\CLSID"), TEXT(""), TEXT("{D7B70EE0-4340-11CF-B063-0020AFC2CD35}"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}\\InprocServer32"), TEXT(""), TEXT("ddraw.dll"), CRF_LEAF)))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDrawClipper"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDrawClipper\\CLSID"), TEXT(""), TEXT("{593817A0-7DB3-11CF-A2DE-00AA00B93356}"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}\\InprocServer32"), TEXT(""), TEXT("ddraw.dll"), CRF_LEAF)))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
return hr;
if (!BIsPlatformNT())
{
// We can't check for the following entry on Win2000 because it is missing.
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}"), TEXT(""), TEXT("*"))))
return hr;
}
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}\\InprocServer32"), TEXT(""), TEXT("ddrawex.dll"), CRF_LEAF)))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
return hr;
// From d3d.inf:
TCHAR* pszHALKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\Direct3D HAL");
BYTE bArrayHALGuid[] = { 0xe0, 0x3d, 0xe6, 0x84, 0xaa, 0x46, 0xcf, 0x11, 0x81, 0x6f, 0x00, 0x00, 0xc0, 0x20, 0x15, 0x6e };
TCHAR* pszRampKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\Ramp Emulation");
BYTE bArrayRampGuid[] = { 0x20, 0x6b, 0x08, 0xf2, 0x9f, 0x25, 0xcf, 0x11, 0xa3, 0x1a, 0x00, 0xaa, 0x00, 0xb9, 0x33, 0x56 };
TCHAR* pszRGBKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\RGB Emulation");
BYTE bArrayRGBGuid[] = { 0x60, 0x5c, 0x66, 0xa4, 0x73, 0x26, 0xcf, 0x11, 0xa3, 0x1a, 0x00, 0xaa, 0x00, 0xb9, 0x33, 0x56 };
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszHALKey, TEXT("Base"), TEXT("hal"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszHALKey, TEXT("Description"), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszHALKey, TEXT("GUID"), bArrayHALGuid, sizeof(bArrayHALGuid))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRampKey, TEXT("Base"), TEXT("ramp"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRampKey, TEXT("Description"), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszRampKey, TEXT("GUID"), bArrayRampGuid, sizeof(bArrayRampGuid))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("Base"), TEXT("rgb"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("Description"), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("GUID"), bArrayRGBGuid, sizeof(bArrayRGBGuid))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit Bump DuDv"), TEXT("ddpf"), TEXT("00080000 0 16 ff ff00 0 0"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit BumpLum DuDv"), TEXT("ddpf"), TEXT("000C0000 0 16 1f 3e0 fc00 0"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit Luminance Alpha"), TEXT("ddpf"), TEXT("00020001 0 16 ff 0 0 ff00"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\24 bit BumpLum DuDv"), TEXT("ddpf"), TEXT("000C0000 0 24 ff ff00 ff0000 0"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\8 bit Luminance"), TEXT("ddpf"), TEXT("00020000 0 8 ff 0 0 0"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("Direct3DRM"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("Direct3DRM\\CLSID"), TEXT(""), TEXT("{4516EC41-8F20-11d0-9B6D-0000C0781BC3}"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT(""), TEXT("d3drm.dll"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectXFile"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectXFile\\CLSID"), TEXT(""), TEXT("{4516EC43-8F20-11D0-9B6D-0000C0781BC3}"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11D0-9B6D-0000C0781BC3}"), TEXT(""), TEXT("*"))))
return hr;
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT(""), TEXT("d3dxof.dll"))))
return hr;
if (BIsPlatformNT())
{
// 23342: This setting is missing on Win9x.
if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
return hr;
}
return S_OK;
}
/****************************************************************************
*
* DiagnoseDisplay
*
****************************************************************************/
VOID DiagnoseDisplay(SysInfo* pSysInfo, DisplayInfo* pDisplayInfoFirst)
{
DisplayInfo* pDisplayInfo;
TCHAR sz[MAX_PATH];
TCHAR szEnglish[MAX_PATH];
TCHAR szFmt[MAX_PATH];
BOOL bShouldReinstall = FALSE;
for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
{
if (pDisplayInfo->m_bDDAccelerationEnabled)
{
if( pDisplayInfo->m_bNoHardware )
{
LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
}
else
{
LoadString(NULL, IDS_ACCELENABLED, sz, 100);
LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
}
}
else
{
LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
}
_tcscpy( pDisplayInfo->m_szDDStatus, sz );
_tcscpy( pDisplayInfo->m_szDDStatusEnglish, szEnglish );
if (pDisplayInfo->m_b3DAccelerationExists)
{
if (pDisplayInfo->m_b3DAccelerationEnabled)
{
LoadString(NULL, IDS_ACCELENABLED, sz, 100);
LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
}
else
{
LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
}
}
else
{
LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
}
_tcscpy( pDisplayInfo->m_szD3DStatus, sz );
_tcscpy( pDisplayInfo->m_szD3DStatusEnglish, szEnglish );
if ( (pDisplayInfo->m_bAGPExistenceValid && !pDisplayInfo->m_bAGPExists) ||
(!pDisplayInfo->m_bDDAccelerationEnabled) )
{
LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
}
else
{
if (pDisplayInfo->m_bAGPEnabled)
{
LoadString(NULL, IDS_ACCELENABLED, sz, 100);
LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
}
else
{
LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
}
}
_tcscpy( pDisplayInfo->m_szAGPStatus, sz );
_tcscpy( pDisplayInfo->m_szAGPStatusEnglish, szEnglish );
_tcscpy( pDisplayInfo->m_szNotes, TEXT("") );
_tcscpy( pDisplayInfo->m_szNotesEnglish, TEXT("") );
// Report any problems:
BOOL bProblem = FALSE;
if( pSysInfo->m_bNetMeetingRunning &&
!pDisplayInfo->m_b3DAccelerationExists )
{
LoadString(NULL, IDS_NETMEETINGWARN, szFmt, MAX_PATH);
wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_NETMEETINGWARN_ENGLISH, szFmt, MAX_PATH);
wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
bProblem = TRUE;
}
if (pDisplayInfo->m_bDriverSignedValid && !pDisplayInfo->m_bDriverSigned)
{
LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1, szFmt, MAX_PATH);
wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1_ENGLISH, szFmt, MAX_PATH);
wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
bProblem = TRUE;
}
if (pDisplayInfo->m_pRegErrorFirst != NULL)
{
LoadString(NULL, IDS_REGISTRYPROBLEM, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_REGISTRYPROBLEM_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
bProblem = TRUE;
bShouldReinstall = TRUE;
}
if( bShouldReinstall )
{
BOOL bTellUser = FALSE;
// Figure out if the user can install DirectX
if( BIsPlatform9x() )
bTellUser = TRUE;
else if( BIsWin2k() && pSysInfo->m_dwDirectXVersionMajor >= 8 )
bTellUser = TRUE;
if( bTellUser )
{
LoadString(NULL, IDS_REINSTALL_DX, sz, 300);
_tcscat( pDisplayInfo->m_szNotes, sz);
LoadString(NULL, IDS_REINSTALL_DX_ENGLISH, sz, 300);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz);
}
}
if (!bProblem)
{
LoadString(NULL, IDS_NOPROBLEM, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_NOPROBLEM_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
}
// Report any DD test results:
if (pDisplayInfo->m_testResultDD.m_bStarted &&
!pDisplayInfo->m_testResultDD.m_bCancelled)
{
LoadString(NULL, IDS_DDRESULTS, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
_tcscat( pDisplayInfo->m_szNotes, pDisplayInfo->m_testResultDD.m_szDescription );
_tcscat( pDisplayInfo->m_szNotes, TEXT("\r\n") );
LoadString(NULL, IDS_DDRESULTS_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
_tcscat( pDisplayInfo->m_szNotesEnglish, pDisplayInfo->m_testResultDD.m_szDescription );
_tcscat( pDisplayInfo->m_szNotesEnglish, TEXT("\r\n") );
}
else
{
LoadString(NULL, IDS_DDINSTRUCTIONS, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_DDINSTRUCTIONS_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
}
// Report any D3D test results:
TestResult* pTestResult;
if( pDisplayInfo->m_dwTestToDisplayD3D == 7 )
pTestResult = &pDisplayInfo->m_testResultD3D7;
else
pTestResult = &pDisplayInfo->m_testResultD3D8;
if (pTestResult->m_bStarted &&
!pTestResult->m_bCancelled)
{
LoadString(NULL, IDS_D3DRESULTS, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
_tcscat( pDisplayInfo->m_szNotes, pTestResult->m_szDescription );
_tcscat( pDisplayInfo->m_szNotes, TEXT("\r\n") );
LoadString(NULL, IDS_D3DRESULTS_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
_tcscat( pDisplayInfo->m_szNotesEnglish, pTestResult->m_szDescription );
_tcscat( pDisplayInfo->m_szNotesEnglish, TEXT("\r\n") );
}
else
{
if( pDisplayInfo->m_b3DAccelerationExists &&
pDisplayInfo->m_b3DAccelerationEnabled )
{
LoadString(NULL, IDS_D3DINSTRUCTIONS, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotes, sz );
LoadString(NULL, IDS_D3DINSTRUCTIONS_ENGLISH, sz, MAX_PATH);
_tcscat( pDisplayInfo->m_szNotesEnglish, sz );
}
}
}
}