Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2321 lines
79 KiB

  1. /****************************************************************************
  2. *
  3. * File: sysinfo.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * CPU type detection code by Rich Granshaw
  7. * CPU speed code by Michael Lyons
  8. * Purpose: Gather system information (OS, hardware, name, etc.) on this machine
  9. *
  10. * \Multimedia\Testsrc\Tools\ShowCPUID\ can be used to debug CPUID problems.
  11. *
  12. * (C) Copyright 1998 Microsoft Corp. All rights reserved.
  13. *
  14. ****************************************************************************/
  15. #include <tchar.h>
  16. #include <Windows.h>
  17. #include <mmsystem.h>
  18. #include <stdio.h>
  19. #include <wbemidl.h>
  20. #include <objbase.h>
  21. #include <shfolder.h>
  22. #include <dsound.h>
  23. #include "dsprv.h"
  24. #include "dsprvobj.h"
  25. #include "sysinfo.h"
  26. #include "fileinfo.h" // for GetLanguageFromFile
  27. #include "resource.h"
  28. #define REGSTR_PATH_D3D TEXT("Software\\Microsoft\\Direct3D")
  29. #define REGSTR_VAL_DDRAW_LOADDEBUGRUNTIME TEXT("LoadDebugRuntime")
  30. #define REGSTR_DINPUT_DLL TEXT("CLSID\\{25E609E4-B259-11CF-BFC7-444553540000}\\InProcServer32")
  31. #define REGSTR_DMUSIC_DLL TEXT("CLSID\\{480FF4B0-28B2-11D1-BEF7-00C04FBF8FEF}\\InProcServer32")
  32. struct PROCESSOR_ID_NUMBERS
  33. {
  34. DWORD dwType; // Intel: 0 = standard, 1 = Overdrive, 2 = dual processor.
  35. DWORD dwFamily;
  36. DWORD dwModel;
  37. DWORD dwSteppingID;
  38. };
  39. extern IWbemServices* g_pIWbemServices;
  40. typedef INT (WINAPI* LPDXSETUPGETVERSION)(DWORD* pdwVersion, DWORD* pdwRevision);
  41. static VOID GetProcessorDescription(BOOL bNT, SYSTEM_INFO* psi, TCHAR* pszDesc, BOOL* pbNoCPUSpeed);
  42. static VOID GetProcessorVendorNameAndType(OSVERSIONINFO& OSVersionInfo,
  43. SYSTEM_INFO& SystemInfo, TCHAR* pszProcessor, BOOL* pbNoCPUSpeed);
  44. static VOID GetVendorNameAndCaps(TCHAR* pszVendorName, TCHAR* pszIDTLongName,
  45. PROCESSOR_ID_NUMBERS& ProcessorIdNumbers, BOOL* pbIsMMX, BOOL* pbIs3DNow, BOOL* pbIsKatmai, /*Pentium III/Streaming SIMD Instrucs*/
  46. LPDWORD pdwKBytesLevel2Cache, LPDWORD pdwIntelBrandIndex, BOOL* pbNoCPUSpeed);
  47. #ifdef _X86_
  48. static INT GetCPUSpeed(VOID);
  49. static INT GetCPUSpeedViaWMI(VOID);
  50. #endif
  51. static VOID GetComputerSystemInfo(TCHAR* szSystemManufacturerEnglish, TCHAR* szSystemModelEnglish);
  52. static VOID GetBIOSInfo(TCHAR* szBIOSEnglish);
  53. static VOID GetFileSystemStoringD3D8Cache( TCHAR* strFileSystemBuffer );
  54. static VOID GetDXDebugLevels(SysInfo* pSysInfo);
  55. static int GetDSDebugLevel();
  56. static BOOL IsDMusicDebugRuntime();
  57. static BOOL IsDMusicDebugRuntimeAvailable();
  58. static int GetDMDebugLevel();
  59. static BOOL IsDInput8DebugRuntime();
  60. static BOOL IsDInput8DebugRuntimeAvailable();
  61. static int GetDIDebugLevel();
  62. static BOOL IsD3DDebugRuntime();
  63. static BOOL IsD3D8DebugRuntimeAvailable();
  64. static BOOL IsDDrawDebugRuntime();
  65. static BOOL IsDPlayDebugRuntime();
  66. static BOOL IsDSoundDebugRuntime();
  67. static BOOL IsNetMeetingRunning();
  68. /****************************************************************************
  69. *
  70. * BIsPlatformNT
  71. *
  72. ****************************************************************************/
  73. BOOL BIsPlatformNT(VOID)
  74. {
  75. OSVERSIONINFO OSVersionInfo;
  76. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  77. GetVersionEx(&OSVersionInfo);
  78. return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  79. }
  80. /****************************************************************************
  81. *
  82. * BIsPlatform9x
  83. *
  84. ****************************************************************************/
  85. BOOL BIsPlatform9x(VOID)
  86. {
  87. OSVERSIONINFO OSVersionInfo;
  88. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  89. GetVersionEx(&OSVersionInfo);
  90. return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
  91. }
  92. /****************************************************************************
  93. *
  94. * BIsWin2k
  95. *
  96. ****************************************************************************/
  97. BOOL BIsWin2k(VOID)
  98. {
  99. OSVERSIONINFO OSVersionInfo;
  100. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  101. GetVersionEx(&OSVersionInfo);
  102. return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  103. OSVersionInfo.dwMajorVersion == 5 &&
  104. OSVersionInfo.dwMinorVersion == 0 ); // should be 05.00.xxxx
  105. }
  106. /****************************************************************************
  107. *
  108. * BIsWhistler
  109. *
  110. ****************************************************************************/
  111. BOOL BIsWhistler(VOID)
  112. {
  113. OSVERSIONINFO OSVersionInfo;
  114. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  115. GetVersionEx(&OSVersionInfo);
  116. return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  117. OSVersionInfo.dwMajorVersion == 5 &&
  118. ( OSVersionInfo.dwMinorVersion == 1 || OSVersionInfo.dwMinorVersion == 2 ) );
  119. // should be 05.01.xxxx (for WinXP) or 05.02.xxxx (for .NET server)
  120. }
  121. /****************************************************************************
  122. *
  123. * BIsWinNT
  124. *
  125. ****************************************************************************/
  126. BOOL BIsWinNT(VOID)
  127. {
  128. OSVERSIONINFO OSVersionInfo;
  129. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  130. GetVersionEx(&OSVersionInfo);
  131. return ( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  132. OSVersionInfo.dwMajorVersion <= 4 );
  133. }
  134. /****************************************************************************
  135. *
  136. * BIsWinME
  137. *
  138. ****************************************************************************/
  139. BOOL BIsWinME(VOID)
  140. {
  141. OSVERSIONINFO OSVersionInfo;
  142. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  143. GetVersionEx(&OSVersionInfo);
  144. return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  145. OSVersionInfo.dwMajorVersion >= 4 &&
  146. OSVersionInfo.dwMinorVersion >= 90 ); // should be 4.90.xxxx
  147. }
  148. /****************************************************************************
  149. *
  150. * BIsWin98 - from http://kbinternal/kb/articles/q189/2/49.htm
  151. *
  152. ****************************************************************************/
  153. BOOL BIsWin98(VOID)
  154. {
  155. OSVERSIONINFO OSVersionInfo;
  156. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  157. GetVersionEx(&OSVersionInfo);
  158. return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  159. OSVersionInfo.dwMajorVersion == 4 &&
  160. OSVersionInfo.dwMinorVersion == 10 ); // should be 4.10.xxxx
  161. }
  162. /****************************************************************************
  163. *
  164. * BIsWin95 - from http://kbinternal/kb/articles/q189/2/49.htm
  165. *
  166. ****************************************************************************/
  167. BOOL BIsWin95(VOID)
  168. {
  169. OSVERSIONINFO OSVersionInfo;
  170. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  171. GetVersionEx(&OSVersionInfo);
  172. return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  173. OSVersionInfo.dwMajorVersion == 4 &&
  174. OSVersionInfo.dwMinorVersion < 10 ); // should be 4.00.0950
  175. }
  176. /****************************************************************************
  177. *
  178. * BIsWin3x
  179. *
  180. ****************************************************************************/
  181. BOOL BIsWin3x(VOID)
  182. {
  183. OSVERSIONINFO OSVersionInfo;
  184. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  185. GetVersionEx(&OSVersionInfo);
  186. return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  187. OSVersionInfo.dwMajorVersion < 4 ); // should be 3.xx.xxxx
  188. }
  189. /****************************************************************************
  190. *
  191. * BIsIA64
  192. *
  193. ****************************************************************************/
  194. BOOL BIsIA64(VOID)
  195. {
  196. OSVERSIONINFO OSVersionInfo;
  197. SYSTEM_INFO SystemInfo;
  198. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  199. GetVersionEx(&OSVersionInfo);
  200. GetSystemInfo(&SystemInfo);
  201. return( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  202. SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 );
  203. }
  204. /****************************************************************************
  205. *
  206. * GetSystemInfo
  207. *
  208. ****************************************************************************/
  209. VOID GetSystemInfo(SysInfo* pSysInfo)
  210. {
  211. TCHAR szSystemPath[MAX_PATH];
  212. HKEY hKey = NULL;
  213. HKEY hSubKey = NULL;
  214. ULONG ulType;
  215. OSVERSIONINFO OSVersionInfo;
  216. SYSTEM_INFO SystemInfo;
  217. DWORD cbData;
  218. LCID lcid;
  219. DWORD dwKeyboardSubType;
  220. WORD wLanguage;
  221. TCHAR sz[200];
  222. TCHAR szDebug[100];
  223. // Get current time
  224. TCHAR szDate[100];
  225. TCHAR szTime[100];
  226. GetLocalTime(&pSysInfo->m_time);
  227. GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, NULL, NULL, szDate, 100);
  228. wsprintf(szTime, TEXT("%02d:%02d:%02d"), pSysInfo->m_time.wHour,
  229. pSysInfo->m_time.wMinute, pSysInfo->m_time.wSecond);
  230. wsprintf(pSysInfo->m_szTimeLocal, TEXT("%s, %s"), szDate, szTime);
  231. wsprintf(szDate, TEXT("%d/%d/%d"), pSysInfo->m_time.wMonth, pSysInfo->m_time.wDay, pSysInfo->m_time.wYear);
  232. wsprintf(pSysInfo->m_szTime, TEXT("%s, %s"), szDate, szTime);
  233. // Get the computer network name
  234. cbData = sizeof(pSysInfo->m_szMachine) - 1;
  235. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"), 0, KEY_READ, &hKey)
  236. && !RegQueryValueEx(hKey, TEXT("ComputerName"), 0, &ulType, (LPBYTE)pSysInfo->m_szMachine, &cbData)
  237. && ulType == REG_SZ)
  238. {
  239. // Got data OK.
  240. }
  241. else
  242. {
  243. LoadString(NULL, IDS_NOMACHINENAME, pSysInfo->m_szMachine, 200);
  244. }
  245. if (hKey)
  246. {
  247. RegCloseKey(hKey);
  248. hKey = 0;
  249. }
  250. // Check for NEC PC-98
  251. pSysInfo->m_bNECPC98 = FALSE;
  252. lcid = GetSystemDefaultLCID();
  253. if (lcid == 0x0411) // Windows 95 J
  254. {
  255. dwKeyboardSubType = GetKeyboardType(1);
  256. if (HIBYTE(dwKeyboardSubType) == 0x0D) // NEC PC-98 series
  257. {
  258. pSysInfo->m_bNECPC98 = TRUE;
  259. LoadString(NULL, IDS_NECPC98, sz, 200);
  260. lstrcat(pSysInfo->m_szMachine, sz);
  261. }
  262. }
  263. // Get Windows version
  264. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  265. GetVersionEx(&OSVersionInfo);
  266. pSysInfo->m_dwMajorVersion = OSVersionInfo.dwMajorVersion;
  267. pSysInfo->m_dwMinorVersion = OSVersionInfo.dwMinorVersion;
  268. pSysInfo->m_dwBuildNumber = OSVersionInfo.dwBuildNumber;
  269. pSysInfo->m_dwPlatformID = OSVersionInfo.dwPlatformId;
  270. lstrcpy(pSysInfo->m_szCSDVersion, OSVersionInfo.szCSDVersion);
  271. pSysInfo->m_bDebug = (GetSystemMetrics(SM_DEBUG) > 0);
  272. // Get OS Name
  273. TCHAR* pszWindowsKey;
  274. if (pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT)
  275. pszWindowsKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
  276. else
  277. pszWindowsKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion");
  278. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszWindowsKey, 0, KEY_READ, &hKey))
  279. {
  280. cbData = 100;
  281. RegQueryValueEx(hKey, TEXT("ProductName"), 0, &ulType, (LPBYTE)pSysInfo->m_szOS, &cbData);
  282. cbData = 100;
  283. RegQueryValueEx(hKey, TEXT("BuildLab"), 0, &ulType, (LPBYTE)pSysInfo->m_szBuildLab, &cbData);
  284. RegCloseKey(hKey);
  285. }
  286. if (lstrlen(pSysInfo->m_szOS) == 0)
  287. {
  288. // it is very strange for ProductName registry info
  289. // (see above) to be missing.
  290. lstrcpy(pSysInfo->m_szOS, TEXT("Windows"));
  291. }
  292. if (pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT)
  293. {
  294. // 25598: Append product type (professional, server, etc)
  295. OSVERSIONINFOEX osve;
  296. ZeroMemory(&osve, sizeof(osve));
  297. osve.dwOSVersionInfoSize = sizeof(osve);
  298. GetVersionEx((OSVERSIONINFO*)&osve);
  299. if (osve.wProductType == VER_NT_SERVER && osve.wSuiteMask & VER_SUITE_DATACENTER)
  300. {
  301. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  302. LoadString(NULL, IDS_DATACENTERSERVER, sz, 200);
  303. lstrcat(pSysInfo->m_szOS, sz);
  304. }
  305. else if (osve.wProductType == VER_NT_SERVER && osve.wSuiteMask & VER_SUITE_ENTERPRISE)
  306. {
  307. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  308. LoadString(NULL, IDS_ADVANCEDSERVER, sz, 200);
  309. lstrcat(pSysInfo->m_szOS, sz);
  310. }
  311. else if (osve.wProductType == VER_NT_SERVER && osve.wSuiteMask & VER_SUITE_BLADE)
  312. {
  313. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  314. LoadString(NULL, IDS_WEBSERVER, sz, 200);
  315. lstrcat(pSysInfo->m_szOS, sz);
  316. }
  317. else if (osve.wProductType == VER_NT_SERVER)
  318. {
  319. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  320. LoadString(NULL, IDS_SERVER, sz, 200);
  321. lstrcat(pSysInfo->m_szOS, sz);
  322. }
  323. else if (osve.wProductType == VER_NT_WORKSTATION && (osve.wSuiteMask & VER_SUITE_PERSONAL))
  324. {
  325. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  326. LoadString(NULL, IDS_PERSONAL, sz, 200);
  327. lstrcat(pSysInfo->m_szOS, sz);
  328. }
  329. else if (osve.wProductType == VER_NT_WORKSTATION)
  330. {
  331. lstrcat(pSysInfo->m_szOS, TEXT(" "));
  332. LoadString(NULL, IDS_PROFESSIONAL, sz, 200);
  333. lstrcat(pSysInfo->m_szOS, sz);
  334. }
  335. }
  336. // Format Windows version
  337. LoadString(NULL, IDS_WINVERFMT, sz, 200);
  338. LoadString(NULL, IDS_DEBUG, szDebug, 100);
  339. lstrcat(szDebug, TEXT(" "));
  340. wsprintf(pSysInfo->m_szOSEx, sz,
  341. pSysInfo->m_bDebug ? szDebug : TEXT(""),
  342. pSysInfo->m_szOS, pSysInfo->m_dwMajorVersion, pSysInfo->m_dwMinorVersion,
  343. LOWORD(pSysInfo->m_dwBuildNumber));
  344. TCHAR szOSTmp[200];
  345. if( _tcslen( pSysInfo->m_szCSDVersion) )
  346. wsprintf( szOSTmp, TEXT("%s %s"), pSysInfo->m_szOSEx, pSysInfo->m_szCSDVersion );
  347. else
  348. lstrcpy( szOSTmp, pSysInfo->m_szOSEx );
  349. if( _tcslen( pSysInfo->m_szBuildLab ) )
  350. wsprintf( pSysInfo->m_szOSExLong, TEXT("%s (%s)"), szOSTmp, pSysInfo->m_szBuildLab );
  351. else
  352. lstrcpy( pSysInfo->m_szOSExLong, szOSTmp );
  353. // Get the original language.
  354. GetSystemDirectory(szSystemPath, MAX_PATH);
  355. if (wLanguage = GetLanguageFromFile(TEXT("user.exe"), szSystemPath))
  356. {
  357. lcid = MAKELCID(wLanguage, SORT_DEFAULT);
  358. }
  359. // Get the language and regional setting and store them (in English) for saved file:
  360. TCHAR szLanguage[200];
  361. TCHAR szLanguageRegional[200];
  362. if ((!GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, szLanguage, 200)))
  363. szLanguage[0] = '\0';
  364. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SENGLANGUAGE, szLanguageRegional, 200))
  365. szLanguageRegional[0] = '\0';
  366. LoadString(NULL, IDS_LANGUAGEFMT_ENGLISH, sz, 200);
  367. wsprintf(pSysInfo->m_szLanguages, sz, szLanguage, szLanguageRegional);
  368. // Now get same info in local language for display:
  369. if ((!GetLocaleInfo(lcid, LOCALE_SNATIVELANGNAME, szLanguage, 200)))
  370. szLanguage[0] = '\0';
  371. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNATIVELANGNAME, szLanguageRegional, 200))
  372. szLanguageRegional[0] = '\0';
  373. LoadString(NULL, IDS_LANGUAGEFMT, sz, 200);
  374. wsprintf(pSysInfo->m_szLanguagesLocal, sz, szLanguage, szLanguageRegional);
  375. // Get info about processor manufacturer and type
  376. BOOL bNoCPUSpeed = TRUE;
  377. GetSystemInfo(&SystemInfo);
  378. GetProcessorDescription(pSysInfo->m_dwPlatformID == VER_PLATFORM_WIN32_NT,
  379. &SystemInfo, pSysInfo->m_szProcessor, &bNoCPUSpeed);
  380. GetComputerSystemInfo(pSysInfo->m_szSystemManufacturerEnglish, pSysInfo->m_szSystemModelEnglish);
  381. GetBIOSInfo(pSysInfo->m_szBIOSEnglish);
  382. #ifdef _X86_
  383. // Append processor speed, if it can be computed
  384. if ( bNoCPUSpeed )
  385. {
  386. INT iMhz = GetCPUSpeed();
  387. if (iMhz > 0)
  388. {
  389. TCHAR szSpeed[50];
  390. wsprintf(szSpeed, TEXT(", ~%dMHz"), iMhz);
  391. lstrcat(pSysInfo->m_szProcessor, szSpeed);
  392. }
  393. }
  394. #endif
  395. BOOL bGotMem = FALSE;
  396. // Get system memory information
  397. if( BIsPlatformNT() )
  398. {
  399. TCHAR szPath[MAX_PATH];
  400. GetSystemDirectory(szPath, MAX_PATH);
  401. lstrcat(szPath, TEXT("\\kernel32.dll"));
  402. HINSTANCE hKernel32 = LoadLibrary(szPath);
  403. if( hKernel32 != NULL )
  404. {
  405. typedef BOOL (WINAPI* PGlobalMemoryStatusEx)(OUT LPMEMORYSTATUSEX lpBuffer);
  406. PGlobalMemoryStatusEx pGlobalMemoryStatusEx = (PGlobalMemoryStatusEx)GetProcAddress(hKernel32, "GlobalMemoryStatusEx");
  407. if( pGlobalMemoryStatusEx != NULL )
  408. {
  409. MEMORYSTATUSEX MemoryStatus;
  410. MemoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
  411. pGlobalMemoryStatusEx(&MemoryStatus);
  412. pSysInfo->m_ullPhysicalMemory = MemoryStatus.ullTotalPhys;
  413. pSysInfo->m_ullUsedPageFile = MemoryStatus.ullTotalPageFile - MemoryStatus.ullAvailPageFile;
  414. pSysInfo->m_ullAvailPageFile = MemoryStatus.ullAvailPageFile;
  415. bGotMem = TRUE;
  416. }
  417. FreeLibrary(hKernel32);
  418. }
  419. }
  420. if( !bGotMem ) // Win9x or LoadLib failed
  421. {
  422. MEMORYSTATUS MemoryStatus;
  423. MemoryStatus.dwLength = sizeof MemoryStatus;
  424. GlobalMemoryStatus(&MemoryStatus);
  425. pSysInfo->m_ullPhysicalMemory = MemoryStatus.dwTotalPhys;
  426. pSysInfo->m_ullUsedPageFile = MemoryStatus.dwTotalPageFile - MemoryStatus.dwAvailPageFile;
  427. pSysInfo->m_ullAvailPageFile = MemoryStatus.dwAvailPageFile;
  428. }
  429. // Format memory information:
  430. DWORDLONG dwMB = (DWORDLONG)(pSysInfo->m_ullPhysicalMemory >> 20);
  431. dwMB += dwMB % 2; // round up to even number
  432. _stprintf(pSysInfo->m_szPhysicalMemory, TEXT("%I64dMB RAM"), dwMB);
  433. DWORDLONG dwUsedMB = (pSysInfo->m_ullUsedPageFile >> 20);
  434. DWORDLONG dwAvailMB = (pSysInfo->m_ullAvailPageFile >> 20);
  435. LoadString(NULL, IDS_PAGEFILEFMT, sz, 200);
  436. _stprintf(pSysInfo->m_szPageFile, sz, dwUsedMB, dwAvailMB);
  437. LoadString(NULL, IDS_PAGEFILEFMT_ENGLISH, sz, 200);
  438. _stprintf(pSysInfo->m_szPageFileEnglish, sz, dwUsedMB, dwAvailMB);
  439. // Get DxDiag version:
  440. TCHAR szFile[MAX_PATH];
  441. if (0 != GetModuleFileName(NULL, szFile, MAX_PATH))
  442. GetFileVersion(szFile, pSysInfo->m_szDxDiagVersion, NULL, NULL, NULL, NULL);
  443. // Get DirectX Version using dsetup.dll
  444. TCHAR szSetupPath[MAX_PATH];
  445. HINSTANCE hInstDSetup;
  446. LPDXSETUPGETVERSION pDXSGetVersion;
  447. BOOL bFound = FALSE;
  448. LoadString(NULL, IDS_NOTFOUND, pSysInfo->m_szDirectXVersionLong, 100);
  449. if (!BIsPlatformNT() && GetDxSetupFolder(szSetupPath))
  450. {
  451. lstrcat(szSetupPath, TEXT("\\dsetup.dll"));
  452. hInstDSetup = LoadLibrary(szSetupPath);
  453. if (hInstDSetup != NULL)
  454. {
  455. pDXSGetVersion = (LPDXSETUPGETVERSION)GetProcAddress(hInstDSetup,
  456. "DirectXSetupGetVersion");
  457. if (pDXSGetVersion != NULL)
  458. {
  459. DWORD dwVersion = 0;
  460. DWORD dwRevision = 0;
  461. if (pDXSGetVersion(&dwVersion, &dwRevision) != 0)
  462. {
  463. wsprintf(pSysInfo->m_szDirectXVersion, TEXT("%d.%02d.%02d.%04d"),
  464. HIWORD(dwVersion), LOWORD(dwVersion),
  465. HIWORD(dwRevision), LOWORD(dwRevision));
  466. bFound = TRUE;
  467. }
  468. }
  469. FreeLibrary(hInstDSetup);
  470. }
  471. }
  472. if (!bFound)
  473. {
  474. // Look in registry for DX version instead
  475. HKEY hkey;
  476. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
  477. 0, KEY_READ, &hkey))
  478. {
  479. cbData = 100;
  480. RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)pSysInfo->m_szDirectXVersion, &cbData);
  481. RegCloseKey(hkey);
  482. if (lstrlen(pSysInfo->m_szDirectXVersion) > 6 &&
  483. lstrlen(pSysInfo->m_szDirectXVersion) < 20)
  484. {
  485. bFound = TRUE;
  486. }
  487. }
  488. }
  489. if (!bFound && !BIsPlatformNT())
  490. {
  491. // Report ddraw.dll version instead
  492. // (except on Win2000, where ddraw.dll version is way different from DX version)
  493. TCHAR szDDrawPath[MAX_PATH];
  494. GetSystemDirectory(szDDrawPath, MAX_PATH);
  495. lstrcat(szDDrawPath, TEXT("\\ddraw.dll"));
  496. GetFileVersion(szDDrawPath, pSysInfo->m_szDirectXVersion, NULL, NULL, NULL);
  497. }
  498. if (lstrlen(pSysInfo->m_szDirectXVersion) > 0)
  499. {
  500. // Bug 18501: Add "friendly" version of version name
  501. DWORD dwMajor;
  502. DWORD dwMinor;
  503. DWORD dwRevision;
  504. DWORD dwBuild;
  505. TCHAR szFriendly[100];
  506. lstrcpy(szFriendly, TEXT(""));
  507. if( _stscanf(pSysInfo->m_szDirectXVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild) != 4 )
  508. {
  509. dwMajor = 0;
  510. dwMinor = 0;
  511. dwRevision = 0;
  512. dwBuild = 0;
  513. }
  514. wsprintf(pSysInfo->m_szDirectXVersion, TEXT("%d.%02d.%02d.%04d"), dwMajor, dwMinor, dwRevision, dwBuild);
  515. // According to http://xevious/directx/versions.htm:
  516. // 4.02.xx.xxxx is DX1
  517. // 4.03.xx.xxxx is DX2
  518. // 4.04.xx.xxxx is DX3
  519. // 4.05.xx.xxxx is DX5
  520. // 4.06.00.xxxx is DX6
  521. // 4.06.02.xxxx is DX6.1
  522. // 4.06.03.xxxx is DX6.1A
  523. // 4.07.00.xxxx is DX7.0
  524. // 4.07.01.xxxx is DX7.1
  525. // Beyond that, who knows...
  526. pSysInfo->m_dwDirectXVersionMajor = 0;
  527. pSysInfo->m_dwDirectXVersionMinor = 0;
  528. pSysInfo->m_cDirectXVersionLetter = TEXT(' ');
  529. if (dwMajor == 4 && dwMinor == 2)
  530. {
  531. lstrcpy(szFriendly, TEXT("DirectX 1"));
  532. pSysInfo->m_dwDirectXVersionMajor = 1;
  533. }
  534. if (dwMajor == 4 && dwMinor == 3)
  535. {
  536. lstrcpy(szFriendly, TEXT("DirectX 2"));
  537. pSysInfo->m_dwDirectXVersionMajor = 2;
  538. }
  539. if (dwMajor == 4 && dwMinor == 4)
  540. {
  541. lstrcpy(szFriendly, TEXT("DirectX 3"));
  542. pSysInfo->m_dwDirectXVersionMajor = 3;
  543. }
  544. if (dwMajor == 4 && dwMinor == 5)
  545. {
  546. lstrcpy(szFriendly, TEXT("DirectX 5"));
  547. pSysInfo->m_dwDirectXVersionMajor = 5;
  548. }
  549. else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 0)
  550. {
  551. lstrcpy(szFriendly, TEXT("DirectX 6"));
  552. pSysInfo->m_dwDirectXVersionMajor = 6;
  553. }
  554. else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 2)
  555. {
  556. lstrcpy(szFriendly, TEXT("DirectX 6.1"));
  557. pSysInfo->m_dwDirectXVersionMajor = 6;
  558. pSysInfo->m_dwDirectXVersionMinor = 1;
  559. }
  560. else if (dwMajor == 4 && dwMinor == 6 && dwRevision == 3)
  561. {
  562. lstrcpy(szFriendly, TEXT("DirectX 6.1a"));
  563. pSysInfo->m_dwDirectXVersionMajor = 6;
  564. pSysInfo->m_dwDirectXVersionMinor = 1;
  565. pSysInfo->m_cDirectXVersionLetter = TEXT('a');
  566. }
  567. else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 0 && dwBuild == 716)
  568. {
  569. lstrcpy(szFriendly, TEXT("DirectX 7.0a"));
  570. pSysInfo->m_dwDirectXVersionMajor = 7;
  571. pSysInfo->m_cDirectXVersionLetter = TEXT('a');
  572. }
  573. else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 0)
  574. {
  575. lstrcpy(szFriendly, TEXT("DirectX 7.0"));
  576. pSysInfo->m_dwDirectXVersionMajor = 7;
  577. }
  578. else if (dwMajor == 4 && dwMinor == 7 && dwRevision == 1)
  579. {
  580. lstrcpy(szFriendly, TEXT("DirectX 7.1"));
  581. pSysInfo->m_dwDirectXVersionMajor = 7;
  582. pSysInfo->m_dwDirectXVersionMinor = 1;
  583. }
  584. else if (dwMajor == 4 && dwMinor == 8 && dwRevision == 0 )
  585. {
  586. lstrcpy(szFriendly, TEXT("DirectX 8.0"));
  587. pSysInfo->m_dwDirectXVersionMajor = 8;
  588. }
  589. else if (dwMajor == 4 && dwMinor == 8 && dwRevision == 1 )
  590. {
  591. lstrcpy(szFriendly, TEXT("DirectX 8.1"));
  592. pSysInfo->m_dwDirectXVersionMajor = 8;
  593. pSysInfo->m_dwDirectXVersionMinor = 1;
  594. }
  595. else if (dwMajor == 4 && dwMinor == 9 )
  596. {
  597. lstrcpy(szFriendly, TEXT("DirectX 9.0"));
  598. pSysInfo->m_dwDirectXVersionMajor = 9;
  599. pSysInfo->m_dwDirectXVersionMinor = 0;
  600. }
  601. else
  602. {
  603. pSysInfo->m_dwDirectXVersionMajor = dwMinor;
  604. pSysInfo->m_dwDirectXVersionMinor = dwRevision;
  605. }
  606. if (lstrlen(szFriendly) > 0)
  607. wsprintf(pSysInfo->m_szDirectXVersionLong, TEXT("%s (%s)"), szFriendly, pSysInfo->m_szDirectXVersion);
  608. else
  609. lstrcpy(pSysInfo->m_szDirectXVersionLong, pSysInfo->m_szDirectXVersion);
  610. }
  611. // 24169: Detect setup switches
  612. pSysInfo->m_dwSetupParam = 0xffffffff;
  613. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"), 0, KEY_READ, &hKey))
  614. {
  615. cbData = sizeof(DWORD);
  616. RegQueryValueEx(hKey, TEXT("Command"), NULL, &ulType, (BYTE*)&(pSysInfo->m_dwSetupParam), &cbData);
  617. RegCloseKey(hKey);
  618. }
  619. // 48330: add debug level in txt file
  620. GetDXDebugLevels( pSysInfo );
  621. switch (pSysInfo->m_dwSetupParam)
  622. {
  623. case 0xffffffff: lstrcpy(pSysInfo->m_szSetupParam, TEXT("Not found")); break;
  624. case 0: lstrcpy(pSysInfo->m_szSetupParam, TEXT("None")); break;
  625. case 1: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Silent")); break;
  626. case 2: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/WindowsUpdate")); break;
  627. case 3: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/PackageInstall")); break;
  628. case 4: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Silent /Reboot")); break;
  629. case 5: lstrcpy(pSysInfo->m_szSetupParam, TEXT("/Reboot")); break;
  630. default:
  631. wsprintf(pSysInfo->m_szSetupParam, TEXT("Unknown Switch (%d)"), pSysInfo->m_dwSetupParam);
  632. break;
  633. }
  634. GetFileSystemStoringD3D8Cache( pSysInfo->m_szD3D8CacheFileSystem );
  635. pSysInfo->m_bNetMeetingRunning = IsNetMeetingRunning();
  636. }
  637. /****************************************************************************
  638. *
  639. * GetProcessorDescription
  640. *
  641. ****************************************************************************/
  642. VOID GetProcessorDescription(BOOL bNT, SYSTEM_INFO* psi, TCHAR* pszDesc, BOOL* pbNoCPUSpeed)
  643. {
  644. OSVERSIONINFO OSVersionInfo;
  645. SYSTEM_INFO SystemInfo;
  646. OSVersionInfo.dwOSVersionInfoSize = sizeof OSVersionInfo;
  647. GetVersionEx(&OSVersionInfo);
  648. GetSystemInfo(&SystemInfo);
  649. GetProcessorVendorNameAndType(OSVersionInfo, SystemInfo, pszDesc, pbNoCPUSpeed);
  650. if (SystemInfo.dwNumberOfProcessors > 1)
  651. {
  652. TCHAR szFmt[100];
  653. TCHAR szNumProc[100];
  654. LoadString(NULL, IDS_NUMPROCFMT, szFmt, 100);
  655. wsprintf(szNumProc, szFmt, SystemInfo.dwNumberOfProcessors);
  656. lstrcat(pszDesc, szNumProc);
  657. }
  658. }
  659. /****************************************************************************
  660. *
  661. * GetProcessorVendorNameAndType
  662. *
  663. ****************************************************************************/
  664. VOID GetProcessorVendorNameAndType(OSVERSIONINFO& OSVersionInfo,
  665. SYSTEM_INFO& SystemInfo, TCHAR* pszProcessor, BOOL* pbNoCPUSpeed)
  666. {
  667. TCHAR szVendorName[50];
  668. TCHAR szLongName[50];
  669. TCHAR szDesc[100];
  670. BOOL bIsMMX = FALSE;
  671. BOOL bIs3DNow = FALSE;
  672. // 10/27/98(RichGr): Intel's Katmai New Instructions (KNI).
  673. BOOL bIsKatmai = FALSE; /* 2/04/99(RichGr): Pentium III/Streaming SIMD Instrucs*/
  674. PROCESSOR_ID_NUMBERS ProcessorIdNumbers;
  675. DWORD dwKBytesLevel2Cache;
  676. DWORD dwIntelBrandIndex;
  677. memset(&szVendorName[0], 0, sizeof szVendorName);
  678. memset(&szLongName[0], 0, sizeof szLongName);
  679. memset(&ProcessorIdNumbers, 0, sizeof ProcessorIdNumbers);
  680. // 6/21/99(RichGr): On the Intel, we can now interpret a 1-byte descriptor to give us
  681. // the size of the Level 2 cache, if present.
  682. dwKBytesLevel2Cache = 0;
  683. // 4/26/01(RichGr): On the Intel, we have a new 1-byte index that specifies the brand.
  684. dwIntelBrandIndex = 0;
  685. if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS // Win9x
  686. || (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT // WinNT
  687. && SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL))
  688. {
  689. GetVendorNameAndCaps(szVendorName, szLongName, ProcessorIdNumbers, &bIsMMX, &bIs3DNow,
  690. &bIsKatmai, &dwKBytesLevel2Cache, &dwIntelBrandIndex, pbNoCPUSpeed);
  691. if (szLongName[0]) // Use this if there's anything there.
  692. lstrcpy(pszProcessor, szLongName);
  693. else
  694. {
  695. lstrcpy(pszProcessor, szVendorName);
  696. lstrcat(pszProcessor, TEXT(" "));
  697. if ( !lstrcmp(szVendorName, TEXT("Intel")))
  698. {
  699. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_386)
  700. lstrcat(pszProcessor, TEXT("80386"));
  701. else
  702. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
  703. lstrcat(pszProcessor, TEXT("80486"));
  704. else
  705. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
  706. {
  707. // 6/21/99(RichGr): A lot of this code is now derived from \\muroc\slm\proj\win\src\shell\cpls\system\sysset.c.
  708. switch ( ProcessorIdNumbers.dwFamily )
  709. {
  710. // We should, of course, never hit these - they've been dealt with above.
  711. case 0:
  712. case 1:
  713. case 2:
  714. case 3:
  715. case 4:
  716. lstrcat(pszProcessor, TEXT("80486"));
  717. break;
  718. case 5:
  719. lstrcat(pszProcessor, TEXT("Pentium"));
  720. if ( ProcessorIdNumbers.dwModel == 3 )
  721. lstrcat(pszProcessor, TEXT(" Overdrive"));
  722. break;
  723. case 6:
  724. switch ( ProcessorIdNumbers.dwModel )
  725. {
  726. //
  727. //Model 1 and 2 are Pentium Pro
  728. //
  729. case 0:
  730. case 1:
  731. case 2:
  732. lstrcat(pszProcessor, TEXT("Pentium Pro"));
  733. break;
  734. //
  735. //Model 3 and 4 are Pentium II
  736. //
  737. case 3:
  738. case 4:
  739. lstrcat(pszProcessor, TEXT("Pentium II"));
  740. break;
  741. //
  742. //Model 5 is either Pentium II or Celeron (depending on if the chip
  743. //has L2 cache or not)
  744. //
  745. case 5:
  746. if ( dwKBytesLevel2Cache == 0 )
  747. //
  748. //No L2 cache so it is a Celeron
  749. //
  750. lstrcat(pszProcessor, TEXT("Celeron"));
  751. else
  752. //
  753. //L2 cache so it is at least a Pentium II.
  754. //
  755. if ( bIsKatmai )
  756. lstrcat(pszProcessor, TEXT("Pentium III"));
  757. else
  758. lstrcat(pszProcessor, TEXT("Pentium II"));
  759. break;
  760. case 6:
  761. if ( dwKBytesLevel2Cache > 128 )
  762. //
  763. //L2 cache > 128K so it is at least a Pentium II
  764. //
  765. if ( bIsKatmai )
  766. lstrcat(pszProcessor, TEXT("Pentium III"));
  767. else
  768. lstrcat(pszProcessor, TEXT("Pentium II"));
  769. else
  770. //
  771. //L2 cache <= 128K so it is a Celeron
  772. //
  773. lstrcat(pszProcessor, TEXT("Celeron"));
  774. break;
  775. case 7:
  776. lstrcat(pszProcessor, TEXT("Pentium III"));
  777. break;
  778. default:
  779. if ( bIsKatmai )
  780. {
  781. // 4/26/01(RichGr): Pentium III Xeons and later have a one-byte Brand Index that we can use.
  782. // More recent machines have a Brand String as well.
  783. // see ftp://download.intel.com/design/Pentium4/manuals/24547103.pdf
  784. if (dwIntelBrandIndex == 1)
  785. lstrcat(pszProcessor, TEXT("Celeron"));
  786. else
  787. if (dwIntelBrandIndex == 0 || dwIntelBrandIndex == 2)
  788. lstrcat(pszProcessor, TEXT("Pentium III"));
  789. else
  790. if (dwIntelBrandIndex == 3)
  791. lstrcat(pszProcessor, TEXT("Pentium III Xeon"));
  792. else
  793. if (dwIntelBrandIndex == 8)
  794. lstrcat(pszProcessor, TEXT("Pentium 4"));
  795. else
  796. lstrcat(pszProcessor, TEXT("Pentium"));
  797. }
  798. else
  799. lstrcat(pszProcessor, TEXT("Pentium II"));
  800. break;
  801. }
  802. break;
  803. default:
  804. wsprintf( szDesc, TEXT("x86 Family %u Model %u Stepping %u"), ProcessorIdNumbers.dwFamily, ProcessorIdNumbers.dwModel,
  805. ProcessorIdNumbers.dwSteppingID );
  806. lstrcat(pszProcessor, szDesc);
  807. break;
  808. }
  809. }
  810. }
  811. else
  812. if ( !lstrcmp(szVendorName, TEXT("AMD")))
  813. {
  814. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
  815. lstrcat(pszProcessor, TEXT("Am486 or Am5X86"));
  816. else
  817. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
  818. {
  819. if (ProcessorIdNumbers.dwFamily == 5)
  820. {
  821. if (ProcessorIdNumbers.dwModel < 6)
  822. {
  823. wsprintf(szDesc, TEXT("K5 (Model %d)"), ProcessorIdNumbers.dwModel);
  824. lstrcat(pszProcessor, szDesc);
  825. }
  826. else
  827. {
  828. lstrcat(pszProcessor, TEXT("K6"));
  829. }
  830. }
  831. else
  832. {
  833. wsprintf(szDesc, TEXT("K%d (Model %d)"), ProcessorIdNumbers.dwFamily, ProcessorIdNumbers.dwModel);
  834. lstrcat(pszProcessor, szDesc);
  835. }
  836. }
  837. }
  838. else
  839. if ( !lstrcmp(szVendorName, TEXT("Cyrix")))
  840. {
  841. if (ProcessorIdNumbers.dwFamily == 4)
  842. {
  843. if (ProcessorIdNumbers.dwModel == 4)
  844. lstrcat(pszProcessor, TEXT("MediaGX"));
  845. }
  846. else
  847. if (ProcessorIdNumbers.dwFamily == 5)
  848. {
  849. if (ProcessorIdNumbers.dwModel == 2)
  850. lstrcat(pszProcessor, TEXT("6x86"));
  851. else
  852. if (ProcessorIdNumbers.dwModel == 4)
  853. lstrcat(pszProcessor, TEXT("GXm"));
  854. }
  855. else
  856. if (ProcessorIdNumbers.dwFamily == 6)
  857. {
  858. lstrcat(pszProcessor, TEXT("6x86MX"));
  859. }
  860. }
  861. else
  862. if ( !lstrcmp(szVendorName, TEXT("IDT")))
  863. {
  864. // 4/21/98(RichGr): There's only 1 chip available at present.
  865. // 7/07/98(RichGr): Now there are two chips.
  866. // Note: Although the C6 is MMX-compatible, Intel does not allow IDT to display the word "MMX"
  867. // in association with the name IDT, so we'll skip that.
  868. // See http://www.winchip.com/ for more info.
  869. if (ProcessorIdNumbers.dwFamily == 5)
  870. {
  871. if (ProcessorIdNumbers.dwModel == 4)
  872. lstrcat(pszProcessor, TEXT("WinChip C6"));
  873. else
  874. if (ProcessorIdNumbers.dwModel >= 8) // 7/07/98(RichGr): Assume later models have the same feature.
  875. lstrcat(pszProcessor, TEXT("WinChip 2"));
  876. }
  877. else
  878. lstrcat(pszProcessor, TEXT("WinChip"));
  879. }
  880. else
  881. {
  882. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_486)
  883. lstrcat(pszProcessor, TEXT("486"));
  884. else
  885. if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
  886. {
  887. if (ProcessorIdNumbers.dwFamily == 5)
  888. lstrcat(pszProcessor, TEXT("P5"));
  889. else
  890. if (ProcessorIdNumbers.dwFamily == 6)
  891. lstrcat(pszProcessor, TEXT("P6"));
  892. else
  893. lstrcat(pszProcessor, TEXT("P5"));
  894. }
  895. }
  896. }
  897. if (bIsKatmai
  898. && !lstrcmp(szVendorName, TEXT("Intel")))
  899. ;
  900. else
  901. {
  902. if (bIsMMX || bIs3DNow)
  903. lstrcat(pszProcessor, TEXT(", "));
  904. if (bIsMMX)
  905. lstrcat(pszProcessor, TEXT(" MMX"));
  906. if (bIs3DNow)
  907. {
  908. if (bIsMMX)
  909. lstrcat(pszProcessor, TEXT(", "));
  910. lstrcat(pszProcessor, TEXT(" 3DNow"));
  911. }
  912. }
  913. }
  914. else
  915. if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) // WinNT
  916. {
  917. if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
  918. {
  919. lstrcpy(pszProcessor, TEXT("IA64 "));
  920. }
  921. else
  922. if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
  923. {
  924. lstrcpy(pszProcessor, TEXT("AMD64 "));
  925. }
  926. else
  927. lstrcpy(pszProcessor, TEXT("Unknown "));
  928. }
  929. }
  930. /****************************************************************************
  931. *
  932. * GetVendorNameAndCaps
  933. *
  934. ****************************************************************************/
  935. VOID GetVendorNameAndCaps(TCHAR* pszVendorName, TCHAR* pszLongName,
  936. PROCESSOR_ID_NUMBERS& ProcessorIdNumbers, BOOL* pbIsMMX, BOOL* pbIs3DNow, BOOL* pbIsKatmai, /*Pentium III/Streaming SIMD Instrucs*/
  937. LPDWORD pdwKBytesLevel2Cache, LPDWORD pdwIntelBrandIndex, BOOL* pbNoCPUSpeed)
  938. {
  939. CHAR szVendorLabel[13];
  940. CHAR szLongName[50];
  941. DWORD dwFamilyModelStep;
  942. BOOL bCPUID_works;
  943. DWORD dwFeaturesFlags;
  944. BYTE byteCacheDescriptors[4] = {0,0,0,0};
  945. DWORD dwIntelBrandIndex;
  946. PCHAR psz;
  947. memset(&szVendorLabel[0], 0, sizeof szVendorLabel);
  948. memset(&szLongName[0], 0, sizeof szLongName);
  949. dwFamilyModelStep = 0;
  950. dwFeaturesFlags = 0;
  951. *pbIsMMX = FALSE;
  952. *pbIs3DNow = FALSE;
  953. *pbIsKatmai = FALSE; /* 2/04/99(RichGr): Pentium III/Streaming SIMD Instrucs*/
  954. bCPUID_works = FALSE;
  955. *pdwKBytesLevel2Cache = 0;
  956. dwIntelBrandIndex = 0;
  957. #ifdef _X86_
  958. // Determine whether CPUID instruction can be executed.
  959. __asm
  960. {
  961. // CPUID trashes lots - save everything. Also, Retail build makes assumptions about reg values.
  962. pushad
  963. // Load value of flags register into eax.
  964. pushfd
  965. pop eax
  966. // Save original flags register value in ebx.
  967. mov ebx, eax
  968. // Alter bit 21 and write new value into flags register.
  969. xor eax, 0x00200000
  970. push eax
  971. popfd
  972. // Retrieve the new value of the flags register.
  973. pushfd
  974. pop eax
  975. // Compare with the original value.
  976. xor eax, ebx
  977. // If the new value is the same as the old, the CPUID instruction cannot
  978. // be executed. Most 486s and all Pentium-class processors should be able
  979. // to execute CPUID.
  980. // 4/21/98(RichGr): One Cyrix 6x86 machine in the Apps Lab (AP_LAREDO) can't execute
  981. // CPUID in ring 3, for no apparent reason. Another similar machine works fine.
  982. je done1
  983. mov bCPUID_works, 1 // bCPUID_works = TRUE
  984. // Execute CPUID with eax = 0 to get Vendor Label.
  985. xor eax, eax
  986. _emit 0x0F // CPUID
  987. _emit 0xA2
  988. // Move Vendor Label from regs to string.
  989. mov dword ptr[szVendorLabel + 0], ebx
  990. mov dword ptr[szVendorLabel + 4], edx
  991. mov dword ptr[szVendorLabel + 8], ecx
  992. // Execute CPUID with eax = 1 to pick up Family, Model and Stepping ID, and to check for MMX support.
  993. mov eax, 1
  994. _emit 0x0F // CPUID
  995. _emit 0xA2
  996. // Save Family/Model/Stepping ID.
  997. mov dwFamilyModelStep, eax
  998. // 4/26/01(RichGr): Save Brand Index (new for PIII Xeons and after). This is the low byte only.
  999. mov dwIntelBrandIndex, ebx
  1000. // 2/04/99(RichGr): Save Features Flags.
  1001. mov dwFeaturesFlags, edx
  1002. // 6/21/99(RichGr): Execute CPUID with eax == 2 to pick up descriptor for size of Level 2 cache.
  1003. mov eax, 2
  1004. _emit 0x0F // CPUID
  1005. _emit 0xA2
  1006. // Save Level 2 cache size descriptor in byte 0, together with 3 other cache descriptors in bytes 1 - 3.
  1007. // See \\muroc\slm\proj\win\src\shell\cpls\system\sysset.c and cpuid.asm,
  1008. // and Intel Architecture Software Developer's Manual (1997), volume 2, p. 105.
  1009. mov dword ptr[byteCacheDescriptors], edx
  1010. done1:
  1011. // Restore everything.
  1012. popad
  1013. }
  1014. #endif // _X86_
  1015. dwIntelBrandIndex &= 0xFF;
  1016. *pdwIntelBrandIndex = dwIntelBrandIndex;
  1017. // 6/21/99(RichGr): The following values were helpfully provided by David Penley(Intel):
  1018. /* 40H No L2 Cache
  1019. 41H L2 Unified cache: 128K Bytes, 4-way set associative, 32 byte line size
  1020. 42H L2 Unified cache: 256K Bytes, 4-way set associative, 32 byte line size
  1021. 43H L2 Unified cache: 512K Bytes, 4-way set associative, 32 byte line size
  1022. 44H L2 Unified cache: 1M Byte, 4-way set associative, 32 byte line size
  1023. 45H L2 Unified cache: 2M Byte, 4-way set associative, 32 byte line size
  1024. Updated manuals can be had at... http://developer.intel.com/design/pentiumiii/xeon/manuals/
  1025. */
  1026. if (szVendorLabel[0])
  1027. {
  1028. if ( !strcmp(&szVendorLabel[0], "GenuineIntel"))
  1029. {
  1030. lstrcpy(pszVendorName, TEXT("Intel"));
  1031. // 4/29/01: This doesn't cover the Pentium 4, but we don't need cache size
  1032. // for it at present.
  1033. if ( byteCacheDescriptors[0] == 0x40 )
  1034. *pdwKBytesLevel2Cache = 0;
  1035. else
  1036. if ( byteCacheDescriptors[0] == 0x41 )
  1037. *pdwKBytesLevel2Cache = 128;
  1038. else
  1039. if ( byteCacheDescriptors[0] == 0x42 )
  1040. *pdwKBytesLevel2Cache = 256;
  1041. else
  1042. if ( byteCacheDescriptors[0] == 0x43 )
  1043. *pdwKBytesLevel2Cache = 512;
  1044. else
  1045. if ( byteCacheDescriptors[0] == 0x44 )
  1046. *pdwKBytesLevel2Cache = 1024;
  1047. else
  1048. if ( byteCacheDescriptors[0] == 0x45 )
  1049. *pdwKBytesLevel2Cache = 2048;
  1050. }
  1051. else
  1052. if ( !strcmp(&szVendorLabel[0], "AuthenticAMD"))
  1053. lstrcpy(pszVendorName, TEXT("AMD"));
  1054. else
  1055. if ( !strcmp(&szVendorLabel[0], "CyrixInstead"))
  1056. lstrcpy(pszVendorName, TEXT("Cyrix"));
  1057. else
  1058. if ( !strcmp(&szVendorLabel[0], "CentaurHauls"))
  1059. lstrcpy(pszVendorName, TEXT("IDT"));
  1060. else
  1061. {
  1062. #ifdef UNICODE
  1063. MultiByteToWideChar(CP_ACP, 0, szVendorLabel, -1, pszVendorName, 50);
  1064. #else
  1065. lstrcpy(pszVendorName, szVendorLabel);
  1066. #endif
  1067. }
  1068. }
  1069. else
  1070. lstrcpy(pszVendorName, TEXT("Intel"));
  1071. if (dwFamilyModelStep)
  1072. {
  1073. ProcessorIdNumbers.dwType = (dwFamilyModelStep & 0x00003000) >> 12;
  1074. ProcessorIdNumbers.dwFamily = (dwFamilyModelStep & 0x00000F00) >> 8;
  1075. ProcessorIdNumbers.dwModel = (dwFamilyModelStep & 0x000000F0) >> 4;
  1076. ProcessorIdNumbers.dwSteppingID = dwFamilyModelStep & 0x0000000F;
  1077. }
  1078. if (dwFeaturesFlags)
  1079. {
  1080. // Check whether MMX is supported.
  1081. if (dwFeaturesFlags & 0x00800000)
  1082. *pbIsMMX = TRUE;
  1083. // 2/04/99(RichGr): Check whether Katmai is supported (aka Pentium III/Streaming SIMD Instrucs).
  1084. if ((dwFeaturesFlags & 0x02000000)
  1085. && !lstrcmp(pszVendorName, TEXT("Intel")))
  1086. *pbIsKatmai = TRUE;
  1087. }
  1088. // 7/07/98(RichGr): Added for IDT's Long Name feature.
  1089. // 9/10/98(RichGr): Attempt this on all processors, and skip if there's nothing there.
  1090. #ifdef _X86_
  1091. if (bCPUID_works)
  1092. {
  1093. __asm
  1094. {
  1095. // CPUID trashes lots - save everything. Also, Retail build makes assumptions about reg values.
  1096. pushad
  1097. // 9/10/98(RichGr): Check for extended CPUID support.
  1098. mov eax, 0x80000000
  1099. _emit 0x0F // CPUID
  1100. _emit 0xA2
  1101. cmp eax, 0x80000001 // Jump if no extended CPUID.
  1102. jb done2
  1103. // Check for AMD's 3DNow feature. Note: They believe this may be added to other non-AMD CPUs as well.
  1104. // Adapted from one of AMD's webpages at: http://www.amd.com/3dsdk/library/macros/amddcpu.html
  1105. mov eax, 0x80000001
  1106. _emit 0x0F // CPUID
  1107. _emit 0xA2
  1108. test edx, 0x80000000 // Check for 3DNow flag.
  1109. jz LongName
  1110. mov eax, pbIs3DNow
  1111. mov dword ptr[eax], 1 // bIs3DNow = TRUE
  1112. // Execute CPUID with eax = 0x80000002 thru 0x80000004 to get 48-byte Long Name (for instance: "IDT WinChip 2-3D").
  1113. LongName:
  1114. mov esi, 0x80000001
  1115. xor edi, edi
  1116. NameLoop:
  1117. inc esi
  1118. mov eax,esi
  1119. cmp eax, 0x80000004
  1120. jg done2
  1121. _emit 0x0F // CPUID
  1122. _emit 0xA2
  1123. // 9/10/98(RichGr): The first time thru, check that there's valid alphanumeric data.
  1124. cmp esi, 0x80000002 // First time?
  1125. jg Move // If not, skip this test.
  1126. cmp al, 0x20 // If first character < ' ', skip.
  1127. jl done2
  1128. cmp al, 0x7a // If first character > 'z', skip.
  1129. jg done2
  1130. // Move Long Name from regs to string.
  1131. Move:
  1132. mov dword ptr[szLongName + edi + 0x0], eax
  1133. mov dword ptr[szLongName + edi + 0x4], ebx
  1134. mov dword ptr[szLongName + edi + 0x8], ecx
  1135. mov dword ptr[szLongName + edi + 0x0c], edx
  1136. add edi, 0x10
  1137. jmp NameLoop
  1138. done2:
  1139. // Restore everything.
  1140. popad
  1141. }
  1142. if ( szLongName[0] )
  1143. {
  1144. // Move beyond Intel's leading spaces.
  1145. for (psz = &szLongName[0]; *psz == ' '; psz++);
  1146. if (*psz)
  1147. {
  1148. #ifdef UNICODE
  1149. MultiByteToWideChar(CP_ACP, 0, psz, -1, pszLongName, 50);
  1150. #else
  1151. strcpy(pszLongName, psz);
  1152. #endif
  1153. // 4/29/01(RichGr): Intel Brand Strings show the maximum rated CPU Speed, no need for further detection.
  1154. if ( !lstrcmp(pszVendorName, TEXT("Intel")))
  1155. *pbNoCPUSpeed = FALSE;
  1156. }
  1157. }
  1158. }
  1159. #endif // _X86_
  1160. }
  1161. #ifdef _X86_
  1162. // Some static variables used by GetCPUSpeed
  1163. static int s_milliseconds;
  1164. static __int64 s_ticks;
  1165. /****************************************************************************
  1166. *
  1167. * fabs
  1168. *
  1169. ****************************************************************************/
  1170. FLOAT inline fabs(FLOAT a)
  1171. {
  1172. if (a < 0.0f)
  1173. return -a;
  1174. else
  1175. return a;
  1176. }
  1177. /****************************************************************************
  1178. *
  1179. * StartTimingCPU
  1180. *
  1181. ****************************************************************************/
  1182. int StartTimingCPU( HANDLE& hProcess, DWORD& oldclass )
  1183. {
  1184. //
  1185. // detect ability to get info
  1186. //
  1187. // 4/03/2000(RichGr): The RDTSC instruction is crashing on some older Cyrix machines,
  1188. // so wrap a __try/__except around everything.
  1189. __try
  1190. {
  1191. __asm
  1192. {
  1193. pushfd ; push extended flags
  1194. pop eax ; store eflags into eax
  1195. mov ebx, eax ; save EBX for testing later
  1196. xor eax, (1<<21) ; switch bit 21
  1197. push eax ; push eflags
  1198. popfd ; pop them again
  1199. pushfd ; push extended flags
  1200. pop eax ; store eflags into eax
  1201. cmp eax, ebx ; see if bit 21 has changed
  1202. jz no_cpuid ; make sure it's now on
  1203. }
  1204. //
  1205. // start timing
  1206. //
  1207. // 10/31/99(RichGr): Bump up the priority to real-time, drawing from ToddLa's code.
  1208. // See file:\\pyrex\user\toddla\speed.c
  1209. hProcess = GetCurrentProcess();
  1210. oldclass = GetPriorityClass(hProcess);
  1211. SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
  1212. Sleep(10);
  1213. s_milliseconds = -(int)timeGetTime();
  1214. __asm
  1215. {
  1216. lea ecx, s_ticks ; get the offset
  1217. mov dword ptr [ecx], 0 ; zero the memory
  1218. mov dword ptr [ecx+4], 0 ;
  1219. // rdtsc ; read time-stamp counter
  1220. __emit 0fh
  1221. __emit 031h
  1222. sub [ecx], eax ; store the negative
  1223. sbb [ecx+4], edx ; in the variable
  1224. }
  1225. }
  1226. __except(EXCEPTION_EXECUTE_HANDLER)
  1227. {
  1228. goto no_cpuid;
  1229. }
  1230. return 0;
  1231. no_cpuid:
  1232. // 10/31/99(RichGr): In case someone changes the code, make sure that the priority is restored
  1233. // to normal if there is an error return.
  1234. if ( hProcess && oldclass )
  1235. SetPriorityClass( hProcess, oldclass );
  1236. return -1;
  1237. }
  1238. /****************************************************************************
  1239. *
  1240. * StopTimingCPU
  1241. *
  1242. ****************************************************************************/
  1243. void StopTimingCPU( HANDLE& hProcess, DWORD& oldclass )
  1244. {
  1245. s_milliseconds += (int)timeGetTime();
  1246. __asm
  1247. {
  1248. lea ecx, s_ticks ; get the offset
  1249. // rdtsc ; read time-stamp counter
  1250. __emit 0fh
  1251. __emit 031h
  1252. add [ecx], eax ; add the tick count
  1253. adc [ecx+4], edx ;
  1254. }
  1255. // 10/31/99(RichGr): Restore the priority to normal.
  1256. if ( hProcess && oldclass )
  1257. SetPriorityClass( hProcess, oldclass );
  1258. return;
  1259. }
  1260. /****************************************************************************
  1261. *
  1262. * CalcCPUSpeed
  1263. *
  1264. ****************************************************************************/
  1265. INT CalcCPUSpeed(VOID)
  1266. {
  1267. //
  1268. // get the actual cpu speed in MHz, and
  1269. // then find the one in the CPU speed list
  1270. // that is closest
  1271. //
  1272. const struct tagCPUSPEEDS
  1273. {
  1274. float fSpeed;
  1275. int iSpeed;
  1276. } cpu_speeds[] =
  1277. {
  1278. //
  1279. // valid CPU speeds that are not integrally divisible by
  1280. // 16.67 MHz
  1281. //
  1282. { 60.00f, 60 },
  1283. { 75.00f, 75 },
  1284. { 90.00f, 90 },
  1285. { 120.00f, 120 },
  1286. { 180.00f, 180 },
  1287. };
  1288. //
  1289. // find the closest one
  1290. //
  1291. float fSpeed=((float)s_ticks)/((float)s_milliseconds*1000.0f);
  1292. int iSpeed=cpu_speeds[0].iSpeed;
  1293. float fDiff=(float)fabs(fSpeed-cpu_speeds[0].fSpeed);
  1294. for (int i=1 ; i<sizeof(cpu_speeds)/sizeof(cpu_speeds[0]) ; i++)
  1295. {
  1296. float fTmpDiff = (float)fabs(fSpeed-cpu_speeds[i].fSpeed);
  1297. if (fTmpDiff < fDiff)
  1298. {
  1299. iSpeed=cpu_speeds[i].iSpeed;
  1300. fDiff=fTmpDiff;
  1301. }
  1302. }
  1303. //
  1304. // now, calculate the nearest multiple of fIncr
  1305. // speed
  1306. //
  1307. //
  1308. // now, if the closest one is not within one incr, calculate
  1309. // the nearest multiple of fIncr speed and see if that's
  1310. // closer
  1311. //
  1312. const float fIncr=16.66666666666666666666667f;
  1313. const int iIncr=4267; // fIncr << 8
  1314. //if (fDiff > fIncr)
  1315. {
  1316. //
  1317. // get the number of fIncr quantums the speed is
  1318. //
  1319. int iQuantums = (int)((fSpeed / fIncr) + 0.5f);
  1320. float fQuantumSpeed = (float)iQuantums * fIncr;
  1321. float fTmpDiff = (float)fabs(fQuantumSpeed - fSpeed);
  1322. if (fTmpDiff < fDiff)
  1323. {
  1324. iSpeed = (iQuantums * iIncr) >> 8;
  1325. fDiff=fTmpDiff;
  1326. }
  1327. }
  1328. return iSpeed;
  1329. }
  1330. /****************************************************************************
  1331. *
  1332. * GetCPUSpeed
  1333. *
  1334. ****************************************************************************/
  1335. INT GetCPUSpeed(VOID)
  1336. {
  1337. INT nCPUSpeed;
  1338. // Try first using WMI - may not work on Win9x
  1339. nCPUSpeed = GetCPUSpeedViaWMI();
  1340. if( nCPUSpeed != -1 )
  1341. return nCPUSpeed;
  1342. // If WMI fails, then fall back on brute force cpu detection.
  1343. #undef MAX_SAMPLES
  1344. #define MAX_SAMPLES 10
  1345. int nSpeed = 0, nSpeeds[MAX_SAMPLES] = {0};
  1346. int nCount = 0, nCounts[MAX_SAMPLES] = {0};
  1347. int i, j;
  1348. HANDLE hProcess = NULL;
  1349. DWORD oldclass = 0;
  1350. // 10/12/99(RichGr): Pick up the most frequently occurring speed in a number of short samples,
  1351. // instead of waiting once for a whole second (see DxDiag).
  1352. for ( i = 0; i < MAX_SAMPLES; i++ )
  1353. {
  1354. if ( !StartTimingCPU( hProcess, oldclass ))
  1355. {
  1356. // 10/21/99(RichGr): Sleep() time is important. On a 266 MHz running Win98 under the kernel
  1357. // debugger, the original value of Sleep(10) sometimes gave a speed of 283 MHz.
  1358. // Sleep(5) to Sleep(30) were also unreliable. Sleep(40) and Sleep(50) looked good,
  1359. // and I picked (50) for a little margin.
  1360. Sleep(50);
  1361. StopTimingCPU( hProcess, oldclass );
  1362. nSpeed = CalcCPUSpeed();
  1363. for ( j = 0; j < MAX_SAMPLES; j++ )
  1364. {
  1365. if ( nSpeeds[j] == 0 || nSpeed == nSpeeds[j] ) // If the speed matches, increment the count.
  1366. {
  1367. nSpeeds[j] = nSpeed;
  1368. nCounts[j]++;
  1369. break;
  1370. }
  1371. }
  1372. }
  1373. }
  1374. // Find the speed with the biggest count.
  1375. for ( i = j = 0, nCount = 0; i < MAX_SAMPLES; i++ )
  1376. {
  1377. if ( nCounts[i] > nCount )
  1378. {
  1379. nCount = nCounts[i];
  1380. j = i;
  1381. }
  1382. }
  1383. return nSpeeds[j];
  1384. }
  1385. /****************************************************************************
  1386. *
  1387. * GetCPUSpeedViaWMI
  1388. *
  1389. ****************************************************************************/
  1390. INT GetCPUSpeedViaWMI(VOID)
  1391. {
  1392. HRESULT hr;
  1393. INT nCPUSpeed = -1;
  1394. IEnumWbemClassObject* pEnumProcessorDevs = NULL;
  1395. IWbemClassObject* pProcessorDev = NULL;
  1396. BSTR pClassName = NULL;
  1397. BSTR pPropName = NULL;
  1398. VARIANT var;
  1399. DWORD uReturned = 0;
  1400. ZeroMemory( &var, sizeof(VARIANT) );
  1401. VariantClear( &var );
  1402. if( NULL == g_pIWbemServices )
  1403. return -1;
  1404. pClassName = SysAllocString( L"Win32_Processor" );
  1405. hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
  1406. &pEnumProcessorDevs );
  1407. if( FAILED(hr) || pEnumProcessorDevs == NULL )
  1408. goto LCleanup;
  1409. // Get the first one in the list
  1410. hr = pEnumProcessorDevs->Next( 1000, // timeout in two seconds
  1411. 1, // return just one storage device
  1412. &pProcessorDev, // pointer to storage device
  1413. &uReturned ); // number obtained: one or zero
  1414. if( FAILED(hr) || uReturned == 0 || pProcessorDev == NULL )
  1415. goto LCleanup;
  1416. // 298510: MaxClockSpeed on WMI on Whistler & beyond works
  1417. if( BIsWhistler() )
  1418. pPropName = SysAllocString( L"MaxClockSpeed" );
  1419. else
  1420. pPropName = SysAllocString( L"CurrentClockSpeed" );
  1421. hr = pProcessorDev->Get( pPropName, 0L, &var, NULL, NULL );
  1422. if( FAILED(hr) )
  1423. goto LCleanup;
  1424. // Success - record VT_I4 value in nCPUSpeed
  1425. nCPUSpeed = var.lVal;
  1426. LCleanup:
  1427. VariantClear( &var );
  1428. if(pPropName)
  1429. SysFreeString(pPropName);
  1430. if(pClassName)
  1431. SysFreeString(pClassName);
  1432. if(pProcessorDev)
  1433. pProcessorDev->Release();
  1434. if(pEnumProcessorDevs)
  1435. pEnumProcessorDevs->Release();
  1436. // Return either -1 or the CPU speed we found.
  1437. return nCPUSpeed;
  1438. }
  1439. #endif // _X86_
  1440. /****************************************************************************
  1441. *
  1442. * GetComputerSystemInfo
  1443. *
  1444. ****************************************************************************/
  1445. VOID GetComputerSystemInfo(TCHAR* szSystemManufacturerEnglish, TCHAR* szSystemModelEnglish)
  1446. {
  1447. HRESULT hr;
  1448. IEnumWbemClassObject* pEnumDevices = NULL;
  1449. IWbemClassObject* pDevice = NULL;
  1450. BSTR pClassName = NULL;
  1451. BSTR pPropName = NULL;
  1452. DWORD uReturned = 0;
  1453. VARIANT var;
  1454. ZeroMemory( &var, sizeof(VARIANT) );
  1455. VariantClear( &var );
  1456. if( NULL == g_pIWbemServices )
  1457. goto LCleanup;
  1458. pClassName = SysAllocString( L"Win32_ComputerSystem" );
  1459. hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
  1460. &pEnumDevices );
  1461. if( FAILED(hr) || pEnumDevices == NULL )
  1462. goto LCleanup;
  1463. // Get the first one in the list
  1464. hr = pEnumDevices->Next( 1000, // timeout in two seconds
  1465. 1, // return just one storage device
  1466. &pDevice, // pointer to storage device
  1467. &uReturned ); // number obtained: one or zero
  1468. if( FAILED(hr) || uReturned == 0 || pDevice == NULL )
  1469. goto LCleanup;
  1470. pPropName = SysAllocString( L"Manufacturer" );
  1471. hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
  1472. if( FAILED(hr) )
  1473. goto LCleanup;
  1474. if(pPropName)
  1475. {
  1476. SysFreeString(pPropName);
  1477. pPropName = NULL;
  1478. }
  1479. if( var.bstrVal != NULL )
  1480. {
  1481. #ifdef UNICODE
  1482. _tcsncpy(szSystemManufacturerEnglish, var.bstrVal, 200);
  1483. szSystemManufacturerEnglish[199]=0;
  1484. #else
  1485. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szSystemManufacturerEnglish, 199, NULL, NULL);
  1486. #endif
  1487. }
  1488. VariantClear( &var );
  1489. pPropName = SysAllocString( L"Model" );
  1490. hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
  1491. if( FAILED(hr) )
  1492. goto LCleanup;
  1493. if(pPropName)
  1494. {
  1495. SysFreeString(pPropName);
  1496. pPropName = NULL;
  1497. }
  1498. if( var.bstrVal != NULL )
  1499. {
  1500. #ifdef UNICODE
  1501. _tcsncpy(szSystemModelEnglish, var.bstrVal, 200);
  1502. szSystemModelEnglish[199]=0;
  1503. #else
  1504. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szSystemModelEnglish, 199, NULL, NULL);
  1505. #endif
  1506. }
  1507. VariantClear( &var );
  1508. LCleanup:
  1509. if( lstrlen(szSystemModelEnglish) == 0 )
  1510. lstrcpy( szSystemModelEnglish, TEXT("n/a") );
  1511. if( lstrlen(szSystemManufacturerEnglish) == 0 )
  1512. lstrcpy( szSystemManufacturerEnglish, TEXT("n/a") );
  1513. if(pPropName)
  1514. SysFreeString(pPropName);
  1515. if(pClassName)
  1516. SysFreeString(pClassName);
  1517. if(pDevice)
  1518. pDevice->Release();
  1519. if(pEnumDevices)
  1520. pEnumDevices->Release();
  1521. return;
  1522. }
  1523. /****************************************************************************
  1524. *
  1525. * GetBIOSInfo
  1526. *
  1527. ****************************************************************************/
  1528. VOID GetBIOSInfo(TCHAR* szBIOSEnglish)
  1529. {
  1530. HRESULT hr;
  1531. IEnumWbemClassObject* pEnumDevices = NULL;
  1532. IWbemClassObject* pDevice = NULL;
  1533. BSTR pClassName = NULL;
  1534. BSTR pPropName = NULL;
  1535. DWORD uReturned = 0;
  1536. VARIANT var;
  1537. ZeroMemory( &var, sizeof(VARIANT) );
  1538. VariantClear( &var );
  1539. if( NULL == g_pIWbemServices )
  1540. goto LCleanup;
  1541. pClassName = SysAllocString( L"Win32_BIOS" );
  1542. hr = g_pIWbemServices->CreateInstanceEnum( pClassName, 0, NULL,
  1543. &pEnumDevices );
  1544. if( FAILED(hr) || pEnumDevices == NULL )
  1545. goto LCleanup;
  1546. // Get the first one in the list
  1547. hr = pEnumDevices->Next( 1000, // timeout in two seconds
  1548. 1, // return just one storage device
  1549. &pDevice, // pointer to storage device
  1550. &uReturned ); // number obtained: one or zero
  1551. if( FAILED(hr) || uReturned == 0 || pDevice == NULL )
  1552. goto LCleanup;
  1553. pPropName = SysAllocString( L"Version" );
  1554. hr = pDevice->Get( pPropName, 0L, &var, NULL, NULL );
  1555. if( FAILED(hr) )
  1556. goto LCleanup;
  1557. if( var.bstrVal != NULL )
  1558. {
  1559. #ifdef UNICODE
  1560. _tcsncpy(szBIOSEnglish, var.bstrVal, 200);
  1561. szBIOSEnglish[199]=0;
  1562. #else
  1563. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), szBIOSEnglish, 199, NULL, NULL);
  1564. #endif
  1565. }
  1566. VariantClear( &var );
  1567. LCleanup:
  1568. if( lstrlen(szBIOSEnglish) == 0 )
  1569. lstrcpy( szBIOSEnglish, TEXT("n/a") );
  1570. if(pPropName)
  1571. SysFreeString(pPropName);
  1572. if(pClassName)
  1573. SysFreeString(pClassName);
  1574. if(pDevice)
  1575. pDevice->Release();
  1576. if(pEnumDevices)
  1577. pEnumDevices->Release();
  1578. return;
  1579. }
  1580. /****************************************************************************
  1581. *
  1582. * GetDXDebugLevels
  1583. *
  1584. ****************************************************************************/
  1585. VOID GetDXDebugLevels(SysInfo* pSysInfo)
  1586. {
  1587. pSysInfo->m_bIsD3D8DebugRuntimeAvailable = IsD3D8DebugRuntimeAvailable();
  1588. pSysInfo->m_bIsD3DDebugRuntime = IsD3DDebugRuntime();
  1589. pSysInfo->m_bIsDInput8DebugRuntimeAvailable = IsDInput8DebugRuntimeAvailable();
  1590. pSysInfo->m_bIsDInput8DebugRuntime = IsDInput8DebugRuntime();
  1591. pSysInfo->m_bIsDMusicDebugRuntimeAvailable = IsDMusicDebugRuntimeAvailable();
  1592. pSysInfo->m_bIsDMusicDebugRuntime = IsDMusicDebugRuntime();
  1593. pSysInfo->m_bIsDDrawDebugRuntime = IsDDrawDebugRuntime();
  1594. pSysInfo->m_bIsDPlayDebugRuntime = IsDPlayDebugRuntime();
  1595. pSysInfo->m_bIsDSoundDebugRuntime = IsDSoundDebugRuntime();
  1596. pSysInfo->m_nD3DDebugLevel = (int) GetProfileInt(TEXT("Direct3D"), TEXT("debug"), 0);
  1597. pSysInfo->m_nDDrawDebugLevel = (int) GetProfileInt(TEXT("DirectDraw"),TEXT("debug"), 0);
  1598. pSysInfo->m_nDIDebugLevel = GetDIDebugLevel();
  1599. pSysInfo->m_nDMusicDebugLevel = GetDMDebugLevel();
  1600. pSysInfo->m_nDPlayDebugLevel = (int) GetProfileInt(TEXT("DirectPlay"), TEXT("Debug"), 0);
  1601. pSysInfo->m_nDSoundDebugLevel = GetDSDebugLevel();
  1602. }
  1603. /****************************************************************************
  1604. *
  1605. * IsD3D8DebugRuntimeAvailable
  1606. *
  1607. ****************************************************************************/
  1608. BOOL IsD3D8DebugRuntimeAvailable()
  1609. {
  1610. TCHAR szPath[MAX_PATH];
  1611. GetSystemDirectory(szPath, MAX_PATH);
  1612. lstrcat(szPath, TEXT("\\d3d8d.dll"));
  1613. if (GetFileAttributes(szPath) != -1)
  1614. return TRUE;
  1615. else
  1616. return FALSE;
  1617. }
  1618. /****************************************************************************
  1619. *
  1620. * IsD3DDebugRuntime
  1621. *
  1622. ****************************************************************************/
  1623. BOOL IsD3DDebugRuntime()
  1624. {
  1625. DWORD size;
  1626. DWORD type;
  1627. DWORD lData;
  1628. HKEY hkey;
  1629. BOOL rc;
  1630. rc = FALSE;
  1631. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_D3D, 0, KEY_READ, &hkey))
  1632. {
  1633. size = sizeof(DWORD);
  1634. if (!RegQueryValueEx(hkey, REGSTR_VAL_DDRAW_LOADDEBUGRUNTIME, NULL, &type, (LPBYTE)&lData, &size))
  1635. if (lData)
  1636. rc = TRUE;
  1637. RegCloseKey(hkey);
  1638. }
  1639. return rc;
  1640. }
  1641. /****************************************************************************
  1642. *
  1643. * GetDIDebugLevel
  1644. *
  1645. ****************************************************************************/
  1646. int GetDIDebugLevel()
  1647. {
  1648. DWORD dwDebugBits;
  1649. DWORD dwDebugBitsMax;
  1650. LONG iGenerator;
  1651. dwDebugBitsMax = 0;
  1652. dwDebugBits = GetProfileInt(TEXT("Debug"), TEXT("dinput"), 0);
  1653. if (dwDebugBits > dwDebugBitsMax)
  1654. dwDebugBitsMax = dwDebugBits;
  1655. enum
  1656. {
  1657. GENERATOR_KBD = 0,
  1658. GENERATOR_MOUSE,
  1659. GENERATOR_JOY,
  1660. GENERATOR_HID,
  1661. GENERATOR_MAX
  1662. };
  1663. static TCHAR* szGeneratorNames[] =
  1664. {
  1665. TEXT("DInput.06"),
  1666. TEXT("DInput.04"),
  1667. TEXT("DInput.08"),
  1668. TEXT("DInput.17"),
  1669. };
  1670. static BOOL bGeneratorArray[4];
  1671. for (iGenerator = 0; iGenerator < GENERATOR_MAX; iGenerator++)
  1672. {
  1673. dwDebugBits = GetProfileInt(TEXT("Debug"), szGeneratorNames[iGenerator], 0);
  1674. bGeneratorArray[iGenerator] = (dwDebugBits > 0);
  1675. if (dwDebugBits > dwDebugBitsMax)
  1676. dwDebugBitsMax = dwDebugBits;
  1677. }
  1678. if (dwDebugBitsMax & 0x20) // verbose
  1679. return 5;
  1680. if (dwDebugBitsMax & 0x02) // function entry
  1681. return 4;
  1682. if (dwDebugBitsMax & 0x01) // trace
  1683. return 3;
  1684. if (dwDebugBitsMax & 0x08) // benign
  1685. return 2;
  1686. if (dwDebugBitsMax & 0x10) // severe
  1687. return 1;
  1688. return 0;
  1689. }
  1690. /****************************************************************************
  1691. *
  1692. * IsDInput8DebugRuntimeAvailable
  1693. *
  1694. ****************************************************************************/
  1695. BOOL IsDInput8DebugRuntimeAvailable()
  1696. {
  1697. TCHAR szPath[MAX_PATH];
  1698. GetSystemDirectory(szPath, MAX_PATH);
  1699. lstrcat(szPath, TEXT("\\dinput8d.dll"));
  1700. if (GetFileAttributes(szPath) != -1)
  1701. return TRUE;
  1702. else
  1703. return FALSE;
  1704. }
  1705. /****************************************************************************
  1706. *
  1707. * IsDInput8DebugRuntime
  1708. *
  1709. ****************************************************************************/
  1710. BOOL IsDInput8DebugRuntime()
  1711. {
  1712. DWORD size;
  1713. DWORD type;
  1714. TCHAR szData[MAX_PATH];
  1715. HKEY hkey;
  1716. BOOL rc;
  1717. rc = FALSE;
  1718. if (!RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_DINPUT_DLL, 0, KEY_READ, &hkey))
  1719. {
  1720. size = sizeof(szData);
  1721. if (!RegQueryValueEx(hkey, NULL, NULL, &type, (LPBYTE)szData, &size))
  1722. {
  1723. if (_tcsstr(szData, TEXT("dinput8d.dll")))
  1724. rc = TRUE;
  1725. }
  1726. RegCloseKey(hkey);
  1727. }
  1728. return rc;
  1729. }
  1730. /****************************************************************************
  1731. *
  1732. * GetDMDebugLevel
  1733. *
  1734. ****************************************************************************/
  1735. int GetDMDebugLevel()
  1736. {
  1737. DWORD dwDMusicDebugLevel = 0;
  1738. DWORD dw;
  1739. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMBAND"), 0)) > dwDMusicDebugLevel)
  1740. dwDMusicDebugLevel = dw;
  1741. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMCOMPOS"), 0)) > dwDMusicDebugLevel)
  1742. dwDMusicDebugLevel = dw;
  1743. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMIME"), 0)) > dwDMusicDebugLevel)
  1744. dwDMusicDebugLevel = dw;
  1745. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMLOADER"), 0)) > dwDMusicDebugLevel)
  1746. dwDMusicDebugLevel = dw;
  1747. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC"), 0)) > dwDMusicDebugLevel)
  1748. dwDMusicDebugLevel = dw;
  1749. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC16"), 0)) > dwDMusicDebugLevel)
  1750. dwDMusicDebugLevel = dw;
  1751. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMUSIC32"), 0)) > dwDMusicDebugLevel)
  1752. dwDMusicDebugLevel = dw;
  1753. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSTYLE"), 0)) > dwDMusicDebugLevel)
  1754. dwDMusicDebugLevel = dw;
  1755. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSYNTH"), 0)) > dwDMusicDebugLevel)
  1756. dwDMusicDebugLevel = dw;
  1757. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DMSCRIPT"), 0)) > dwDMusicDebugLevel)
  1758. dwDMusicDebugLevel = dw;
  1759. if ((dw = GetProfileInt( TEXT("Debug"), TEXT("DSWAVE"), 0)) > dwDMusicDebugLevel)
  1760. dwDMusicDebugLevel = dw;
  1761. return dwDMusicDebugLevel;
  1762. }
  1763. /****************************************************************************
  1764. *
  1765. * IsDMusicDebugRuntimeAvailable
  1766. *
  1767. ****************************************************************************/
  1768. BOOL IsDMusicDebugRuntimeAvailable()
  1769. {
  1770. TCHAR szPath[MAX_PATH];
  1771. GetSystemDirectory(szPath, MAX_PATH);
  1772. lstrcat(szPath, TEXT("\\dmusicd.dll"));
  1773. if (GetFileAttributes(szPath) != -1)
  1774. return TRUE;
  1775. else
  1776. return FALSE;
  1777. }
  1778. /****************************************************************************
  1779. *
  1780. * IsDMusicDebugRuntime
  1781. *
  1782. ****************************************************************************/
  1783. BOOL IsDMusicDebugRuntime()
  1784. {
  1785. DWORD size;
  1786. DWORD type;
  1787. TCHAR szData[MAX_PATH];
  1788. HKEY hkey;
  1789. BOOL rc;
  1790. rc = FALSE;
  1791. if (!RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_DMUSIC_DLL, 0, KEY_READ, &hkey))
  1792. {
  1793. size = sizeof(szData);
  1794. if (!RegQueryValueEx(hkey, NULL, NULL, &type, (LPBYTE)szData, &size))
  1795. {
  1796. if (_tcsstr(szData, TEXT("dmusicd.dll")) ||
  1797. _tcsstr(szData, TEXT("DMUSICD.DLL")))
  1798. {
  1799. rc = TRUE;
  1800. }
  1801. }
  1802. RegCloseKey(hkey);
  1803. }
  1804. return rc;
  1805. }
  1806. /****************************************************************************
  1807. *
  1808. * GetDSDebugLevel
  1809. *
  1810. ****************************************************************************/
  1811. int GetDSDebugLevel()
  1812. {
  1813. DWORD dwSoundLevel = 0;
  1814. // Pick up the DMusic DLL debug settings that are controlled on the
  1815. // DSound page
  1816. HRESULT hr;
  1817. HINSTANCE hinst;
  1818. LPKSPROPERTYSET pksps = NULL;
  1819. hinst = LoadLibrary( TEXT("dsound.dll") );
  1820. if (hinst != NULL)
  1821. {
  1822. if (SUCCEEDED(hr = DirectSoundPrivateCreate(&pksps)))
  1823. {
  1824. hr = PrvGetDebugInformation(pksps, NULL, &dwSoundLevel, NULL, NULL);
  1825. pksps->Release();
  1826. }
  1827. FreeLibrary(hinst);
  1828. }
  1829. return dwSoundLevel;
  1830. }
  1831. /****************************************************************************
  1832. *
  1833. * IsFileDebug
  1834. *
  1835. ****************************************************************************/
  1836. BOOL IsFileDebug( TCHAR* szPath )
  1837. {
  1838. UINT cb;
  1839. DWORD dwHandle;
  1840. BYTE FileVersionBuffer[4096];
  1841. VS_FIXEDFILEINFO* pVersion = NULL;
  1842. cb = GetFileVersionInfoSize(szPath, &dwHandle/*ignored*/);
  1843. if (cb > 0)
  1844. {
  1845. if (cb > sizeof(FileVersionBuffer))
  1846. cb = sizeof(FileVersionBuffer);
  1847. if(GetFileVersionInfo(szPath, 0, cb, FileVersionBuffer))
  1848. {
  1849. if(VerQueryValue(FileVersionBuffer, TEXT("\\"), (VOID**)&pVersion, &cb))
  1850. {
  1851. if( pVersion )
  1852. {
  1853. if( pVersion->dwFileFlags & VS_FF_DEBUG )
  1854. return TRUE;
  1855. else
  1856. return FALSE;
  1857. }
  1858. }
  1859. }
  1860. }
  1861. return FALSE;
  1862. }
  1863. /****************************************************************************
  1864. *
  1865. * IsDDrawDebugRuntime
  1866. *
  1867. ****************************************************************************/
  1868. BOOL IsDDrawDebugRuntime()
  1869. {
  1870. TCHAR szPath[MAX_PATH];
  1871. GetSystemDirectory(szPath, MAX_PATH);
  1872. lstrcat(szPath, TEXT("\\ddraw.dll"));
  1873. return IsFileDebug(szPath);
  1874. }
  1875. /****************************************************************************
  1876. *
  1877. * IsDPlayDebugRuntime
  1878. *
  1879. ****************************************************************************/
  1880. BOOL IsDPlayDebugRuntime()
  1881. {
  1882. TCHAR szPath[MAX_PATH];
  1883. GetSystemDirectory(szPath, MAX_PATH);
  1884. lstrcat(szPath, TEXT("\\dpnet.dll"));
  1885. return IsFileDebug(szPath);
  1886. }
  1887. /****************************************************************************
  1888. *
  1889. * IsDSoundDebugRuntime
  1890. *
  1891. ****************************************************************************/
  1892. BOOL IsDSoundDebugRuntime()
  1893. {
  1894. TCHAR szPath[MAX_PATH];
  1895. GetSystemDirectory(szPath, MAX_PATH);
  1896. lstrcat(szPath, TEXT("\\dsound.dll"));
  1897. return IsFileDebug(szPath);
  1898. }
  1899. /****************************************************************************
  1900. *
  1901. * BIsDxDiag64Bit
  1902. *
  1903. ****************************************************************************/
  1904. BOOL BIsDxDiag64Bit(VOID)
  1905. {
  1906. #ifdef _WIN64
  1907. return TRUE;
  1908. #else
  1909. return FALSE;
  1910. #endif
  1911. }
  1912. /****************************************************************************
  1913. *
  1914. * GetFileSystemStoringD3D8Cache
  1915. *
  1916. ****************************************************************************/
  1917. VOID GetFileSystemStoringD3D8Cache( TCHAR* strFileSystemBuffer )
  1918. {
  1919. TCHAR strPath[MAX_PATH + 16];
  1920. BOOL bFound = FALSE;
  1921. GetSystemDirectory( strPath, MAX_PATH);
  1922. lstrcat( strPath, TEXT("\\d3d8caps.dat") );
  1923. if (GetFileAttributes(strPath) != 0xffffffff)
  1924. bFound = TRUE;
  1925. if( !bFound && BIsPlatformNT() )
  1926. {
  1927. // stolen from \dxg\d3d8\fw\fcache.cpp, OpenCacheFile().
  1928. HMODULE hShlwapi = NULL;
  1929. typedef HRESULT (WINAPI * PSHGETSPECIALFOLDERPATH) (HWND, LPTSTR, int, BOOL);
  1930. PSHGETSPECIALFOLDERPATH pSHGetSpecialFolderPath = NULL;
  1931. hShlwapi = LoadLibrary( TEXT("SHELL32.DLL") );
  1932. if( NULL != hShlwapi )
  1933. {
  1934. #ifdef UNICODE
  1935. pSHGetSpecialFolderPath = (PSHGETSPECIALFOLDERPATH)
  1936. GetProcAddress(hShlwapi,"SHGetSpecialFolderPathW");
  1937. #else
  1938. pSHGetSpecialFolderPath = (PSHGETSPECIALFOLDERPATH)
  1939. GetProcAddress(hShlwapi,"SHGetSpecialFolderPathA");
  1940. #endif
  1941. if(pSHGetSpecialFolderPath)
  1942. {
  1943. HRESULT hr;
  1944. // <user name>\Local Settings\Applicaiton Data (non roaming)
  1945. hr = pSHGetSpecialFolderPath( NULL, strPath,
  1946. CSIDL_LOCAL_APPDATA,
  1947. FALSE );
  1948. if( SUCCEEDED(hr) )
  1949. {
  1950. lstrcat( strPath, TEXT("\\d3d8caps.dat") );
  1951. if (GetFileAttributes(strPath) != 0xffffffff)
  1952. bFound = TRUE;
  1953. }
  1954. }
  1955. FreeLibrary(hShlwapi);
  1956. }
  1957. }
  1958. if( bFound )
  1959. {
  1960. DWORD dwVolumeSerialNumber;
  1961. DWORD dwMaxComponentLength;
  1962. DWORD dwFileSystemFlags;
  1963. // Trim to root dir -- "x:\"
  1964. strPath[3] = 0;
  1965. BOOL bSuccess = GetVolumeInformation( strPath, NULL, 0, &dwVolumeSerialNumber,
  1966. &dwMaxComponentLength, &dwFileSystemFlags,
  1967. strFileSystemBuffer, MAX_PATH );
  1968. if( !bSuccess )
  1969. lstrcpy( strFileSystemBuffer, TEXT("Unknown") );
  1970. }
  1971. else
  1972. {
  1973. lstrcpy( strFileSystemBuffer, TEXT("n/a") );
  1974. }
  1975. return;
  1976. }
  1977. /****************************************************************************
  1978. *
  1979. * IsNetMeetingRunning
  1980. *
  1981. ****************************************************************************/
  1982. BOOL IsNetMeetingRunning()
  1983. {
  1984. HWND hNetMeeting = FindWindow( TEXT("MPWClass"), NULL );
  1985. return( hNetMeeting != NULL );
  1986. }
  1987. //-----------------------------------------------------------------------------
  1988. // Name: DXUtil_strcmpi()
  1989. // Desc: compares 2 strings
  1990. //-----------------------------------------------------------------------------
  1991. int DXUtil_strcmpi( TCHAR* str1, TCHAR* str2 )
  1992. {
  1993. int nResult = CompareString( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, str1, -1, str2, -1 );
  1994. if( nResult == CSTR_EQUAL )
  1995. return 0;
  1996. if( nResult == CSTR_LESS_THAN )
  1997. return -1;
  1998. else
  1999. return 1;
  2000. }