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

2329 lines
77 KiB
C++

/****************************************************************************
*
* File: sysinfo.cpp
* Project: DxDiag (DirectX Diagnostic Tool)
* Author: Mike Anderson (manders@microsoft.com)
* CPU type detection code by Rich Granshaw
* CPU speed code by Michael Lyons
* Purpose: Gather system information (OS, hardware, name, etc.) on this machine
*
* \Multimedia\Testsrc\Tools\ShowCPUID\ can be used to debug CPUID problems.
*
* (C) Copyright 1998 Microsoft Corp. All rights reserved.
*
****************************************************************************/
#include <tchar.h>
#include <Windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <wbemidl.h>
#include <objbase.h>
#include <shfolder.h>
#include <dsound.h>
#include "dsprv.h"
#include "dsprvobj.h"
#include "sysinfo.h"
#include "fileinfo.h" // for GetLanguageFromFile
#include "resource.h"
#define REGSTR_PATH_D3D TEXT("Software\\Microsoft\\Direct3D")
#define REGSTR_VAL_DDRAW_LOADDEBUGRUNTIME TEXT("LoadDebugRuntime")
#define REGSTR_DINPUT_DLL TEXT("CLSID\\{25E609E4-B259-11CF-BFC7-444553540000}\\InProcServer32")
#define REGSTR_DMUSIC_DLL TEXT("CLSID\\{480FF4B0-28B2-11D1-BEF7-00C04FBF8FEF}\\InProcServer32")
struct PROCESSOR_ID_NUMBERS
{
DWORD dwType; // Intel: 0 = standard, 1 = Overdrive, 2 = dual processor.
DWORD dwFamily;
DWORD dwModel;
DWORD dwSteppingID;
};
extern IWbemServices* g_pIWbemServices;
typedef INT (WINAPI* LPDXSETUPGETVERSION)(DWORD* pdwVersion, DWORD* pdwRevision);
static VOID GetProcessorDescription(BOOL bNT, SYSTEM_INFO* psi, TCHAR* pszDesc, BOOL* pbNoCPUSpeed);
static VOID GetProcessorVendorNameAndType(OSVERSIONINFO& OSVersionInfo,
SYSTEM_INFO& SystemInfo, TCHAR* pszProcessor, BOOL* pbNoCPUSpeed);
static VOID GetVendorNameAndCaps(TCHAR* pszVendorName, TCHAR* pszIDTLongName,
PROCESSOR_ID_NUMBERS& ProcessorIdNumbers, BOOL* pbIsMMX, BOOL* pbIs3DNow, BOOL* pbIsKatmai, /*Pentium III/Streaming SIMD Instrucs*/
LPDWORD pdwKBytesLevel2Cache, LPDWORD pdwIntelBrandIndex, BOOL* pbNoCPUSpeed);
#ifdef _X86_
static INT GetCPUSpeed(VOID);
static INT GetCPUSpeedViaWMI(VOID);
#endif
static VOID GetComputerSystemInfo(TCHAR* szSystemManufacturerEnglish, TCHAR* szSystemModelEnglish);
static VOID GetBIOSInfo(TCHAR* szBIOSEnglish);
static VOID GetFileSystemStoringD3D8Cache( TCHAR* strFileSystemBuffer );
static VOID GetDXDebugLevels(SysInfo* pSysInfo);
static int GetDSDebugLevel();
static BOOL IsDMusicDebugRuntime();
static BOOL IsDMusicDebugRuntimeAvailable();
static int GetDMDebugLevel();
static BOOL IsDInput8DebugRuntime();
static BOOL IsDInput8DebugRuntimeAvailable();
static int GetDIDebugLevel();
static BOOL IsD3DDebugRuntime();
static BOOL IsD3D8DebugRuntimeAvailable();
static BOOL IsDDrawDebugRuntime();
static BOOL IsDPlayDebugRuntime();
static BOOL IsDSoundDebugRuntime();
static BOOL IsNetMeetingRunning();
/****************************************************************************
*
* BIsPlatformNT
*
****************************************************************************/
BOOL BIsPlatformNT(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
/****************************************************************************
*
* BIsPlatform9x
*
****************************************************************************/
BOOL BIsPlatform9x(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
}
/****************************************************************************
*
* BIsWin2k
*
****************************************************************************/
BOOL BIsWin2k(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion == 5 &&
OSVersionInfo.dwMinorVersion == 0 ); // should be 05.00.xxxx
}
/****************************************************************************
*
* BIsWhistler
*
****************************************************************************/
BOOL BIsWhistler(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion == 5 &&
OSVersionInfo.dwMinorVersion == 1 ); // should be 05.01.xxxx
}
/****************************************************************************
*
* BIsWinNT
*
****************************************************************************/
BOOL BIsWinNT(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion <= 4 );
}
/****************************************************************************
*
* BIsWinME
*
****************************************************************************/
BOOL BIsWinME(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
OSVersionInfo.dwMajorVersion >= 4 &&
OSVersionInfo.dwMinorVersion >= 90 ); // should be 4.90.xxxx
}
/****************************************************************************
*
* BIsWin98 - from http://kbinternal/kb/articles/q189/2/49.htm
*
****************************************************************************/
BOOL BIsWin98(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
OSVersionInfo.dwMajorVersion == 4 &&
OSVersionInfo.dwMinorVersion == 10 ); // should be 4.10.xxxx
}
/****************************************************************************
*
* BIsWin95 - from http://kbinternal/kb/articles/q189/2/49.htm
*
****************************************************************************/
BOOL BIsWin95(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
OSVersionInfo.dwMajorVersion == 4 &&
OSVersionInfo.dwMinorVersion < 10 ); // should be 4.00.0950
}
/****************************************************************************
*
* BIsWin3x
*
****************************************************************************/
BOOL BIsWin3x(VOID)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
OSVersionInfo.dwMajorVersion < 4 ); // should be 3.xx.xxxx
}
/****************************************************************************
*
* BIsIA64
*
****************************************************************************/
BOOL BIsIA64(VOID)
{
OSVERSIONINFO OSVersionInfo;
SYSTEM_INFO SystemInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
GetSystemInfo(&SystemInfo);
return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 );
}
/****************************************************************************
*
* GetSystemInfo
*
****************************************************************************/
VOID GetSystemInfo(SysInfo* pSysInfo)
{
TCHAR szSystemPath[MAX_PATH];
HKEY hKey = NULL;
HKEY hSubKey = NULL;
ULONG ulType;
OSVERSIONINFO OSVersionInfo;
SYSTEM_INFO SystemInfo;
DWORD cbData;
LCID lcid;
DWORD dwKeyboardSubType;
WORD wLanguage;
TCHAR sz[200];
TCHAR szDebug[100];
// Get current time
TCHAR szDate[100];
TCHAR szTime[100];
GetLocalTime(&pSysInfo->m_time);
GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, NULL, NULL, szDate, 100);
wsprintf(szTime, TEXT("%02d:%02d:%02d"), pSysInfo->m_time.wHour,
pSysInfo->m_time.wMinute, pSysInfo->m_time.wSecond);
wsprintf(pSysInfo->m_szTimeLocal, TEXT("%s, %s"), szDate, szTime);
wsprintf(szDate, TEXT("%d/%d/%d"), pSysInfo->m_time.wMonth, pSysInfo->m_time.wDay, pSysInfo->m_time.wYear);
wsprintf(pSysInfo->m_szTime, TEXT("%s, %s"), szDate, szTime);
// Get the computer network name
cbData = sizeof(pSysInfo->m_szMachine) - 1;
if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"), 0, KEY_READ, &hKey)
&& !RegQueryValueEx(hKey, TEXT("ComputerName"), 0, &ulType, (LPBYTE)pSysInfo->m_szMachine, &cbData)
&& ulType == REG_SZ)
{
// Got data OK.
}
else
{
LoadString(NULL, IDS_NOMACHINENAME, pSysInfo->m_szMachine, 200);
}
if (hKey)
{
RegCloseKey(hKey);
hKey = 0;
}
// Check for NEC PC-98
pSysInfo->m_bNECPC98 = FALSE;
lcid = GetSystemDefaultLCID();
if (lcid == 0x0411) // Windows 95 J
{
dwKeyboardSubType = GetKeyboardType(1);
if (HIBYTE(dwKeyboardSubType) == 0x0D) // NEC PC-98 series
{
pSysInfo->m_bNECPC98 = TRUE;
LoadString(NULL, IDS_NECPC98, sz, 200);
lstrcat(pSysInfo->m_szMachine, sz);
}
}
// Get Windows version
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
pSysInfo->m_dwMajorVersion = OSVersionInfo.dwMajorVersion;
pSysInfo->m_dwMinorVersion = OSVersionInfo.dwMinorVersion;
pSysInfo->m_dwBuildNumber = OSVersionInfo.dwBuildNumber;
pSysInfo->m_dwPlatformID = OSVersionInfo.dwPlatformId;
lstrcpy(pSysInfo->m_szCSDVersion, OSVersionInfo.szCSDVersion);
pSysInfo->m_bDebug = (GetSystemMetrics(SM_DEBUG) > 0);
// Get OS Name
TCHAR* pszWindowsKey;
if (pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT)
pszWindowsKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
else
pszWindowsKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion");
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszWindowsKey, 0, KEY_READ, &hKey))
{
cbData = 100;
RegQueryValueEx(hKey, TEXT("ProductName"), 0, &ulType, (LPBYTE)pSysInfo->m_szOS, &cbData);
cbData = 100;
RegQueryValueEx(hKey, TEXT("BuildLab"), 0, &ulType, (LPBYTE)pSysInfo->m_szBuildLab, &cbData);
RegCloseKey(hKey);
}
if (lstrlen(pSysInfo->m_szOS) == 0)
{
// it is very strange for ProductName registry info
// (see above) to be missing.
lstrcpy(pSysInfo->m_szOS, TEXT("Windows"));
}
if (pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT)
{
// 25598: Append product type (professional, server, etc)
OSVERSIONINFOEX osve;
ZeroMemory(&osve, sizeof(osve));
osve.dwOSVersionInfoSize = sizeof(osve);
GetVersionEx((OSVERSIONINFO*)&osve);
if (osve.wProductType == VER_NT_SERVER && osve.wSuiteMask & VER_SUITE_DATACENTER)
{
lstrcat(pSysInfo->m_szOS, TEXT(" "));
LoadString(NULL, IDS_DATACENTERSERVER, sz, 200);
lstrcat(pSysInfo->m_szOS, sz);
}
else if (osve.wProductType == VER_NT_SERVER && osve.wSuiteMask & VER_SUITE_ENTERPRISE)
{
lstrcat(pSysInfo->m_szOS, TEXT(" "));
LoadString(NULL, IDS_ADVANCEDSERVER, sz, 200);
lstrcat(pSysInfo->m_szOS, sz);
}
else if (osve.wProductType == VER_NT_SERVER)
{
lstrcat(pSysInfo->m_szOS, TEXT(" "));
LoadString(NULL, IDS_SERVER, sz, 200);
lstrcat(pSysInfo->m_szOS, sz);
}
else if (osve.wProductType == VER_NT_WORKSTATION && (osve.wSuiteMask & VER_SUITE_PERSONAL))
{
lstrcat(pSysInfo->m_szOS, TEXT(" "));
LoadString(NULL, IDS_PERSONAL, sz, 200);
lstrcat(pSysInfo->m_szOS, sz);
}
else if (osve.wProductType == VER_NT_WORKSTATION)
{
lstrcat(pSysInfo->m_szOS, TEXT(" "));
LoadString(NULL, IDS_PROFESSIONAL, sz, 200);
lstrcat(pSysInfo->m_szOS, sz);
}
}
// Format Windows version
LoadString(NULL, IDS_WINVERFMT, sz, 200);
LoadString(NULL, IDS_DEBUG, szDebug, 100);
lstrcat(szDebug, TEXT(" "));
wsprintf(pSysInfo->m_szOSEx, sz,
pSysInfo->m_bDebug ? szDebug : TEXT(""),
pSysInfo->m_szOS, pSysInfo->m_dwMajorVersion, pSysInfo->m_dwMinorVersion,
LOWORD(pSysInfo->m_dwBuildNumber));
TCHAR szOSTmp[200];
if( _tcslen( pSysInfo->m_szCSDVersion) )
wsprintf( szOSTmp, TEXT("%s %s"), pSysInfo->m_szOSEx, pSysInfo->m_szCSDVersion );
else
wsprintf( szOSTmp, TEXT("%s"), pSysInfo->m_szOSEx );
if( _tcslen( pSysInfo->m_szBuildLab ) )
wsprintf( pSysInfo->m_szOSExLong, TEXT("%s (%s)"), szOSTmp, pSysInfo->m_szBuildLab );
else
wsprintf( pSysInfo->m_szOSExLong, TEXT("%s"), szOSTmp );
// Get the original language.
GetSystemDirectory(szSystemPath, MAX_PATH);
if (wLanguage = GetLanguageFromFile(TEXT("user.exe"), szSystemPath))
{
lcid = MAKELCID(wLanguage, SORT_DEFAULT);
}
// Get the language and regional setting and store them (in English) for saved file:
TCHAR szLanguage[200];
TCHAR szLanguageRegional[200];
if ((!GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, szLanguage, 200)))
szLanguage[0] = '\0';
if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SENGLANGUAGE, szLanguageRegional, 200))
szLanguageRegional[0] = '\0';
LoadString(NULL, IDS_LANGUAGEFMT_ENGLISH, sz, 200);
wsprintf(pSysInfo->m_szLanguages, sz, szLanguage, szLanguageRegional);
// Now get same info in local language for display:
if ((!GetLocaleInfo(lcid, LOCALE_SNATIVELANGNAME, szLanguage, 200)))
szLanguage[0] = '\0';
if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNATIVELANGNAME, szLanguageRegional, 200))
szLanguageRegional[0] = '\0';
LoadString(NULL, IDS_LANGUAGEFMT, sz, 200);
wsprintf(pSysInfo->m_szLanguagesLocal, sz, szLanguage, szLanguageRegional);
// Get info about processor manufacturer and type
BOOL bNoCPUSpeed = TRUE;
GetSystemInfo(&SystemInfo);
GetProcessorDescription(pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT,
&SystemInfo, pSysInfo->m_szProcessor, &bNoCPUSpeed);
GetComputerSystemInfo(pSysInfo->m_szSystemManufacturerEnglish, pSysInfo->m_szSystemModelEnglish);
GetBIOSInfo(pSysInfo->m_szBIOSEnglish);
#ifdef _X86_
// Append processor speed, if it can be computed
if ( bNoCPUSpeed )
{
INT iMhz = GetCPUSpeed();
if (iMhz > 0)
{
TCHAR szSpeed[50];
wsprintf(szSpeed, TEXT(", ~%dMHz"), iMhz);
lstrcat(pSysInfo->m_szProcessor, szSpeed);
}
}
#endif
BOOL bGotMem = FALSE;
// Get system memory information
if( BIsPlatformNT() )
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\kernel32.dll"));
HINSTANCE hKernel32 = LoadLibrary(szPath);
if( hKernel32 != NULL )
{
typedef BOOL (WINAPI* PGlobalMemoryStatusEx)(OUT LPMEMORYSTATUSEX lpBuffer);
PGlobalMemoryStatusEx pGlobalMemoryStatusEx = (PGlobalMemoryStatusEx)GetProcAddress(hKernel32, "GlobalMemoryStatusEx");
if( pGlobalMemoryStatusEx != NULL )
{
MEMORYSTATUSEX MemoryStatus;
MemoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
pGlobalMemoryStatusEx(&MemoryStatus);
pSysInfo->m_ullPhysicalMemory = MemoryStatus.ullTotalPhys;
pSysInfo->m_ullUsedPageFile = MemoryStatus.ullTotalPageFile - MemoryStatus.ullAvailPageFile;
pSysInfo->m_ullAvailPageFile = MemoryStatus.ullAvailPageFile;
bGotMem = TRUE;
}
FreeLibrary(hKernel32);
}
}
if( !bGotMem ) // Win9x or LoadLib failed
{
MEMORYSTATUS MemoryStatus;
MemoryStatus.dwLength = sizeof MemoryStatus;
GlobalMemoryStatus(&MemoryStatus);
pSysInfo->m_ullPhysicalMemory = MemoryStatus.dwTotalPhys;
pSysInfo->m_ullUsedPageFile = MemoryStatus.dwTotalPageFile - MemoryStatus.dwAvailPageFile;
pSysInfo->m_ullAvailPageFile = MemoryStatus.dwAvailPageFile;
}
// Format memory information:
DWORDLONG dwMB = (DWORDLONG)(pSysInfo->m_ullPhysicalMemory >> 20);
dwMB += dwMB % 2; // round up to even number
_stprintf(pSysInfo->m_szPhysicalMemory, TEXT("%I64dMB RAM"), dwMB);
DWORDLONG dwUsedMB = (pSysInfo->m_ullUsedPageFile >> 20);
DWORDLONG dwAvailMB = (pSysInfo->m_ullAvailPageFile >> 20);
LoadString(NULL, IDS_PAGEFILEFMT, sz, 200);
_stprintf(pSysInfo->m_szPageFile, sz, dwUsedMB, dwAvailMB);
LoadString(NULL, IDS_PAGEFILEFMT_ENGLISH, sz, 200);
_stprintf(pSysInfo->m_szPageFileEnglish, sz, dwUsedMB, dwAvailMB);
// Get DxDiag version:
TCHAR szFile[MAX_PATH];
if (0 != GetModuleFileName(NULL, szFile, MAX_PATH))
GetFileVersion(szFile, pSysInfo->m_szDxDiagVersion, NULL, NULL, NULL, NULL);
// Get DirectX Version using dsetup.dll
TCHAR szSetupPath[MAX_PATH];
HINSTANCE hInstDSetup;
LPDXSETUPGETVERSION pDXSGetVersion;
BOOL bFound = FALSE;
LoadString(NULL, IDS_NOTFOUND, pSysInfo->m_szDirectXVersionLong, 100);
if (!BIsPlatformNT() && GetDxSetupFolder(szSetupPath))
{
lstrcat(szSetupPath, TEXT("\\dsetup.dll"));
hInstDSetup = LoadLibrary(szSetupPath);
if (hInstDSetup != NULL)
{
pDXSGetVersion = (LPDXSETUPGETVERSION)GetProcAddress(hInstDSetup,
"DirectXSetupGetVersion");
if (pDXSGetVersion != NULL)
{
DWORD dwVersion = 0;
DWORD dwRevision = 0;
if (pDXSGetVersion(&dwVersion, &dwRevision) != 0)
{
wsprintf(pSysInfo->m_szDirectXVersion, TEXT("%d.%02d.%02d.%04d"),
HIWORD(dwVersion), LOWORD(dwVersion),
HIWORD(dwRevision), LOWORD(dwRevision));
bFound = TRUE;
}
}
FreeLibrary(hInstDSetup);
}
}
if (!bFound)
{
// Look in registry for DX version instead
HKEY hkey;
DWORD cbData;
ULONG ulType;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
0, KEY_READ, &hkey))
{
cbData = 100;
RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)pSysInfo->m_szDirectXVersion, &cbData);
RegCloseKey(hkey);
if (lstrlen(pSysInfo->m_szDirectXVersion) > 6 &&
lstrlen(pSysInfo->m_szDirectXVersion) < 20)
{
bFound = TRUE;
}
}
}
if (!bFound && !BIsPlatformNT())
{
// Report ddraw.dll version instead
// (except on Win2000, where ddraw.dll version is way different from DX version)
TCHAR szDDrawPath[MAX_PATH];
GetSystemDirectory(szDDrawPath, MAX_PATH);
lstrcat(szDDrawPath, TEXT("\\ddraw.dll"));
GetFileVersion(szDDrawPath, pSysInfo->m_szDirectXVersion, NULL, NULL, NULL);
}
if (lstrlen(pSysInfo->m_szDirectXVersion) > 0)
{
// Bug 18501: Add "friendly" version of version name
DWORD dwMajor;
DWORD dwMinor;
DWORD dwRevision;
DWORD dwBuild;
TCHAR szFriendly[100];
lstrcpy(szFriendly, TEXT(""));
_stscanf(pSysInfo->m_szDirectXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
wsprintf(pSysInfo->m_szDirectXVersion, TEXT("%d.%02d.%02d.%04d"), dwMajor, dwMinor, dwRevision, dwBuild);
// According to http://xevious/directx/versions.htm:
// 4.02.xx.xxxx is DX1
// 4.03.xx.xxxx is DX2
// 4.04.xx.xxxx is DX3
// 4.05.xx.xxxx is DX5
// 4.06.00.xxxx is DX6
// 4.06.02.xxxx is DX6.1
// 4.06.03.xxxx is DX6.1A
// 4.07.00.xxxx is DX7.0
// 4.07.01.xxxx is DX7.1
// Beyond that, who knows...
pSysInfo->m_dwDirectXVersionMajor = 0;
pSysInfo->m_dwDirectXVersionMinor = 0;
pSysInfo->m_cDirectXVersionLetter = TEXT(' ');
if (dwMajor == 4 && dwMinor == 2)
{
lstrcpy(szFriendly, TEXT("DirectX 1"));
pSysInfo->m_dwDirectXVersionMajor = 1;
}
if (dwMajor == 4 && dwMinor == 3)
{
lstrcpy(szFriendly, TEXT("DirectX 2"));
pSysInfo->m_dwDirectXVersionMajor = 2;
}
if (dwMajor == 4 && dwMinor == 4)
{
lstrcpy(szFriendly, TEXT("DirectX 3"));
pSysInfo->m_dwDirectXVersionMajor = 3;
}
if (dwMajor == 4 && dwMinor == 5)
{
lstrcpy(szFriendly, TEXT("DirectX 5"));
pSysInfo->m_dwDirectXVersionMajor = 5;
}
else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 0)
{
lstrcpy(szFriendly, TEXT("DirectX 6"));
pSysInfo->m_dwDirectXVersionMajor = 6;
}
else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 2)
{
lstrcpy(szFriendly, TEXT("DirectX 6.1"));
pSysInfo->m_dwDirectXVersionMajor = 6;
pSysInfo->m_dwDirectXVersionMinor = 1;
}
else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 3)
{
lstrcpy(szFriendly, TEXT("DirectX 6.1a"));
pSysInfo->m_dwDirectXVersionMajor = 6;
pSysInfo->m_dwDirectXVersionMinor = 1;
pSysInfo->m_cDirectXVersionLetter = TEXT('a');
}
else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 0 && dwBuild == 716)
{
lstrcpy(szFriendly, TEXT("DirectX 7.0a"));
pSysInfo->m_dwDirectXVersionMajor = 7;
pSysInfo->m_cDirectXVersionLetter = TEXT('a');
}
else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 0)
{
lstrcpy(szFriendly, TEXT("DirectX 7.0"));
pSysInfo->m_dwDirectXVersionMajor = 7;
}
else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 1)
{
lstrcpy(szFriendly, TEXT("DirectX 7.1"));
pSysInfo->m_dwDirectXVersionMajor = 7;
pSysInfo->m_dwDirectXVersionMinor = 1;
}
else if (dwMajor == 4 && dwMinor == 8 && dwRevision == 0 )
{
lstrcpy(szFriendly, TEXT("DirectX 8.0"));
pSysInfo->m_dwDirectXVersionMajor = 8;
}
else
{
lstrcpy(szFriendly, TEXT("DirectX 8.1"));
pSysInfo->m_dwDirectXVersionMajor = dwMinor;
pSysInfo->m_dwDirectXVersionMinor = dwRevision;
}
if (lstrlen(szFriendly) > 0)
wsprintf(pSysInfo->m_szDirectXVersionLong, TEXT("%s (%s)"), szFriendly, pSysInfo->m_szDirectXVersion);
else
lstrcpy(pSysInfo->m_szDirectXVersionLong, pSysInfo->m_szDirectXVersion);
}
// 24169: Detect setup switches
pSysInfo->m_dwSetupParam = 0xffffffff;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"), 0, NULL, &hKey))
{
cbData = sizeof(DWORD);
RegQueryValueEx(hKey, TEXT("Command"), NULL, &ulType, (BYTE*)&(pSysInfo->m_dwSetupParam), &cbData);
RegCloseKey(hKey);
}
// 48330: add debug level in txt file
GetDXDebugLevels( pSysInfo );
switch (pSysInfo->m_dwSetupParam)
{
case 0xffffffff: lstrcpy(pSysInfo->m_szSetupParam, TEXT("Not found")); break;
case 0: lstrcpy(pSysInfo->m_szSetupParam, TEXT("None")); break;
case 1: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Silent")); break;
case 2: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/WindowsUpdate")); break;
case 3: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/PackageInstall")); break;
case 4: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Silent /Reboot")); break;
case 5: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Reboot")); break;
default:
wsprintf(pSysInfo->m_szSetupParam, TEXT("Unknown Switch (%d)"), pSysInfo->m_dwSetupParam);
break;
}
GetFileSystemStoringD3D8Cache( pSysInfo->m_szD3D8CacheFileSystem );
pSysInfo->m_bNetMeetingRunning = IsNetMeetingRunning();
}
/****************************************************************************
*
* GetProcessorDescription
*
****************************************************************************/
VOID GetProcessorDescription(BOOL bNT, SYSTEM_INFO* psi, TCHAR* pszDesc, BOOL* pbNoCPUSpeed)
{
OSVERSIONINFO OSVersionInfo;
SYSTEM_INFO SystemInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
GetVersionEx(&OSVersionInfo);
GetSystemInfo(&SystemInfo);
GetProcessorVendorNameAndType(OSVersionInfo, SystemInfo, pszDesc, pbNoCPUSpeed);
if (SystemInfo.dwNumberOfProcessors > 1)
{
TCHAR szFmt[100];
TCHAR szNumProc[100];
LoadString(NULL, IDS_NUMPROCFMT, szFmt, 100);
wsprintf(szNumProc, szFmt, SystemInfo.dwNumberOfProcessors);
lstrcat(pszDesc, szNumProc);
}
}
/****************************************************************************
*
* GetProcessorVendorNameAndType
*
****************************************************************************/
VOID GetProcessorVendorNameAndType(OSVERSIONINFO& OSVersionInfo,
SYSTEM_INFO& SystemInfo, TCHAR* pszProcessor, BOOL* pbNoCPUSpeed)
{
TCHAR szVendorName[50];
TCHAR szLongName[50];
TCHAR szDesc[100];
BOOL bIsMMX = FALSE;
BOOL bIs3DNow = FALSE;
// 10/27/98(RichGr): Intel's Katmai New Instructions (KNI).
BOOL bIsKatmai = FALSE; /* 2/04/99(RichGr): Pentium III/Streaming SIMD Instrucs*/
PROCESSOR_ID_NUMBERS ProcessorIdNumbers;
DWORD dwKBytesLevel2Cache;
DWORD dwIntelBrandIndex;
memset(&szVendorName[0], 0, sizeof szVendorName);
memset(&szLongName[0], 0, sizeof szLongName);
memset(&ProcessorIdNumbers, 0, sizeof ProcessorIdNumbers);
// 6/21/99(RichGr): On the Intel, we can now interpret a 1-byte descriptor to give us
// the size of the Level 2 cache, if present.
dwKBytesLevel2Cache = 0;
// 4/26/01(RichGr): On the Intel, we have a new 1-byte index that specifies the brand.
dwIntelBrandIndex = 0;
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS // Win9x
|| (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT // WinNT
&& SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL))
{
GetVendorNameAndCaps(szVendorName, szLongName, ProcessorIdNumbers, &bIsMMX, &bIs3DNow,
&bIsKatmai, &dwKBytesLevel2Cache, &dwIntelBrandIndex, pbNoCPUSpeed);
if (szLongName[0]) // Use this if there's anything there.
lstrcpy(pszProcessor, szLongName);
else
{
lstrcpy(pszProcessor, szVendorName);
lstrcat(pszProcessor, TEXT(" "));
if ( !lstrcmp(szVendorName, TEXT("Intel")))
{
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_386)
lstrcat(pszProcessor, TEXT("80386"));
else
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
lstrcat(pszProcessor, TEXT("80486"));
else
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
{
// 6/21/99(RichGr): A lot of this code is now derived from \\muroc\slm\proj\win\src\shell\cpls\system\sysset.c.
switch ( ProcessorIdNumbers.dwFamily )
{
// We should, of course, never hit these - they've been dealt with above.
case 0:
case 1:
case 2:
case 3:
case 4:
lstrcat(pszProcessor, TEXT("80486"));
break;
case 5:
lstrcat(pszProcessor, TEXT("Pentium"));
if ( ProcessorIdNumbers.dwModel == 3 )
lstrcat(pszProcessor, TEXT(" Overdrive"));
break;
case 6:
switch ( ProcessorIdNumbers.dwModel )
{
//
//Model 1 and 2 are Pentium Pro
//
case 0:
case 1:
case 2:
lstrcat(pszProcessor, TEXT("Pentium Pro"));
break;
//
//Model 3 and 4 are Pentium II
//
case 3:
case 4:
lstrcat(pszProcessor, TEXT("Pentium II"));
break;
//
//Model 5 is either Pentium II or Celeron (depending on if the chip
//has L2 cache or not)
//
case 5:
if ( dwKBytesLevel2Cache == 0 )
//
//No L2 cache so it is a Celeron
//
lstrcat(pszProcessor, TEXT("Celeron"));
else
//
//L2 cache so it is at least a Pentium II.
//
if ( bIsKatmai )
lstrcat(pszProcessor, TEXT("Pentium III"));
else
lstrcat(pszProcessor, TEXT("Pentium II"));
break;
case 6:
if ( dwKBytesLevel2Cache > 128 )
//
//L2 cache > 128K so it is at least a Pentium II
//
if ( bIsKatmai )
lstrcat(pszProcessor, TEXT("Pentium III"));
else
lstrcat(pszProcessor, TEXT("Pentium II"));
else
//
//L2 cache <= 128K so it is a Celeron
//
lstrcat(pszProcessor, TEXT("Celeron"));
break;
case 7:
lstrcat(pszProcessor, TEXT("Pentium III"));
break;
default:
if ( bIsKatmai )
{
// 4/26/01(RichGr): Pentium III Xeons and later have a one-byte Brand Index that we can use.
// More recent machines have a Brand String as well.
// see ftp://download.intel.com/design/Pentium4/manuals/24547103.pdf
if (dwIntelBrandIndex == 1)
lstrcat(pszProcessor, TEXT("Celeron"));
else
if (dwIntelBrandIndex == 0 || dwIntelBrandIndex == 2)
lstrcat(pszProcessor, TEXT("Pentium III"));
else
if (dwIntelBrandIndex == 3)
lstrcat(pszProcessor, TEXT("Pentium III Xeon"));
else
if (dwIntelBrandIndex == 8)
lstrcat(pszProcessor, TEXT("Pentium 4"));
else
lstrcat(pszProcessor, TEXT("Pentium"));
}
else
lstrcat(pszProcessor, TEXT("Pentium II"));
break;
}
break;
default:
wsprintf( szDesc, TEXT("x86 Family %u Model %u Stepping %u"), ProcessorIdNumbers.dwFamily, ProcessorIdNumbers.dwModel,
ProcessorIdNumbers.dwSteppingID );
lstrcat(pszProcessor, szDesc);
break;
}
}
}
else
if ( !lstrcmp(szVendorName, TEXT("AMD")))
{
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
lstrcat(pszProcessor, TEXT("Am486 or Am5X86"));
else
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
{
if (ProcessorIdNumbers.dwFamily == 5)
{
if (ProcessorIdNumbers.dwModel < 6)
{
wsprintf(szDesc, TEXT("K5 (Model %d)"), ProcessorIdNumbers.dwModel);
lstrcat(pszProcessor, szDesc);
}
else
{
lstrcat(pszProcessor, TEXT("K6"));
}
}
else
{
wsprintf(szDesc, TEXT("K%d (Model %d)"), ProcessorIdNumbers.dwFamily, ProcessorIdNumbers.dwModel);
lstrcat(pszProcessor, szDesc);
}
}
}
else
if ( !lstrcmp(szVendorName, TEXT("Cyrix")))
{
if (ProcessorIdNumbers.dwFamily == 4)
{
if (ProcessorIdNumbers.dwModel == 4)
lstrcat(pszProcessor, TEXT("MediaGX"));
}
else
if (ProcessorIdNumbers.dwFamily == 5)
{
if (ProcessorIdNumbers.dwModel == 2)
lstrcat(pszProcessor, TEXT("6x86"));
else
if (ProcessorIdNumbers.dwModel == 4)
lstrcat(pszProcessor, TEXT("GXm"));
}
else
if (ProcessorIdNumbers.dwFamily == 6)
{
lstrcat(pszProcessor, TEXT("6x86MX"));
}
}
else
if ( !lstrcmp(szVendorName, TEXT("IDT")))
{
// 4/21/98(RichGr): There's only 1 chip available at present.
// 7/07/98(RichGr): Now there are two chips.
// Note: Although the C6 is MMX-compatible, Intel does not allow IDT to display the word "MMX"
// in association with the name IDT, so we'll skip that.
// See http://www.winchip.com/ for more info.
if (ProcessorIdNumbers.dwFamily == 5)
{
if (ProcessorIdNumbers.dwModel == 4)
lstrcat(pszProcessor, TEXT("WinChip C6"));
else
if (ProcessorIdNumbers.dwModel >= 8) // 7/07/98(RichGr): Assume later models have the same feature.
lstrcat(pszProcessor, TEXT("WinChip 2"));
}
else
lstrcat(pszProcessor, TEXT("WinChip"));
}
else
{
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
lstrcat(pszProcessor, TEXT("486"));
else
if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
{
if (ProcessorIdNumbers.dwFamily == 5)
lstrcat(pszProcessor, TEXT("P5"));
else
if (ProcessorIdNumbers.dwFamily == 6)
lstrcat(pszProcessor, TEXT("P6"));
else
lstrcat(pszProcessor, TEXT("P5"));
}
}
}
if (bIsKatmai
&& !lstrcmp(szVendorName, TEXT("Intel")))
;
else
{
if (bIsMMX || bIs3DNow)
lstrcat(pszProcessor, TEXT(", "));
if (bIsMMX)
lstrcat(pszProcessor, TEXT(" MMX"));
if (bIs3DNow)
{
if (bIsMMX)
lstrcat(pszProcessor, TEXT(", "));
lstrcat(pszProcessor, TEXT(" 3DNow"));
}
}
}
else
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) // WinNT
{
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
{
lstrcpy(pszProcessor, TEXT("IA64"));
}
else
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_MIPS)
{
lstrcpy(pszProcessor, TEXT("MIPS "));
wsprintf(szDesc, TEXT("R%d000"), SystemInfo.wProcessorLevel);
lstrcat(pszProcessor, szDesc);
if (SystemInfo.wProcessorRevision)
{
wsprintf(szDesc, TEXT(" rev. %d"), LOBYTE(SystemInfo.wProcessorRevision));
lstrcat(pszProcessor, szDesc);
}
}
else
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA)
{
lstrcpy(pszProcessor, TEXT("Alpha "));
wsprintf(szDesc, TEXT("%d"), SystemInfo.wProcessorLevel);
lstrcat(pszProcessor, szDesc);
if (SystemInfo.wProcessorRevision)
{
wsprintf(szDesc, TEXT(" Model %C - Pass %d"), HIBYTE(SystemInfo.wProcessorRevision) + 'A',
LOBYTE(SystemInfo.wProcessorRevision));
lstrcat(pszProcessor, szDesc);
}
}
else
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_PPC)
{
lstrcpy(pszProcessor, TEXT("Power PC "));
if (SystemInfo.wProcessorLevel == 1)
lstrcat(pszProcessor, TEXT("601"));
else
if (SystemInfo.wProcessorLevel == 3)
lstrcat(pszProcessor, TEXT("603"));
else
if (SystemInfo.wProcessorLevel == 4)
lstrcat(pszProcessor, TEXT("604"));
else
if (SystemInfo.wProcessorLevel == 6)
lstrcat(pszProcessor, TEXT("603+"));
else
if (SystemInfo.wProcessorLevel == 9)
lstrcat(pszProcessor, TEXT("604+"));
else
if (SystemInfo.wProcessorLevel == 20)
lstrcat(pszProcessor, TEXT("620"));
if (SystemInfo.wProcessorRevision)
{
wsprintf(szDesc, TEXT(" rev. %d.%d"), HIBYTE(SystemInfo.wProcessorRevision), LOBYTE(SystemInfo.wProcessorRevision));
lstrcat(pszProcessor, szDesc);
}
}
else
lstrcpy(pszProcessor, TEXT("Unknown "));
}
}
/****************************************************************************
*
* GetVendorNameAndCaps
*
****************************************************************************/
VOID GetVendorNameAndCaps(TCHAR* pszVendorName, TCHAR* pszLongName,
PROCESSOR_ID_NUMBERS& ProcessorIdNumbers, BOOL* pbIsMMX, BOOL* pbIs3DNow, BOOL* pbIsKatmai, /*Pentium III/Streaming SIMD Instrucs*/
LPDWORD pdwKBytesLevel2Cache, LPDWORD pdwIntelBrandIndex, BOOL* pbNoCPUSpeed)
{
CHAR szVendorLabel[13];
CHAR szLongName[50];
DWORD dwFamilyModelStep;
BOOL bCPUID_works;
DWORD dwFeaturesFlags;
BYTE byteCacheDescriptors[4] = {0,0,0,0};
DWORD dwIntelBrandIndex;
PCHAR psz;
memset(&szVendorLabel[0], 0, sizeof szVendorLabel);
memset(&szLongName[0], 0, sizeof szLongName);
dwFamilyModelStep = 0;
dwFeaturesFlags = 0;
*pbIsMMX = FALSE;
*pbIs3DNow = FALSE;
*pbIsKatmai = FALSE; /* 2/04/99(RichGr): Pentium III/Streaming SIMD Instrucs*/
bCPUID_works = FALSE;
*pdwKBytesLevel2Cache = 0;
dwIntelBrandIndex = 0;
#ifdef _X86_
// Determine whether CPUID instruction can be executed.
__asm
{
// CPUID trashes lots - save everything. Also, Retail build makes assumptions about reg values.
pushad
// Load value of flags register into eax.
pushfd
pop eax
// Save original flags register value in ebx.
mov ebx, eax
// Alter bit 21 and write new value into flags register.
xor eax, 0x00200000
push eax
popfd
// Retrieve the new value of the flags register.
pushfd
pop eax
// Compare with the original value.
xor eax, ebx
// If the new value is the same as the old, the CPUID instruction cannot
// be executed. Most 486s and all Pentium-class processors should be able
// to execute CPUID.
// 4/21/98(RichGr): One Cyrix 6x86 machine in the Apps Lab (AP_LAREDO) can't execute
// CPUID in ring 3, for no apparent reason. Another similar machine works fine.
je done1
mov bCPUID_works, 1 // bCPUID_works = TRUE
// Execute CPUID with eax = 0 to get Vendor Label.
xor eax, eax
_emit 0x0F // CPUID
_emit 0xA2
// Move Vendor Label from regs to string.
mov dword ptr[szVendorLabel + 0], ebx
mov dword ptr[szVendorLabel + 4], edx
mov dword ptr[szVendorLabel + 8], ecx
// Execute CPUID with eax = 1 to pick up Family, Model and Stepping ID, and to check for MMX support.
mov eax, 1
_emit 0x0F // CPUID
_emit 0xA2
// Save Family/Model/Stepping ID.
mov dwFamilyModelStep, eax
// 4/26/01(RichGr): Save Brand Index (new for PIII Xeons and after). This is the low byte only.
mov dwIntelBrandIndex, ebx
// 2/04/99(RichGr): Save Features Flags.
mov dwFeaturesFlags, edx
// 6/21/99(RichGr): Execute CPUID with eax == 2 to pick up descriptor for size of Level 2 cache.
mov eax, 2
_emit 0x0F // CPUID
_emit 0xA2
// Save Level 2 cache size descriptor in byte 0, together with 3 other cache descriptors in bytes 1 - 3.
// See \\muroc\slm\proj\win\src\shell\cpls\system\sysset.c and cpuid.asm,
// and Intel Architecture Software Developer's Manual (1997), volume 2, p. 105.
mov dword ptr[byteCacheDescriptors], edx
done1:
// Restore everything.
popad
}
#endif // _X86_
dwIntelBrandIndex &= 0xFF;
*pdwIntelBrandIndex = dwIntelBrandIndex;
// 6/21/99(RichGr): The following values were helpfully provided by David Penley(Intel):
/* 40H No L2 Cache
41H L2 Unified cache: 128K Bytes, 4-way set associative, 32 byte line size
42H L2 Unified cache: 256K Bytes, 4-way set associative, 32 byte line size
43H L2 Unified cache: 512K Bytes, 4-way set associative, 32 byte line size
44H L2 Unified cache: 1M Byte, 4-way set associative, 32 byte line size
45H L2 Unified cache: 2M Byte, 4-way set associative, 32 byte line size
Updated manuals can be had at... http://developer.intel.com/design/pentiumiii/xeon/manuals/
*/
if (szVendorLabel[0])
{
if ( !strcmp(&szVendorLabel[0], "GenuineIntel"))
{
lstrcpy(pszVendorName, TEXT("Intel"));
// 4/29/01: This doesn't cover the Pentium 4, but we don't need cache size
// for it at present.
if ( byteCacheDescriptors[0] == 0x40 )
*pdwKBytesLevel2Cache = 0;
else
if ( byteCacheDescriptors[0] == 0x41 )
*pdwKBytesLevel2Cache = 128;
else
if ( byteCacheDescriptors[0] == 0x42 )
*pdwKBytesLevel2Cache = 256;
else
if ( byteCacheDescriptors[0] == 0x43 )
*pdwKBytesLevel2Cache = 512;
else
if ( byteCacheDescriptors[0] == 0x44 )
*pdwKBytesLevel2Cache = 1024;
else
if ( byteCacheDescriptors[0] == 0x45 )
*pdwKBytesLevel2Cache = 2048;
}
else
if ( !strcmp(&szVendorLabel[0], "AuthenticAMD"))
lstrcpy(pszVendorName, TEXT("AMD"));
else
if ( !strcmp(&szVendorLabel[0], "CyrixInstead"))
lstrcpy(pszVendorName, TEXT("Cyrix"));
else
if ( !strcmp(&szVendorLabel[0], "CentaurHauls"))
lstrcpy(pszVendorName, TEXT("IDT"));
else
{
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, szVendorLabel, -1, pszVendorName, 50);
#else
lstrcpy(pszVendorName, szVendorLabel);
#endif
}
}
else
lstrcpy(pszVendorName, TEXT("Intel"));
if (dwFamilyModelStep)
{
ProcessorIdNumbers.dwType = (dwFamilyModelStep & 0x00003000) >> 12;
ProcessorIdNumbers.dwFamily = (dwFamilyModelStep & 0x00000F00) >> 8;
ProcessorIdNumbers.dwModel = (dwFamilyModelStep & 0x000000F0) >> 4;
ProcessorIdNumbers.dwSteppingID = dwFamilyModelStep & 0x0000000F;
}
if (dwFeaturesFlags)
{
// Check whether MMX is supported.
if (dwFeaturesFlags & 0x00800000)
*pbIsMMX = TRUE;
// 2/04/99(RichGr): Check whether Katmai is supported (aka Pentium III/Streaming SIMD Instrucs).
if ((dwFeaturesFlags & 0x02000000)
&& !lstrcmp(pszVendorName, TEXT("Intel")))
*pbIsKatmai = TRUE;
}
// 7/07/98(RichGr): Added for IDT's Long Name feature.
// 9/10/98(RichGr): Attempt this on all processors, and skip if there's nothing there.
#ifdef _X86_
if (bCPUID_works)
{
__asm
{
// CPUID trashes lots - save everything. Also, Retail build makes assumptions about reg values.
pushad
// 9/10/98(RichGr): Check for extended CPUID support.
mov eax, 0x80000000
_emit 0x0F // CPUID
_emit 0xA2
cmp eax, 0x80000001 // Jump if no extended CPUID.
jb done2
// Check for AMD's 3DNow feature. Note: They believe this may be added to other non-AMD CPUs as well.
// Adapted from one of AMD's webpages at: http://www.amd.com/3dsdk/library/macros/amddcpu.html
mov eax, 0x80000001
_emit 0x0F // CPUID
_emit 0xA2
test edx, 0x80000000 // Check for 3DNow flag.
jz LongName
mov eax, pbIs3DNow
mov dword ptr[eax], 1 // bIs3DNow = TRUE
// Execute CPUID with eax = 0x80000002 thru 0x80000004 to get 48-byte Long Name (for instance: "IDT WinChip 2-3D").
LongName:
mov esi, 0x80000001
xor edi, edi
NameLoop:
inc esi
mov eax,esi
cmp eax, 0x80000004
jg done2
_emit 0x0F // CPUID
_emit 0xA2
// 9/10/98(RichGr): The first time thru, check that there's valid alphanumeric data.
cmp esi, 0x80000002 // First time?
jg Move // If not, skip this test.
cmp al, 0x20 // If first character < ' ', skip.
jl done2
cmp al, 0x7a // If first character > 'z', skip.
jg done2
// Move Long Name from regs to string.
Move:
mov dword ptr[szLongName + edi + 0x0], eax
mov dword ptr[szLongName + edi + 0x4], ebx
mov dword ptr[szLongName + edi + 0x8], ecx
mov dword ptr[szLongName + edi + 0x0c], edx
add edi, 0x10
jmp NameLoop
done2:
// Restore everything.
popad
}
if ( szLongName[0] )
{
// Move beyond Intel's leading spaces.
for (psz = &szLongName[0]; *psz == ' '; psz++);
if (*psz)
{
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, psz, -1, pszLongName, 50);
#else
strcpy(pszLongName, psz);
#endif
// 4/29/01(RichGr): Intel Brand Strings show the maximum rated CPU Speed, no need for further detection.
if ( !lstrcmp(pszVendorName, TEXT("Intel")))
*pbNoCPUSpeed = FALSE;
}
}
}
#endif // _X86_
}
#ifdef _X86_
// Some static variables used by GetCPUSpeed
static int s_milliseconds;
static __int64 s_ticks;
/****************************************************************************
*
* fabs
*
****************************************************************************/
FLOAT inline fabs(FLOAT a)
{
if (a < 0.0f)
return -a;
else
return a;
}
/****************************************************************************
*
* StartTimingCPU
*
****************************************************************************/
int StartTimingCPU( HANDLE& hProcess, DWORD& oldclass )
{
//
// detect ability to get info
//
// 4/03/2000(RichGr): The RDTSC instruction is crashing on some older Cyrix machines,
// so wrap a __try/__except around everything.
__try
{
__asm
{
pushfd ; push extended flags
pop eax ; store eflags into eax
mov ebx, eax ; save EBX for testing later
xor eax, (1<<21) ; switch bit 21
push eax ; push eflags
popfd ; pop them again
pushfd ; push extended flags
pop eax ; store eflags into eax
cmp eax, ebx ; see if bit 21 has changed
jz no_cpuid ; make sure it's now on
}
//
// start timing
//
// 10/31/99(RichGr): Bump up the priority to real-time, drawing from ToddLa's code.
// See file:\\pyrex\user\toddla\speed.c
hProcess = GetCurrentProcess();
oldclass = GetPriorityClass(hProcess);
SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
Sleep(10);
s_milliseconds = -(int)timeGetTime();
__asm
{
lea ecx, s_ticks ; get the offset
mov dword ptr [ecx], 0 ; zero the memory
mov dword ptr [ecx+4], 0 ;
// rdtsc ; read time-stamp counter
__emit 0fh
__emit 031h
sub [ecx], eax ; store the negative
sbb [ecx+4], edx ; in the variable
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
goto no_cpuid;
}
return 0;
no_cpuid:
// 10/31/99(RichGr): In case someone changes the code, make sure that the priority is restored
// to normal if there is an error return.
if ( hProcess && oldclass )
SetPriorityClass( hProcess, oldclass );
return -1;
}
/****************************************************************************
*
* StopTimingCPU
*
****************************************************************************/
void StopTimingCPU( HANDLE& hProcess, DWORD& oldclass )
{
s_milliseconds += (int)timeGetTime();
__asm
{
lea ecx, s_ticks ; get the offset
// rdtsc ; read time-stamp counter
__emit 0fh
__emit 031h
add [ecx], eax ; add the tick count
adc [ecx+4], edx ;
}
// 10/31/99(RichGr): Restore the priority to normal.
if ( hProcess && oldclass )
SetPriorityClass( hProcess, oldclass );
return;
}
/****************************************************************************
*
* CalcCPUSpeed
*
****************************************************************************/
INT CalcCPUSpeed(VOID)
{
//
// get the actual cpu speed in MHz, and
// then find the one in the CPU speed list
// that is closest
//
const struct tagCPUSPEEDS
{
float fSpeed;
int iSpeed;
} cpu_speeds[] =
{
//
// valid CPU speeds that are not integrally divisible by
// 16.67 MHz
//
{ 60.00f, 60 },
{ 75.00f, 75 },
{ 90.00f, 90 },
{ 120.00f, 120 },
{ 180.00f, 180 },
};
//
// find the closest one
//
float fSpeed=((float)s_ticks)/((float)s_milliseconds*1000.0f);
int iSpeed=cpu_speeds[0].iSpeed;
float fDiff=(float)fabs(fSpeed-cpu_speeds[0].fSpeed);
for (int i=1 ; i<sizeof(cpu_speeds)/sizeof(cpu_speeds[0]) ; i++)
{
float fTmpDiff = (float)fabs(fSpeed-cpu_speeds[i].fSpeed);
if (fTmpDiff < fDiff)
{
iSpeed=cpu_speeds[i].iSpeed;
fDiff=fTmpDiff;
}
}
//
// now, calculate the nearest multiple of fIncr
// speed
//
//
// now, if the closest one is not within one incr, calculate
// the nearest multiple of fIncr speed and see if that's
// closer
//
const float fIncr=16.66666666666666666666667f;
const int iIncr=4267; // fIncr << 8
//if (fDiff > fIncr)
{
//
// get the number of fIncr quantums the speed is
//
int iQuantums = (int)((fSpeed / fIncr) + 0.5f);
float fQuantumSpeed = (float)iQuantums * fIncr;
float fTmpDiff = (float)fabs(fQuantumSpeed - fSpeed);
if (fTmpDiff < fDiff)
{
iSpeed = (iQuantums * iIncr) >> 8;
fDiff=fTmpDiff;
}
}
return iSpeed;
}
/****************************************************************************
*
* GetCPUSpeed
*
****************************************************************************/
INT GetCPUSpeed(VOID)
{
INT nCPUSpeed;
// Try first using WMI - may not work on Win9x
nCPUSpeed = GetCPUSpeedViaWMI();
if( nCPUSpeed != -1 )
return nCPUSpeed;
// If WMI fails, then fall back on brute force cpu detection.
#undef MAX_SAMPLES
#define MAX_SAMPLES 10
int nSpeed = 0, nSpeeds[MAX_SAMPLES] = {0};
int nCount = 0, nCounts[MAX_SAMPLES] = {0};
int i, j;
HANDLE hProcess = NULL;
DWORD oldclass = 0;
// 10/12/99(RichGr): Pick up the most frequently occurring speed in a number of short samples,
// instead of waiting once for a whole second (see DxDiag).
for ( i = 0; i < MAX_SAMPLES; i++ )
{
if ( !StartTimingCPU( hProcess, oldclass ))
{
// 10/21/99(RichGr): Sleep() time is important. On a 266 MHz running Win98 under the kernel
// debugger, the original value of Sleep(10) sometimes gave a speed of 283 MHz.
// Sleep(5) to Sleep(30) were also unreliable. Sleep(40) and Sleep(50) looked good,
// and I picked (50) for a little margin.
Sleep(50);
StopTimingCPU( hProcess, oldclass );
nSpeed = CalcCPUSpeed();
for ( j = 0; j < MAX_SAMPLES; j++ )
{
if ( nSpeeds[j] == 0 || nSpeed == nSpeeds[j] ) // If the speed matches, increment the count.
{
nSpeeds[j] = nSpeed;
nCounts[j]++;
break;
}
}
}
}
// Find the speed with the biggest count.
for ( i = j = 0, nCount = 0; i < MAX_SAMPLES; i++ )
{
if ( nCounts[i] > nCount )
{
nCount = nCounts[i];
j = i;
}
}
return nSpeeds[j];
}
/****************************************************************************
*
* GetCPUSpeedViaWMI
*
****************************************************************************/
INT GetCPUSpeedViaWMI(VOID)
{
HRESULT hr;
INT nCPUSpeed = -1;
IEnumWbemClassObject* pEnumProcessorDevs = NULL;
IWbemClassObject* pProcessorDev = NULL;
BSTR pClassName = NULL;
BSTR pPropName = NULL;
VARIANT var;
DWORD uReturned = 0;
ZeroMemory( &var, sizeof(VARIANT) );
VariantClear( &var );
if( NULL == g_pIWbemServices )
return -1;
pClassName = SysAllocString( L"Win32_Processor" );
hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
&pEnumProcessorDevs );
if( FAILED(hr) || pEnumProcessorDevs == NULL )
goto LCleanup;
// Get the first one in the list
hr = pEnumProcessorDevs->Next( 1000, // timeout in two seconds
1, // return just one storage device
&pProcessorDev, // pointer to storage device
&uReturned ); // number obtained: one or zero
if( FAILED(hr) || uReturned == 0 || pProcessorDev == NULL )
goto LCleanup;
// 298510: MaxClockSpeed on WMI on Whistler & beyond works
if( BIsWhistler() )
pPropName = SysAllocString( L"MaxClockSpeed" );
else
pPropName = SysAllocString( L"CurrentClockSpeed" );
hr = pProcessorDev->Get( pPropName, 0L, &var, NULL, NULL );
if( FAILED(hr) )
goto LCleanup;
// Success - record VT_I4 value in nCPUSpeed
nCPUSpeed = var.lVal;
LCleanup:
VariantClear( &var );
if(pPropName)
SysFreeString(pPropName);
if(pClassName)
SysFreeString(pClassName);
if(pProcessorDev)
pProcessorDev->Release();
if(pEnumProcessorDevs)
pEnumProcessorDevs->Release();
// Return either -1 or the CPU speed we found.
return nCPUSpeed;
}
#endif // _X86_
/****************************************************************************
*
* GetComputerSystemInfo
*
****************************************************************************/
VOID GetComputerSystemInfo(TCHAR* szSystemManufacturerEnglish, TCHAR* szSystemModelEnglish)
{
HRESULT hr;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevice = NULL;
BSTR pClassName = NULL;
BSTR pPropName = NULL;
DWORD uReturned = 0;
VARIANT var;
ZeroMemory( &var, sizeof(VARIANT) );
VariantClear( &var );
if( NULL == g_pIWbemServices )
goto LCleanup;
pClassName = SysAllocString( L"Win32_ComputerSystem" );
hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
&pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
// Get the first one in the list
hr = pEnumDevices->Next( 1000, // timeout in two seconds
1, // return just one storage device
&pDevice, // pointer to storage device
&uReturned ); // number obtained: one or zero
if( FAILED(hr) || uReturned == 0 || pDevice == NULL )
goto LCleanup;
pPropName = SysAllocString( L"Manufacturer" );
hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
if( FAILED(hr) )
goto LCleanup;
if(pPropName)
{
SysFreeString(pPropName);
pPropName = NULL;
}
if( var.bstrVal != NULL )
{
#ifdef UNICODE
lstrcpy(szSystemManufacturerEnglish, var.bstrVal);
#else
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szSystemManufacturerEnglish, 199, NULL, NULL);
#endif
}
VariantClear( &var );
pPropName = SysAllocString( L"Model" );
hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
if( FAILED(hr) )
goto LCleanup;
if(pPropName)
{
SysFreeString(pPropName);
pPropName = NULL;
}
if( var.bstrVal != NULL )
{
#ifdef UNICODE
lstrcpy(szSystemModelEnglish, var.bstrVal);
#else
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szSystemModelEnglish, 199, NULL, NULL);
#endif
}
VariantClear( &var );
LCleanup:
if( NULL == szSystemModelEnglish )
lstrcpy( szSystemModelEnglish, TEXT("n/a") );
if( NULL == szSystemManufacturerEnglish )
lstrcpy( szSystemManufacturerEnglish, TEXT("n/a") );
if(pPropName)
SysFreeString(pPropName);
if(pClassName)
SysFreeString(pClassName);
if(pDevice)
pDevice->Release();
if(pEnumDevices)
pEnumDevices->Release();
return;
}
/****************************************************************************
*
* GetBIOSInfo
*
****************************************************************************/
VOID GetBIOSInfo(TCHAR* szBIOSEnglish)
{
HRESULT hr;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevice = NULL;
BSTR pClassName = NULL;
BSTR pPropName = NULL;
DWORD uReturned = 0;
VARIANT var;
ZeroMemory( &var, sizeof(VARIANT) );
VariantClear( &var );
if( NULL == g_pIWbemServices )
goto LCleanup;
pClassName = SysAllocString( L"Win32_BIOS" );
hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
&pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
// Get the first one in the list
hr = pEnumDevices->Next( 1000, // timeout in two seconds
1, // return just one storage device
&pDevice, // pointer to storage device
&uReturned ); // number obtained: one or zero
if( FAILED(hr) || uReturned == 0 || pDevice == NULL )
goto LCleanup;
pPropName = SysAllocString( L"Version" );
hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
if( FAILED(hr) )
goto LCleanup;
if( var.bstrVal != NULL )
{
#ifdef UNICODE
lstrcpy(szBIOSEnglish, var.bstrVal);
#else
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szBIOSEnglish, 199, NULL, NULL);
#endif
}
VariantClear( &var );
LCleanup:
if( NULL == szBIOSEnglish )
lstrcpy( szBIOSEnglish, TEXT("n/a") );
if(pPropName)
SysFreeString(pPropName);
if(pClassName)
SysFreeString(pClassName);
if(pDevice)
pDevice->Release();
if(pEnumDevices)
pEnumDevices->Release();
return;
}
/****************************************************************************
*
* GetDXDebugLevels
*
****************************************************************************/
VOID GetDXDebugLevels(SysInfo* pSysInfo)
{
pSysInfo->m_bIsD3D8DebugRuntimeAvailable = IsD3D8DebugRuntimeAvailable();
pSysInfo->m_bIsD3DDebugRuntime = IsD3DDebugRuntime();
pSysInfo->m_bIsDInput8DebugRuntimeAvailable = IsDInput8DebugRuntimeAvailable();
pSysInfo->m_bIsDInput8DebugRuntime = IsDInput8DebugRuntime();
pSysInfo->m_bIsDMusicDebugRuntimeAvailable = IsDMusicDebugRuntimeAvailable();
pSysInfo->m_bIsDMusicDebugRuntime = IsDMusicDebugRuntime();
pSysInfo->m_bIsDDrawDebugRuntime = IsDDrawDebugRuntime();
pSysInfo->m_bIsDPlayDebugRuntime = IsDPlayDebugRuntime();
pSysInfo->m_bIsDSoundDebugRuntime = IsDSoundDebugRuntime();
pSysInfo->m_nD3DDebugLevel = (int) GetProfileInt(TEXT("Direct3D"), TEXT("debug"), 0);
pSysInfo->m_nDDrawDebugLevel = (int) GetProfileInt(TEXT("DirectDraw"),TEXT("debug"), 0);
pSysInfo->m_nDIDebugLevel = GetDIDebugLevel();
pSysInfo->m_nDMusicDebugLevel = GetDMDebugLevel();
pSysInfo->m_nDPlayDebugLevel = (int) GetProfileInt(TEXT("DirectPlay"), TEXT("Debug"), 0);
pSysInfo->m_nDSoundDebugLevel = GetDSDebugLevel();
}
/****************************************************************************
*
* IsD3D8DebugRuntimeAvailable
*
****************************************************************************/
BOOL IsD3D8DebugRuntimeAvailable()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\d3d8d.dll"));
if (GetFileAttributes(szPath) != -1)
return TRUE;
else
return FALSE;
}
/****************************************************************************
*
* IsD3DDebugRuntime
*
****************************************************************************/
BOOL IsD3DDebugRuntime()
{
DWORD size;
DWORD type;
DWORD lData;
HKEY hkey;
BOOL rc;
rc = FALSE;
if (!RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_D3D, &hkey))
{
size = sizeof(DWORD);
if (!RegQueryValueEx(hkey, REGSTR_VAL_DDRAW_LOADDEBUGRUNTIME, NULL, &type, (LPBYTE)&lData, &size))
if (lData)
rc = TRUE;
RegCloseKey(hkey);
}
return rc;
}
/****************************************************************************
*
* GetDIDebugLevel
*
****************************************************************************/
int GetDIDebugLevel()
{
DWORD dwDebugBits;
DWORD dwDebugBitsMax;
LONG iGenerator;
dwDebugBitsMax = 0;
dwDebugBits = GetProfileInt(TEXT("Debug"), TEXT("dinput"), 0);
if (dwDebugBits > dwDebugBitsMax)
dwDebugBitsMax = dwDebugBits;
enum
{
GENERATOR_KBD = 0,
GENERATOR_MOUSE,
GENERATOR_JOY,
GENERATOR_HID,
GENERATOR_MAX
};
static TCHAR* szGeneratorNames[] =
{
TEXT("DInput.06"),
TEXT("DInput.04"),
TEXT("DInput.08"),
TEXT("DInput.17"),
};
static BOOL bGeneratorArray[4];
for (iGenerator = 0; iGenerator < GENERATOR_MAX; iGenerator++)
{
dwDebugBits = GetProfileInt(TEXT("Debug"), szGeneratorNames[iGenerator], 0);
bGeneratorArray[iGenerator] = (dwDebugBits > 0);
if (dwDebugBits > dwDebugBitsMax)
dwDebugBitsMax = dwDebugBits;
}
if (dwDebugBitsMax & 0x20) // verbose
return 5;
if (dwDebugBitsMax & 0x02) // function entry
return 4;
if (dwDebugBitsMax & 0x01) // trace
return 3;
if (dwDebugBitsMax & 0x08) // benign
return 2;
if (dwDebugBitsMax & 0x10) // severe
return 1;
return 0;
}
/****************************************************************************
*
* IsDInput8DebugRuntimeAvailable
*
****************************************************************************/
BOOL IsDInput8DebugRuntimeAvailable()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\dinput8d.dll"));
if (GetFileAttributes(szPath) != -1)
return TRUE;
else
return FALSE;
}
/****************************************************************************
*
* IsDInput8DebugRuntime
*
****************************************************************************/
BOOL IsDInput8DebugRuntime()
{
DWORD size;
DWORD type;
TCHAR szData[MAX_PATH];
HKEY hkey;
BOOL rc;
rc = FALSE;
if (!RegOpenKey(HKEY_CLASSES_ROOT, REGSTR_DINPUT_DLL, &hkey))
{
size = sizeof(szData);
if (!RegQueryValueEx(hkey, NULL, NULL, &type, (LPBYTE)&szData, &size))
{
if (_tcsstr(szData, TEXT("dinput8d.dll")))
rc = TRUE;
}
RegCloseKey(hkey);
}
return rc;
}
/****************************************************************************
*
* GetDMDebugLevel
*
****************************************************************************/
int GetDMDebugLevel()
{
DWORD dwDMusicDebugLevel = 0;
DWORD dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMBAND"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMCOMPOS"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMIME"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMLOADER"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC16"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC32"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSTYLE"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSYNTH"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSCRIPT"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DSWAVE"), 0)) > dwDMusicDebugLevel)
dwDMusicDebugLevel = dw;
return dwDMusicDebugLevel;
}
/****************************************************************************
*
* IsDMusicDebugRuntimeAvailable
*
****************************************************************************/
BOOL IsDMusicDebugRuntimeAvailable()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\dmusicd.dll"));
if (GetFileAttributes(szPath) != -1)
return TRUE;
else
return FALSE;
}
/****************************************************************************
*
* IsDMusicDebugRuntime
*
****************************************************************************/
BOOL IsDMusicDebugRuntime()
{
DWORD size;
DWORD type;
TCHAR szData[MAX_PATH];
HKEY hkey;
BOOL rc;
rc = FALSE;
if (!RegOpenKey(HKEY_CLASSES_ROOT, REGSTR_DMUSIC_DLL, &hkey))
{
size = sizeof(szData);
if (!RegQueryValueEx(hkey, NULL, NULL, &type, (LPBYTE)&szData, &size))
{
if (_tcsstr(szData, TEXT("dmusicd.dll")) ||
_tcsstr(szData, TEXT("DMUSICD.DLL")))
{
rc = TRUE;
}
}
RegCloseKey(hkey);
}
return rc;
}
/****************************************************************************
*
* GetDSDebugLevel
*
****************************************************************************/
int GetDSDebugLevel()
{
DWORD dwSoundLevel = 0;
// Pick up the DMusic DLL debug settings that are controlled on the
// DSound page
HRESULT hr;
HINSTANCE hinst;
LPKSPROPERTYSET pksps = NULL;
hinst = LoadLibrary(TEXT("dsound.dll"));
if (hinst != NULL)
{
if (SUCCEEDED(hr = DirectSoundPrivateCreate(&pksps)))
{
hr = PrvGetDebugInformation(pksps, NULL, &dwSoundLevel, NULL, NULL);
pksps->Release();
}
FreeLibrary(hinst);
}
return dwSoundLevel;
}
/****************************************************************************
*
* IsFileDebug
*
****************************************************************************/
BOOL IsFileDebug( TCHAR* szPath )
{
UINT cb;
DWORD dwHandle;
BYTE FileVersionBuffer[4096];
VS_FIXEDFILEINFO* pVersion = NULL;
cb = GetFileVersionInfoSize(szPath, &dwHandle/*ignored*/);
if (cb > 0)
{
if (cb > sizeof(FileVersionBuffer))
cb = sizeof(FileVersionBuffer);
if(GetFileVersionInfo(szPath, 0, cb, &FileVersionBuffer))
{
if(VerQueryValue(&FileVersionBuffer, TEXT("\\"), (VOID**)&pVersion, &cb))
{
if( pVersion )
{
if( pVersion->dwFileFlags & VS_FF_DEBUG )
return TRUE;
else
return FALSE;
}
}
}
}
return FALSE;
}
/****************************************************************************
*
* IsDDrawDebugRuntime
*
****************************************************************************/
BOOL IsDDrawDebugRuntime()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\ddraw.dll"));
return IsFileDebug(szPath);
}
/****************************************************************************
*
* IsDPlayDebugRuntime
*
****************************************************************************/
BOOL IsDPlayDebugRuntime()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\dpnet.dll"));
return IsFileDebug(szPath);
}
/****************************************************************************
*
* IsDSoundDebugRuntime
*
****************************************************************************/
BOOL IsDSoundDebugRuntime()
{
TCHAR szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, TEXT("\\dsound.dll"));
return IsFileDebug(szPath);
}
/****************************************************************************
*
* BIsDxDiag64Bit
*
****************************************************************************/
BOOL BIsDxDiag64Bit(VOID)
{
#ifdef _WIN64
return TRUE;
#else
return FALSE;
#endif
}
/****************************************************************************
*
* GetFileSystemStoringD3D8Cache
*
****************************************************************************/
VOID GetFileSystemStoringD3D8Cache( TCHAR* strFileSystemBuffer )
{
TCHAR strPath[MAX_PATH + 16];
BOOL bFound = FALSE;
GetSystemDirectory( strPath, MAX_PATH);
lstrcat( strPath, TEXT("\\d3d8caps.dat") );
if (GetFileAttributes(strPath) != 0xffffffff)
bFound = TRUE;
if( !bFound && BIsPlatformNT() )
{
// stolen from \dxg\d3d8\fw\fcache.cpp, OpenCacheFile().
HMODULE hShlwapi = NULL;
typedef HRESULT (WINAPI * PSHGETSPECIALFOLDERPATH) (HWND, LPTSTR, int, BOOL);
PSHGETSPECIALFOLDERPATH pSHGetSpecialFolderPath = NULL;
hShlwapi = LoadLibrary( TEXT("SHELL32.DLL") );
if( NULL != hShlwapi )
{
#ifdef UNICODE
pSHGetSpecialFolderPath = (PSHGETSPECIALFOLDERPATH)
GetProcAddress(hShlwapi,"SHGetSpecialFolderPathW");
#else
pSHGetSpecialFolderPath = (PSHGETSPECIALFOLDERPATH)
GetProcAddress(hShlwapi,"SHGetSpecialFolderPathA");
#endif
if(pSHGetSpecialFolderPath)
{
HRESULT hr;
// <user name>\Local Settings\Applicaiton Data (non roaming)
hr = pSHGetSpecialFolderPath( NULL, strPath,
CSIDL_LOCAL_APPDATA,
FALSE );
if( SUCCEEDED(hr) )
{
lstrcat( strPath, TEXT("\\d3d8caps.dat") );
if (GetFileAttributes(strPath) != 0xffffffff)
bFound = TRUE;
}
}
FreeLibrary(hShlwapi);
}
}
if( bFound )
{
DWORD dwVolumeSerialNumber;
DWORD dwMaxComponentLength;
DWORD dwFileSystemFlags;
// Trim to root dir -- "x:\"
strPath[3] = 0;
BOOL bSuccess = GetVolumeInformation( strPath, NULL, 0, &dwVolumeSerialNumber,
&dwMaxComponentLength, &dwFileSystemFlags,
strFileSystemBuffer, MAX_PATH );
if( !bSuccess )
lstrcpy( strFileSystemBuffer, TEXT("Unknown") );
}
else
{
lstrcpy( strFileSystemBuffer, TEXT("n/a") );
}
return;
}
/****************************************************************************
*
* IsNetMeetingRunning
*
****************************************************************************/
BOOL IsNetMeetingRunning()
{
HWND hNetMeeting = FindWindow( TEXT("MPWClass"), NULL );
return( hNetMeeting != NULL );
}