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.

763 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. #define REGSTR_VAL_DYNASETTINGSCHANGE TEXT("DynaSettingsChange")
  22. //
  23. // Guid for "Troubleshooter" shell extentions
  24. //
  25. GUID g_CLSID_CplExt = { 0xf92e8c40, 0x3d33, 0x11d2,
  26. { 0xb1, 0xaa, 0x08, 0x00, 0x36, 0xa7, 0x5b, 0x03}
  27. };
  28. //
  29. // Global variables
  30. //
  31. //
  32. // Dos display device name
  33. //
  34. TCHAR gszWinDisplayDevice[MAX_PATH];
  35. //
  36. // NT display device name
  37. //
  38. TCHAR gszNtDisplayDevice[MAX_PATH];
  39. //
  40. // Registry path for current device
  41. //
  42. TCHAR gszRegistryPath[MAX_PATH];
  43. //
  44. // Current acceleration level.
  45. //
  46. DWORD AccelLevel = ACCELERATION_FULL;
  47. //
  48. // Last saved acceleration level.
  49. //
  50. DWORD AccelLevelInReg = ACCELERATION_FULL;
  51. //
  52. // Registry security.
  53. //
  54. BOOL gbReadOnly = FALSE;
  55. //
  56. // Is DisableUSWC key present?.
  57. //
  58. BOOL gbDisableUSWC = FALSE;
  59. //
  60. // Context-sentitive help
  61. //
  62. static const DWORD sc_PerformanceHelpIds[] =
  63. {
  64. IDI_MONITOR, IDH_NOHELP,
  65. IDC_DESCRIPTION, IDH_NOHELP,
  66. IDC_ACCELERATION_SLIDER, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_ACCELERATION,
  67. IDC_ACCELERATION_TEXT, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_ACCELERATION,
  68. IDC_ENABLE_USWC, IDH_DISPLAY_SETTINGS_ADVANCED_TROUBLESHOOT_WRITE_COMBINING,
  69. 0, 0
  70. };
  71. void 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(DisplayDevice));
  87. DisplayDevice.cb = sizeof(DisplayDevice);
  88. fSuccess = EnumDisplayDevices(NULL, iEnum, &DisplayDevice, 0);
  89. if(fSuccess)
  90. {
  91. if(0 == lstrcmp(&DisplayDevice.DeviceName[0], pszDisplay))
  92. {
  93. fSuccess = (lstrlen(DisplayDevice.DeviceKey) < cChars);
  94. ASSERT(fSuccess);
  95. if(fSuccess)
  96. {
  97. StringCchCopy(pszDeviceKey, cChars, 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. StringCchCopy(gszWinDisplayDevice, ARRAYSIZE(gszWinDisplayDevice), pDisplayDevice);
  196. bSuccess = TRUE;
  197. GlobalUnlock(stgm.hGlobal);
  198. }
  199. }
  200. //
  201. // let's build registry path for its hardware profile.
  202. //
  203. if (bSuccess)
  204. {
  205. TCHAR szServicePath[MAX_PATH];
  206. bSuccess = FALSE;
  207. if(GetDeviceKey(gszWinDisplayDevice, szServicePath, ARRAYSIZE(szServicePath)))
  208. {
  209. //
  210. // Upcase all character.
  211. //
  212. TCHAR *psz = szServicePath;
  213. while (*psz)
  214. {
  215. *psz = _totupper(*psz);
  216. psz++;
  217. }
  218. //
  219. // Find \SYSTEM from service path
  220. //
  221. psz = _tcsstr(szServicePath,TEXT("\\SYSTEM"));
  222. //
  223. // Skip '\'
  224. //
  225. psz++;
  226. StringCchCopy(gszRegistryPath, ARRAYSIZE(gszRegistryPath), psz);
  227. bSuccess = TRUE;
  228. }
  229. }
  230. if (bSuccess)
  231. {
  232. //
  233. // Read current acceleration level from registry.
  234. //
  235. HKEY hKeyAccelLevel = NULL;
  236. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  237. gszRegistryPath,
  238. 0,
  239. KEY_WRITE | KEY_READ,
  240. &hKeyAccelLevel) != ERROR_SUCCESS)
  241. {
  242. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  243. gszRegistryPath,
  244. 0,
  245. KEY_READ,
  246. &hKeyAccelLevel) != ERROR_SUCCESS)
  247. {
  248. hKeyAccelLevel = NULL;
  249. }
  250. else
  251. {
  252. gbReadOnly = TRUE;
  253. }
  254. }
  255. if (hKeyAccelLevel)
  256. {
  257. DWORD cb = sizeof(AccelLevel);
  258. if (RegQueryValueEx(hKeyAccelLevel,
  259. SZ_HW_ACCELERATION,
  260. NULL,NULL,
  261. (LPBYTE) &AccelLevel,
  262. &cb) == ERROR_SUCCESS)
  263. {
  264. //
  265. // Update last saved accel level.
  266. //
  267. AccelLevelInReg = AccelLevel;
  268. }
  269. else
  270. {
  271. //
  272. // If there is no registry value, assume full acceleration.
  273. //
  274. AccelLevelInReg = AccelLevel = ACCELERATION_FULL;
  275. }
  276. RegCloseKey(hKeyAccelLevel);
  277. bSuccess = TRUE;
  278. }
  279. }
  280. //
  281. // Read current DisableUSWC status.
  282. //
  283. HKEY hKeyGraphicsDrivers = NULL;
  284. bDisableUSWCReadOnly = FALSE;
  285. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  286. REGSTR_GRAPHICS_DRIVERS,
  287. 0,
  288. KEY_WRITE | KEY_READ,
  289. &hKeyGraphicsDrivers) != ERROR_SUCCESS)
  290. {
  291. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  292. REGSTR_GRAPHICS_DRIVERS,
  293. 0,
  294. KEY_READ,
  295. &hKeyGraphicsDrivers) != ERROR_SUCCESS)
  296. {
  297. hKeyGraphicsDrivers = NULL;
  298. }
  299. else
  300. {
  301. bDisableUSWCReadOnly = TRUE;
  302. }
  303. }
  304. if (NULL != hKeyGraphicsDrivers)
  305. {
  306. HKEY hKeyDisableUSWC = NULL;
  307. gbDisableUSWC =
  308. (RegOpenKeyEx(hKeyGraphicsDrivers,
  309. REGSTR_DISABLE_USWC,
  310. 0,
  311. KEY_READ,
  312. &hKeyDisableUSWC) == ERROR_SUCCESS);
  313. if (NULL != hKeyDisableUSWC)
  314. RegCloseKey(hKeyDisableUSWC);
  315. RegCloseKey(hKeyGraphicsDrivers);
  316. }
  317. }
  318. //
  319. // Setup slider.
  320. //
  321. HWND hSlider = GetDlgItem(hDlg, IDC_ACCELERATION_SLIDER);
  322. //
  323. // Slider range is between ACCEL_FULL and ACCEL_NONE.
  324. //
  325. SendMessage(hSlider, TBM_SETRANGE, (WPARAM)FALSE,
  326. MAKELPARAM(ACCELERATION_FULL, ACCELERATION_NONE));
  327. //
  328. // Set currect slider position based on current accel level.
  329. //
  330. SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE,
  331. (LPARAM) ACCEL_LEVEL_TO_SLIDER_POS(AccelLevel));
  332. //
  333. // Update message based on current acceleration level.
  334. //
  335. UpdateGraphicsText(hDlg, AccelLevel);
  336. if (!bSuccess || gbReadOnly)
  337. {
  338. //
  339. // Disable slider control
  340. //
  341. EnableWindow(hSlider, FALSE);
  342. }
  343. //
  344. // Setup DisableUSWC combobox
  345. //
  346. HWND hEnableUSWC = GetDlgItem(hDlg, IDC_ENABLE_USWC);
  347. if (NULL != hEnableUSWC)
  348. {
  349. CheckDlgButton(hDlg, IDC_ENABLE_USWC, !gbDisableUSWC);
  350. EnableWindow(hEnableUSWC, !bDisableUSWCReadOnly);
  351. }
  352. }
  353. break;
  354. case WM_HSCROLL:
  355. if (GetWindowLongPtr((HWND)lParam, GWLP_ID) == IDC_ACCELERATION_SLIDER)
  356. {
  357. //
  358. // Slider has been moved.
  359. //
  360. HWND hSlider = (HWND) lParam;
  361. //
  362. // Obtain currect slider position.
  363. //
  364. DWORD dwSliderPos = (DWORD) SendMessage(hSlider, TBM_GETPOS, 0, 0L);
  365. //
  366. // Convert slider position to accel level.
  367. //
  368. DWORD AccelNew = SLIDER_POS_TO_ACCEL_LEVEL(dwSliderPos);
  369. //
  370. // If accleration level has been changed, update description, and
  371. // enable apply button.
  372. //
  373. if (AccelNew != AccelLevel)
  374. {
  375. AccelLevel = AccelNew;
  376. UpdateGraphicsText(hDlg, AccelNew);
  377. PropSheet_Changed(GetParent(hDlg), hDlg);
  378. }
  379. }
  380. break;
  381. case WM_COMMAND:
  382. if (IDC_ENABLE_USWC == GET_WM_COMMAND_ID(wParam, lParam))
  383. {
  384. BOOL bDisableUSWC =
  385. (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ENABLE_USWC));
  386. if (gbDisableUSWC != bDisableUSWC)
  387. {
  388. //
  389. // Enable Apply button
  390. //
  391. PropSheet_Changed(GetParent(hDlg), hDlg);
  392. }
  393. }
  394. break;
  395. case WM_NOTIFY:
  396. if (((NMHDR *)lParam)->code == PSN_APPLY)
  397. {
  398. TCHAR szCaption[128];
  399. TCHAR szMessage[256];
  400. BOOL bSuccess = TRUE;
  401. int val = 0;
  402. BOOL bCancel = FALSE;
  403. BOOL bAccelLevelDirty;
  404. BOOL bDisableUSWC;
  405. BOOL bUSWCDirty;
  406. bDisableUSWC =
  407. (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ENABLE_USWC));
  408. bUSWCDirty = (gbDisableUSWC != bDisableUSWC);
  409. bAccelLevelDirty = (AccelLevel != AccelLevelInReg);
  410. //
  411. // Popup dialogs to ask user to apply it dynamically or not.
  412. //
  413. if (bAccelLevelDirty)
  414. {
  415. val = GetDynaCDSPreference();
  416. if (val & DCDSF_ASK)
  417. {
  418. if (!bUSWCDirty)
  419. {
  420. switch (DialogBoxParam(g_hInst,
  421. MAKEINTRESOURCE(DLG_ASKDYNACDS),
  422. hDlg,
  423. AskDynamicApply,
  424. (LPARAM)&val))
  425. {
  426. case 0: // user cancelled
  427. case -1: // dialog could not be displayed
  428. bCancel = TRUE;
  429. break;
  430. }
  431. }
  432. else
  433. {
  434. val = 0;
  435. }
  436. }
  437. }
  438. if ((!(bUSWCDirty || bAccelLevelDirty)) ||
  439. bCancel)
  440. {
  441. //
  442. // Nothing to do
  443. //
  444. SetWindowLongPtr(hDlg,
  445. DWLP_MSGRESULT,
  446. ((!(bUSWCDirty || bAccelLevelDirty)) ?
  447. PSNRET_NOERROR :
  448. PSNRET_INVALID_NOCHANGEPAGE));
  449. break;
  450. }
  451. //
  452. // Acceleration Level
  453. //
  454. if (AccelLevel != AccelLevelInReg)
  455. {
  456. //
  457. // AccelLevel has been changed. save it to registry.
  458. //
  459. HKEY hKeyAccelLevel;
  460. bSuccess = FALSE;
  461. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  462. gszRegistryPath,
  463. 0,
  464. KEY_WRITE,
  465. &hKeyAccelLevel) == ERROR_SUCCESS)
  466. {
  467. if (RegSetValueEx(hKeyAccelLevel,
  468. SZ_HW_ACCELERATION,
  469. NULL, REG_DWORD,
  470. (LPBYTE) &AccelLevel,
  471. sizeof(AccelLevel)) == ERROR_SUCCESS)
  472. {
  473. bSuccess = TRUE;
  474. }
  475. RegCloseKey(hKeyAccelLevel);
  476. }
  477. if (bSuccess)
  478. {
  479. //
  480. // Update last saved data.
  481. //
  482. AccelLevelInReg = AccelLevel;
  483. //
  484. // Apply it dynamically?
  485. //
  486. if ((val & DCDSF_DYNA) == DCDSF_DYNA)
  487. {
  488. // Apply it dynamically.
  489. ChangeDisplaySettings(NULL, CDS_RAWMODE);
  490. }
  491. }
  492. }
  493. //
  494. // Disable USWC
  495. //
  496. if (bSuccess && bUSWCDirty)
  497. {
  498. HKEY hKeyGraphicsDrivers = NULL;
  499. bSuccess = FALSE;
  500. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  501. REGSTR_GRAPHICS_DRIVERS,
  502. 0,
  503. KEY_WRITE,
  504. &hKeyGraphicsDrivers) == ERROR_SUCCESS)
  505. {
  506. if (bDisableUSWC)
  507. {
  508. //
  509. // Create the key
  510. //
  511. HKEY hKeyDisableUSWC = NULL;
  512. DWORD Disposition;
  513. bSuccess = (RegCreateKeyEx(hKeyGraphicsDrivers,
  514. REGSTR_DISABLE_USWC,
  515. 0,
  516. NULL,
  517. REG_OPTION_NON_VOLATILE,
  518. KEY_READ,
  519. NULL,
  520. &hKeyDisableUSWC,
  521. &Disposition) == ERROR_SUCCESS);
  522. if (bSuccess)
  523. RegCloseKey(hKeyDisableUSWC);
  524. }
  525. else
  526. {
  527. //
  528. // Delete the key
  529. //
  530. bSuccess =
  531. (RegDeleteKey(hKeyGraphicsDrivers,
  532. REGSTR_DISABLE_USWC) == ERROR_SUCCESS);
  533. }
  534. if (bSuccess)
  535. gbDisableUSWC = bDisableUSWC;
  536. RegCloseKey(hKeyGraphicsDrivers);
  537. }
  538. if (bSuccess)
  539. {
  540. //
  541. // Notify the user it a reboot is needed
  542. //
  543. if ((LoadString(g_hInst,
  544. IDS_WC_CAPTION,
  545. szCaption,
  546. ARRAYSIZE(szCaption)) != 0) &&
  547. (LoadString(g_hInst,
  548. IDS_WC_MESSAGE,
  549. szMessage,
  550. ARRAYSIZE(szMessage)) !=0))
  551. {
  552. MessageBox(hDlg,
  553. szMessage,
  554. szCaption,
  555. MB_OK | MB_ICONINFORMATION);
  556. }
  557. }
  558. }
  559. if (bSuccess)
  560. {
  561. if (bUSWCDirty || (0 == val))
  562. PropSheet_RestartWindows(GetParent(hDlg));
  563. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  564. }
  565. else
  566. {
  567. //
  568. // Notify the user that an unexpected error occured
  569. //
  570. if ((LoadString(g_hInst,
  571. IDS_ERR_CAPTION,
  572. szCaption,
  573. ARRAYSIZE(szCaption)) != 0) &&
  574. (LoadString(g_hInst,
  575. IDS_ERR_MESSAGE,
  576. szMessage,
  577. ARRAYSIZE(szMessage)) !=0))
  578. {
  579. MessageBox(hDlg,
  580. szMessage,
  581. szCaption,
  582. MB_OK | MB_ICONERROR);
  583. }
  584. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  585. }
  586. }
  587. break;
  588. case WM_HELP:
  589. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  590. TEXT("display.hlp"),
  591. HELP_WM_HELP,
  592. (DWORD_PTR)(LPTSTR)sc_PerformanceHelpIds);
  593. break;
  594. case WM_CONTEXTMENU:
  595. WinHelp((HWND)wParam,
  596. TEXT("display.hlp"),
  597. HELP_CONTEXTMENU,
  598. (DWORD_PTR)(LPTSTR)sc_PerformanceHelpIds);
  599. break;
  600. default:
  601. return FALSE;
  602. }
  603. return TRUE;
  604. }