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.

1044 lines
31 KiB

  1. // **************************************************************************
  2. // Access.c
  3. //
  4. // Accessability Property sheet page creator
  5. //
  6. // **************************************************************************
  7. #include "Access.h"
  8. #ifdef UNICODE // Windows uses UNICODE
  9. #define _UNICODE // but tchar.h uses _UNICODE
  10. #endif
  11. DWORD g_dwOrigFKFlags;
  12. BOOL g_bFKOn;
  13. #include <stdlib.h>
  14. #include <stddef.h>
  15. #include <tchar.h>
  16. #define OLDDISABLED 32760
  17. #ifndef FKF_VALID
  18. #define FKF_VALID 0x0000007F
  19. #endif
  20. #ifndef SKF_VALID
  21. #define SKF_VALID 0x000001FF
  22. #endif
  23. #ifndef MKF_VALID
  24. #define MKF_VALID 0x000000FF
  25. #endif
  26. #ifndef ATF_VALID
  27. #define ATF_VALID 0x00000003
  28. #endif
  29. #ifndef SSF_VALID
  30. #define SSF_VALID 0x00000007
  31. #endif
  32. #ifndef TKF_VALID
  33. #define TKF_VALID 0x0000003F
  34. #endif
  35. //////////////////////////////////////////////////////////////////////////
  36. // collection of data that represents the saved accessability state
  37. typedef struct ACCSTATE // as
  38. {
  39. // Keyboard property page
  40. STICKYKEYS sk;
  41. FILTERKEYS fk;
  42. TOGGLEKEYS tk;
  43. BOOL fExtraKeyboardHelp;
  44. // Sound Property page
  45. SOUNDSENTRY ss;
  46. BOOL fShowSounds;
  47. // Display Property page
  48. HIGHCONTRAST hc;
  49. TCHAR szDefaultScheme[256]; // hc.lpszDefaultScheme
  50. CARET_SETTINGS cs;
  51. // Mouse Property page
  52. MOUSEKEYS mk;
  53. // General Property page
  54. BOOL fShowWarnMsgOnFeatureActivate;
  55. BOOL fPlaySndOnFeatureActivate;
  56. ACCESSTIMEOUT ato;
  57. SERIALKEYS serk;
  58. TCHAR szActivePort[MAX_PATH]; // serk.szActivePort
  59. TCHAR szPort[MAX_PATH]; // serk.szPort
  60. } ACCSTATE, *PACCSTATE;
  61. //////////////////////////////////////////////////////////////////////////
  62. extern BOOL g_SPISetValue = FALSE;
  63. static ACCSTATE s_asOrg; // original settings from app start-up
  64. static ACCSTATE s_asPrev; // previous saved settings
  65. extern BOOL g_fWinNT = -1; // TRUE if we're running on NT and must
  66. // disable some features
  67. extern BOOL g_fSaveSettings = TRUE;
  68. extern BOOL g_fShowWarnMsgOnFeatureActivate = TRUE;
  69. extern BOOL g_fPlaySndOnFeatureActivate = TRUE;
  70. extern BOOL g_fCopyToLogon = FALSE;
  71. extern BOOL g_fCopyToDefault = FALSE;
  72. // Keyboard property page
  73. // extern STICKYKEYS g_sk = {0};
  74. STICKYKEYS g_sk;
  75. FILTERKEYS g_fk;
  76. // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
  77. // and g_nLastWait are part of FilterKeys
  78. DWORD g_dwLastBounceKeySetting = 0;
  79. DWORD g_nLastRepeatDelay = 0;
  80. DWORD g_nLastRepeatRate = 0;
  81. DWORD g_nLastWait = 0;
  82. TOGGLEKEYS g_tk;
  83. BOOL g_fExtraKeyboardHelp = TRUE;
  84. // Sound Property page
  85. SOUNDSENTRY g_ss;
  86. BOOL g_fShowSounds;
  87. // Display Property page
  88. HIGHCONTRAST g_hc;
  89. CARET_SETTINGS g_cs;
  90. // Mouse Property page
  91. MOUSEKEYS g_mk;
  92. // General Property page
  93. ACCESSTIMEOUT g_ato;
  94. SERIALKEYS g_serk;
  95. TCHAR g_szActivePort[MAX_PATH];
  96. TCHAR g_szPort[MAX_PATH];
  97. #define CONTROL_PANEL_DESKTOP TEXT("Control Panel\\Desktop")
  98. #define CURSOR_BLINK_RATE TEXT("CursorBlinkRate")
  99. #define DEFAULT_BLINK_RATE 530
  100. //////////////////////////////////////////////////////////////////////////
  101. void CopyHighContrast(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc)
  102. {
  103. LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme;
  104. memcpy(phcDest, phcSrc, sizeof(*phcDest));
  105. phcDest->lpszDefaultScheme = lpszDefaultScheme;
  106. if (NULL != phcDest->lpszDefaultScheme)
  107. {
  108. lstrcpy(phcDest->lpszDefaultScheme, phcSrc->lpszDefaultScheme);
  109. }
  110. }
  111. //////////////////////////////////////////////////////////////////////////
  112. BOOL IsHighContrastEqual(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc)
  113. {
  114. BOOL fIsEqual = FALSE;
  115. LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme;
  116. // Temporarily make the pointers match
  117. phcDest->lpszDefaultScheme = phcSrc->lpszDefaultScheme;
  118. // match the bits of the structures and the pointed to data
  119. fIsEqual = (0 == memcmp(phcDest, phcSrc, sizeof(*phcDest)) &&
  120. 0 == lstrcmp(lpszDefaultScheme, phcSrc->lpszDefaultScheme));
  121. phcDest->lpszDefaultScheme = lpszDefaultScheme;
  122. return(fIsEqual);
  123. }
  124. //////////////////////////////////////////////////////////////////////////
  125. void CopySerialKeys(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc)
  126. {
  127. LPTSTR lpszActivePort = pskDest->lpszActivePort;
  128. LPTSTR lpszPort = pskDest->lpszPort;
  129. memcpy(pskDest, pskSrc, sizeof(*pskDest));
  130. pskDest->lpszActivePort = lpszActivePort;
  131. if (NULL != pskDest->lpszActivePort)
  132. {
  133. lstrcpy(pskDest->lpszActivePort, pskSrc->lpszActivePort);
  134. }
  135. pskDest->lpszPort = lpszPort;
  136. if (NULL != pskDest->lpszPort)
  137. {
  138. lstrcpy(pskDest->lpszPort, pskSrc->lpszPort);
  139. }
  140. }
  141. //////////////////////////////////////////////////////////////////////////
  142. BOOL IsSerialKeysEqual(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc)
  143. {
  144. BOOL fIsEqual = FALSE;
  145. LPTSTR lpszActivePort = pskDest->lpszActivePort;
  146. LPTSTR lpszPort = pskDest->lpszPort;
  147. // Temporarily make the pointers match
  148. pskDest->lpszActivePort = pskSrc->lpszActivePort;
  149. pskDest->lpszPort = pskSrc->lpszPort;
  150. // match the bits of the structures and the pointed to data
  151. fIsEqual = (0 == memcmp(pskDest, pskSrc, sizeof(*pskDest)) &&
  152. (NULL == lpszActivePort ||
  153. 0 == lstrcmp(lpszActivePort, pskSrc->lpszActivePort)) &&
  154. (NULL == lpszPort ||
  155. 0 == lstrcmp(lpszPort, pskSrc->lpszPort)));
  156. pskDest->lpszActivePort = lpszActivePort;
  157. pskDest->lpszPort = lpszPort;
  158. return(fIsEqual);
  159. }
  160. //////////////////////////////////////////////////////////////////////////
  161. BOOL IsAccStateEqual(PACCSTATE pasDest, PACCSTATE pasSrc)
  162. {
  163. BOOL fIsEqual = FALSE;
  164. HIGHCONTRAST hc = pasDest->hc;
  165. SERIALKEYS serk = pasDest->serk;
  166. int nLen;
  167. // Clear out the unused sections of the string buffers
  168. nLen = lstrlen(pasDest->szDefaultScheme);
  169. memset(&pasDest->szDefaultScheme[nLen], 0,
  170. sizeof(pasDest->szDefaultScheme)-nLen*sizeof(*pasDest->szDefaultScheme));
  171. nLen = lstrlen(pasDest->szActivePort);
  172. memset(&pasDest->szActivePort[nLen], 0,
  173. sizeof(pasDest->szActivePort)-nLen*sizeof(*pasDest->szActivePort));
  174. nLen = lstrlen(pasDest->szPort);
  175. memset(&pasDest->szPort[nLen], 0,
  176. sizeof(pasDest->szPort)-nLen*sizeof(*pasDest->szPort));
  177. nLen = lstrlen(pasSrc->szDefaultScheme);
  178. memset(&pasSrc->szDefaultScheme[nLen], 0,
  179. sizeof(pasSrc->szDefaultScheme)-nLen*sizeof(*pasSrc->szDefaultScheme));
  180. nLen = lstrlen(pasSrc->szActivePort);
  181. memset(&pasSrc->szActivePort[nLen], 0,
  182. sizeof(pasSrc->szActivePort)-nLen*sizeof(*pasSrc->szActivePort));
  183. nLen = lstrlen(pasSrc->szActivePort);
  184. memset(&pasSrc->szPort[nLen], 0,
  185. sizeof(pasSrc->szPort)-nLen*sizeof(*pasSrc->szPort));
  186. // Temporarily make the elements with pointers match
  187. pasDest->hc = pasSrc->hc;
  188. pasDest->serk = pasSrc->serk;
  189. // match the bits of the structures and the elements with pointers
  190. fIsEqual = (0 == memcmp(pasDest, pasSrc, sizeof(*pasDest)) &&
  191. IsHighContrastEqual(&hc, &pasSrc->hc) &&
  192. IsSerialKeysEqual(&serk, &pasSrc->serk));
  193. pasDest->hc = hc;
  194. pasDest->serk = serk;
  195. return(fIsEqual);
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. int WINAPI RegQueryInt (int nDefault, HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName) {
  199. DWORD dwType;
  200. DWORD dwVal = nDefault;
  201. DWORD cbData = sizeof(int);
  202. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
  203. RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) &dwVal, &cbData);
  204. RegCloseKey(hkey);
  205. }
  206. return(dwVal);
  207. }
  208. //////////////////////////////////////////////////////////////////////////
  209. BOOL WINAPI RegSetInt (HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName, int nVal) {
  210. BOOL fOk = FALSE;
  211. DWORD dwDisposition;
  212. LONG lRet;
  213. if (ERROR_SUCCESS == RegCreateKeyEx(hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
  214. KEY_SET_VALUE, NULL, &hkey, &dwDisposition)) {
  215. lRet = RegSetValueEx(hkey, lpValueName, 0, REG_DWORD, (CONST BYTE *) &nVal, sizeof(nVal));
  216. fOk = (ERROR_SUCCESS == lRet);
  217. RegCloseKey(hkey);
  218. }
  219. return fOk;
  220. }
  221. //////////////////////////////////////////////////////////////////////////
  222. void WINAPI RegQueryStr(
  223. LPTSTR lpDefault,
  224. HKEY hkey,
  225. LPTSTR lpSubKey,
  226. LPTSTR lpValueName,
  227. LPTSTR lpszValue,
  228. DWORD cbData) // note this is bytes, not characters.
  229. {
  230. DWORD dwType;
  231. lstrcpy(lpszValue, lpDefault);
  232. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
  233. RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) lpszValue, &cbData);
  234. RegCloseKey(hkey);
  235. }
  236. }
  237. /***************************************************************************\
  238. **AccessWriteProfileString
  239. *
  240. * History:
  241. * 12-19-95 a-jimhar Created (was called AccessWriteProfileString)
  242. * 02-08-95 a-jimhar revised and moved from accrare.c to access.c
  243. \***************************************************************************/
  244. BOOL RegSetStr(
  245. HKEY hkey,
  246. LPCTSTR lpSection,
  247. LPCTSTR lpKeyName,
  248. LPCTSTR lpString)
  249. {
  250. BOOL fRet = FALSE;
  251. LONG lErr;
  252. DWORD dwDisposition;
  253. lErr = RegCreateKeyEx(
  254. hkey,
  255. lpSection,
  256. 0,
  257. NULL,
  258. REG_OPTION_NON_VOLATILE,
  259. KEY_SET_VALUE,
  260. NULL,
  261. &hkey,
  262. &dwDisposition);
  263. if (ERROR_SUCCESS == lErr)
  264. {
  265. if (NULL != lpString)
  266. {
  267. lErr = RegSetValueEx(
  268. hkey,
  269. lpKeyName,
  270. 0,
  271. REG_SZ,
  272. (CONST BYTE *)lpString,
  273. (lstrlen(lpString) + 1) * sizeof(*lpString));
  274. }
  275. else
  276. {
  277. lErr = RegSetValueEx(
  278. hkey,
  279. lpKeyName,
  280. 0,
  281. REG_SZ,
  282. (CONST BYTE *)__TEXT(""),
  283. 1 * sizeof(*lpString));
  284. }
  285. if (ERROR_SUCCESS == lErr)
  286. {
  287. fRet = TRUE;
  288. }
  289. RegCloseKey(hkey);
  290. }
  291. return(fRet);
  292. }
  293. DWORD WINAPI RegQueryStrDW(
  294. DWORD dwDefault,
  295. HKEY hkey,
  296. LPTSTR lpSubKey,
  297. LPTSTR lpValueName)
  298. {
  299. DWORD dwRet = dwDefault;
  300. TCHAR szTemp[40];
  301. TCHAR szDefault[40];
  302. const LPTSTR pwszd = __TEXT("%d");
  303. wsprintf(szDefault, pwszd, dwDefault);
  304. RegQueryStr(
  305. szDefault,
  306. hkey,
  307. lpSubKey,
  308. lpValueName,
  309. szTemp,
  310. sizeof(szTemp));
  311. dwRet = _ttol(szTemp);
  312. return dwRet;
  313. }
  314. BOOL RegSetStrDW(
  315. HKEY hkey,
  316. LPTSTR lpSection,
  317. LPCTSTR lpKeyName,
  318. DWORD dwValue)
  319. {
  320. BOOL fRet;
  321. TCHAR szTemp[40];
  322. const LPTSTR pwszd = __TEXT("%d");
  323. wsprintf(szTemp, pwszd, dwValue);
  324. fRet = RegSetStr(hkey, lpSection, lpKeyName, szTemp);
  325. return fRet;
  326. }
  327. //////////////////////////////////////////////////////////////////////////
  328. /*------------------------------------------------------------------
  329. * Function void KillAccStat()
  330. *
  331. * Purpose Check if accstat is already running. If it is we need
  332. * to check to see if it should be. It should only be running
  333. * if each feature that is on also has the 'show status on
  334. * screen flag checked. If not we want to kill accstat.
  335. *
  336. * Params: None
  337. *
  338. * Return: TRUE if we had to kill accstat
  339. * FALSE if accstat not running/valid session
  340. *------------------------------------------------------------------*/
  341. void KillAccStat (void) {
  342. BOOL fCanTurnOff = FALSE; // Can we turn off accstat due to invalid feature?
  343. BOOL fValidFeature = FALSE; // Are there any valid features?
  344. // Accstat may be running. Determine if it should be running
  345. // We need to check the FilterKeys, MouseKeys and StickyKeys
  346. if (g_sk.dwFlags & SKF_STICKYKEYSON)
  347. if (!(g_sk.dwFlags & SKF_INDICATOR))
  348. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  349. else
  350. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  351. if (g_fk.dwFlags & FKF_FILTERKEYSON)
  352. if (!(g_fk.dwFlags & FKF_INDICATOR))
  353. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  354. else
  355. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  356. if (g_mk.dwFlags & MKF_MOUSEKEYSON)
  357. if (!(g_mk.dwFlags & MKF_INDICATOR))
  358. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  359. else
  360. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  361. // Now we have two flags: fCanTurnOff is TRUE if there is a mismatched flag set
  362. // ie, feature on, indicator off. ValidFeature is TRUE if any feature has
  363. // ON and INDICATOR set which implies accstat must remain active.
  364. if (!fValidFeature && fCanTurnOff) {
  365. TCHAR szBuf[256];
  366. HWND hwndAccStat;
  367. LoadString(g_hinst, IDS_ACCSTAT_WINDOW_TITLE, szBuf, ARRAY_SIZE(szBuf));
  368. if (IsWindow(hwndAccStat = FindWindow(NULL, szBuf))) {
  369. // Note sending 1 as the lParam tells accstat to shutup and
  370. // go away NOW.
  371. SendMessage(hwndAccStat, WM_SYSCOMMAND, SC_CLOSE, 1);
  372. }
  373. }
  374. }
  375. //////////////////////////////////////////////////////////////////////////
  376. void WINAPI GetAccessibilitySettings (void) {
  377. BOOL fUpdate;
  378. if (g_fWinNT == -1) {
  379. OSVERSIONINFO osvi;
  380. osvi.dwOSVersionInfoSize = sizeof(osvi);
  381. GetVersionEx(&osvi);
  382. g_fWinNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  383. }
  384. g_fShowWarnMsgOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
  385. GENERAL_KEY, WARNING_SOUNDS);
  386. s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate;
  387. // Query the Sound On Activation entry
  388. g_fPlaySndOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
  389. GENERAL_KEY, SOUND_ON_ACTIVATION);
  390. s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate;
  391. g_fSaveSettings = TRUE;
  392. // Keyboard property page
  393. g_sk.cbSize = sizeof(g_sk);
  394. AccessSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(g_sk), &g_sk, 0);
  395. s_asPrev.sk = g_sk;
  396. g_fk.cbSize = sizeof(g_fk);
  397. AccessSystemParametersInfo(SPI_GETFILTERKEYS, sizeof(g_fk), &g_fk, 0);
  398. g_fk.dwFlags |= FKF_AVAILABLE;
  399. // FILTERKEYS used to use OLDDISABLED as it's "unused" flag. This doesn't
  400. // work very well on NT (SPI_SETFILTERKEYS calls fail). We now use 0
  401. // for disabled values. Take this opertunity to change any OLDDISABLED
  402. // values to 0 and save if needed.
  403. fUpdate = FALSE;
  404. if (OLDDISABLED == g_fk.iBounceMSec)
  405. {
  406. g_fk.iBounceMSec = 0;
  407. fUpdate = TRUE;
  408. }
  409. if (OLDDISABLED == g_fk.iDelayMSec)
  410. {
  411. g_fk.iDelayMSec = 0;
  412. fUpdate = TRUE;
  413. }
  414. if (OLDDISABLED == g_fk.iRepeatMSec)
  415. {
  416. g_fk.iRepeatMSec = 0;
  417. fUpdate = TRUE;
  418. }
  419. if (OLDDISABLED == g_fk.iWaitMSec)
  420. {
  421. g_fk.iWaitMSec = 0;
  422. fUpdate = TRUE;
  423. }
  424. if (fUpdate)
  425. {
  426. AccessSystemParametersInfo(
  427. SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  428. }
  429. s_asPrev.fk = g_fk;
  430. // fix Filter keys bug
  431. g_dwOrigFKFlags = g_fk.dwFlags;
  432. g_bFKOn = g_fk.dwFlags & FKF_FILTERKEYSON;
  433. // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
  434. // and g_nLastWait are part of FilterKeys
  435. if (0 != g_fk.iBounceMSec) {
  436. // Bounce keys enabeled
  437. g_fk.iDelayMSec = 0;
  438. g_fk.iRepeatMSec = 0;
  439. g_fk.iWaitMSec = 0;
  440. g_dwLastBounceKeySetting = g_fk.iBounceMSec;
  441. g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
  442. g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
  443. g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
  444. }
  445. else
  446. {
  447. if (0 == g_fk.iDelayMSec)
  448. {
  449. g_fk.iRepeatMSec = 0;
  450. }
  451. g_dwLastBounceKeySetting = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING);
  452. g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
  453. g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
  454. if (0 != g_fk.iWaitMSec)
  455. {
  456. g_nLastWait = g_fk.iWaitMSec;
  457. }
  458. else
  459. {
  460. g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
  461. }
  462. }
  463. g_tk.cbSize = sizeof(g_tk);
  464. AccessSystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(g_tk), &g_tk, 0);
  465. s_asPrev.tk = g_tk;
  466. AccessSystemParametersInfo(SPI_GETKEYBOARDPREF, 0, &g_fExtraKeyboardHelp, 0);
  467. s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
  468. // Sound Property page
  469. g_ss.cbSize = sizeof(g_ss);
  470. AccessSystemParametersInfo(SPI_GETSOUNDSENTRY, sizeof(g_ss), &g_ss, 0);
  471. s_asPrev.ss = g_ss;
  472. SystemParametersInfo(SPI_GETSHOWSOUNDS, 0, &g_fShowSounds, 0);
  473. // BUG, BUG GetSystemMetrics() is not updating value on reboot :a-anilk
  474. // g_fShowSounds = GetSystemMetrics(SM_SHOWSOUNDS);
  475. s_asPrev.fShowSounds = g_fShowSounds;
  476. // Display Property page
  477. g_hc.cbSize = sizeof(g_hc);
  478. AccessSystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(g_hc), &g_hc, 0);
  479. // Currently NT will not store these flags. We fake them so we
  480. // can tell if they actually changed.
  481. s_asPrev.hc.lpszDefaultScheme = s_asPrev.szDefaultScheme;
  482. CopyHighContrast(&s_asPrev.hc, &g_hc);
  483. SystemParametersInfo(SPI_GETCARETWIDTH, 0, (PVOID)&g_cs.dwCaretWidth, 0);
  484. g_cs.dwCaretBlinkRate = RegQueryStrDW(
  485. DEFAULT_BLINK_RATE
  486. , HKEY_CURRENT_USER
  487. , CONTROL_PANEL_DESKTOP
  488. , CURSOR_BLINK_RATE);
  489. if (g_cs.dwCaretBlinkRate == BLINK_OFF)
  490. g_cs.dwCaretBlinkRate = CURSORMAX;
  491. s_asPrev.cs.dwCaretBlinkRate = g_cs.dwCaretBlinkRate;
  492. s_asPrev.cs.dwCaretWidth = g_cs.dwCaretWidth;
  493. // Mouse Property page
  494. g_mk.cbSize = sizeof(g_mk);
  495. AccessSystemParametersInfo(SPI_GETMOUSEKEYS, sizeof(g_mk), &g_mk, 0);
  496. s_asPrev.mk = g_mk;
  497. // General Property page
  498. g_ato.cbSize = sizeof(g_ato);
  499. AccessSystemParametersInfo(SPI_GETACCESSTIMEOUT, sizeof(g_ato), &g_ato, 0);
  500. s_asPrev.ato = g_ato;
  501. g_serk.cbSize = sizeof(g_serk);
  502. g_serk.lpszActivePort = g_szActivePort;
  503. g_serk.lpszPort = g_szPort;
  504. AccessSystemParametersInfo(SPI_GETSERIALKEYS, sizeof(g_serk), &g_serk, 0);
  505. s_asPrev.serk.lpszActivePort = s_asPrev.szActivePort;
  506. s_asPrev.serk.lpszPort = s_asPrev.szPort;
  507. CopySerialKeys(&s_asPrev.serk, &g_serk);
  508. if (NULL == s_asOrg.hc.lpszDefaultScheme)
  509. {
  510. // s_asOrg has not yet been initialized
  511. s_asOrg = s_asPrev;
  512. s_asOrg.hc.lpszDefaultScheme = s_asOrg.szDefaultScheme;
  513. s_asOrg.serk.lpszActivePort = s_asOrg.szActivePort;
  514. s_asOrg.serk.lpszPort = s_asOrg.szPort;
  515. }
  516. }
  517. //////////////////////////////////////////////////////////////////////////
  518. //a-anilk: Change, Admin options, Keyboard flags: 05/06/99
  519. void WINAPI SetAccessibilitySettings (void) {
  520. HKEY hkey;
  521. DWORD dwDisposition;
  522. UINT fWinIni = SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE;
  523. BOOL fAnyNotifyChange = FALSE;
  524. g_SPISetValue = TRUE;
  525. SetCursor(LoadCursor(NULL, IDC_WAIT));
  526. if (g_fShowWarnMsgOnFeatureActivate) {
  527. g_hc.dwFlags |= HCF_CONFIRMHOTKEY;
  528. g_fk.dwFlags |= FKF_CONFIRMHOTKEY;
  529. g_sk.dwFlags |= SKF_CONFIRMHOTKEY;
  530. g_mk.dwFlags |= MKF_CONFIRMHOTKEY;
  531. g_tk.dwFlags |= TKF_CONFIRMHOTKEY;
  532. } else {
  533. g_hc.dwFlags &= ~HCF_CONFIRMHOTKEY;
  534. g_fk.dwFlags &= ~FKF_CONFIRMHOTKEY;
  535. g_sk.dwFlags &= ~SKF_CONFIRMHOTKEY;
  536. g_mk.dwFlags &= ~MKF_CONFIRMHOTKEY;
  537. g_tk.dwFlags &= ~TKF_CONFIRMHOTKEY;
  538. }
  539. if (g_fPlaySndOnFeatureActivate) {
  540. g_hc.dwFlags |= HCF_HOTKEYSOUND;
  541. g_fk.dwFlags |= FKF_HOTKEYSOUND;
  542. g_sk.dwFlags |= SKF_HOTKEYSOUND;
  543. g_mk.dwFlags |= MKF_HOTKEYSOUND;
  544. g_tk.dwFlags |= TKF_HOTKEYSOUND;
  545. g_ato.dwFlags |= ATF_ONOFFFEEDBACK;
  546. } else {
  547. g_hc.dwFlags &= ~HCF_HOTKEYSOUND;
  548. g_fk.dwFlags &= ~FKF_HOTKEYSOUND;
  549. g_sk.dwFlags &= ~SKF_HOTKEYSOUND;
  550. g_mk.dwFlags &= ~MKF_HOTKEYSOUND;
  551. g_tk.dwFlags &= ~TKF_HOTKEYSOUND;
  552. g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK;
  553. }
  554. // Keyboard property page
  555. if (0 != memcmp(&g_sk, &s_asPrev.sk, sizeof(g_sk)))
  556. {
  557. if (g_fWinNT)
  558. {
  559. g_sk.dwFlags &= SKF_VALID;
  560. }
  561. AccessSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(g_sk), &g_sk, fWinIni);
  562. s_asPrev.sk = g_sk;
  563. fAnyNotifyChange = TRUE;
  564. }
  565. if (g_bFKOn)
  566. g_fk.dwFlags |= FKF_FILTERKEYSON;
  567. else
  568. g_fk.dwFlags &= ~FKF_FILTERKEYSON;
  569. g_dwOrigFKFlags = g_fk.dwFlags;
  570. if (0 != memcmp(&g_fk, &s_asPrev.fk, sizeof(g_fk)))
  571. {
  572. if (g_fWinNT)
  573. {
  574. g_fk.dwFlags &= FKF_VALID;
  575. }
  576. // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
  577. // and g_nLastWait are part of FilterKeys
  578. if (0 != g_fk.iBounceMSec) {
  579. // Bounce keys enabeled
  580. g_fk.iDelayMSec = 0;
  581. g_fk.iRepeatMSec = 0;
  582. g_fk.iWaitMSec = 0;
  583. g_dwLastBounceKeySetting = g_fk.iBounceMSec;
  584. }
  585. else
  586. {
  587. g_nLastWait = g_fk.iWaitMSec;
  588. if (0 != g_fk.iDelayMSec)
  589. {
  590. // Slow key enabled
  591. g_nLastRepeatDelay = g_fk.iDelayMSec;
  592. g_nLastRepeatRate = g_fk.iRepeatMSec;
  593. }
  594. else
  595. {
  596. // neither Bounce or Slow
  597. g_fk.iRepeatMSec = 0;
  598. }
  599. }
  600. AccessSystemParametersInfo(SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, fWinIni);
  601. s_asPrev.fk = g_fk;
  602. fAnyNotifyChange = TRUE;
  603. }
  604. // always save these
  605. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING, g_dwLastBounceKeySetting);
  606. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY, g_nLastRepeatDelay);
  607. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE, g_nLastRepeatRate);
  608. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT, g_nLastWait);
  609. if (0 != memcmp(&g_tk, &s_asPrev.tk, sizeof(g_tk)))
  610. {
  611. if (g_fWinNT)
  612. {
  613. g_tk.dwFlags &= TKF_VALID;
  614. }
  615. AccessSystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(g_tk), &g_tk, fWinIni);
  616. s_asPrev.tk = g_tk;
  617. fAnyNotifyChange = TRUE;
  618. }
  619. if (g_fExtraKeyboardHelp != s_asPrev.fExtraKeyboardHelp)
  620. {
  621. // Set this too. Some controls check this flag...0x100B
  622. AccessSystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(g_fExtraKeyboardHelp), fWinIni);
  623. AccessSystemParametersInfo(SPI_SETKEYBOARDPREF, g_fExtraKeyboardHelp, 0, fWinIni);
  624. s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
  625. fAnyNotifyChange = TRUE;
  626. }
  627. // Display Property page
  628. // BUGBUG a-jimhar 03-22-96 verify changes to display property page save
  629. // code when display page is added back in on NT
  630. if (!IsHighContrastEqual(&g_hc, &s_asPrev.hc))
  631. {
  632. AccessSystemParametersInfo(SPI_SETHIGHCONTRAST, sizeof(g_hc), &g_hc, fWinIni);
  633. if (ERROR_SUCCESS == RegCreateKeyEx(
  634. HKEY_CURRENT_USER,
  635. HC_KEY,
  636. 0,
  637. __TEXT(""),
  638. REG_OPTION_NON_VOLATILE,
  639. KEY_SET_VALUE,
  640. NULL,
  641. &hkey,
  642. &dwDisposition))
  643. {
  644. RegSetValueEx(hkey, HIGHCONTRAST_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme,
  645. (lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme));
  646. RegSetValueEx(hkey, VOLATILE_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme,
  647. (lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme));
  648. RegCloseKey(hkey);
  649. hkey = NULL;
  650. }
  651. CopyHighContrast(&s_asPrev.hc, &g_hc);
  652. fAnyNotifyChange = TRUE;
  653. }
  654. if (g_cs.dwCaretBlinkRate != s_asPrev.cs.dwCaretBlinkRate)
  655. {
  656. DWORD dwCaretBlinkRate = (g_cs.dwCaretBlinkRate < CURSORMAX)?g_cs.dwCaretBlinkRate:BLINK_OFF;
  657. // Set the blink rate for this session
  658. SetCaretBlinkTime(dwCaretBlinkRate);
  659. // and persist it to the registry
  660. RegSetStrDW(HKEY_CURRENT_USER, CONTROL_PANEL_DESKTOP, CURSOR_BLINK_RATE, dwCaretBlinkRate);
  661. }
  662. if (g_cs.dwCaretWidth != s_asPrev.cs.dwCaretWidth)
  663. AccessSystemParametersInfo(SPI_SETCARETWIDTH, 0, IntToPtr(g_cs.dwCaretWidth), fWinIni);
  664. s_asPrev.cs = g_cs;
  665. // Mouse Property page
  666. if (0 != memcmp(&g_mk, &s_asPrev.mk, sizeof(g_mk)))
  667. {
  668. if (g_fWinNT)
  669. {
  670. g_mk.dwFlags &= MKF_VALID;
  671. }
  672. AccessSystemParametersInfo(SPI_SETMOUSEKEYS, sizeof(g_mk), &g_mk, fWinIni);
  673. s_asPrev.mk = g_mk;
  674. fAnyNotifyChange = TRUE;
  675. }
  676. // General Property page
  677. if (g_fPlaySndOnFeatureActivate) {
  678. g_ato.dwFlags |= ATF_ONOFFFEEDBACK;
  679. } else {
  680. g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK;
  681. }
  682. if (0 != memcmp(&g_ato, &s_asPrev.ato, sizeof(g_ato)))
  683. {
  684. if (g_fWinNT)
  685. {
  686. g_ato.dwFlags &= ATF_VALID;
  687. }
  688. AccessSystemParametersInfo(SPI_SETACCESSTIMEOUT, sizeof(g_ato), &g_ato, fWinIni);
  689. s_asPrev.ato = g_ato;
  690. fAnyNotifyChange = TRUE;
  691. }
  692. if (!IsSerialKeysEqual(&g_serk, &s_asPrev.serk))
  693. {
  694. AccessSystemParametersInfo(SPI_SETSERIALKEYS, sizeof(g_serk), &g_serk, fWinIni);
  695. CopySerialKeys(&s_asPrev.serk, &g_serk);
  696. fAnyNotifyChange = TRUE;
  697. }
  698. if (g_fSaveSettings) {
  699. if (RegCreateKeyEx(HKEY_CURRENT_USER, GENERAL_KEY, 0, __TEXT(""), REG_OPTION_NON_VOLATILE,
  700. KEY_SET_VALUE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS) {
  701. // Save the Warning Sounds entry
  702. if (g_fShowWarnMsgOnFeatureActivate != s_asPrev.fShowWarnMsgOnFeatureActivate)
  703. {
  704. RegSetValueEx(hkey, WARNING_SOUNDS, 0, REG_DWORD, (PBYTE) &g_fShowWarnMsgOnFeatureActivate,
  705. sizeof(g_fShowWarnMsgOnFeatureActivate));
  706. s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate;
  707. }
  708. // Save the Sound On Activation entry
  709. if (g_fPlaySndOnFeatureActivate != s_asPrev.fPlaySndOnFeatureActivate)
  710. {
  711. RegSetValueEx(hkey, SOUND_ON_ACTIVATION, 0, REG_DWORD, (PBYTE) &g_fPlaySndOnFeatureActivate,
  712. sizeof(g_fPlaySndOnFeatureActivate));
  713. s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate;
  714. }
  715. RegCloseKey(hkey);
  716. hkey = NULL;
  717. }
  718. }
  719. // Sound Property page
  720. if (0 != memcmp(&g_ss, &s_asPrev.ss, sizeof(g_ss)))
  721. {
  722. if (g_fWinNT)
  723. {
  724. g_ss.dwFlags &= SSF_VALID;
  725. }
  726. AccessSystemParametersInfo(SPI_SETSOUNDSENTRY, sizeof(g_ss), &g_ss, fWinIni);
  727. s_asPrev.ss = g_ss;
  728. fAnyNotifyChange = TRUE;
  729. }
  730. // We do the sound property page last because the SPI_SETSHOWSOUNDS call is used
  731. // to send out notifications. We make this call if either g_fShowSounds changed
  732. // or we need to send out notifications
  733. // Changed Nov.18 '98 to send out WM_SETTINGSCHANGE Seperately.
  734. if (g_fShowSounds != s_asPrev.fShowSounds /*||
  735. (fAnyNotifyChange && g_fSaveSettings)*/)
  736. {
  737. // if (g_fSaveSettings) fWinIni |= SPIF_SENDWININICHANGE;
  738. AccessSystemParametersInfo(SPI_SETSHOWSOUNDS, g_fShowSounds, NULL, fWinIni);
  739. s_asPrev.fShowSounds = g_fShowSounds;
  740. }
  741. g_SPISetValue = FALSE;
  742. // Do Admin options
  743. SaveDefaultSettings(g_fCopyToLogon, g_fCopyToDefault);
  744. SetCursor(LoadCursor(NULL, IDC_ARROW));
  745. }
  746. //////////////////////////////////////////////////////////////////////////
  747. INT_PTR WINAPI KeyboardDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  748. INT_PTR WINAPI SoundDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  749. INT_PTR WINAPI GeneralDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  750. INT_PTR WINAPI DisplayDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  751. INT_PTR WINAPI MouseDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  752. #define MAX_PAGES 10
  753. // ************************************************************************
  754. // OpenAccessPropertySheet
  755. // Opens property sheet
  756. // ************************************************************************
  757. BOOL OpenAccessPropertySheet (HWND hwnd, int nID) {
  758. HPROPSHEETPAGE rPages[MAX_PAGES];
  759. PROPSHEETPAGE psp;
  760. PROPSHEETHEADER psh;
  761. INT_PTR nPsRet;
  762. KillAccStat();
  763. GetAccessibilitySettings();
  764. // Simple errorchecking - only allow control to move to tabs 0-4.
  765. // Any tab request greater than 4 is invalid - so default to tab 0
  766. if ((nID < 0) || (nID > 4)) nID = 0;
  767. // Initialize the property sheets
  768. psh.dwSize = sizeof(psh);
  769. // SteveDon 5-26-98
  770. // no longer use PSH_PROPTITLE because we want it to read "Accessibility Options"
  771. // rather than "Accessibility Properties" or "Properties for Accessibility"
  772. psh.dwFlags = 0; // psh.dwFlags = PSH_PROPTITLE; // | PSH_PROPSHEETPAGE | PSP_USEICONID;
  773. psh.hwndParent = hwnd;
  774. psh.hInstance = g_hinst;
  775. psh.pszCaption = MAKEINTRESOURCE(IDS_PROPERTY_TITLE); //ACCESSIBILITY);
  776. psh.pszIcon = MAKEINTRESOURCE(IDI_ACCESS);
  777. psh.nPages = 0;
  778. psh.nStartPage = 0;
  779. psh.phpage = rPages;
  780. // Add First Sheet, keyboard
  781. psp.dwSize = sizeof(psp);
  782. psp.dwFlags = PSP_DEFAULT;
  783. psp.hInstance = g_hinst;
  784. psp.pszTemplate = MAKEINTRESOURCE(IDD_KEYBOARD);
  785. psp.pfnDlgProc = KeyboardDlg;
  786. psp.lParam = 0;
  787. psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
  788. if (psh.phpage[psh.nPages]) psh.nPages++;
  789. // Add second sheet, Sound
  790. psp.dwSize = sizeof(psp);
  791. psp.dwFlags = PSP_DEFAULT;
  792. psp.hInstance = g_hinst;
  793. psp.pszTemplate = MAKEINTRESOURCE(IDD_SOUND);
  794. psp.pfnDlgProc = SoundDlg;
  795. psp.lParam = 0;
  796. psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
  797. if (psh.phpage[psh.nPages]) psh.nPages++;
  798. // Add third sheet, Display
  799. psp.dwSize = sizeof(psp);
  800. psp.dwFlags = PSP_DEFAULT;
  801. psp.hInstance = g_hinst;
  802. psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAY);
  803. psp.pfnDlgProc = DisplayDlg;
  804. psp.lParam = 0;
  805. psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
  806. if (psh.phpage[psh.nPages]) psh.nPages++;
  807. // Add fourth sheet, Mouse
  808. psp.dwSize = sizeof(psp);
  809. psp.dwFlags = PSP_DEFAULT;
  810. psp.hInstance = g_hinst;
  811. psp.pszTemplate = MAKEINTRESOURCE(IDD_MOUSE);
  812. psp.pfnDlgProc = MouseDlg;
  813. psp.lParam = 0;
  814. psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
  815. if (psh.phpage[psh.nPages]) psh.nPages++;
  816. // Add fifth sheet, General
  817. psp.dwSize = sizeof(psp);
  818. psp.dwFlags = PSP_DEFAULT;
  819. psp.hInstance = g_hinst;
  820. psp.pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
  821. psp.pfnDlgProc = GeneralDlg;
  822. psp.lParam = 0;
  823. psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
  824. if (psh.phpage[psh.nPages]) psh.nPages++;
  825. // Simple errorchecking - only allow control to move to tabs 0 to psh.nPages
  826. // Any tab request greater than psh.nPages is invalid
  827. if (0 <= nID && nID < (int)psh.nPages)
  828. {
  829. psh.nStartPage = nID;
  830. }
  831. nPsRet = PropertySheet(&psh);
  832. if ( nPsRet <= 0 )
  833. return FALSE;
  834. else
  835. return TRUE;
  836. }
  837. ///////////////////////////////// End of File /////////////////////////////////