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

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