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.

1043 lines
32 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. DWORD dwOrigCount = cbData;
  232. lstrcpy(lpszValue, lpDefault);
  233. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
  234. RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) lpszValue, &cbData);
  235. lpszValue[dwOrigCount/sizeof (TCHAR)-1] = TEXT('\0');
  236. RegCloseKey(hkey);
  237. }
  238. }
  239. /***************************************************************************\
  240. **AccessWriteProfileString
  241. *
  242. * History:
  243. * 12-19-95 a-jimhar Created (was called AccessWriteProfileString)
  244. * 02-08-95 a-jimhar revised and moved from accrare.c to access.c
  245. \***************************************************************************/
  246. BOOL RegSetStr(
  247. HKEY hkey,
  248. LPCTSTR lpSection,
  249. LPCTSTR lpKeyName,
  250. LPCTSTR lpString)
  251. {
  252. BOOL fRet = FALSE;
  253. LONG lErr;
  254. DWORD dwDisposition;
  255. lErr = RegCreateKeyEx(
  256. hkey,
  257. lpSection,
  258. 0,
  259. NULL,
  260. REG_OPTION_NON_VOLATILE,
  261. KEY_SET_VALUE,
  262. NULL,
  263. &hkey,
  264. &dwDisposition);
  265. if (ERROR_SUCCESS == lErr)
  266. {
  267. if (NULL != lpString)
  268. {
  269. lErr = RegSetValueEx(
  270. hkey,
  271. lpKeyName,
  272. 0,
  273. REG_SZ,
  274. (CONST BYTE *)lpString,
  275. (lstrlen(lpString) + 1) * sizeof(*lpString));
  276. }
  277. else
  278. {
  279. lErr = RegSetValueEx(
  280. hkey,
  281. lpKeyName,
  282. 0,
  283. REG_SZ,
  284. (CONST BYTE *)__TEXT(""),
  285. 1 * sizeof(*lpString));
  286. }
  287. if (ERROR_SUCCESS == lErr)
  288. {
  289. fRet = TRUE;
  290. }
  291. RegCloseKey(hkey);
  292. }
  293. return(fRet);
  294. }
  295. DWORD WINAPI RegQueryStrDW(
  296. DWORD dwDefault,
  297. HKEY hkey,
  298. LPTSTR lpSubKey,
  299. LPTSTR lpValueName)
  300. {
  301. DWORD dwRet = dwDefault;
  302. TCHAR szTemp[40];
  303. TCHAR szDefault[40];
  304. const LPTSTR pwszd = __TEXT("%d");
  305. wsprintf(szDefault, pwszd, dwDefault);
  306. RegQueryStr(
  307. szDefault,
  308. hkey,
  309. lpSubKey,
  310. lpValueName,
  311. szTemp,
  312. sizeof(szTemp));
  313. dwRet = _ttol(szTemp);
  314. return dwRet;
  315. }
  316. BOOL RegSetStrDW(
  317. HKEY hkey,
  318. LPTSTR lpSection,
  319. LPCTSTR lpKeyName,
  320. DWORD dwValue)
  321. {
  322. BOOL fRet;
  323. TCHAR szTemp[40];
  324. const LPTSTR pwszd = __TEXT("%d");
  325. wsprintf(szTemp, pwszd, dwValue);
  326. fRet = RegSetStr(hkey, lpSection, lpKeyName, szTemp);
  327. return fRet;
  328. }
  329. //////////////////////////////////////////////////////////////////////////
  330. /*------------------------------------------------------------------
  331. * Function void KillAccStat()
  332. *
  333. * Purpose Check if accstat is already running. If it is we need
  334. * to check to see if it should be. It should only be running
  335. * if each feature that is on also has the 'show status on
  336. * screen flag checked. If not we want to kill accstat.
  337. *
  338. * Params: None
  339. *
  340. * Return: TRUE if we had to kill accstat
  341. * FALSE if accstat not running/valid session
  342. *------------------------------------------------------------------*/
  343. void KillAccStat (void) {
  344. BOOL fCanTurnOff = FALSE; // Can we turn off accstat due to invalid feature?
  345. BOOL fValidFeature = FALSE; // Are there any valid features?
  346. // Accstat may be running. Determine if it should be running
  347. // We need to check the FilterKeys, MouseKeys and StickyKeys
  348. if (g_sk.dwFlags & SKF_STICKYKEYSON)
  349. if (!(g_sk.dwFlags & SKF_INDICATOR))
  350. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  351. else
  352. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  353. if (g_fk.dwFlags & FKF_FILTERKEYSON)
  354. if (!(g_fk.dwFlags & FKF_INDICATOR))
  355. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  356. else
  357. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  358. if (g_mk.dwFlags & MKF_MOUSEKEYSON)
  359. if (!(g_mk.dwFlags & MKF_INDICATOR))
  360. fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
  361. else
  362. fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
  363. // Now we have two flags: fCanTurnOff is TRUE if there is a mismatched flag set
  364. // ie, feature on, indicator off. ValidFeature is TRUE if any feature has
  365. // ON and INDICATOR set which implies accstat must remain active.
  366. if (!fValidFeature && fCanTurnOff) {
  367. TCHAR szBuf[256];
  368. HWND hwndAccStat;
  369. LoadString(g_hinst, IDS_ACCSTAT_WINDOW_TITLE, szBuf, ARRAY_SIZE(szBuf));
  370. if (IsWindow(hwndAccStat = FindWindow(NULL, szBuf))) {
  371. // Note sending 1 as the lParam tells accstat to shutup and
  372. // go away NOW.
  373. SendMessage(hwndAccStat, WM_SYSCOMMAND, SC_CLOSE, 1);
  374. }
  375. }
  376. }
  377. //////////////////////////////////////////////////////////////////////////
  378. void WINAPI GetAccessibilitySettings (void) {
  379. BOOL fUpdate;
  380. if (g_fWinNT == -1) {
  381. OSVERSIONINFO osvi;
  382. osvi.dwOSVersionInfoSize = sizeof(osvi);
  383. GetVersionEx(&osvi);
  384. g_fWinNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  385. }
  386. g_fShowWarnMsgOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
  387. GENERAL_KEY, WARNING_SOUNDS);
  388. s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate;
  389. // Query the Sound On Activation entry
  390. g_fPlaySndOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
  391. GENERAL_KEY, SOUND_ON_ACTIVATION);
  392. s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate;
  393. g_fSaveSettings = TRUE;
  394. // Keyboard property page
  395. g_sk.cbSize = sizeof(g_sk);
  396. AccessSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(g_sk), &g_sk, 0);
  397. s_asPrev.sk = g_sk;
  398. g_fk.cbSize = sizeof(g_fk);
  399. AccessSystemParametersInfo(SPI_GETFILTERKEYS, sizeof(g_fk), &g_fk, 0);
  400. g_fk.dwFlags |= FKF_AVAILABLE;
  401. // FILTERKEYS used to use OLDDISABLED as it's "unused" flag. This doesn't
  402. // work very well on NT (SPI_SETFILTERKEYS calls fail). We now use 0
  403. // for disabled values. Take this opertunity to change any OLDDISABLED
  404. // values to 0 and save if needed.
  405. fUpdate = FALSE;
  406. if (OLDDISABLED == g_fk.iBounceMSec)
  407. {
  408. g_fk.iBounceMSec = 0;
  409. fUpdate = TRUE;
  410. }
  411. if (OLDDISABLED == g_fk.iDelayMSec)
  412. {
  413. g_fk.iDelayMSec = 0;
  414. fUpdate = TRUE;
  415. }
  416. if (OLDDISABLED == g_fk.iRepeatMSec)
  417. {
  418. g_fk.iRepeatMSec = 0;
  419. fUpdate = TRUE;
  420. }
  421. if (OLDDISABLED == g_fk.iWaitMSec)
  422. {
  423. g_fk.iWaitMSec = 0;
  424. fUpdate = TRUE;
  425. }
  426. if (fUpdate)
  427. {
  428. AccessSystemParametersInfo(
  429. SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  430. }
  431. s_asPrev.fk = g_fk;
  432. // fix Filter keys bug
  433. g_dwOrigFKFlags = g_fk.dwFlags;
  434. g_bFKOn = g_fk.dwFlags & FKF_FILTERKEYSON;
  435. // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
  436. // and g_nLastWait are part of FilterKeys
  437. if (0 != g_fk.iBounceMSec) {
  438. // Bounce keys enabeled
  439. g_fk.iDelayMSec = 0;
  440. g_fk.iRepeatMSec = 0;
  441. g_fk.iWaitMSec = 0;
  442. g_dwLastBounceKeySetting = g_fk.iBounceMSec;
  443. g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
  444. g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
  445. g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
  446. }
  447. else
  448. {
  449. if (0 == g_fk.iDelayMSec)
  450. {
  451. g_fk.iRepeatMSec = 0;
  452. }
  453. g_dwLastBounceKeySetting = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING);
  454. g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
  455. g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
  456. if (0 != g_fk.iWaitMSec)
  457. {
  458. g_nLastWait = g_fk.iWaitMSec;
  459. }
  460. else
  461. {
  462. g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
  463. }
  464. }
  465. g_tk.cbSize = sizeof(g_tk);
  466. AccessSystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(g_tk), &g_tk, 0);
  467. s_asPrev.tk = g_tk;
  468. AccessSystemParametersInfo(SPI_GETKEYBOARDPREF, 0, &g_fExtraKeyboardHelp, 0);
  469. s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
  470. // Sound Property page
  471. g_ss.cbSize = sizeof(g_ss);
  472. AccessSystemParametersInfo(SPI_GETSOUNDSENTRY, sizeof(g_ss), &g_ss, 0);
  473. s_asPrev.ss = g_ss;
  474. SystemParametersInfo(SPI_GETSHOWSOUNDS, 0, &g_fShowSounds, 0);
  475. // BUG, BUG GetSystemMetrics() is not updating value on reboot :a-anilk
  476. // g_fShowSounds = GetSystemMetrics(SM_SHOWSOUNDS);
  477. s_asPrev.fShowSounds = g_fShowSounds;
  478. // Display Property page
  479. g_hc.cbSize = sizeof(g_hc);
  480. AccessSystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(g_hc), &g_hc, 0);
  481. // Currently NT will not store these flags. We fake them so we
  482. // can tell if they actually changed.
  483. s_asPrev.hc.lpszDefaultScheme = s_asPrev.szDefaultScheme;
  484. CopyHighContrast(&s_asPrev.hc, &g_hc);
  485. SystemParametersInfo(SPI_GETCARETWIDTH, 0, (PVOID)&g_cs.dwCaretWidth, 0);
  486. g_cs.dwCaretBlinkRate = RegQueryStrDW(
  487. DEFAULT_BLINK_RATE
  488. , HKEY_CURRENT_USER
  489. , CONTROL_PANEL_DESKTOP
  490. , CURSOR_BLINK_RATE);
  491. if (g_cs.dwCaretBlinkRate == BLINK_OFF)
  492. g_cs.dwCaretBlinkRate = CURSORMAX;
  493. s_asPrev.cs.dwCaretBlinkRate = g_cs.dwCaretBlinkRate;
  494. s_asPrev.cs.dwCaretWidth = g_cs.dwCaretWidth;
  495. // Mouse Property page
  496. g_mk.cbSize = sizeof(g_mk);
  497. AccessSystemParametersInfo(SPI_GETMOUSEKEYS, sizeof(g_mk), &g_mk, 0);
  498. s_asPrev.mk = g_mk;
  499. // General Property page
  500. g_ato.cbSize = sizeof(g_ato);
  501. AccessSystemParametersInfo(SPI_GETACCESSTIMEOUT, sizeof(g_ato), &g_ato, 0);
  502. s_asPrev.ato = g_ato;
  503. g_serk.cbSize = sizeof(g_serk);
  504. g_serk.lpszActivePort = g_szActivePort;
  505. g_serk.lpszPort = g_szPort;
  506. AccessSystemParametersInfo(SPI_GETSERIALKEYS, sizeof(g_serk), &g_serk, 0);
  507. s_asPrev.serk.lpszActivePort = s_asPrev.szActivePort;
  508. s_asPrev.serk.lpszPort = s_asPrev.szPort;
  509. CopySerialKeys(&s_asPrev.serk, &g_serk);
  510. if (NULL == s_asOrg.hc.lpszDefaultScheme)
  511. {
  512. // s_asOrg has not yet been initialized
  513. s_asOrg = s_asPrev;
  514. s_asOrg.hc.lpszDefaultScheme = s_asOrg.szDefaultScheme;
  515. s_asOrg.serk.lpszActivePort = s_asOrg.szActivePort;
  516. s_asOrg.serk.lpszPort = s_asOrg.szPort;
  517. }
  518. }
  519. //////////////////////////////////////////////////////////////////////////
  520. //a-anilk: Change, Admin options, Keyboard flags: 05/06/99
  521. void WINAPI SetAccessibilitySettings (void) {
  522. HKEY hkey;
  523. DWORD dwDisposition;
  524. UINT fWinIni = SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE;
  525. BOOL fAnyNotifyChange = FALSE;
  526. g_SPISetValue = TRUE;
  527. SetCursor(LoadCursor(NULL, IDC_WAIT));
  528. if (g_fShowWarnMsgOnFeatureActivate) {
  529. g_hc.dwFlags |= HCF_CONFIRMHOTKEY;
  530. g_fk.dwFlags |= FKF_CONFIRMHOTKEY;
  531. g_sk.dwFlags |= SKF_CONFIRMHOTKEY;
  532. g_mk.dwFlags |= MKF_CONFIRMHOTKEY;
  533. g_tk.dwFlags |= TKF_CONFIRMHOTKEY;
  534. } else {
  535. g_hc.dwFlags &= ~HCF_CONFIRMHOTKEY;
  536. g_fk.dwFlags &= ~FKF_CONFIRMHOTKEY;
  537. g_sk.dwFlags &= ~SKF_CONFIRMHOTKEY;
  538. g_mk.dwFlags &= ~MKF_CONFIRMHOTKEY;
  539. g_tk.dwFlags &= ~TKF_CONFIRMHOTKEY;
  540. }
  541. if (g_fPlaySndOnFeatureActivate) {
  542. g_hc.dwFlags |= HCF_HOTKEYSOUND;
  543. g_fk.dwFlags |= FKF_HOTKEYSOUND;
  544. g_sk.dwFlags |= SKF_HOTKEYSOUND;
  545. g_mk.dwFlags |= MKF_HOTKEYSOUND;
  546. g_tk.dwFlags |= TKF_HOTKEYSOUND;
  547. g_ato.dwFlags |= ATF_ONOFFFEEDBACK;
  548. } else {
  549. g_hc.dwFlags &= ~HCF_HOTKEYSOUND;
  550. g_fk.dwFlags &= ~FKF_HOTKEYSOUND;
  551. g_sk.dwFlags &= ~SKF_HOTKEYSOUND;
  552. g_mk.dwFlags &= ~MKF_HOTKEYSOUND;
  553. g_tk.dwFlags &= ~TKF_HOTKEYSOUND;
  554. g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK;
  555. }
  556. // Keyboard property page
  557. if (0 != memcmp(&g_sk, &s_asPrev.sk, sizeof(g_sk)))
  558. {
  559. if (g_fWinNT)
  560. {
  561. g_sk.dwFlags &= SKF_VALID;
  562. }
  563. AccessSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(g_sk), &g_sk, fWinIni);
  564. s_asPrev.sk = g_sk;
  565. fAnyNotifyChange = TRUE;
  566. }
  567. if (g_bFKOn)
  568. g_fk.dwFlags |= FKF_FILTERKEYSON;
  569. else
  570. g_fk.dwFlags &= ~FKF_FILTERKEYSON;
  571. g_dwOrigFKFlags = g_fk.dwFlags;
  572. if (0 != memcmp(&g_fk, &s_asPrev.fk, sizeof(g_fk)))
  573. {
  574. if (g_fWinNT)
  575. {
  576. g_fk.dwFlags &= FKF_VALID;
  577. }
  578. // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
  579. // and g_nLastWait are part of FilterKeys
  580. if (0 != g_fk.iBounceMSec) {
  581. // Bounce keys enabeled
  582. g_fk.iDelayMSec = 0;
  583. g_fk.iRepeatMSec = 0;
  584. g_fk.iWaitMSec = 0;
  585. g_dwLastBounceKeySetting = g_fk.iBounceMSec;
  586. }
  587. else
  588. {
  589. g_nLastWait = g_fk.iWaitMSec;
  590. if (0 != g_fk.iDelayMSec)
  591. {
  592. // Slow key enabled
  593. g_nLastRepeatDelay = g_fk.iDelayMSec;
  594. g_nLastRepeatRate = g_fk.iRepeatMSec;
  595. }
  596. else
  597. {
  598. // neither Bounce or Slow
  599. g_fk.iRepeatMSec = 0;
  600. }
  601. }
  602. AccessSystemParametersInfo(SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, fWinIni);
  603. s_asPrev.fk = g_fk;
  604. fAnyNotifyChange = TRUE;
  605. }
  606. // always save these
  607. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING, g_dwLastBounceKeySetting);
  608. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY, g_nLastRepeatDelay);
  609. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE, g_nLastRepeatRate);
  610. RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT, g_nLastWait);
  611. if (0 != memcmp(&g_tk, &s_asPrev.tk, sizeof(g_tk)))
  612. {
  613. if (g_fWinNT)
  614. {
  615. g_tk.dwFlags &= TKF_VALID;
  616. }
  617. AccessSystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(g_tk), &g_tk, fWinIni);
  618. s_asPrev.tk = g_tk;
  619. fAnyNotifyChange = TRUE;
  620. }
  621. if (g_fExtraKeyboardHelp != s_asPrev.fExtraKeyboardHelp)
  622. {
  623. // Set this too. Some controls check this flag...0x100B
  624. AccessSystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(g_fExtraKeyboardHelp), fWinIni);
  625. AccessSystemParametersInfo(SPI_SETKEYBOARDPREF, g_fExtraKeyboardHelp, 0, fWinIni);
  626. s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
  627. fAnyNotifyChange = TRUE;
  628. }
  629. // Display Property page
  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 /////////////////////////////////