2322 lines
77 KiB
C++
2322 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 || OSVersionInfo.dwMinorVersion == 2 ) );
|
|
// should be 05.01.xxxx (for WinXP) or 05.02.xxxx (for .NET server)
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* 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 && osve.wSuiteMask & VER_SUITE_BLADE)
|
|
{
|
|
lstrcat(pSysInfo->m_szOS, TEXT(" "));
|
|
LoadString(NULL, IDS_WEBSERVER, 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
|
|
lstrcpy( szOSTmp, pSysInfo->m_szOSEx );
|
|
|
|
if( _tcslen( pSysInfo->m_szBuildLab ) )
|
|
wsprintf( pSysInfo->m_szOSExLong, TEXT("%s (%s)"), szOSTmp, pSysInfo->m_szBuildLab );
|
|
else
|
|
lstrcpy( pSysInfo->m_szOSExLong, 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;
|
|
|
|
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(""));
|
|
if( _stscanf(pSysInfo->m_szDirectXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild) != 4 )
|
|
{
|
|
dwMajor = 0;
|
|
dwMinor = 0;
|
|
dwRevision = 0;
|
|
dwBuild = 0;
|
|
}
|
|
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 if (dwMajor == 4 && dwMinor == 8 && dwRevision == 1 )
|
|
{
|
|
lstrcpy(szFriendly, TEXT("DirectX 8.1"));
|
|
pSysInfo->m_dwDirectXVersionMajor = 8;
|
|
pSysInfo->m_dwDirectXVersionMinor = 1;
|
|
}
|
|
else if (dwMajor == 4 && dwMinor == 9 )
|
|
{
|
|
lstrcpy(szFriendly, TEXT("DirectX 9.0"));
|
|
pSysInfo->m_dwDirectXVersionMajor = 9;
|
|
pSysInfo->m_dwDirectXVersionMinor = 0;
|
|
}
|
|
else
|
|
{
|
|
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, KEY_READ, &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_AMD64)
|
|
{
|
|
lstrcpy(pszProcessor, TEXT("AMD64 "));
|
|
}
|
|
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
|
|
_tcsncpy(szSystemManufacturerEnglish, var.bstrVal, 200);
|
|
szSystemManufacturerEnglish[199]=0;
|
|
#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
|
|
_tcsncpy(szSystemModelEnglish, var.bstrVal, 200);
|
|
szSystemModelEnglish[199]=0;
|
|
#else
|
|
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szSystemModelEnglish, 199, NULL, NULL);
|
|
#endif
|
|
}
|
|
|
|
VariantClear( &var );
|
|
|
|
LCleanup:
|
|
|
|
if( lstrlen(szSystemModelEnglish) == 0 )
|
|
lstrcpy( szSystemModelEnglish, TEXT("n/a") );
|
|
if( lstrlen(szSystemManufacturerEnglish) == 0 )
|
|
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
|
|
_tcsncpy(szBIOSEnglish, var.bstrVal, 200);
|
|
szBIOSEnglish[199]=0;
|
|
#else
|
|
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szBIOSEnglish, 199, NULL, NULL);
|
|
#endif
|
|
}
|
|
|
|
VariantClear( &var );
|
|
|
|
LCleanup:
|
|
|
|
if( lstrlen(szBIOSEnglish) == 0 )
|
|
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 (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_D3D, 0, KEY_READ, &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 (!RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_DINPUT_DLL, 0, KEY_READ, &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 (!RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_DMUSIC_DLL, 0, KEY_READ, &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 );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DXUtil_strcmpi()
|
|
// Desc: compares 2 strings
|
|
//-----------------------------------------------------------------------------
|
|
int DXUtil_strcmpi( TCHAR* str1, TCHAR* str2 )
|
|
{
|
|
int nResult = CompareString( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, str1, -1, str2, -1 );
|
|
|
|
if( nResult == CSTR_EQUAL )
|
|
return 0;
|
|
if( nResult == CSTR_LESS_THAN )
|
|
return -1;
|
|
else
|
|
return 1;
|
|
}
|