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.

1721 lines
66 KiB

  1. /****************************************************************************
  2. *
  3. * File: dispinfo.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * Purpose: Gather information about the display(s) on this machine
  7. *
  8. * (C) Copyright 1998-1999 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #include <tchar.h>
  12. #include <Windows.h>
  13. #define COMPILE_MULTIMON_STUBS // for multimon.h
  14. #include <multimon.h>
  15. #define DIRECTDRAW_VERSION 5 // run on DX5 and later versions
  16. #include <ddraw.h>
  17. #include <d3d.h>
  18. #include <stdio.h>
  19. #include "sysinfo.h" // for BIsPlatformNT
  20. #include "reginfo.h"
  21. #include "dispinfo.h"
  22. #include "dispinfo8.h"
  23. #include "fileinfo.h" // for GetFileVersion
  24. #include "sysinfo.h"
  25. #include "resource.h"
  26. // Taken from DirectDraw's ddcreate.c
  27. // This is the first GUID of secondary display devices
  28. static const GUID DisplayGUID =
  29. {0x67685559,0x3106,0x11d0,{0xb9,0x71,0x0,0xaa,0x0,0x34,0x2f,0x9f}};
  30. typedef HRESULT (WINAPI* LPDIRECTDRAWCREATE)(GUID FAR *lpGUID,
  31. LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
  32. static VOID GetRegDisplayInfo9x(DisplayInfo* pDisplayInfo);
  33. static VOID GetRegDisplayInfoNT(DisplayInfo* pDisplayInfo);
  34. static HRESULT GetDirectDrawInfo(LPDIRECTDRAWCREATE pDDCreate, DisplayInfo* pDisplayInfo);
  35. static HRESULT CALLBACK EnumDevicesCallback(GUID* pGuid, LPSTR pszDesc, LPSTR pszName,
  36. D3DDEVICEDESC* pd3ddevdesc1, D3DDEVICEDESC* pd3ddevdesc2, VOID* pvContext);
  37. static BOOL FindDevice(INT iDevice, TCHAR* pszDeviceClass, TCHAR* pszDeviceClassNot, TCHAR* pszHardwareKey);
  38. static BOOL GetDeviceValue(TCHAR* pszHardwareKey, TCHAR* pszKey, TCHAR* pszValue, BYTE *buf, DWORD cbbuf);
  39. static HRESULT CheckRegistry(RegError** ppRegErrorFirst);
  40. static BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData );
  41. static VOID GetRegDisplayInfoWhistler(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage );
  42. static VOID GetRegDisplayInfoWin2k(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage );
  43. /****************************************************************************
  44. *
  45. * GetBasicDisplayInfo - Get minimal info on each display
  46. *
  47. ****************************************************************************/
  48. HRESULT GetBasicDisplayInfo(DisplayInfo** ppDisplayInfoFirst)
  49. {
  50. DisplayInfo* pDisplayInfo;
  51. DisplayInfo* pDisplayInfoNew;
  52. TCHAR szHardwareKey[MAX_PATH];
  53. TCHAR szDriver[MAX_PATH];
  54. // Check OS version. Win95 cannot use EnumDisplayDevices; Win98/NT5 can:
  55. if( BIsWinNT() || BIsWin3x() )
  56. return S_OK; // NT4 and earlier and pre-Win95 not supported
  57. if( BIsWin95() )
  58. {
  59. // Win95:
  60. if (!FindDevice(0, TEXT("Display"), NULL, szHardwareKey))
  61. return E_FAIL;
  62. pDisplayInfoNew = new DisplayInfo;
  63. if (pDisplayInfoNew == NULL)
  64. return E_OUTOFMEMORY;
  65. ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
  66. *ppDisplayInfoFirst = pDisplayInfoNew;
  67. pDisplayInfoNew->m_bCanRenderWindow = TRUE;
  68. pDisplayInfoNew->m_hMonitor = NULL; // Win95 doesn't like multimon
  69. lstrcpy(pDisplayInfoNew->m_szKeyDeviceID, szHardwareKey);
  70. if (GetDeviceValue(szHardwareKey, NULL, TEXT("Driver"), (LPBYTE)szDriver, sizeof(szDriver)))
  71. {
  72. lstrcpy(pDisplayInfoNew->m_szKeyDeviceKey, TEXT("System\\CurrentControlSet\\Services\\Class\\"));
  73. lstrcat(pDisplayInfoNew->m_szKeyDeviceKey, szDriver);
  74. }
  75. GetDeviceValue(szHardwareKey, NULL, TEXT("DeviceDesc"), (LPBYTE)pDisplayInfoNew->m_szDescription, sizeof(pDisplayInfoNew->m_szDescription));
  76. HDC hdc;
  77. hdc = GetDC(NULL);
  78. if (hdc != NULL)
  79. {
  80. wsprintf(pDisplayInfoNew->m_szDisplayMode, TEXT("%d x %d (%d bit)"),
  81. GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), GetDeviceCaps(hdc, BITSPIXEL));
  82. lstrcpy( pDisplayInfoNew->m_szDisplayModeEnglish, pDisplayInfoNew->m_szDisplayMode );
  83. ReleaseDC(NULL, hdc);
  84. pDisplayInfoNew->m_dwWidth = GetDeviceCaps(hdc, HORZRES);
  85. pDisplayInfoNew->m_dwHeight = GetDeviceCaps(hdc, VERTRES);
  86. pDisplayInfoNew->m_dwBpp = GetDeviceCaps(hdc, BITSPIXEL);
  87. }
  88. // On Win98 and NT, we get the monitor key through a call to EnumDisplayDevices.
  89. // On Win95, we have to use the registry to get the monitor key.
  90. HKEY hKey = NULL;
  91. DWORD cbData;
  92. TCHAR szKey[200];
  93. ULONG ulType;
  94. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Enum\\MONITOR\\DEFAULT_MONITOR\\0001"), 0, KEY_READ, &hKey))
  95. {
  96. cbData = sizeof szKey;
  97. if (ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("Driver"), 0, &ulType, (LPBYTE)szKey, &cbData)
  98. && szKey[0])
  99. {
  100. lstrcpy(pDisplayInfoNew->m_szMonitorKey, TEXT("System\\CurrentControlSet\\Services\\Class\\"));
  101. lstrcat(pDisplayInfoNew->m_szMonitorKey, szKey);
  102. }
  103. RegCloseKey(hKey);
  104. }
  105. }
  106. else
  107. {
  108. // Win98 / NT5:
  109. LONG iDevice = 0;
  110. DISPLAY_DEVICE dispdev;
  111. DISPLAY_DEVICE dispdev2;
  112. ZeroMemory(&dispdev, sizeof(dispdev));
  113. dispdev.cb = sizeof(dispdev);
  114. ZeroMemory(&dispdev2, sizeof(dispdev2));
  115. dispdev2.cb = sizeof(dispdev2);
  116. while (EnumDisplayDevices(NULL, iDevice, (DISPLAY_DEVICE*)&dispdev, 0))
  117. {
  118. // Mirroring drivers are for monitors that echo another display, so
  119. // they should be ignored. NT5 seems to create a mirroring driver called
  120. // "NetMeeting driver", and we definitely don't want that.
  121. if (dispdev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  122. {
  123. iDevice++;
  124. continue;
  125. }
  126. // Skip devices that aren't attached since they cause problems
  127. if ( (dispdev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0 )
  128. {
  129. iDevice++;
  130. continue;
  131. }
  132. pDisplayInfoNew = new DisplayInfo;
  133. if (pDisplayInfoNew == NULL)
  134. return E_OUTOFMEMORY;
  135. ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
  136. if (*ppDisplayInfoFirst == NULL)
  137. {
  138. *ppDisplayInfoFirst = pDisplayInfoNew;
  139. }
  140. else
  141. {
  142. for (pDisplayInfo = *ppDisplayInfoFirst;
  143. pDisplayInfo->m_pDisplayInfoNext != NULL;
  144. pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
  145. {
  146. }
  147. pDisplayInfo->m_pDisplayInfoNext = pDisplayInfoNew;
  148. }
  149. pDisplayInfoNew->m_bCanRenderWindow = TRUE;
  150. pDisplayInfoNew->m_guid = DisplayGUID;
  151. pDisplayInfoNew->m_guid.Data1 += iDevice;
  152. lstrcpy(pDisplayInfoNew->m_szDeviceName, dispdev.DeviceName);
  153. lstrcpy(pDisplayInfoNew->m_szDescription, dispdev.DeviceString);
  154. lstrcpy(pDisplayInfoNew->m_szKeyDeviceID, TEXT("Enum\\"));
  155. lstrcat(pDisplayInfoNew->m_szKeyDeviceID, dispdev.DeviceID);
  156. lstrcpy(pDisplayInfoNew->m_szKeyDeviceKey, dispdev.DeviceKey);
  157. DEVMODE devmode;
  158. ZeroMemory(&devmode, sizeof(devmode));
  159. devmode.dmSize = sizeof(devmode);
  160. if (EnumDisplaySettings(dispdev.DeviceName, ENUM_CURRENT_SETTINGS, &devmode))
  161. {
  162. pDisplayInfoNew->m_dwWidth = devmode.dmPelsWidth;
  163. pDisplayInfoNew->m_dwHeight = devmode.dmPelsHeight;
  164. pDisplayInfoNew->m_dwBpp = devmode.dmBitsPerPel;
  165. wsprintf(pDisplayInfoNew->m_szDisplayMode, TEXT("%d x %d (%d bit)"),
  166. devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel);
  167. lstrcpy( pDisplayInfoNew->m_szDisplayModeEnglish, pDisplayInfoNew->m_szDisplayMode );
  168. if (devmode.dmDisplayFrequency > 0)
  169. {
  170. TCHAR sz[10];
  171. wsprintf(sz, TEXT(" (%dHz)"), devmode.dmDisplayFrequency);
  172. lstrcat(pDisplayInfoNew->m_szDisplayMode, sz);
  173. lstrcat(pDisplayInfoNew->m_szDisplayModeEnglish, sz);
  174. pDisplayInfoNew->m_dwRefreshRate = devmode.dmDisplayFrequency;
  175. }
  176. }
  177. // Call EnumDisplayDevices a second time to get monitor name and monitor key
  178. if (EnumDisplayDevices(dispdev.DeviceName, 0, &dispdev2, 0))
  179. {
  180. lstrcpy(pDisplayInfoNew->m_szMonitorName, dispdev2.DeviceString);
  181. lstrcpy(pDisplayInfoNew->m_szMonitorKey, dispdev2.DeviceKey);
  182. }
  183. // Try to figure out the m_hMonitor
  184. pDisplayInfoNew->m_hMonitor = NULL;
  185. EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, (LPARAM) pDisplayInfoNew );
  186. iDevice++;
  187. }
  188. }
  189. // Now look for non-display devices (like 3dfx Voodoo):
  190. HKEY hkey;
  191. HKEY hkey2;
  192. DWORD dwIndex;
  193. TCHAR szName[MAX_PATH+1];
  194. DWORD cb;
  195. DWORD dwType;
  196. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("Hardware\\DirectDrawDrivers"), &hkey))
  197. {
  198. dwIndex = 0;
  199. while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szName, MAX_PATH+1))
  200. {
  201. BOOL bGoodDevice = FALSE;
  202. TCHAR szDriverName[200];
  203. HDC hdc;
  204. if (lstrcmp(szName, TEXT("3a0cfd01-9320-11cf-ac-a1-00-a0-24-13-c2-e2")) == 0 ||
  205. lstrcmp(szName, TEXT("aba52f41-f744-11cf-b4-52-00-00-1d-1b-41-26")) == 0)
  206. {
  207. // 24940: It's a Voodoo1, which will succeed GetDC (and crash later) if
  208. // no Voodoo1 is present but a Voodoo2 is. So instead of the GetDC test,
  209. // see if a V1 is present in registry's CurrentConfig.
  210. INT i;
  211. for (i=0 ; ; i++)
  212. {
  213. TCHAR szDevice[MAX_DDDEVICEID_STRING];
  214. if (FindDevice(i, NULL, TEXT("Display"), szDevice))
  215. {
  216. if (_tcsstr(szDevice, TEXT("VEN_121A&DEV_0001")) != NULL)
  217. {
  218. bGoodDevice = TRUE;
  219. break;
  220. }
  221. }
  222. else
  223. {
  224. break;
  225. }
  226. }
  227. }
  228. else
  229. {
  230. // To confirm that this is a real active DD device, create a DC with it
  231. if (ERROR_SUCCESS == RegOpenKey(hkey, szName, &hkey2))
  232. {
  233. cb = 200;
  234. if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("DriverName"), NULL, &dwType,
  235. (CONST LPBYTE)szDriverName, &cb) && cb > 0)
  236. {
  237. // I think the following "if" will always fail, but we're about to ship so
  238. // I'm being paranoid and doing everything that DDraw does:
  239. if (szDriverName[0] == '\\' && szDriverName[1] == '\\' && szDriverName[2] == '.')
  240. hdc = CreateDC( NULL, szDriverName, NULL, NULL);
  241. else
  242. hdc = CreateDC( szDriverName, NULL, NULL, NULL);
  243. if (hdc != NULL)
  244. {
  245. bGoodDevice = TRUE;
  246. DeleteDC(hdc);
  247. }
  248. }
  249. RegCloseKey(hkey2);
  250. }
  251. }
  252. if (!bGoodDevice)
  253. {
  254. dwIndex++;
  255. continue;
  256. }
  257. pDisplayInfoNew = new DisplayInfo;
  258. if (pDisplayInfoNew == NULL)
  259. return E_OUTOFMEMORY;
  260. ZeroMemory(pDisplayInfoNew, sizeof(DisplayInfo));
  261. if (*ppDisplayInfoFirst == NULL)
  262. {
  263. *ppDisplayInfoFirst = pDisplayInfoNew;
  264. }
  265. else
  266. {
  267. for (pDisplayInfo = *ppDisplayInfoFirst;
  268. pDisplayInfo->m_pDisplayInfoNext != NULL;
  269. pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
  270. {
  271. }
  272. pDisplayInfo->m_pDisplayInfoNext = pDisplayInfoNew;
  273. }
  274. pDisplayInfoNew->m_bCanRenderWindow = FALSE;
  275. pDisplayInfoNew->m_hMonitor = NULL;
  276. _stscanf(szName, TEXT("%08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x"),
  277. &pDisplayInfoNew->m_guid.Data1,
  278. &pDisplayInfoNew->m_guid.Data2,
  279. &pDisplayInfoNew->m_guid.Data3,
  280. &pDisplayInfoNew->m_guid.Data4[0],
  281. &pDisplayInfoNew->m_guid.Data4[1],
  282. &pDisplayInfoNew->m_guid.Data4[2],
  283. &pDisplayInfoNew->m_guid.Data4[3],
  284. &pDisplayInfoNew->m_guid.Data4[4],
  285. &pDisplayInfoNew->m_guid.Data4[5],
  286. &pDisplayInfoNew->m_guid.Data4[6],
  287. &pDisplayInfoNew->m_guid.Data4[7]);
  288. if (ERROR_SUCCESS == RegOpenKey(hkey, szName, &hkey2))
  289. {
  290. cb = sizeof(pDisplayInfoNew->m_szDescription);
  291. RegQueryValueEx(hkey2, TEXT("Description"), NULL, &dwType, (LPBYTE)pDisplayInfoNew->m_szDescription, &cb);
  292. cb = sizeof(pDisplayInfoNew->m_szDriverName);
  293. RegQueryValueEx(hkey2, TEXT("DriverName"), NULL, &dwType, (LPBYTE)pDisplayInfoNew->m_szDriverName, &cb);
  294. RegCloseKey(hkey2);
  295. }
  296. dwIndex++;
  297. }
  298. RegCloseKey(hkey);
  299. }
  300. return S_OK;
  301. }
  302. /****************************************************************************
  303. *
  304. * MonitorEnumProc
  305. *
  306. ****************************************************************************/
  307. BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor,
  308. LPRECT lprcMonitor, LPARAM dwData )
  309. {
  310. DisplayInfo* pDisplayInfoNew = (DisplayInfo*) dwData;
  311. // Get the MONITORINFOEX for this HMONITOR
  312. MONITORINFOEX monInfo;
  313. ZeroMemory( &monInfo, sizeof(MONITORINFOEX) );
  314. monInfo.cbSize = sizeof(MONITORINFOEX);
  315. GetMonitorInfo( hMonitor, &monInfo );
  316. // Compare the display device for this HMONITOR and the one
  317. // we just enumed with EnumDisplayDevices
  318. if( lstrcmp( monInfo.szDevice, pDisplayInfoNew->m_szDeviceName ) == 0 )
  319. {
  320. // If they match, then record the HMONITOR
  321. pDisplayInfoNew->m_hMonitor = hMonitor;
  322. return FALSE;
  323. }
  324. // Keep looking...
  325. return TRUE;
  326. }
  327. /****************************************************************************
  328. *
  329. * GetExtraDisplayInfo
  330. *
  331. ****************************************************************************/
  332. HRESULT GetExtraDisplayInfo(DisplayInfo* pDisplayInfoFirst)
  333. {
  334. HRESULT hr;
  335. DisplayInfo* pDisplayInfo;
  336. BOOL bDDAccelEnabled;
  337. BOOL bD3DAccelEnabled;
  338. BOOL bAGPEnabled;
  339. BOOL bNT = BIsPlatformNT();
  340. bDDAccelEnabled = IsDDHWAccelEnabled();
  341. bD3DAccelEnabled = IsD3DHWAccelEnabled();
  342. bAGPEnabled = IsAGPEnabled();
  343. for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
  344. pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
  345. {
  346. if (bNT)
  347. GetRegDisplayInfoNT(pDisplayInfo);
  348. else
  349. GetRegDisplayInfo9x(pDisplayInfo);
  350. pDisplayInfo->m_bDDAccelerationEnabled = bDDAccelEnabled;
  351. pDisplayInfo->m_b3DAccelerationEnabled = bD3DAccelEnabled;
  352. pDisplayInfo->m_bAGPEnabled = bAGPEnabled;
  353. if (FAILED(hr = CheckRegistry(&pDisplayInfo->m_pRegErrorFirst)))
  354. return hr;
  355. }
  356. return S_OK;
  357. }
  358. /****************************************************************************
  359. *
  360. * GetDDrawDisplayInfo
  361. *
  362. ****************************************************************************/
  363. HRESULT GetDDrawDisplayInfo(DisplayInfo* pDisplayInfoFirst)
  364. {
  365. HRESULT hr;
  366. HRESULT hrRet = S_OK;
  367. DisplayInfo* pDisplayInfo;
  368. TCHAR szPath[MAX_PATH];
  369. HINSTANCE hInstDDraw;
  370. LPDIRECTDRAWCREATE pDDCreate;
  371. GetSystemDirectory(szPath, MAX_PATH);
  372. lstrcat(szPath, TEXT("\\ddraw.dll"));
  373. hInstDDraw = LoadLibrary(szPath);
  374. if (hInstDDraw == NULL)
  375. return E_FAIL;
  376. pDDCreate = (LPDIRECTDRAWCREATE)GetProcAddress(hInstDDraw, "DirectDrawCreate");
  377. if (pDDCreate == NULL)
  378. {
  379. FreeLibrary(hInstDDraw);
  380. return E_FAIL;
  381. }
  382. // Init D3D8 so we can use GetDX8AdapterInfo()
  383. InitD3D8();
  384. for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
  385. pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
  386. {
  387. pDisplayInfo->m_b3DAccelerationExists = FALSE; // until proven otherwise
  388. if (FAILED(hr = GetDirectDrawInfo(pDDCreate, pDisplayInfo)))
  389. hrRet = hr; // but keep going
  390. }
  391. // Cleanup the D3D8 library
  392. CleanupD3D8();
  393. FreeLibrary(hInstDDraw);
  394. return hrRet;
  395. }
  396. /****************************************************************************
  397. *
  398. * DestroyDisplayInfo
  399. *
  400. ****************************************************************************/
  401. VOID DestroyDisplayInfo(DisplayInfo* pDisplayInfoFirst)
  402. {
  403. DisplayInfo* pDisplayInfo;
  404. DisplayInfo* pDisplayInfoNext;
  405. for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
  406. pDisplayInfo = pDisplayInfoNext)
  407. {
  408. DestroyReg( &pDisplayInfo->m_pRegErrorFirst );
  409. pDisplayInfoNext = pDisplayInfo->m_pDisplayInfoNext;
  410. delete pDisplayInfo;
  411. }
  412. }
  413. /****************************************************************************
  414. *
  415. * GetRegDisplayInfo9x - Uses the registry keys to get more info about a
  416. * display adapter.
  417. *
  418. ****************************************************************************/
  419. VOID GetRegDisplayInfo9x(DisplayInfo* pDisplayInfo)
  420. {
  421. TCHAR szFullKey[200];
  422. HKEY hkey;
  423. DWORD cbData;
  424. DWORD dwType;
  425. // set to n/a by default
  426. _tcscpy( pDisplayInfo->m_szMiniVddDate, TEXT("n/a") );
  427. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szKeyDeviceID, 0, KEY_READ, &hkey))
  428. {
  429. cbData = sizeof(pDisplayInfo->m_szManufacturer);
  430. RegQueryValueEx(hkey, TEXT("Mfg"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szManufacturer, &cbData);
  431. RegCloseKey(hkey);
  432. }
  433. if (pDisplayInfo->m_dwRefreshRate == 0)
  434. {
  435. wsprintf(szFullKey, TEXT("%s\\Modes\\%d\\%d,%d"), pDisplayInfo->m_szKeyDeviceKey,
  436. pDisplayInfo->m_dwBpp, pDisplayInfo->m_dwWidth, pDisplayInfo->m_dwHeight);
  437. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
  438. {
  439. TCHAR szRefresh[100];
  440. TCHAR szRefresh2[100];
  441. TCHAR szRefreshEnglish2[100];
  442. cbData = sizeof(szRefresh);
  443. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("RefreshRate"), 0, &dwType, (LPBYTE)szRefresh, &cbData))
  444. {
  445. _stscanf(szRefresh, TEXT("%d"), &pDisplayInfo->m_dwRefreshRate);
  446. if (lstrcmp(szRefresh, TEXT("0")) == 0)
  447. LoadString(NULL, IDS_DEFAULTREFRESH, szRefresh2, 100);
  448. else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
  449. LoadString(NULL, IDS_OPTIMALREFRESH, szRefresh2, 100);
  450. else
  451. wsprintf(szRefresh2, TEXT("(%sHz)"), szRefresh);
  452. lstrcat(pDisplayInfo->m_szDisplayMode, TEXT(" "));
  453. lstrcat(pDisplayInfo->m_szDisplayMode, szRefresh2);
  454. if (lstrcmp(szRefresh, TEXT("0")) == 0)
  455. LoadString(NULL, IDS_DEFAULTREFRESH_ENGLISH, szRefreshEnglish2, 100);
  456. else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
  457. LoadString(NULL, IDS_OPTIMALREFRESH_ENGLISH, szRefreshEnglish2, 100);
  458. else
  459. wsprintf(szRefreshEnglish2, TEXT("(%sHz)"), szRefresh);
  460. lstrcat(pDisplayInfo->m_szDisplayModeEnglish, szRefreshEnglish2);
  461. lstrcat(pDisplayInfo->m_szDisplayModeEnglish, TEXT(" "));
  462. if (pDisplayInfo->m_dwRefreshRate == 0)
  463. pDisplayInfo->m_dwRefreshRate = 1; // 23399: so it doesn't check again
  464. }
  465. RegCloseKey(hkey);
  466. }
  467. }
  468. lstrcpy(szFullKey, pDisplayInfo->m_szKeyDeviceKey);
  469. lstrcat(szFullKey, TEXT("\\DEFAULT"));
  470. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
  471. {
  472. // If no specific refresh rate was listed for the current mode, report the
  473. // default rate.
  474. if (pDisplayInfo->m_dwRefreshRate == 0)
  475. {
  476. TCHAR szRefresh[100];
  477. TCHAR szRefresh2[100];
  478. TCHAR szRefreshEnglish2[100];
  479. cbData = sizeof(szRefresh);
  480. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("RefreshRate"), 0, &dwType, (LPBYTE)szRefresh, &cbData))
  481. {
  482. if (lstrcmp(szRefresh, TEXT("0")) == 0)
  483. LoadString(NULL, IDS_DEFAULTREFRESH, szRefresh2, 100);
  484. else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
  485. LoadString(NULL, IDS_OPTIMALREFRESH, szRefresh2, 100);
  486. else
  487. wsprintf(szRefresh2, TEXT("(%sHz)"), szRefresh);
  488. lstrcat(pDisplayInfo->m_szDisplayMode, TEXT(" "));
  489. lstrcat(pDisplayInfo->m_szDisplayMode, szRefresh2);
  490. if (lstrcmp(szRefresh, TEXT("0")) == 0)
  491. LoadString(NULL, IDS_DEFAULTREFRESH_ENGLISH, szRefreshEnglish2, 100);
  492. else if (lstrcmp(szRefresh, TEXT("-1")) == 0)
  493. LoadString(NULL, IDS_OPTIMALREFRESH_ENGLISH, szRefreshEnglish2, 100);
  494. else
  495. wsprintf(szRefreshEnglish2, TEXT("(%sHz)"), szRefresh);
  496. lstrcat(pDisplayInfo->m_szDisplayModeEnglish, szRefreshEnglish2);
  497. lstrcat(pDisplayInfo->m_szDisplayModeEnglish, TEXT(" "));
  498. if (pDisplayInfo->m_dwRefreshRate == 0)
  499. pDisplayInfo->m_dwRefreshRate = 1; // 23399: so it doesn't check again
  500. }
  501. }
  502. cbData = sizeof(pDisplayInfo->m_szDriverName);
  503. RegQueryValueEx(hkey, TEXT("drv"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szDriverName, &cbData);
  504. if (lstrlen(pDisplayInfo->m_szDriverName) > 0)
  505. {
  506. TCHAR szPath[MAX_PATH];
  507. GetSystemDirectory(szPath, MAX_PATH);
  508. lstrcat(szPath, TEXT("\\"));
  509. lstrcat(szPath, pDisplayInfo->m_szDriverName);
  510. GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
  511. pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage,
  512. &pDisplayInfo->m_bDriverBeta, &pDisplayInfo->m_bDriverDebug);
  513. FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
  514. GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
  515. }
  516. cbData = sizeof(pDisplayInfo->m_szVdd);
  517. RegQueryValueEx(hkey, TEXT("vdd"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szVdd, &cbData);
  518. cbData = sizeof(pDisplayInfo->m_szMiniVdd);
  519. RegQueryValueEx(hkey, TEXT("minivdd"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMiniVdd, &cbData);
  520. if (lstrlen(pDisplayInfo->m_szMiniVdd) > 0)
  521. {
  522. TCHAR szPath[MAX_PATH];
  523. GetSystemDirectory(szPath, MAX_PATH);
  524. lstrcat(szPath, TEXT("\\drivers\\"));
  525. lstrcat(szPath, pDisplayInfo->m_szMiniVdd);
  526. TCHAR szDateLocal[100];
  527. GetFileDateAndSize( szPath, szDateLocal, pDisplayInfo->m_szMiniVddDate,
  528. &pDisplayInfo->m_cbMiniVdd );
  529. }
  530. RegCloseKey(hkey);
  531. }
  532. lstrcpy(szFullKey, pDisplayInfo->m_szKeyDeviceKey);
  533. lstrcat(szFullKey, TEXT("\\INFO"));
  534. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
  535. {
  536. cbData = sizeof pDisplayInfo->m_szChipType;
  537. RegQueryValueEx(hkey, TEXT("ChipType"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szChipType, &cbData);
  538. cbData = sizeof pDisplayInfo->m_szDACType;
  539. RegQueryValueEx(hkey, TEXT("DACType"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szDACType, &cbData);
  540. cbData = sizeof pDisplayInfo->m_szRevision;
  541. RegQueryValueEx(hkey, TEXT("Revision"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szRevision, &cbData);
  542. if (cbData > 0)
  543. {
  544. lstrcat(pDisplayInfo->m_szChipType, TEXT(" Rev "));
  545. lstrcat(pDisplayInfo->m_szChipType, pDisplayInfo->m_szRevision);
  546. }
  547. RegCloseKey(hkey);
  548. }
  549. if (lstrlen(pDisplayInfo->m_szDriverVersion) == 0)
  550. {
  551. TCHAR szPath[MAX_PATH];
  552. GetSystemDirectory(szPath, MAX_PATH);
  553. lstrcat(szPath, TEXT("\\"));
  554. lstrcat(szPath, pDisplayInfo->m_szDriverName);
  555. lstrcat(szPath, TEXT(".drv"));
  556. GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
  557. pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
  558. FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
  559. GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
  560. if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
  561. {
  562. lstrcat(pDisplayInfo->m_szDriverName, TEXT(".drv"));
  563. }
  564. else
  565. {
  566. GetSystemDirectory(szPath, MAX_PATH);
  567. lstrcat(szPath, TEXT("\\"));
  568. lstrcat(szPath, pDisplayInfo->m_szDriverName);
  569. lstrcat(szPath, TEXT("32.dll"));
  570. GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
  571. pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
  572. FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
  573. GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
  574. if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
  575. {
  576. lstrcat(pDisplayInfo->m_szDriverName, TEXT("32.dll"));
  577. }
  578. else
  579. {
  580. GetSystemDirectory(szPath, MAX_PATH);
  581. lstrcat(szPath, TEXT("\\"));
  582. lstrcat(szPath, pDisplayInfo->m_szDriverName);
  583. lstrcat(szPath, TEXT(".dll"));
  584. GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
  585. pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage);
  586. FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
  587. GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
  588. if (lstrlen(pDisplayInfo->m_szDriverVersion) != 0)
  589. {
  590. lstrcat(pDisplayInfo->m_szDriverName, TEXT(".dll"));
  591. }
  592. }
  593. }
  594. }
  595. // Use monitor key to get monitor max resolution (and monitor name, if we don't have it yet)
  596. if (lstrlen(pDisplayInfo->m_szMonitorKey) > 0)
  597. {
  598. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szMonitorKey, 0, KEY_READ, &hkey))
  599. {
  600. cbData = sizeof(pDisplayInfo->m_szMonitorMaxRes);
  601. RegQueryValueEx(hkey, TEXT("MaxResolution"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorMaxRes, &cbData);
  602. if (lstrlen(pDisplayInfo->m_szMonitorName) == 0)
  603. {
  604. cbData = sizeof(pDisplayInfo->m_szMonitorName);
  605. RegQueryValueEx(hkey, TEXT("DriverDesc"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorName, &cbData);
  606. }
  607. RegCloseKey(hkey);
  608. }
  609. }
  610. }
  611. /****************************************************************************
  612. *
  613. * GetRegDisplayInfoNT - Uses the registry keys to get more info about a
  614. * display adapter.
  615. *
  616. ****************************************************************************/
  617. VOID GetRegDisplayInfoNT(DisplayInfo* pDisplayInfo)
  618. {
  619. TCHAR* pch;
  620. DWORD dwType;
  621. DWORD cbData;
  622. TCHAR szKeyVideo[MAX_PATH+1];
  623. TCHAR szKeyImage[MAX_PATH+1];
  624. TCHAR szKey[MAX_PATH+1];
  625. TCHAR szName[MAX_PATH+1];
  626. HKEY hkey;
  627. HKEY hkeyInfo;
  628. // set to n/a by default
  629. _tcscpy( pDisplayInfo->m_szMiniVddDate, TEXT("n/a") );
  630. // On NT, m_szKeyDeviceID isn't quite as specific as we need--must go
  631. // one level further in the registry.
  632. lstrcpy(szKey, TEXT("System\\CurrentControlSet\\"));
  633. lstrcat(szKey, pDisplayInfo->m_szKeyDeviceID);
  634. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkey))
  635. {
  636. if (ERROR_SUCCESS == RegEnumKey(hkey, 0, szName, MAX_PATH+1))
  637. {
  638. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkeyInfo))
  639. {
  640. cbData = sizeof(pDisplayInfo->m_szManufacturer);
  641. RegQueryValueEx(hkeyInfo, TEXT("Mfg"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szManufacturer, &cbData);
  642. RegCloseKey(hkeyInfo);
  643. }
  644. }
  645. RegCloseKey(hkey);
  646. }
  647. // Forked path due to bug 182866: dispinfo.cpp makes an invalid assumption
  648. // about the structure of video key.
  649. // szKey will be filled with where the video info is.
  650. // either "\System\ControlSet001\Services\[Service]\Device0",
  651. // or "\System\ControlSet001\Video\[GUID]\0000" depending on
  652. // pDisplayInfo->m_szKeyDeviceKey
  653. if( _tcsstr( pDisplayInfo->m_szKeyDeviceKey, TEXT("\\Services\\") ) != NULL )
  654. GetRegDisplayInfoWin2k( pDisplayInfo, szKeyVideo, szKeyImage );
  655. else
  656. GetRegDisplayInfoWhistler( pDisplayInfo, szKeyVideo, szKeyImage );
  657. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyVideo, 0, KEY_READ, &hkeyInfo))
  658. {
  659. WCHAR wszChipType[200];
  660. WCHAR wszDACType[200];
  661. TCHAR szDriver[200];
  662. cbData = 200 * sizeof(WCHAR);
  663. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.ChipType"), 0, &dwType, (LPBYTE)wszChipType, &cbData))
  664. {
  665. #ifdef UNICODE
  666. lstrcpy(pDisplayInfo->m_szChipType, wszChipType);
  667. #else
  668. WideCharToMultiByte(CP_ACP, 0, wszChipType, -1, pDisplayInfo->m_szChipType, 200, NULL, NULL);
  669. #endif
  670. }
  671. cbData = 200 * sizeof(WCHAR);
  672. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.DacType"), 0, &dwType, (LPBYTE)wszDACType, &cbData))
  673. {
  674. #ifdef UNICODE
  675. lstrcpy(pDisplayInfo->m_szDACType, wszDACType);
  676. #else
  677. WideCharToMultiByte(CP_ACP, 0, wszDACType, -1, pDisplayInfo->m_szDACType, 200, NULL, NULL);
  678. #endif
  679. }
  680. DWORD dwDisplayMemory;
  681. cbData = sizeof(dwDisplayMemory);
  682. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("HardwareInformation.MemorySize"), 0, &dwType, (LPBYTE)&dwDisplayMemory, &cbData))
  683. {
  684. // Round to nearest 512K:
  685. dwDisplayMemory = ((dwDisplayMemory + (256 * 1024)) / (512 * 1024));
  686. // So dwDisplayMemory is (number of bytes / 512K), which makes the
  687. // following line easier.
  688. wsprintf(pDisplayInfo->m_szDisplayMemory, TEXT("%d.%d MB"), dwDisplayMemory / 2,
  689. (dwDisplayMemory % 2) * 5);
  690. wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, pDisplayInfo->m_szDisplayMemory );
  691. }
  692. cbData = 200;
  693. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("InstalledDisplayDrivers"), 0, &dwType, (LPBYTE)szDriver, &cbData))
  694. {
  695. lstrcpy(pDisplayInfo->m_szDriverName, szDriver);
  696. lstrcat(pDisplayInfo->m_szDriverName, TEXT(".dll"));
  697. TCHAR szPath[MAX_PATH];
  698. GetSystemDirectory(szPath, MAX_PATH);
  699. lstrcat(szPath, TEXT("\\"));
  700. lstrcat(szPath, pDisplayInfo->m_szDriverName);
  701. GetFileVersion(szPath, pDisplayInfo->m_szDriverVersion,
  702. pDisplayInfo->m_szDriverAttributes, pDisplayInfo->m_szDriverLanguageLocal, pDisplayInfo->m_szDriverLanguage,
  703. &pDisplayInfo->m_bDriverBeta, &pDisplayInfo->m_bDriverDebug);
  704. FileIsSigned(szPath, &pDisplayInfo->m_bDriverSigned, &pDisplayInfo->m_bDriverSignedValid);
  705. GetFileDateAndSize(szPath, pDisplayInfo->m_szDriverDateLocal, pDisplayInfo->m_szDriverDate, &pDisplayInfo->m_cbDriver);
  706. }
  707. RegCloseKey(hkeyInfo);
  708. }
  709. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyImage, 0, KEY_READ, &hkeyInfo))
  710. {
  711. TCHAR szImagePath[MAX_PATH];
  712. cbData = MAX_PATH;
  713. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInfo, TEXT("ImagePath"), 0, &dwType, (LPBYTE)szImagePath, &cbData))
  714. {
  715. pch = _tcsrchr(szImagePath, TEXT('\\'));
  716. lstrcpy(pDisplayInfo->m_szMiniVdd, pch + 1);
  717. if (lstrlen(pDisplayInfo->m_szMiniVdd) > 0)
  718. {
  719. TCHAR szPath[MAX_PATH];
  720. GetSystemDirectory(szPath, MAX_PATH);
  721. lstrcat(szPath, TEXT("\\drivers\\"));
  722. lstrcat(szPath, pDisplayInfo->m_szMiniVdd);
  723. TCHAR szDateLocal[100];
  724. GetFileDateAndSize( szPath, szDateLocal, pDisplayInfo->m_szMiniVddDate,
  725. &pDisplayInfo->m_cbMiniVdd );
  726. }
  727. }
  728. RegCloseKey(hkeyInfo);
  729. }
  730. // Use monitor key to get monitor max resolution (and monitor name, if we don't have it yet)
  731. if (lstrlen(pDisplayInfo->m_szMonitorKey) > 0)
  732. {
  733. // Note: Have to skip first 18 characters of string because it's "Registry\Machine\"
  734. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pDisplayInfo->m_szMonitorKey + 18, 0, KEY_READ, &hkeyInfo))
  735. {
  736. cbData = sizeof(pDisplayInfo->m_szMonitorMaxRes);
  737. RegQueryValueEx(hkeyInfo, TEXT("MaxResolution"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorMaxRes, &cbData);
  738. if (lstrlen(pDisplayInfo->m_szMonitorName) == 0)
  739. {
  740. cbData = sizeof(pDisplayInfo->m_szMonitorName);
  741. RegQueryValueEx(hkeyInfo, TEXT("DriverDesc"), 0, &dwType, (LPBYTE)pDisplayInfo->m_szMonitorName, &cbData);
  742. }
  743. RegCloseKey(hkeyInfo);
  744. }
  745. }
  746. }
  747. /****************************************************************************
  748. *
  749. * GetRegDisplayInfoWhistler - Returns string location of video struct and
  750. * ImageInfo info in registry
  751. *
  752. ****************************************************************************/
  753. VOID GetRegDisplayInfoWhistler(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage )
  754. {
  755. TCHAR* pch;
  756. TCHAR szKey[MAX_PATH];
  757. DWORD dwType;
  758. DWORD cbData;
  759. HKEY hkeyService;
  760. // m_szKeyDeviceKey will be something like
  761. // "\Registry\Machine\System\ControlSet001\Video\[GUID]\0000",
  762. // The "\Registry\Machine\" part is useless, so we skip past the
  763. // first 18 characters in the string.
  764. lstrcpy(szKey, pDisplayInfo->m_szKeyDeviceKey + 18);
  765. // Slice off the "\0000" and add "\Video" to get the service
  766. pch = _tcsrchr(szKey, TEXT('\\'));
  767. if (pch != NULL)
  768. *pch = 0;
  769. lstrcat(szKey, TEXT("\\Video\\"));
  770. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkeyService))
  771. {
  772. TCHAR szService[MAX_PATH];
  773. cbData = MAX_PATH;
  774. if (ERROR_SUCCESS == RegQueryValueEx(hkeyService, TEXT("Service"), 0, &dwType, (LPBYTE)szService, &cbData))
  775. {
  776. lstrcpy(szKeyImage, TEXT("System\\CurrentControlSet\\Services\\") );
  777. lstrcat(szKeyImage, szService);
  778. }
  779. RegCloseKey(hkeyService);
  780. }
  781. // return something like "\System\ControlSet001\Services\atirage\Device0".
  782. lstrcpy(szKeyVideo, pDisplayInfo->m_szKeyDeviceKey + 18);
  783. }
  784. /****************************************************************************
  785. *
  786. * GetRegDisplayInfoWin2k - Returns string location of video struct and
  787. * ImageInfo info in registry
  788. *
  789. ****************************************************************************/
  790. VOID GetRegDisplayInfoWin2k(DisplayInfo* pDisplayInfo, TCHAR* szKeyVideo, TCHAR* szKeyImage )
  791. {
  792. TCHAR* pch;
  793. // m_szKeyDeviceKey will be something like
  794. // "\Registry\Machine\System\ControlSet001\Services\atirage\Device0".
  795. // The "\Registry\Machine\" part is useless, so we skip past the
  796. // first 18 characters in the string.
  797. lstrcpy(szKeyImage, pDisplayInfo->m_szKeyDeviceKey + 18);
  798. // Slice off the "\Device0" to get the miniport driver path
  799. pch = _tcsrchr(szKeyImage, TEXT('\\'));
  800. if (pch != NULL)
  801. *pch = 0;
  802. // return something like "\System\ControlSet001\Services\atirage\Device0".
  803. lstrcpy(szKeyVideo, pDisplayInfo->m_szKeyDeviceKey + 18);
  804. }
  805. /****************************************************************************
  806. *
  807. * GetDirectDrawInfo
  808. *
  809. ****************************************************************************/
  810. HRESULT GetDirectDrawInfo(LPDIRECTDRAWCREATE pDDCreate, DisplayInfo* pDisplayInfo)
  811. {
  812. HRESULT hr;
  813. LPDIRECTDRAW pdd = NULL;
  814. GUID* pGUID;
  815. DDCAPS ddcaps;
  816. DWORD dwDisplayMemory;
  817. if (pDisplayInfo->m_guid == GUID_NULL)
  818. pGUID = NULL;
  819. else
  820. pGUID = &pDisplayInfo->m_guid;
  821. if (FAILED(hr = pDDCreate(pGUID, &pdd, NULL)))
  822. goto LFail;
  823. ddcaps.dwSize = sizeof(ddcaps);
  824. if (FAILED(hr = pdd->GetCaps(&ddcaps, NULL)))
  825. goto LFail;
  826. // If AGP is disabled, we won't be able to tell if AGP is supported because
  827. // the flag will not be set. So in that case, assume that AGP is supported.
  828. // If AGP is not disabled, check the existence of AGP and note that we are
  829. // confident in the knowledge of whether AGP exists or not. I know, it's yucky.
  830. if (pDisplayInfo->m_bAGPEnabled)
  831. {
  832. pDisplayInfo->m_bAGPExistenceValid = TRUE;
  833. if (ddcaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM)
  834. pDisplayInfo->m_bAGPExists = TRUE;
  835. }
  836. if( ddcaps.dwCaps & DDCAPS_NOHARDWARE )
  837. pDisplayInfo->m_bNoHardware = TRUE;
  838. else
  839. pDisplayInfo->m_bNoHardware = FALSE;
  840. // 28873: if( DDCAPS_NOHARDWARE && m_bDDAccelerationEnabled ) then GetAvailableVidMem is wrong.
  841. if( pDisplayInfo->m_bNoHardware && pDisplayInfo->m_bDDAccelerationEnabled )
  842. {
  843. LoadString(NULL, IDS_NA, pDisplayInfo->m_szDisplayMemory, 100);
  844. wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, TEXT("n/a") );
  845. }
  846. else
  847. {
  848. if (lstrlen(pDisplayInfo->m_szDisplayMemory) == 0)
  849. {
  850. // 26678: returns wrong vid mem for 2nd monitor, so ignore non-hardware devices
  851. if( (ddcaps.dwCaps & DDCAPS_NOHARDWARE) == 0 )
  852. {
  853. // 24351: ddcaps.dwVidMemTotal sometimes includes AGP-accessible memory,
  854. // which we don't want. So use GetAvailableVidMem whenever we can, and
  855. // fall back to ddcaps.dwVidMemTotal if that's a problem.
  856. dwDisplayMemory = 0;
  857. LPDIRECTDRAW2 pdd2;
  858. if (SUCCEEDED(pdd->QueryInterface(IID_IDirectDraw2, (VOID**)&pdd2)))
  859. {
  860. DDSCAPS ddscaps;
  861. ddscaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
  862. pdd2->GetAvailableVidMem(&ddscaps, &dwDisplayMemory, NULL);
  863. pdd2->Release();
  864. }
  865. if (dwDisplayMemory == 0)
  866. {
  867. dwDisplayMemory = ddcaps.dwVidMemTotal;
  868. }
  869. // Add GDI memory except on no-GDI cards (Voodoo-type cards)
  870. if (pDisplayInfo->m_bCanRenderWindow)
  871. {
  872. DDSURFACEDESC ddsd;
  873. ddsd.dwSize = sizeof(ddsd);
  874. if (FAILED(hr = pdd->GetDisplayMode(&ddsd)))
  875. goto LFail;
  876. dwDisplayMemory += ddsd.dwWidth * ddsd.dwHeight *
  877. (ddsd.ddpfPixelFormat.dwRGBBitCount / 8);
  878. }
  879. // Round to nearest 512K:
  880. dwDisplayMemory = ((dwDisplayMemory + (256 * 1024)) / (512 * 1024));
  881. // So dwDisplayMemory is (number of bytes / 512K), which makes the
  882. // following line easier.
  883. wsprintf(pDisplayInfo->m_szDisplayMemory, TEXT("%d.%d MB"), dwDisplayMemory / 2,
  884. (dwDisplayMemory % 2) * 5);
  885. wsprintf(pDisplayInfo->m_szDisplayMemoryEnglish, pDisplayInfo->m_szDisplayMemory );
  886. }
  887. }
  888. }
  889. // 24427: Detect driver DDI version
  890. // 24656: Also detect D3D acceleration without DDCAPS_3D, since that flag is
  891. // sometimes sensitive to the current desktop color depth.
  892. // First, see if DD/D3D are disabled, and if so, briefly re-enable them
  893. BOOL bDDDisabled;
  894. BOOL bD3DDisabled;
  895. HKEY hkeyDD;
  896. HKEY hkeyD3D;
  897. DWORD dwSize;
  898. DWORD dwType;
  899. DWORD dwData;
  900. bDDDisabled = FALSE;
  901. bD3DDisabled = FALSE;
  902. hkeyDD = NULL;
  903. hkeyD3D = NULL;
  904. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  905. TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkeyDD))
  906. {
  907. dwSize = sizeof(dwData);
  908. dwData = 0;
  909. RegQueryValueEx(hkeyDD, TEXT("EmulationOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize);
  910. if (dwData != 0)
  911. {
  912. bDDDisabled = TRUE;
  913. // Re-enable DD
  914. dwData = 0;
  915. RegSetValueEx(hkeyDD, TEXT("EmulationOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
  916. }
  917. // Note: don't close key yet
  918. }
  919. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  920. TEXT("SOFTWARE\\Microsoft\\Direct3D\\Drivers"), 0, KEY_ALL_ACCESS, &hkeyD3D))
  921. {
  922. dwSize = sizeof(dwData);
  923. dwData = 0;
  924. RegQueryValueEx(hkeyD3D, TEXT("SoftwareOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize);
  925. if (dwData != 0)
  926. {
  927. bD3DDisabled = TRUE;
  928. // Re-enable D3D
  929. dwData = 0;
  930. RegSetValueEx(hkeyD3D, TEXT("SoftwareOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
  931. }
  932. // Note: don't close key yet
  933. }
  934. LPDIRECT3D pd3d;
  935. if (SUCCEEDED(pdd->QueryInterface(IID_IDirect3D, (VOID**)&pd3d)))
  936. {
  937. DWORD dwVersion = 0;
  938. if (SUCCEEDED(pd3d->EnumDevices(EnumDevicesCallback, (VOID*)&dwVersion)))
  939. {
  940. pDisplayInfo->m_dwDDIVersion = dwVersion;
  941. }
  942. pd3d->Release();
  943. }
  944. // While were in this function wrapped with crash protection try to
  945. // get adapter info from D3D8, and match it up with the DisplayInfo list.
  946. // This will also tell us if m_dwDDIVersion==8.
  947. GetDX8AdapterInfo(pDisplayInfo);
  948. switch (pDisplayInfo->m_dwDDIVersion)
  949. {
  950. case 0:
  951. wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("Unknown"));
  952. break;
  953. case 7:
  954. if( IsD3D8Working() )
  955. wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("7"));
  956. else
  957. wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("7 (or higher)"));
  958. break;
  959. case 8:
  960. wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("8 (or higher)"));
  961. break;
  962. default:
  963. wsprintf(pDisplayInfo->m_szDDIVersion, TEXT("%d"), pDisplayInfo->m_dwDDIVersion);
  964. break;
  965. }
  966. if (pDisplayInfo->m_dwDDIVersion != 0)
  967. pDisplayInfo->m_b3DAccelerationExists = TRUE;
  968. // Re-disable DD and D3D, if necessary
  969. dwData = 1;
  970. if (bDDDisabled)
  971. RegSetValueEx(hkeyDD, TEXT("EmulationOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
  972. if (bD3DDisabled)
  973. RegSetValueEx(hkeyD3D, TEXT("SoftwareOnly"), 0, REG_DWORD, (BYTE*)&dwData, sizeof(dwData));
  974. if (hkeyDD != NULL)
  975. RegCloseKey(hkeyDD);
  976. if (hkeyD3D != NULL)
  977. RegCloseKey(hkeyD3D);
  978. pdd->Release();
  979. return S_OK;
  980. LFail:
  981. if (pdd != NULL)
  982. pdd->Release();
  983. return hr;
  984. }
  985. /****************************************************************************
  986. *
  987. * EnumDevicesCallback
  988. *
  989. ****************************************************************************/
  990. HRESULT CALLBACK EnumDevicesCallback(GUID* pGuid, LPSTR pszDesc, LPSTR pszName,
  991. D3DDEVICEDESC* pd3ddevdesc1, D3DDEVICEDESC* pd3ddevdesc2, VOID* pvContext)
  992. {
  993. DWORD* pdwVersion = (DWORD*)pvContext;
  994. DWORD dwDevCaps;
  995. if (pd3ddevdesc1->dcmColorModel == D3DCOLOR_RGB)
  996. {
  997. dwDevCaps = pd3ddevdesc1->dwDevCaps;
  998. if (dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
  999. *pdwVersion = 7;
  1000. else if (dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2)
  1001. *pdwVersion = 6;
  1002. else if (dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX)
  1003. *pdwVersion = 5;
  1004. else if (dwDevCaps & D3DDEVCAPS_FLOATTLVERTEX)
  1005. *pdwVersion = 3;
  1006. }
  1007. return D3DENUMRET_OK;
  1008. }
  1009. /****************************************************************************
  1010. *
  1011. * IsDDHWAccelEnabled
  1012. *
  1013. ****************************************************************************/
  1014. BOOL IsDDHWAccelEnabled(VOID)
  1015. {
  1016. HKEY hkey;
  1017. DWORD dwSize;
  1018. DWORD dwType;
  1019. DWORD dwData;
  1020. BOOL bResult = TRUE;
  1021. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1022. TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkey))
  1023. {
  1024. dwSize = sizeof(dwData);
  1025. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("EmulationOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
  1026. {
  1027. if (dwData != 0)
  1028. bResult = FALSE;
  1029. RegCloseKey(hkey);
  1030. }
  1031. }
  1032. return bResult;
  1033. }
  1034. /****************************************************************************
  1035. *
  1036. * IsD3DHWAccelEnabled
  1037. *
  1038. ****************************************************************************/
  1039. BOOL IsD3DHWAccelEnabled(VOID)
  1040. {
  1041. HKEY hkey;
  1042. DWORD dwSize;
  1043. DWORD dwType;
  1044. DWORD dwData;
  1045. BOOL bIsD3DHWAccelEnabled = TRUE;
  1046. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1047. TEXT("SOFTWARE\\Microsoft\\Direct3D\\Drivers"), 0, KEY_ALL_ACCESS, &hkey))
  1048. {
  1049. dwSize = sizeof(dwData);
  1050. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("SoftwareOnly"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
  1051. {
  1052. if (dwData != 0)
  1053. bIsD3DHWAccelEnabled = FALSE;
  1054. RegCloseKey( hkey );
  1055. }
  1056. }
  1057. return bIsD3DHWAccelEnabled;
  1058. }
  1059. /****************************************************************************
  1060. *
  1061. * IsAGPEnabled
  1062. *
  1063. ****************************************************************************/
  1064. BOOL IsAGPEnabled(VOID)
  1065. {
  1066. HKEY hkey;
  1067. DWORD dwSize;
  1068. DWORD dwType;
  1069. DWORD dwData;
  1070. BOOL bIsAGPEnabled = TRUE;
  1071. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1072. TEXT("SOFTWARE\\Microsoft\\DirectDraw"), 0, KEY_ALL_ACCESS, &hkey))
  1073. {
  1074. dwSize = sizeof(dwData);
  1075. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("DisableAGPSupport"), NULL, &dwType, (BYTE *)&dwData, &dwSize))
  1076. {
  1077. if (dwData != 0)
  1078. bIsAGPEnabled = FALSE;
  1079. RegCloseKey( hkey );
  1080. }
  1081. }
  1082. return bIsAGPEnabled;
  1083. }
  1084. //
  1085. // GetDeviceValue
  1086. //
  1087. // read a value from the HW or SW of a PnP device
  1088. //
  1089. BOOL GetDeviceValue(TCHAR* pszHardwareKey, TCHAR* pszKey, TCHAR* pszValue, BYTE *buf, DWORD cbbuf)
  1090. {
  1091. HKEY hkeyHW;
  1092. HKEY hkeySW;
  1093. BOOL f = FALSE;
  1094. DWORD cb;
  1095. TCHAR szSoftwareKey[MAX_PATH];
  1096. *(DWORD*)buf = 0;
  1097. //
  1098. // open the HW key
  1099. //
  1100. if (RegOpenKey(HKEY_LOCAL_MACHINE, pszHardwareKey, &hkeyHW) == ERROR_SUCCESS)
  1101. {
  1102. //
  1103. // try to read the value from the HW key
  1104. //
  1105. *buf = 0;
  1106. cb = cbbuf;
  1107. if (RegQueryValueEx(hkeyHW, pszValue, NULL, NULL, buf, &cb) == ERROR_SUCCESS)
  1108. {
  1109. f = TRUE;
  1110. }
  1111. else
  1112. {
  1113. //
  1114. // now try the SW key
  1115. //
  1116. static TCHAR szSW[] = TEXT("System\\CurrentControlSet\\Services\\Class\\");
  1117. lstrcpy(szSoftwareKey, szSW);
  1118. cb = sizeof(szSoftwareKey) - sizeof(szSW);
  1119. RegQueryValueEx(hkeyHW, TEXT("Driver"), NULL, NULL, (LPBYTE)(szSoftwareKey + sizeof(szSW) - 1), &cb);
  1120. if (pszKey)
  1121. {
  1122. lstrcat(szSoftwareKey, TEXT("\\"));
  1123. lstrcat(szSoftwareKey, pszKey);
  1124. }
  1125. if (RegOpenKey(HKEY_LOCAL_MACHINE, szSoftwareKey, &hkeySW) == ERROR_SUCCESS)
  1126. {
  1127. *buf = 0;
  1128. cb = cbbuf;
  1129. if (RegQueryValueEx(hkeySW, pszValue, NULL, NULL, buf, &cb) == ERROR_SUCCESS)
  1130. {
  1131. f = TRUE;
  1132. }
  1133. RegCloseKey(hkeySW);
  1134. }
  1135. }
  1136. RegCloseKey(hkeyHW);
  1137. }
  1138. return f;
  1139. }
  1140. //
  1141. // FindDevice
  1142. //
  1143. // enum the started PnP devices looking for a device of a particular class
  1144. //
  1145. // iDevice what device to return (0= first device, 1=second et)
  1146. // szDeviceClass what class device (ie "Display") NULL will match all
  1147. // szDeviceID buffer to return the hardware ID (MAX_PATH bytes)
  1148. //
  1149. // return TRUE if a device was found.
  1150. //
  1151. // example:
  1152. //
  1153. // for (int i=0; FindDevice(i, "Display", DeviceID); i++)
  1154. // {
  1155. // }
  1156. //
  1157. BOOL FindDevice(INT iDevice, TCHAR* pszDeviceClass, TCHAR* pszDeviceClassNot, TCHAR* pszHardwareKey)
  1158. {
  1159. HKEY hkeyPnP;
  1160. HKEY hkey;
  1161. DWORD n;
  1162. DWORD cb;
  1163. DWORD dw;
  1164. TCHAR ach[MAX_PATH+1];
  1165. if (RegOpenKey(HKEY_DYN_DATA, TEXT("Config Manager\\Enum"), &hkeyPnP) != ERROR_SUCCESS)
  1166. return FALSE;
  1167. for (n=0; RegEnumKey(hkeyPnP, n, ach, MAX_PATH+1) == 0; n++)
  1168. {
  1169. static TCHAR szHW[] = TEXT("Enum\\");
  1170. if (RegOpenKey(hkeyPnP, ach, &hkey) != ERROR_SUCCESS)
  1171. continue;
  1172. lstrcpy(pszHardwareKey, szHW);
  1173. cb = MAX_PATH - sizeof(szHW);
  1174. RegQueryValueEx(hkey, TEXT("HardwareKey"), NULL, NULL, (BYTE*)pszHardwareKey + sizeof(szHW) - 1, &cb);
  1175. dw = 0;
  1176. cb = sizeof(dw);
  1177. RegQueryValueEx(hkey, TEXT("Problem"), NULL, NULL, (BYTE*)&dw, &cb);
  1178. RegCloseKey(hkey);
  1179. if (dw != 0) // if this device has a problem skip it
  1180. continue;
  1181. if (pszDeviceClass || pszDeviceClassNot)
  1182. {
  1183. GetDeviceValue(pszHardwareKey, NULL, TEXT("Class"), (BYTE*)ach, sizeof(ach));
  1184. if (pszDeviceClass && lstrcmpi(pszDeviceClass, ach) != 0)
  1185. continue;
  1186. if (pszDeviceClassNot && lstrcmpi(pszDeviceClassNot, ach) == 0)
  1187. continue;
  1188. }
  1189. //
  1190. // we found a device, make sure it is the one the caller wants
  1191. //
  1192. if (iDevice-- == 0)
  1193. {
  1194. RegCloseKey(hkeyPnP);
  1195. return TRUE;
  1196. }
  1197. }
  1198. RegCloseKey(hkeyPnP);
  1199. return FALSE;
  1200. }
  1201. /****************************************************************************
  1202. *
  1203. * CheckRegistry
  1204. *
  1205. ****************************************************************************/
  1206. HRESULT CheckRegistry(RegError** ppRegErrorFirst)
  1207. {
  1208. HRESULT hr;
  1209. HKEY HKLM = HKEY_LOCAL_MACHINE;
  1210. HKEY HKCR = HKEY_CLASSES_ROOT;
  1211. TCHAR szVersion[100];
  1212. HKEY hkey;
  1213. DWORD cbData;
  1214. ULONG ulType;
  1215. DWORD dwMajor = 0;
  1216. DWORD dwMinor = 0;
  1217. DWORD dwRevision = 0;
  1218. DWORD dwBuild = 0;
  1219. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
  1220. 0, KEY_READ, &hkey))
  1221. {
  1222. cbData = 100;
  1223. RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)szVersion, &cbData);
  1224. RegCloseKey(hkey);
  1225. if (lstrlen(szVersion) > 6 &&
  1226. lstrlen(szVersion) < 20)
  1227. {
  1228. _stscanf(szVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
  1229. }
  1230. }
  1231. // No registry checking on DX versions before DX7
  1232. if (dwMinor < 7)
  1233. return S_OK;
  1234. // From ddraw.inf (compatibility hacks not included):
  1235. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDraw"), TEXT(""), TEXT("*"))))
  1236. return hr;
  1237. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDraw\\CLSID"), TEXT(""), TEXT("{D7B70EE0-4340-11CF-B063-0020AFC2CD35}"))))
  1238. return hr;
  1239. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}"), TEXT(""), TEXT("*"))))
  1240. return hr;
  1241. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}\\InprocServer32"), TEXT(""), TEXT("ddraw.dll"), CRF_LEAF)))
  1242. return hr;
  1243. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{D7B70EE0-4340-11CF-B063-0020AFC2CD35}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  1244. return hr;
  1245. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDrawClipper"), TEXT(""), TEXT("*"))))
  1246. return hr;
  1247. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectDrawClipper\\CLSID"), TEXT(""), TEXT("{593817A0-7DB3-11CF-A2DE-00AA00B93356}"))))
  1248. return hr;
  1249. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}"), TEXT(""), TEXT("*"))))
  1250. return hr;
  1251. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}\\InprocServer32"), TEXT(""), TEXT("ddraw.dll"), CRF_LEAF)))
  1252. return hr;
  1253. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{593817A0-7DB3-11CF-A2DE-00AA00B93356}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  1254. return hr;
  1255. if (!BIsPlatformNT())
  1256. {
  1257. // We can't check for the following entry on Win2000 because it is missing.
  1258. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}"), TEXT(""), TEXT("*"))))
  1259. return hr;
  1260. }
  1261. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}\\InprocServer32"), TEXT(""), TEXT("ddrawex.dll"), CRF_LEAF)))
  1262. return hr;
  1263. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4FD2A832-86C8-11d0-8FCA-00C04FD9189D}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  1264. return hr;
  1265. // From d3d.inf:
  1266. TCHAR* pszHALKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\Direct3D HAL");
  1267. BYTE bArrayHALGuid[] = { 0xe0, 0x3d, 0xe6, 0x84, 0xaa, 0x46, 0xcf, 0x11, 0x81, 0x6f, 0x00, 0x00, 0xc0, 0x20, 0x15, 0x6e };
  1268. TCHAR* pszRampKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\Ramp Emulation");
  1269. BYTE bArrayRampGuid[] = { 0x20, 0x6b, 0x08, 0xf2, 0x9f, 0x25, 0xcf, 0x11, 0xa3, 0x1a, 0x00, 0xaa, 0x00, 0xb9, 0x33, 0x56 };
  1270. TCHAR* pszRGBKey = TEXT("Software\\Microsoft\\Direct3D\\Drivers\\RGB Emulation");
  1271. BYTE bArrayRGBGuid[] = { 0x60, 0x5c, 0x66, 0xa4, 0x73, 0x26, 0xcf, 0x11, 0xa3, 0x1a, 0x00, 0xaa, 0x00, 0xb9, 0x33, 0x56 };
  1272. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszHALKey, TEXT("Base"), TEXT("hal"))))
  1273. return hr;
  1274. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszHALKey, TEXT("Description"), TEXT("*"))))
  1275. return hr;
  1276. if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszHALKey, TEXT("GUID"), bArrayHALGuid, sizeof(bArrayHALGuid))))
  1277. return hr;
  1278. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRampKey, TEXT("Base"), TEXT("ramp"))))
  1279. return hr;
  1280. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRampKey, TEXT("Description"), TEXT("*"))))
  1281. return hr;
  1282. if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszRampKey, TEXT("GUID"), bArrayRampGuid, sizeof(bArrayRampGuid))))
  1283. return hr;
  1284. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("Base"), TEXT("rgb"))))
  1285. return hr;
  1286. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("Description"), TEXT("*"))))
  1287. return hr;
  1288. if (FAILED(hr = CheckRegBinary(ppRegErrorFirst, HKLM, pszRGBKey, TEXT("GUID"), bArrayRGBGuid, sizeof(bArrayRGBGuid))))
  1289. return hr;
  1290. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit Bump DuDv"), TEXT("ddpf"), TEXT("00080000 0 16 ff ff00 0 0"))))
  1291. return hr;
  1292. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit BumpLum DuDv"), TEXT("ddpf"), TEXT("000C0000 0 16 1f 3e0 fc00 0"))))
  1293. return hr;
  1294. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\16 bit Luminance Alpha"), TEXT("ddpf"), TEXT("00020001 0 16 ff 0 0 ff00"))))
  1295. return hr;
  1296. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\24 bit BumpLum DuDv"), TEXT("ddpf"), TEXT("000C0000 0 24 ff ff00 ff0000 0"))))
  1297. return hr;
  1298. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKLM, TEXT("Software\\Microsoft\\Direct3D\\DX6TextureEnumInclusionList\\8 bit Luminance"), TEXT("ddpf"), TEXT("00020000 0 8 ff 0 0 0"))))
  1299. return hr;
  1300. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("Direct3DRM"), TEXT(""), TEXT("*"))))
  1301. return hr;
  1302. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("Direct3DRM\\CLSID"), TEXT(""), TEXT("{4516EC41-8F20-11d0-9B6D-0000C0781BC3}"))))
  1303. return hr;
  1304. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}"), TEXT(""), TEXT("*"))))
  1305. return hr;
  1306. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT(""), TEXT("d3drm.dll"))))
  1307. return hr;
  1308. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC41-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  1309. return hr;
  1310. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectXFile"), TEXT(""), TEXT("*"))))
  1311. return hr;
  1312. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectXFile\\CLSID"), TEXT(""), TEXT("{4516EC43-8F20-11D0-9B6D-0000C0781BC3}"))))
  1313. return hr;
  1314. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11D0-9B6D-0000C0781BC3}"), TEXT(""), TEXT("*"))))
  1315. return hr;
  1316. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT(""), TEXT("d3dxof.dll"))))
  1317. return hr;
  1318. if (BIsPlatformNT())
  1319. {
  1320. // 23342: This setting is missing on Win9x.
  1321. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{4516EC43-8F20-11d0-9B6D-0000C0781BC3}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  1322. return hr;
  1323. }
  1324. return S_OK;
  1325. }
  1326. /****************************************************************************
  1327. *
  1328. * DiagnoseDisplay
  1329. *
  1330. ****************************************************************************/
  1331. VOID DiagnoseDisplay(SysInfo* pSysInfo, DisplayInfo* pDisplayInfoFirst)
  1332. {
  1333. DisplayInfo* pDisplayInfo;
  1334. TCHAR sz[MAX_PATH];
  1335. TCHAR szEnglish[MAX_PATH];
  1336. TCHAR szFmt[MAX_PATH];
  1337. BOOL bShouldReinstall = FALSE;
  1338. for (pDisplayInfo = pDisplayInfoFirst; pDisplayInfo != NULL;
  1339. pDisplayInfo = pDisplayInfo->m_pDisplayInfoNext)
  1340. {
  1341. if (pDisplayInfo->m_bDDAccelerationEnabled)
  1342. {
  1343. if( pDisplayInfo->m_bNoHardware )
  1344. {
  1345. LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
  1346. LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
  1347. }
  1348. else
  1349. {
  1350. LoadString(NULL, IDS_ACCELENABLED, sz, 100);
  1351. LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
  1352. }
  1353. }
  1354. else
  1355. {
  1356. LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
  1357. LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
  1358. }
  1359. _tcscpy( pDisplayInfo->m_szDDStatus, sz );
  1360. _tcscpy( pDisplayInfo->m_szDDStatusEnglish, szEnglish );
  1361. if (pDisplayInfo->m_b3DAccelerationExists)
  1362. {
  1363. if (pDisplayInfo->m_b3DAccelerationEnabled)
  1364. {
  1365. LoadString(NULL, IDS_ACCELENABLED, sz, 100);
  1366. LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
  1367. }
  1368. else
  1369. {
  1370. LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
  1371. LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
  1372. }
  1373. }
  1374. else
  1375. {
  1376. LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
  1377. LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
  1378. }
  1379. _tcscpy( pDisplayInfo->m_szD3DStatus, sz );
  1380. _tcscpy( pDisplayInfo->m_szD3DStatusEnglish, szEnglish );
  1381. if ( (pDisplayInfo->m_bAGPExistenceValid && !pDisplayInfo->m_bAGPExists) ||
  1382. (!pDisplayInfo->m_bDDAccelerationEnabled) )
  1383. {
  1384. LoadString(NULL, IDS_ACCELUNAVAIL, sz, 100);
  1385. LoadString(NULL, IDS_ACCELUNAVAIL_ENGLISH, szEnglish, 100);
  1386. }
  1387. else
  1388. {
  1389. if (pDisplayInfo->m_bAGPEnabled)
  1390. {
  1391. LoadString(NULL, IDS_ACCELENABLED, sz, 100);
  1392. LoadString(NULL, IDS_ACCELENABLED_ENGLISH, szEnglish, 100);
  1393. }
  1394. else
  1395. {
  1396. LoadString(NULL, IDS_ACCELDISABLED, sz, 100);
  1397. LoadString(NULL, IDS_ACCELDISABLED_ENGLISH, szEnglish, 100);
  1398. }
  1399. }
  1400. _tcscpy( pDisplayInfo->m_szAGPStatus, sz );
  1401. _tcscpy( pDisplayInfo->m_szAGPStatusEnglish, szEnglish );
  1402. _tcscpy( pDisplayInfo->m_szNotes, TEXT("") );
  1403. _tcscpy( pDisplayInfo->m_szNotesEnglish, TEXT("") );
  1404. // Report any problems:
  1405. BOOL bProblem = FALSE;
  1406. if( pSysInfo->m_bNetMeetingRunning &&
  1407. !pDisplayInfo->m_b3DAccelerationExists )
  1408. {
  1409. LoadString(NULL, IDS_NETMEETINGWARN, szFmt, MAX_PATH);
  1410. wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
  1411. _tcscat( pDisplayInfo->m_szNotes, sz );
  1412. LoadString(NULL, IDS_NETMEETINGWARN_ENGLISH, szFmt, MAX_PATH);
  1413. wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
  1414. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1415. bProblem = TRUE;
  1416. }
  1417. if (pDisplayInfo->m_bDriverSignedValid && !pDisplayInfo->m_bDriverSigned)
  1418. {
  1419. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1, szFmt, MAX_PATH);
  1420. wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
  1421. _tcscat( pDisplayInfo->m_szNotes, sz );
  1422. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1_ENGLISH, szFmt, MAX_PATH);
  1423. wsprintf(sz, szFmt, pDisplayInfo->m_szDriverName);
  1424. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1425. bProblem = TRUE;
  1426. }
  1427. if (pDisplayInfo->m_pRegErrorFirst != NULL)
  1428. {
  1429. LoadString(NULL, IDS_REGISTRYPROBLEM, sz, MAX_PATH);
  1430. _tcscat( pDisplayInfo->m_szNotes, sz );
  1431. LoadString(NULL, IDS_REGISTRYPROBLEM_ENGLISH, sz, MAX_PATH);
  1432. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1433. bProblem = TRUE;
  1434. bShouldReinstall = TRUE;
  1435. }
  1436. if( bShouldReinstall )
  1437. {
  1438. BOOL bTellUser = FALSE;
  1439. // Figure out if the user can install DirectX
  1440. if( BIsPlatform9x() )
  1441. bTellUser = TRUE;
  1442. else if( BIsWin2k() && pSysInfo->m_dwDirectXVersionMajor >= 8 )
  1443. bTellUser = TRUE;
  1444. if( bTellUser )
  1445. {
  1446. LoadString(NULL, IDS_REINSTALL_DX, sz, 300);
  1447. _tcscat( pDisplayInfo->m_szNotes, sz);
  1448. LoadString(NULL, IDS_REINSTALL_DX_ENGLISH, sz, 300);
  1449. _tcscat( pDisplayInfo->m_szNotesEnglish, sz);
  1450. }
  1451. }
  1452. if (!bProblem)
  1453. {
  1454. LoadString(NULL, IDS_NOPROBLEM, sz, MAX_PATH);
  1455. _tcscat( pDisplayInfo->m_szNotes, sz );
  1456. LoadString(NULL, IDS_NOPROBLEM_ENGLISH, sz, MAX_PATH);
  1457. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1458. }
  1459. // Report any DD test results:
  1460. if (pDisplayInfo->m_testResultDD.m_bStarted &&
  1461. !pDisplayInfo->m_testResultDD.m_bCancelled)
  1462. {
  1463. LoadString(NULL, IDS_DDRESULTS, sz, MAX_PATH);
  1464. _tcscat( pDisplayInfo->m_szNotes, sz );
  1465. _tcscat( pDisplayInfo->m_szNotes, pDisplayInfo->m_testResultDD.m_szDescription );
  1466. _tcscat( pDisplayInfo->m_szNotes, TEXT("\r\n") );
  1467. LoadString(NULL, IDS_DDRESULTS_ENGLISH, sz, MAX_PATH);
  1468. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1469. _tcscat( pDisplayInfo->m_szNotesEnglish, pDisplayInfo->m_testResultDD.m_szDescription );
  1470. _tcscat( pDisplayInfo->m_szNotesEnglish, TEXT("\r\n") );
  1471. }
  1472. else
  1473. {
  1474. LoadString(NULL, IDS_DDINSTRUCTIONS, sz, MAX_PATH);
  1475. _tcscat( pDisplayInfo->m_szNotes, sz );
  1476. LoadString(NULL, IDS_DDINSTRUCTIONS_ENGLISH, sz, MAX_PATH);
  1477. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1478. }
  1479. // Report any D3D test results:
  1480. TestResult* pTestResult;
  1481. if( pDisplayInfo->m_dwTestToDisplayD3D == 7 )
  1482. pTestResult = &pDisplayInfo->m_testResultD3D7;
  1483. else
  1484. pTestResult = &pDisplayInfo->m_testResultD3D8;
  1485. if (pTestResult->m_bStarted &&
  1486. !pTestResult->m_bCancelled)
  1487. {
  1488. LoadString(NULL, IDS_D3DRESULTS, sz, MAX_PATH);
  1489. _tcscat( pDisplayInfo->m_szNotes, sz );
  1490. _tcscat( pDisplayInfo->m_szNotes, pTestResult->m_szDescription );
  1491. _tcscat( pDisplayInfo->m_szNotes, TEXT("\r\n") );
  1492. LoadString(NULL, IDS_D3DRESULTS_ENGLISH, sz, MAX_PATH);
  1493. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1494. _tcscat( pDisplayInfo->m_szNotesEnglish, pTestResult->m_szDescription );
  1495. _tcscat( pDisplayInfo->m_szNotesEnglish, TEXT("\r\n") );
  1496. }
  1497. else
  1498. {
  1499. if( pDisplayInfo->m_b3DAccelerationExists &&
  1500. pDisplayInfo->m_b3DAccelerationEnabled )
  1501. {
  1502. LoadString(NULL, IDS_D3DINSTRUCTIONS, sz, MAX_PATH);
  1503. _tcscat( pDisplayInfo->m_szNotes, sz );
  1504. LoadString(NULL, IDS_D3DINSTRUCTIONS_ENGLISH, sz, MAX_PATH);
  1505. _tcscat( pDisplayInfo->m_szNotesEnglish, sz );
  1506. }
  1507. }
  1508. }
  1509. }