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.

863 lines
26 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: sethc.c
  3. *
  4. * Copyright (c) 1997, Microsoft Corporation
  5. *
  6. * SetHC -- exe to set or clear high contrast state.
  7. *
  8. * History:
  9. * 02-01-97 Fritz Sands Created
  10. * Bug fixes : a-anilk June 99
  11. \***************************************************************************/
  12. /***************************************************************************
  13. * Use the following define if for some reason we have to go back to using
  14. * a message loop to let shell have time to update the UI
  15. *
  16. #define NEED_MSG_PUMP
  17. **************************************************************************/
  18. #ifndef RC_INVOKED
  19. #include <nt.h>
  20. #include <ntrtl.h>
  21. #include <nturtl.h>
  22. #endif
  23. #include <windows.h>
  24. #include <winuserp.h>
  25. #include <cpl.h>
  26. #include <stdarg.h>
  27. #include <stdlib.h>
  28. #include <WININET.H>
  29. #include <shlobj.h>
  30. #include <objbase.h>
  31. #include <shlguid.h>
  32. #include <uxthemep.h>
  33. #include "access.h"
  34. #pragma hdrstop
  35. HINSTANCE g_hInstance;
  36. #ifdef DBG
  37. #define DBPRINTF MyOutputDebugString
  38. void MyOutputDebugString( LPCTSTR lpOutputString, ...);
  39. #else
  40. #define DBPRINTF 1 ? (void)0 : (void)
  41. #endif
  42. /*
  43. * High Contrast Stuff
  44. */
  45. #define HC_KEY TEXT("Control Panel\\Accessibility\\HighContrast")
  46. #define HIGHCONTRASTSCHEME TEXT("High Contrast Scheme")
  47. #define REGSTR_VAL_FLAGS TEXT("Flags")
  48. #define REGSTR_PATH_APPEARANCE TEXT("Control Panel\\Appearance")
  49. #define REGSTR_PATH_LOOKSCHEMES TEXT("Control Panel\\Appearance\\Schemes")
  50. #define APPEARANCESCHEME REGSTR_PATH_LOOKSCHEMES
  51. #define DEFSCHEMEKEY REGSTR_PATH_APPEARANCE
  52. #define DEFSCHEMENAME TEXT("Current")
  53. #define WHITEBLACK_HC TEXT("High Contrast Black (large)")
  54. #define CURHCSCHEME TEXT("Volatile HC Scheme")
  55. // the extension for an appearance filename
  56. #define THEME_EXT L".msstyles"
  57. // the following is a Windows Classic color scheme or a THEME_EXT file name
  58. #define PRE_HC_SCHEME TEXT("Pre-High Contrast Scheme")
  59. // the following is the color scheme when pre-HC was a .mstheme
  60. #define PRE_HC_THM_COLOR TEXT("Pre-High Contrast Color")
  61. // the following is the font size when pre-HC was a .mstheme
  62. #define PRE_HC_THM_SIZE TEXT("Pre-High Contrast Size")
  63. // the following is the wallpaper for pre-HC
  64. #define PRE_HC_WALLPAPER TEXT("Pre-High Contrast Wallpaper")
  65. // increase this value so we can store a theme filename
  66. #ifdef MAX_SCHEME_NAME_SIZE
  67. #undef MAX_SCHEME_NAME_SIZE
  68. #endif
  69. #define MAX_SCHEME_NAME_SIZE 512
  70. #define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])
  71. /*
  72. * Note -- this must match the desktop applet
  73. */
  74. #define SCHEME_VERSION 2 // Ver 2 == Unicode
  75. typedef struct {
  76. SHORT version;
  77. WORD wDummy; // for alignment
  78. NONCLIENTMETRICS ncm;
  79. LOGFONT lfIconTitle;
  80. COLORREF rgb[COLOR_MAX];
  81. } SCHEMEDATA;
  82. typedef DWORD (WINAPI* PFNDIALOGRTN)(BOOL);
  83. PFNDIALOGRTN g_aRtn[] = {
  84. NULL,
  85. StickyKeysNotification, //ACCESS_STICKYKEYS
  86. FilterKeysNotification, //ACCESS_FILTERKEYS
  87. ToggleKeysNotification, //ACCESS_TOGGLEKEYS
  88. MouseKeysNotification, //ACCESS_MOUSEKEYS
  89. HighContNotification, //ACCESS_HIGHCONTRAST
  90. };
  91. /***************************************************************************
  92. * GetRegValue
  93. *
  94. * Passed the key, and the identifier, return the string data from the
  95. * registry.
  96. ***************************************************************************/
  97. long GetRegValue(LPWSTR RegKey, LPWSTR RegEntry, LPWSTR RegVal, long Size)
  98. {
  99. HKEY hReg; // Registry handle for schemes
  100. DWORD Type; // Type of value
  101. long retval;
  102. retval = RegCreateKey(HKEY_CURRENT_USER, RegKey, &hReg);
  103. if (retval != ERROR_SUCCESS)
  104. return retval;
  105. retval = RegQueryValueEx(hReg,
  106. RegEntry,
  107. NULL,
  108. (LPDWORD)&Type,
  109. (LPBYTE)RegVal,
  110. &Size);
  111. RegCloseKey(hReg);
  112. return retval;
  113. }
  114. /***************************************************************************
  115. * SetRegValue
  116. *
  117. * Passed the key, and the identifier, set the string data from the
  118. * registry.
  119. ***************************************************************************/
  120. long SetRegValue(LPTSTR RegKey, LPWSTR RegEntry, LPVOID RegVal, long Size, DWORD Type)
  121. {
  122. HKEY hReg; // Registry handle for schemes
  123. DWORD Reserved = 0;
  124. long retval;
  125. if (RegCreateKey(HKEY_CURRENT_USER,RegKey, &hReg) != ERROR_SUCCESS)
  126. return 0;
  127. // A common error is to omit the `+1', so we just smash the correct
  128. // value into place regardless.
  129. if (Type == REG_SZ)
  130. Size = (lstrlen(RegVal) + 1) * sizeof(WCHAR);
  131. retval = RegSetValueEx(hReg,
  132. RegEntry,
  133. 0,
  134. Type,
  135. RegVal,
  136. Size);
  137. RegCloseKey(hReg);
  138. return retval;
  139. }
  140. /***************************************************************************
  141. * SaveAndRemoveWallpaper
  142. *
  143. * Gets the current wallpaper setting from the system and saves it in the
  144. * accessibility registry entries. No error return as there isn't anything
  145. * we can do.
  146. *
  147. * ISSUE we aren't getting all the active desktop properties; just wallpaper.
  148. * This isn't a regression in that we didn't even restore wallpaper in W2K.
  149. *
  150. ***************************************************************************/
  151. void SaveAndRemoveWallpaper()
  152. {
  153. WCHAR szWallpaper[MAX_SCHEME_NAME_SIZE] = {0};
  154. IActiveDesktop *p;
  155. HRESULT hr;
  156. hr = CoCreateInstance(
  157. &CLSID_ActiveDesktop
  158. , NULL
  159. , CLSCTX_INPROC_SERVER
  160. , &IID_IActiveDesktop
  161. , (void **)&p);
  162. if (SUCCEEDED(hr))
  163. {
  164. hr = p->lpVtbl->GetWallpaper(p, szWallpaper, MAX_SCHEME_NAME_SIZE, 0);
  165. if (SUCCEEDED(hr))
  166. {
  167. // save the current wallpaper setting
  168. SetRegValue(HC_KEY, PRE_HC_WALLPAPER, szWallpaper, 0, REG_SZ);
  169. // now remove the wallpaper, if necessary
  170. if (szWallpaper[0])
  171. {
  172. szWallpaper[0] = 0;
  173. hr = p->lpVtbl->SetWallpaper(p, szWallpaper, 0);
  174. if (SUCCEEDED(hr))
  175. hr = p->lpVtbl->ApplyChanges(p, AD_APPLY_ALL);
  176. }
  177. }
  178. p->lpVtbl->Release(p);
  179. }
  180. }
  181. /***************************************************************************
  182. * RestoreWallpaper
  183. *
  184. * Restores the pre-high contrast wallpaper setting. Reads the setting
  185. * stored in the accessibility registry entries and restores the system
  186. * setting. No error return as there isn't anything we can do.
  187. *
  188. ***************************************************************************/
  189. void RestoreWallpaper()
  190. {
  191. long lRv;
  192. TCHAR szWallpaper[MAX_SCHEME_NAME_SIZE] = {0};
  193. lRv = GetRegValue(HC_KEY, PRE_HC_WALLPAPER, szWallpaper, MAX_SCHEME_NAME_SIZE);
  194. if (lRv == ERROR_SUCCESS && szWallpaper[0])
  195. {
  196. IActiveDesktop *p;
  197. HRESULT hr;
  198. hr = CoCreateInstance(
  199. &CLSID_ActiveDesktop
  200. , NULL
  201. , CLSCTX_INPROC_SERVER
  202. , &IID_IActiveDesktop
  203. , (void **)&p);
  204. if (SUCCEEDED(hr))
  205. {
  206. hr = p->lpVtbl->SetWallpaper(p, szWallpaper, 0);
  207. if (SUCCEEDED(hr))
  208. hr = p->lpVtbl->ApplyChanges(p, AD_APPLY_ALL);
  209. p->lpVtbl->Release(p);
  210. }
  211. }
  212. }
  213. /***************************************************************************
  214. * AppearanceRestored
  215. *
  216. * lpszName [in] the name of a theme file (mstheme).
  217. *
  218. * Function returns TRUE if lpszName is a theme file and it was restored
  219. * otherwise it returns FALSE. May return TRUE if restoring the theme
  220. * fails (not much we can do if theme api's fail).
  221. *
  222. ***************************************************************************/
  223. BOOL AppearanceRestored(LPCWSTR lpszName)
  224. {
  225. HRESULT hr;
  226. HTHEMEFILE hThemeFile;
  227. int cch = lstrlen(lpszName) - lstrlen(THEME_EXT);
  228. TCHAR szColor[MAX_SCHEME_NAME_SIZE] = {0};
  229. TCHAR szSize[MAX_SCHEME_NAME_SIZE] = {0};
  230. if (cch <= 0 || lstrcmpi(&lpszName[cch], THEME_EXT))
  231. {
  232. DBPRINTF(TEXT("AppearanceRestored: %s is not a theme file\r\n"), lpszName);
  233. return FALSE; // this isn't a theme file
  234. }
  235. // This is a theme file, get the color and size parts of the theme
  236. GetRegValue(HC_KEY, PRE_HC_THM_COLOR, szColor, ARRAYSIZE(szColor));
  237. GetRegValue(HC_KEY, PRE_HC_THM_SIZE, szSize, ARRAYSIZE(szSize));
  238. // Load the theme file, color and size then apply it
  239. hr = OpenThemeFile(lpszName, szColor, szSize, &hThemeFile, TRUE);
  240. DBPRINTF(TEXT("AppearanceRestored: OpenThemeFile(%s, %s, %s) returned 0x%x\r\n"), lpszName, szColor, szSize, hr);
  241. if (SUCCEEDED(hr))
  242. {
  243. hr = ApplyTheme(hThemeFile, AT_LOAD_SYSMETRICS | AT_SYNC_LOADMETRICS, NULL);
  244. DBPRINTF(TEXT("AppearanceRestored: ApplyTheme() returned 0x%x\r\n"), hr);
  245. CloseThemeFile(hThemeFile);
  246. }
  247. return TRUE;
  248. }
  249. /***************************************************************************
  250. * DelRegValue
  251. *
  252. * Passed the key and the subkey, delete the subkey.
  253. *
  254. ***************************************************************************/
  255. long DelRegValue(LPTSTR RegKey, LPTSTR RegEntry)
  256. {
  257. HKEY hReg; // Registry handle for schemes
  258. DWORD Reserved = 0;
  259. long retval;
  260. retval = RegCreateKey(HKEY_CURRENT_USER,RegKey, &hReg);
  261. if (retval != ERROR_SUCCESS)
  262. return retval;
  263. retval = RegDeleteValue(hReg, RegEntry);
  264. RegCloseKey(hReg);
  265. return retval;
  266. }
  267. #define COLOR_MAX_400 (COLOR_INFOBK + 1)
  268. void FAR SetMagicColors(HDC, DWORD, WORD);
  269. /***************************************************************************
  270. *
  271. *
  272. * SetCurrentSchemeName
  273. *
  274. * Input: szName -> name of scheme or theme to become current
  275. * Output: Boolean success/failure
  276. *
  277. ***************************************************************************/
  278. typedef LONG (CALLBACK *APPLETPROC)(HWND, UINT, LPARAM, LPARAM);
  279. typedef BOOL (CALLBACK *SETSCHEME)(LPCTSTR);
  280. typedef BOOL (CALLBACK *SETSCHEMEA)(LPCSTR);
  281. BOOL SetCurrentSchemeName(LPCWSTR lpszName, BOOL fNoReg)
  282. {
  283. BOOL fRc = FALSE;
  284. if (fNoReg)
  285. {
  286. // Setting a non-persistent scheme; we come to this code path for
  287. // both setting or unsetting HC via hot keys
  288. HKEY hkSchemes;
  289. // For Whistler, because it may confuse users, we are always turning off
  290. // theming and any wallpaper. Otherwise, sometimes they'll loose these
  291. // settings (when they log off and log back on) and sometimes they won't
  292. // (when they use the hot keys to turn HC off).
  293. DBPRINTF(TEXT("SetCurrentSchemeName: To %s w/o persisting to registry\r\n"), lpszName);
  294. if (IsThemeActive())
  295. {
  296. DBPRINTF(TEXT("SetCurrentSchemeName: Turning off active Themes\r\n"));
  297. ApplyTheme(NULL, 0, NULL);
  298. }
  299. if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_LOOKSCHEMES, &hkSchemes) == ERROR_SUCCESS) {
  300. SCHEMEDATA sd;
  301. DWORD dwType, dwSize;
  302. BOOL b;
  303. HDC hdc;
  304. int iColors[COLOR_MAX];
  305. int i;
  306. COLORREF rgbColors[COLOR_MAX];
  307. dwType = REG_BINARY;
  308. dwSize = sizeof(sd);
  309. if (RegQueryValueEx(hkSchemes, lpszName, NULL, &dwType, (LPBYTE)&sd, &dwSize) == ERROR_SUCCESS) {
  310. int n;
  311. if (sd.version != SCHEME_VERSION) {
  312. RegCloseKey(hkSchemes);
  313. return FALSE;
  314. }
  315. n = (int)(dwSize - (sizeof(sd) - sizeof(sd.rgb))) / sizeof(COLORREF);
  316. sd.ncm.cbSize = sizeof(NONCLIENTMETRICS);
  317. b = SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(sd.ncm),
  318. (void far *)&sd.ncm,
  319. 0);
  320. b = SystemParametersInfo(SPI_SETICONTITLELOGFONT, sizeof(LOGFONT),
  321. (void far *)(LPLOGFONT)&sd.lfIconTitle,
  322. 0);
  323. if (n == COLOR_MAX_400)
  324. {
  325. sd.rgb[COLOR_HOTLIGHT] = sd.rgb[COLOR_ACTIVECAPTION];
  326. sd.rgb[COLOR_GRADIENTACTIVECAPTION] = RGB(0,0,0);
  327. sd.rgb[COLOR_GRADIENTINACTIVECAPTION] = RGB(0,0,0);
  328. }
  329. #if(WINVER >= 0x0501)
  330. // new Whistler colors
  331. sd.rgb[COLOR_MENUBAR] = sd.rgb[COLOR_MENU];
  332. sd.rgb[COLOR_MENUHILIGHT] = sd.rgb[COLOR_MENUTEXT];
  333. // reset "flatmenu" and "dropshadows" settings
  334. SystemParametersInfo(SPI_SETFLATMENU, 0, IntToPtr(FALSE), SPIF_SENDCHANGE);
  335. SystemParametersInfo(SPI_SETDROPSHADOW, 0, IntToPtr(FALSE), SPIF_SENDCHANGE);
  336. #endif /* WINVER >= 0x0501 */
  337. //
  338. // restore magic colors back to Win31 defaults.
  339. //
  340. hdc = GetDC(NULL);
  341. SetMagicColors(hdc, 0x00c0dcc0, 8); // money green
  342. SetMagicColors(hdc, 0x00f0caa6, 9); // IBM blue
  343. SetMagicColors(hdc, 0x00f0fbff, 246); // off white
  344. ReleaseDC(NULL, hdc);
  345. for (i=0; i<COLOR_MAX; i++)
  346. {
  347. iColors[i] = i;
  348. rgbColors[i] = sd.rgb[i] & 0x00FFFFFF;
  349. }
  350. SetSysColors(COLOR_MAX, iColors, rgbColors);
  351. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 5000, NULL);
  352. }
  353. RegCloseKey(hkSchemes);
  354. fRc = TRUE;
  355. }
  356. } else
  357. {
  358. /*
  359. * We need to persist this setting. First see if lpszName is a
  360. * theme file and restore it if it is
  361. */
  362. fRc = AppearanceRestored(lpszName);
  363. if (!fRc)
  364. {
  365. /*
  366. * The user is in "Windows Classic" appearance so use desk CPL to restore
  367. */
  368. HINSTANCE hinst = LoadLibrary(TEXT("DESK.CPL"));
  369. if (NULL != hinst)
  370. {
  371. APPLETPROC ap = (APPLETPROC)GetProcAddress((HMODULE)hinst, "CPlApplet");
  372. if (ap)
  373. {
  374. if (ap(0, CPL_INIT, 0, 0))
  375. {
  376. SETSCHEME ss = (SETSCHEME)GetProcAddress(hinst, "DeskSetCurrentSchemeW");
  377. if (ss)
  378. {
  379. fRc = ss(lpszName);
  380. DBPRINTF(TEXT("SetCurrentSchemeName: DeskSetCurrentSchemeW(%s) returned %d\r\n"), lpszName, fRc);
  381. }
  382. ap(0, CPL_EXIT, 0, 0);
  383. }
  384. }
  385. FreeLibrary(hinst);
  386. }
  387. }
  388. }
  389. return fRc;
  390. }
  391. /***************************************************************************
  392. *
  393. * GetCurrentSchemeName
  394. *
  395. * szBuf [out] Buffer to receive name of scheme (MAXSCHEMENAME) or theme file
  396. * ctchBuf [in] Size of szBuf
  397. * szColor [out] If szBuf is a theme file, the color scheme name
  398. * ctchColor [in] Size of szColor
  399. * szSize [out] If szBuf is a theme file, the font size
  400. * ctchSize [in] Size of szSize
  401. *
  402. * Returns the name of the current scheme. This will be either the name
  403. * of a theme file (if Professional visual style is on) or the name of
  404. * a color scheme (if Windows Classic visual style is on). If the
  405. * current scheme does not have a name, create one (ID_PRE_HC_SCHEME).
  406. *
  407. * If anything goes wrong, there isn't much we can do.
  408. *
  409. ***************************************************************************/
  410. void GetCurrentSchemeName(LPTSTR szBuf, long ctchBuf, LPTSTR szColor, long ctchColor, LPTSTR szSize, long ctchSize)
  411. {
  412. HRESULT hr;
  413. // First try to get a theme filename
  414. hr = GetCurrentThemeName(szBuf, ctchBuf, szColor, ctchColor, szSize, ctchSize);
  415. if (FAILED(hr))
  416. {
  417. // User is in Windows Classic appearance (visual style)
  418. szColor[0] = 0;
  419. szSize[0] = 0;
  420. if (GetRegValue(DEFSCHEMEKEY, DEFSCHEMENAME, szBuf, MAX_SCHEME_NAME_SIZE * sizeof(WCHAR))
  421. != ERROR_SUCCESS)
  422. {
  423. SCHEMEDATA scm;
  424. int i;
  425. /* Load the current scheme into scm */
  426. scm.version = SCHEME_VERSION;
  427. scm.wDummy = 0;
  428. scm.ncm.cbSize = sizeof(NONCLIENTMETRICS);
  429. SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  430. sizeof(NONCLIENTMETRICS),
  431. &scm.ncm,
  432. 0);
  433. SystemParametersInfo(SPI_GETICONTITLELOGFONT,
  434. sizeof(LOGFONT),
  435. &scm.lfIconTitle,
  436. 0);
  437. for (i = 0; i < COLOR_MAX; i++) {
  438. scm.rgb[i] = GetSysColor(i);
  439. }
  440. /* Now give it a name */
  441. SetRegValue(APPEARANCESCHEME, PRE_HC_SCHEME, &scm, sizeof(scm), REG_BINARY);
  442. /*
  443. * NOTE -- PRE_HC_SCHEME in APPEARANCESCHEME is actual scheme data, NOT a scheme
  444. * name, This data has info about settings if the user did not have a
  445. * desktop scheme in place before switching to high contrast mode.
  446. */
  447. wcscpy(szBuf, PRE_HC_SCHEME);
  448. }
  449. }
  450. }
  451. void WINAPI RegQueryStr(
  452. LPWSTR lpDefault,
  453. HKEY hkey,
  454. LPWSTR lpSubKey,
  455. LPWSTR lpValueName,
  456. LPWSTR lpszValue,
  457. DWORD cbData) // note this is bytes, not characters.
  458. {
  459. DWORD dwType;
  460. lstrcpy(lpszValue, lpDefault);
  461. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
  462. RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) lpszValue, &cbData);
  463. RegCloseKey(hkey);
  464. }
  465. }
  466. DWORD WINAPI RegQueryStrDW(
  467. DWORD dwDefault,
  468. HKEY hkey,
  469. LPWSTR lpSubKey,
  470. LPWSTR lpValueName)
  471. {
  472. DWORD dwRet = dwDefault;
  473. WCHAR szTemp[40];
  474. WCHAR szDefault[40];
  475. const LPWSTR pwszd = TEXT("%d");
  476. wsprintf(szDefault, pwszd, dwDefault);
  477. RegQueryStr(
  478. szDefault,
  479. hkey,
  480. lpSubKey,
  481. lpValueName,
  482. szTemp,
  483. sizeof(szTemp));
  484. dwRet = _wtoi(szTemp);
  485. return dwRet;
  486. }
  487. /***************************************************************************
  488. *
  489. *
  490. * SetHighContrast
  491. *
  492. * Input: None
  493. * Output: None
  494. *
  495. * Outline:
  496. *
  497. ***************************************************************************/
  498. int SetHighContrast(BOOL fEnabledOld, BOOL fNoReg)
  499. {
  500. BOOL fOk = 0;
  501. TCHAR szBuf[MAX_SCHEME_NAME_SIZE];
  502. TCHAR szColor[MAX_SCHEME_NAME_SIZE];
  503. TCHAR szSize[MAX_SCHEME_NAME_SIZE];
  504. HIGHCONTRAST hc;
  505. szBuf[0] = TEXT('\0');
  506. if (!fEnabledOld)
  507. {
  508. /*
  509. * Get the current scheme information (create it if necessary)
  510. * Note -- we need to put this in the registry, even in "no registry"
  511. * cases, so we can restore the values.
  512. */
  513. GetCurrentSchemeName(szBuf, MAX_SCHEME_NAME_SIZE, szColor, MAX_SCHEME_NAME_SIZE, szSize, MAX_SCHEME_NAME_SIZE);
  514. DBPRINTF(TEXT("SetHighContrast: Save to registry ThemeFile=%s Color=%s Size=%s\r\n"), szBuf, szColor, szSize);
  515. SetRegValue(HC_KEY, PRE_HC_SCHEME, szBuf, 0, REG_SZ); /* Save it */
  516. SetRegValue(HC_KEY, PRE_HC_THM_COLOR, szColor, 0, REG_SZ);
  517. SetRegValue(HC_KEY, PRE_HC_THM_SIZE, szSize, 0, REG_SZ);
  518. /*
  519. * NOTE -- PRE_HC_SCHEME in HC_KEY is the NAME of the scheme (which may be a made-up
  520. * name) holding the settings before High Contrast was invoked.
  521. */
  522. }
  523. hc.cbSize = sizeof(hc);
  524. SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof hc, &hc, 0);
  525. if ((NULL != hc.lpszDefaultScheme) && (TEXT('\0') != *(hc.lpszDefaultScheme)))
  526. {
  527. lstrcpy(szBuf, hc.lpszDefaultScheme);
  528. }
  529. else
  530. {
  531. /*
  532. * Get the name of the HC scheme. By design, we have to look
  533. * in about fifty places... We get the default one first, then try
  534. * to get better and better ones. That way, when we're done, we have
  535. * the best one that succeeded.
  536. */
  537. lstrcpy(szBuf, WHITEBLACK_HC);
  538. GetRegValue(HC_KEY, HIGHCONTRASTSCHEME, szBuf, sizeof(szBuf));
  539. GetRegValue(DEFSCHEMEKEY, CURHCSCHEME, szBuf, sizeof(szBuf));
  540. }
  541. fOk = SetCurrentSchemeName(szBuf, fNoReg);
  542. if (fOk)
  543. SaveAndRemoveWallpaper();
  544. return (short)fOk;
  545. }
  546. /***************************************************************************
  547. *
  548. *
  549. * ClearHighContrast
  550. *
  551. * Input: None
  552. * Output: None
  553. *
  554. * Outline:
  555. *
  556. * If high contrast is currently on:
  557. *
  558. * Get the PRE_HC_SCHEME.
  559. *
  560. * If able to get it:
  561. *
  562. * Make it the current scheme.
  563. *
  564. * If the name is IDS_PRE_HC_SCHEME, then delete the scheme
  565. * data and set the current scheme name to null. (Clean up.)
  566. *
  567. * End if
  568. *
  569. * Set the key that says that high contrast is now off.
  570. *
  571. * End if
  572. *
  573. ***************************************************************************/
  574. BOOL FAR PASCAL ClearHighContrast(BOOL fNoReg)
  575. {
  576. BOOL fOk = FALSE;
  577. WCHAR szBuf[MAX_SCHEME_NAME_SIZE];
  578. szBuf[0] = '\0';
  579. if (ERROR_SUCCESS == GetRegValue(HC_KEY, PRE_HC_SCHEME, szBuf, sizeof(szBuf)))
  580. {
  581. DBPRINTF(TEXT("ClearHighContrast: Reset to pre-HC scheme %s\r\n"), szBuf);
  582. fOk = SetCurrentSchemeName(szBuf, fNoReg); // reset the scheme
  583. // If persisting this setting, wallpaper may need to be restored.
  584. // If clearing a temporary setting then, to avoid user confusion,
  585. // we turned theming and wallpaper off permanently. Otherwise,
  586. // sometimes they'll loose these settings (when they log off and
  587. // log back on) and sometimes they won't (when they use the hot
  588. // keys to turn HC off).
  589. if (!fNoReg)
  590. {
  591. RestoreWallpaper();
  592. if (lstrcmpi(szBuf, PRE_HC_SCHEME) == 0)
  593. {
  594. DelRegValue(APPEARANCESCHEME, PRE_HC_SCHEME);
  595. DBPRINTF(TEXT("DelRegValue(%s, %s)\r\n"), APPEARANCESCHEME, PRE_HC_SCHEME);
  596. DelRegValue(DEFSCHEMEKEY, DEFSCHEMENAME);
  597. DBPRINTF(TEXT("DelRegValue(%s, %s)\r\n"), DEFSCHEMEKEY, DEFSCHEMENAME);
  598. }
  599. }
  600. }
  601. return fOk;
  602. }
  603. #if NEED_MSG_PUMP
  604. /***************************************************************************\
  605. * WndProc
  606. *
  607. * Processes messages for the main window.
  608. \***************************************************************************/
  609. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  610. {
  611. switch (message)
  612. {
  613. case WM_TIMER:
  614. if (wParam == 1)
  615. {
  616. KillTimer(hWnd, wParam);
  617. DBPRINTF(TEXT("WM_TIMER\r\n"));
  618. DestroyWindow(hWnd);
  619. }
  620. break;
  621. case WM_DESTROY:
  622. PostQuitMessage(0);
  623. break;
  624. default:
  625. return DefWindowProc(hWnd, message, wParam, lParam);
  626. }
  627. return 0;
  628. }
  629. #endif
  630. /***************************************************************************\
  631. * WinMain
  632. *
  633. * History:
  634. * 02-01-97 Fritz Sands Created
  635. * 12-19-00 micw added windowing code so theming calls would work
  636. \***************************************************************************/
  637. int WINAPI WinMain(
  638. HINSTANCE hInstance,
  639. HINSTANCE hPrevInstance,
  640. LPSTR lpszCmdParam,
  641. int nCmdShow)
  642. {
  643. #if NEED_MSG_PUMP
  644. MSG msg;
  645. WNDCLASSEX wcex;
  646. LPTSTR pszWindowClass = TEXT("SetHC"); // message-only window doesn't need localization
  647. HWND hWnd;
  648. #endif
  649. UINT index;
  650. BOOL fSet, fWasSet, fNoReg;
  651. CoInitialize(NULL);
  652. // Safety checks to make sure that it is not run from command line
  653. // Should have 3 characters, And all of them numeric...:a-anilk
  654. if ( strlen(lpszCmdParam) != 3 )
  655. return 0;
  656. for ( index = 0; index < 3 ; index++ )
  657. {
  658. if ( lpszCmdParam[index] < '0' || lpszCmdParam[index] > '9' )
  659. {
  660. return 0;
  661. }
  662. }
  663. fSet = lpszCmdParam[0] - '0';
  664. fWasSet = lpszCmdParam[1] - '0';
  665. fNoReg = lpszCmdParam[2] - '0';
  666. DBPRINTF(TEXT("WinMain: fSet=%d fWasSet=%d fNoReg=%d\r\n"), fSet, fWasSet, fNoReg);
  667. // this is to deal with HighContrast, StickyKey, ToggleKey, FilterKey and MouseKeys
  668. if ( fSet == 2 )
  669. {
  670. // this is which Dialog will be displayed
  671. LONG lPopup = lpszCmdParam[1] - '0';
  672. // This indicate wheather we will actually display the dialog or just do the work without asking
  673. BOOL fNotify = lpszCmdParam[2] - '0';
  674. DBPRINTF(TEXT("WinMain: lPopup=%d fNotify=%d\r\n"), lPopup, fNotify );
  675. // Make sure we don't access outside the bounds of the funtion pointer array
  676. if ( lPopup < 1 || lPopup > 5 )
  677. return 0;
  678. // Index into a table of functions pointers and call the
  679. // funtion to bring up the right hotkey dialog.
  680. g_aRtn[lPopup]( fNotify );
  681. CoUninitialize();
  682. return 1;
  683. }
  684. #if NEED_MSG_PUMP
  685. // Create a message only window to process messages from theme api
  686. wcex.cbSize = sizeof(WNDCLASSEX);
  687. wcex.style = 0;
  688. wcex.lpfnWndProc = (WNDPROC)WndProc;
  689. wcex.cbClsExtra = 0;
  690. wcex.cbWndExtra = 0;
  691. wcex.hInstance = hInstance;
  692. wcex.hIcon = NULL;
  693. wcex.hCursor = NULL;
  694. wcex.hbrBackground = NULL;
  695. wcex.lpszMenuName = NULL;
  696. wcex.lpszClassName = pszWindowClass;
  697. wcex.hIconSm = NULL;
  698. RegisterClassEx(&wcex);
  699. hWnd = CreateWindow(pszWindowClass,NULL,0,0,0,0,0,HWND_MESSAGE,NULL,hInstance,NULL);
  700. if (!hWnd)
  701. {
  702. return 0;
  703. }
  704. #endif
  705. if (fSet)
  706. {
  707. SetHighContrast(fWasSet, fNoReg);
  708. }
  709. else
  710. {
  711. ClearHighContrast(fNoReg);
  712. }
  713. #if NEED_MSG_PUMP
  714. SetTimer(hWnd, 1, 4000, NULL);
  715. // The calls to set/unset visual style require that messages
  716. // be processed. When the timer goes we'll exit.
  717. while (GetMessage(&msg, NULL, 0, 0))
  718. {
  719. TranslateMessage(&msg);
  720. DispatchMessage(&msg);
  721. }
  722. #endif
  723. CoUninitialize();
  724. return 1;
  725. }
  726. #ifdef DEBUG
  727. void MyOutputDebugString( LPCTSTR lpOutputString, ...)
  728. {
  729. TCHAR achBuffer[500];
  730. /* create the output buffer */
  731. va_list args;
  732. va_start(args, lpOutputString);
  733. wvsprintf(achBuffer, lpOutputString, args);
  734. va_end(args);
  735. OutputDebugString(achBuffer);
  736. }
  737. #endif