Source code of Windows XP (NT5)
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.

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