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.

796 lines
22 KiB

  1. //
  2. // [Display Troubleshooter Control Panel Extenstion]
  3. //
  4. //
  5. // - Aug.25.1998
  6. //
  7. // Created by Hideyuki Nagase [hideyukn]
  8. //
  9. #include "deskperf.h"
  10. #define DECL_CRTFREE
  11. #include <crtfree.h>
  12. //
  13. // Defines
  14. //
  15. #define ACCELERATION_FULL 0
  16. #define ACCELERATION_NONE 5
  17. #define SLIDER_POS_TO_ACCEL_LEVEL(x) (ACCELERATION_NONE - (x))
  18. #define ACCEL_LEVEL_TO_SLIDER_POS(x) (ACCELERATION_NONE - (x))
  19. #define REGSTR_GRAPHICS_DRIVERS TEXT("System\\CurrentControlSet\\Control\\GraphicsDrivers")
  20. #define REGSTR_DISABLE_USWC TEXT("DisableUSWC")
  21. //
  22. // Guid for "Troubleshooter" shell extentions
  23. //
  24. GUID g_CLSID_CplExt = { 0xf92e8c40, 0x3d33, 0x11d2,
  25. { 0xb1, 0xaa, 0x08, 0x00, 0x36, 0xa7, 0x5b, 0x03}
  26. };
  27. //
  28. // Global variables
  29. //
  30. //
  31. // Dos display device name
  32. //
  33. TCHAR gszWinDisplayDevice[MAX_PATH];
  34. //
  35. // NT display device name
  36. //
  37. TCHAR gszNtDisplayDevice[MAX_PATH];
  38. //
  39. // Registry path for current device
  40. //
  41. TCHAR gszRegistryPath[MAX_PATH];
  42. //
  43. // Current acceleration level.
  44. //
  45. DWORD AccelLevel = ACCELERATION_FULL;
  46. //
  47. // Last saved acceleration level.
  48. //
  49. DWORD AccelLevelInReg = ACCELERATION_FULL;
  50. //
  51. // Registry security.
  52. //
  53. BOOL gbReadOnly = FALSE;
  54. //
  55. // Is DisableUSWC key present?.
  56. //
  57. BOOL gbDisableUSWC = FALSE;
  58. //
  59. // Context-sentitive help
  60. //
  61. static const DWORD sc_PerformanceHelpIds[] =
  62. {
  63. IDI_MONITOR, IDH_NOHELP,
  64. IDC_DESCRIPTION, IDH_NOHELP,
  65. IDC_ACCELERATION_SLIDER, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_ACCELERATION,
  66. IDC_ACCELERATION_TEXT, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_ACCELERATION,
  67. IDC_ENABLE_USWC, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_WRITE_COMBINING,
  68. 0, 0
  69. };
  70. void
  71. UpdateGraphicsText(HWND hDlg, DWORD AccelPos)
  72. {
  73. TCHAR MessageBuffer[200];
  74. LoadString(g_hInst, IDS_LEVEL0 + AccelPos, MessageBuffer, ARRAYSIZE(MessageBuffer));
  75. SetDlgItemText(hDlg, IDC_ACCELERATION_TEXT, (LPTSTR) MessageBuffer);
  76. }
  77. BOOL GetDeviceKey(LPCTSTR pszDisplay, LPTSTR pszDeviceKey, int cChars)
  78. {
  79. DISPLAY_DEVICE DisplayDevice;
  80. BOOL fFound = FALSE;
  81. BOOL fSuccess = TRUE;
  82. int iEnum = 0;
  83. // Enumerate all the devices in the system.
  84. while(fSuccess && !fFound)
  85. {
  86. ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
  87. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  88. fSuccess = EnumDisplayDevices(NULL, iEnum, &DisplayDevice, 0);
  89. if(fSuccess)
  90. {
  91. if(0 == lstrcmp(&DisplayDevice.DeviceName[0], pszDisplay))
  92. {
  93. ASSERT(lstrlen(DisplayDevice.DeviceKey) < cChars);
  94. fSuccess = (lstrlen(DisplayDevice.DeviceKey) < cChars);
  95. if(fSuccess)
  96. {
  97. lstrcpy(pszDeviceKey, DisplayDevice.DeviceKey);
  98. fFound = TRUE;
  99. }
  100. }
  101. ++iEnum;
  102. }
  103. }
  104. return fFound;
  105. }
  106. INT_PTR
  107. CALLBACK
  108. AskDynamicApply(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
  109. {
  110. int *pTemp;
  111. switch (msg)
  112. {
  113. case WM_INITDIALOG:
  114. if ((pTemp = (int *)lp) != NULL)
  115. {
  116. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pTemp);
  117. CheckDlgButton(hDlg, (*pTemp & DCDSF_DYNA)?
  118. IDC_YESDYNA : IDC_NODYNA, BST_CHECKED);
  119. }
  120. else
  121. EndDialog(hDlg, -1);
  122. break;
  123. case WM_COMMAND:
  124. switch (GET_WM_COMMAND_ID(wp, lp))
  125. {
  126. case IDOK:
  127. if ((pTemp = (int *)GetWindowLongPtr(hDlg, DWLP_USER)) != NULL)
  128. {
  129. *pTemp = IsDlgButtonChecked(hDlg, IDC_YESDYNA)? DCDSF_DYNA : 0;
  130. if (!IsDlgButtonChecked(hDlg, IDC_SHUTUP))
  131. *pTemp |= DCDSF_ASK;
  132. SetDisplayCPLPreference(REGSTR_VAL_DYNASETTINGSCHANGE, *pTemp);
  133. }
  134. EndDialog(hDlg, TRUE);
  135. break;
  136. case IDCANCEL:
  137. EndDialog(hDlg, FALSE);
  138. break;
  139. default:
  140. return FALSE;
  141. }
  142. break;
  143. default:
  144. return FALSE;
  145. }
  146. return TRUE;
  147. }
  148. INT_PTR
  149. CALLBACK
  150. PropertySheeDlgProc(
  151. HWND hDlg,
  152. UINT uMessage,
  153. WPARAM wParam,
  154. LPARAM lParam
  155. )
  156. {
  157. switch (uMessage)
  158. {
  159. case WM_INITDIALOG:
  160. if (!g_lpdoTarget)
  161. {
  162. return FALSE;
  163. }
  164. else
  165. {
  166. BOOL bSuccess = FALSE;
  167. BOOL bDisableUSWCReadOnly = TRUE;
  168. //
  169. // LATER: Check we are on Terminal Server client or not.
  170. //
  171. BOOL bLocalConsole = TRUE;
  172. if (bLocalConsole)
  173. {
  174. //
  175. // Get the display device name from IDataObject.
  176. //
  177. FORMATETC fmte = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_DEVICE),
  178. (DVTARGETDEVICE FAR *) NULL,
  179. DVASPECT_CONTENT,
  180. -1,
  181. TYMED_HGLOBAL};
  182. STGMEDIUM stgm;
  183. HRESULT hres = g_lpdoTarget->GetData(&fmte, &stgm);
  184. if (SUCCEEDED(hres) && stgm.hGlobal)
  185. {
  186. //
  187. // The storage now contains Display device path (\\.\DisplayX) in UNICODE.
  188. //
  189. PWSTR pDisplayDevice = (PWSTR) GlobalLock(stgm.hGlobal);
  190. if (pDisplayDevice)
  191. {
  192. //
  193. // Copy the data to local buffer.
  194. //
  195. #ifdef UNICODE
  196. lstrcpy(gszWinDisplayDevice,pDisplayDevice);
  197. bSuccess = TRUE;
  198. #else
  199. bSuccess = (BOOL) WideCharToMultiByte(
  200. CP_ACP,0,
  201. pDisplayDevice,lstrlenW(pDisplayDevice)+1,
  202. gszWinDisplayDevice,MAX_PATH,
  203. NULL,NULL);
  204. #endif
  205. GlobalUnlock(stgm.hGlobal);
  206. }
  207. }
  208. //
  209. // let's build registry path for its hardware profile.
  210. //
  211. if (bSuccess)
  212. {
  213. TCHAR szServicePath[MAX_PATH];
  214. bSuccess = FALSE;
  215. if(GetDeviceKey(gszWinDisplayDevice, szServicePath, sizeof(szServicePath) / sizeof(TCHAR)))
  216. {
  217. //
  218. // Upcase all character.
  219. //
  220. TCHAR *psz = szServicePath;
  221. while (*psz)
  222. {
  223. *psz = _totupper(*psz);
  224. psz++;
  225. }
  226. //
  227. // Find \SYSTEM from service path
  228. //
  229. psz = _tcsstr(szServicePath,TEXT("\\SYSTEM"));
  230. //
  231. // Skip '\'
  232. //
  233. psz++;
  234. lstrcpy(gszRegistryPath,psz);
  235. bSuccess = TRUE;
  236. }
  237. }
  238. if (bSuccess)
  239. {
  240. //
  241. // Read current acceleration level from registry.
  242. //
  243. HKEY hKeyAccelLevel = NULL;
  244. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  245. gszRegistryPath,
  246. 0,
  247. KEY_ALL_ACCESS,
  248. &hKeyAccelLevel) != ERROR_SUCCESS)
  249. {
  250. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  251. gszRegistryPath,
  252. 0,
  253. KEY_READ,
  254. &hKeyAccelLevel) != ERROR_SUCCESS)
  255. {
  256. hKeyAccelLevel = NULL;
  257. }
  258. else
  259. {
  260. gbReadOnly = TRUE;
  261. }
  262. }
  263. if (hKeyAccelLevel)
  264. {
  265. DWORD cb = sizeof(AccelLevel);
  266. if (RegQueryValueEx(hKeyAccelLevel,
  267. SZ_HW_ACCELERATION,
  268. NULL,NULL,
  269. (LPBYTE) &AccelLevel,
  270. &cb) == ERROR_SUCCESS)
  271. {
  272. //
  273. // Update last saved accel level.
  274. //
  275. AccelLevelInReg = AccelLevel;
  276. }
  277. else
  278. {
  279. //
  280. // If there is no registry value, assume full acceleration.
  281. //
  282. AccelLevelInReg = AccelLevel = ACCELERATION_FULL;
  283. }
  284. RegCloseKey(hKeyAccelLevel);
  285. bSuccess = TRUE;
  286. }
  287. }
  288. //
  289. // Read current DisableUSWC status.
  290. //
  291. HKEY hKeyGraphicsDrivers = NULL;
  292. bDisableUSWCReadOnly = FALSE;
  293. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  294. REGSTR_GRAPHICS_DRIVERS,
  295. 0,
  296. KEY_ALL_ACCESS,
  297. &hKeyGraphicsDrivers) != ERROR_SUCCESS)
  298. {
  299. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  300. REGSTR_GRAPHICS_DRIVERS,
  301. 0,
  302. KEY_READ,
  303. &hKeyGraphicsDrivers) != ERROR_SUCCESS)
  304. {
  305. hKeyGraphicsDrivers = NULL;
  306. }
  307. else
  308. {
  309. bDisableUSWCReadOnly = TRUE;
  310. }
  311. }
  312. if (NULL != hKeyGraphicsDrivers)
  313. {
  314. HKEY hKeyDisableUSWC = NULL;
  315. gbDisableUSWC =
  316. (RegOpenKeyEx(hKeyGraphicsDrivers,
  317. REGSTR_DISABLE_USWC,
  318. 0,
  319. KEY_READ,
  320. &hKeyDisableUSWC) == ERROR_SUCCESS);
  321. if (NULL != hKeyDisableUSWC)
  322. RegCloseKey(hKeyDisableUSWC);
  323. RegCloseKey(hKeyGraphicsDrivers);
  324. }
  325. }
  326. //
  327. // Setup slider.
  328. //
  329. HWND hSlider = GetDlgItem(hDlg, IDC_ACCELERATION_SLIDER);
  330. //
  331. // Slider range is between ACCEL_FULL and ACCEL_NONE.
  332. //
  333. SendMessage(hSlider, TBM_SETRANGE, (WPARAM)FALSE,
  334. MAKELPARAM(ACCELERATION_FULL, ACCELERATION_NONE));
  335. //
  336. // Set currect slider position based on current accel level.
  337. //
  338. SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE,
  339. (LPARAM) ACCEL_LEVEL_TO_SLIDER_POS(AccelLevel));
  340. //
  341. // Update message based on current acceleration level.
  342. //
  343. UpdateGraphicsText(hDlg, AccelLevel);
  344. if (!bSuccess || gbReadOnly)
  345. {
  346. //
  347. // Disable slider control
  348. //
  349. EnableWindow(hSlider, FALSE);
  350. }
  351. //
  352. // Setup DisableUSWC combobox
  353. //
  354. HWND hEnableUSWC = GetDlgItem(hDlg, IDC_ENABLE_USWC);
  355. if (NULL != hEnableUSWC)
  356. {
  357. CheckDlgButton(hDlg, IDC_ENABLE_USWC, !gbDisableUSWC);
  358. EnableWindow(hEnableUSWC, !bDisableUSWCReadOnly);
  359. }
  360. }
  361. break;
  362. case WM_HSCROLL:
  363. if (GetWindowLongPtr((HWND)lParam, GWLP_ID) == IDC_ACCELERATION_SLIDER)
  364. {
  365. //
  366. // Slider has been moved.
  367. //
  368. HWND hSlider = (HWND) lParam;
  369. //
  370. // Obtain currect slider position.
  371. //
  372. DWORD dwSliderPos = (DWORD) SendMessage(hSlider, TBM_GETPOS, 0, 0L);
  373. //
  374. // Convert slider position to accel level.
  375. //
  376. DWORD AccelNew = SLIDER_POS_TO_ACCEL_LEVEL(dwSliderPos);
  377. //
  378. // If accleration level has been changed, update description, and
  379. // enable apply button.
  380. //
  381. if (AccelNew != AccelLevel)
  382. {
  383. AccelLevel = AccelNew;
  384. UpdateGraphicsText(hDlg, AccelNew);
  385. PropSheet_Changed(GetParent(hDlg), hDlg);
  386. }
  387. }
  388. break;
  389. case WM_COMMAND:
  390. if (IDC_ENABLE_USWC == GET_WM_COMMAND_ID(wParam, lParam))
  391. {
  392. BOOL bDisableUSWC =
  393. (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ENABLE_USWC));
  394. if (gbDisableUSWC != bDisableUSWC)
  395. {
  396. //
  397. // Enable Apply button
  398. //
  399. PropSheet_Changed(GetParent(hDlg), hDlg);
  400. }
  401. }
  402. break;
  403. case WM_NOTIFY:
  404. if (((NMHDR *)lParam)->code == PSN_APPLY)
  405. {
  406. TCHAR szCaption[128];
  407. TCHAR szMessage[256];
  408. BOOL bSuccess = TRUE;
  409. int val = 0;
  410. BOOL bCancel = FALSE;
  411. BOOL bAccelLevelDirty;
  412. BOOL bDisableUSWC;
  413. BOOL bUSWCDirty;
  414. bDisableUSWC =
  415. (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ENABLE_USWC));
  416. bUSWCDirty = (gbDisableUSWC != bDisableUSWC);
  417. bAccelLevelDirty = (AccelLevel != AccelLevelInReg);
  418. //
  419. // Popup dialogs to ask user to apply it dynamically or not.
  420. //
  421. if (bAccelLevelDirty)
  422. {
  423. val = GetDynaCDSPreference();
  424. if (val & DCDSF_ASK)
  425. {
  426. if (!bUSWCDirty)
  427. {
  428. switch (DialogBoxParam(g_hInst,
  429. MAKEINTRESOURCE(DLG_ASKDYNACDS),
  430. hDlg,
  431. AskDynamicApply,
  432. (LPARAM)&val))
  433. {
  434. case 0: // user cancelled
  435. case -1: // dialog could not be displayed
  436. bCancel = TRUE;
  437. break;
  438. }
  439. }
  440. else
  441. {
  442. val = 0;
  443. }
  444. }
  445. }
  446. if ((!(bUSWCDirty || bAccelLevelDirty)) ||
  447. bCancel)
  448. {
  449. //
  450. // Nothing to do
  451. //
  452. SetWindowLongPtr(hDlg,
  453. DWLP_MSGRESULT,
  454. ((!(bUSWCDirty || bAccelLevelDirty)) ?
  455. PSNRET_NOERROR :
  456. PSNRET_INVALID_NOCHANGEPAGE));
  457. break;
  458. }
  459. //
  460. // Acceleration Level
  461. //
  462. if (AccelLevel != AccelLevelInReg)
  463. {
  464. //
  465. // AccelLevel has been changed. save it to registry.
  466. //
  467. HKEY hKeyAccelLevel;
  468. bSuccess = FALSE;
  469. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  470. gszRegistryPath,
  471. 0,
  472. KEY_ALL_ACCESS,
  473. &hKeyAccelLevel) == ERROR_SUCCESS)
  474. {
  475. if (AccelLevel == ACCELERATION_FULL)
  476. {
  477. //
  478. // If acceration is set to ACCELERATION_FULL (default)
  479. // remove registry value.
  480. //
  481. if (RegDeleteValue(hKeyAccelLevel,
  482. SZ_HW_ACCELERATION) == ERROR_SUCCESS)
  483. {
  484. bSuccess = TRUE;
  485. }
  486. }
  487. else
  488. {
  489. //
  490. // Otherwise, save it to registry.
  491. //
  492. if (RegSetValueEx(hKeyAccelLevel,
  493. SZ_HW_ACCELERATION,
  494. NULL, REG_DWORD,
  495. (LPBYTE) &AccelLevel,
  496. sizeof(AccelLevel)) == ERROR_SUCCESS)
  497. {
  498. bSuccess = TRUE;
  499. }
  500. }
  501. RegCloseKey(hKeyAccelLevel);
  502. }
  503. if (bSuccess)
  504. {
  505. //
  506. // Update last saved data.
  507. //
  508. AccelLevelInReg = AccelLevel;
  509. //
  510. // Apply it dynamically?
  511. //
  512. if ((val & DCDSF_DYNA) == DCDSF_DYNA)
  513. {
  514. // Apply it dynamically.
  515. ChangeDisplaySettings(NULL, CDS_RAWMODE);
  516. }
  517. }
  518. }
  519. //
  520. // Disable USWC
  521. //
  522. if (bSuccess && bUSWCDirty)
  523. {
  524. HKEY hKeyGraphicsDrivers = NULL;
  525. bSuccess = FALSE;
  526. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  527. REGSTR_GRAPHICS_DRIVERS,
  528. 0,
  529. KEY_ALL_ACCESS,
  530. &hKeyGraphicsDrivers) == ERROR_SUCCESS)
  531. {
  532. if (bDisableUSWC)
  533. {
  534. //
  535. // Create the key
  536. //
  537. HKEY hKeyDisableUSWC = NULL;
  538. DWORD Disposition;
  539. bSuccess = (RegCreateKeyEx(hKeyGraphicsDrivers,
  540. REGSTR_DISABLE_USWC,
  541. 0,
  542. NULL,
  543. REG_OPTION_NON_VOLATILE,
  544. KEY_READ,
  545. NULL,
  546. &hKeyDisableUSWC,
  547. &Disposition) == ERROR_SUCCESS);
  548. if (bSuccess)
  549. RegCloseKey(hKeyDisableUSWC);
  550. }
  551. else
  552. {
  553. //
  554. // Delete the key
  555. //
  556. bSuccess =
  557. (RegDeleteKey(hKeyGraphicsDrivers,
  558. REGSTR_DISABLE_USWC) == ERROR_SUCCESS);
  559. }
  560. if (bSuccess)
  561. gbDisableUSWC = bDisableUSWC;
  562. RegCloseKey(hKeyGraphicsDrivers);
  563. }
  564. if (bSuccess)
  565. {
  566. //
  567. // Notify the user it a reboot is needed
  568. //
  569. if ((LoadString(g_hInst,
  570. IDS_WC_CAPTION,
  571. szCaption,
  572. SIZEOF(szCaption) / sizeof(TCHAR)) != 0) &&
  573. (LoadString(g_hInst,
  574. IDS_WC_MESSAGE,
  575. szMessage,
  576. SIZEOF(szMessage) / sizeof(TCHAR)) !=0))
  577. {
  578. MessageBox(hDlg,
  579. szMessage,
  580. szCaption,
  581. MB_OK | MB_ICONINFORMATION);
  582. }
  583. }
  584. }
  585. if (bSuccess)
  586. {
  587. if (bUSWCDirty || (0 == val))
  588. PropSheet_RestartWindows(GetParent(hDlg));
  589. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  590. }
  591. else
  592. {
  593. //
  594. // Notify the user that an unexpected error occured
  595. //
  596. if ((LoadString(g_hInst,
  597. IDS_ERR_CAPTION,
  598. szCaption,
  599. SIZEOF(szCaption) / sizeof(TCHAR)) != 0) &&
  600. (LoadString(g_hInst,
  601. IDS_ERR_MESSAGE,
  602. szMessage,
  603. SIZEOF(szMessage) / sizeof(TCHAR)) !=0))
  604. {
  605. MessageBox(hDlg,
  606. szMessage,
  607. szCaption,
  608. MB_OK | MB_ICONERROR);
  609. }
  610. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  611. }
  612. }
  613. break;
  614. case WM_HELP:
  615. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  616. TEXT("display.hlp"),
  617. HELP_WM_HELP,
  618. (DWORD_PTR)(LPTSTR)sc_PerformanceHelpIds);
  619. break;
  620. case WM_CONTEXTMENU:
  621. WinHelp((HWND)wParam,
  622. TEXT("display.hlp"),
  623. HELP_CONTEXTMENU,
  624. (DWORD_PTR)(LPTSTR)sc_PerformanceHelpIds);
  625. break;
  626. default:
  627. return FALSE;
  628. }
  629. return TRUE;
  630. }