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.

3173 lines
103 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: access.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the Access Pack functions.
  7. *
  8. * History:
  9. * 11 Feb 93 GregoryW Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. CONST ACCESSIBILITYPROC aAccessibilityProc[] = {
  14. HighContrastHotKey,
  15. FilterKeys,
  16. xxxStickyKeys,
  17. MouseKeys,
  18. ToggleKeys
  19. #if 0
  20. ,UtilityManager
  21. #endif
  22. };
  23. typedef struct tagMODBITINFO {
  24. int BitPosition;
  25. BYTE ScanCode;
  26. USHORT Vk;
  27. } MODBITINFO, *PMODBITINFO;
  28. CONST MODBITINFO aModBit[] =
  29. {
  30. { 0x01, SCANCODE_LSHIFT, VK_LSHIFT },
  31. { 0x02, SCANCODE_RSHIFT, VK_RSHIFT | KBDEXT },
  32. { 0x04, SCANCODE_CTRL, VK_LCONTROL },
  33. { 0x08, SCANCODE_CTRL, VK_RCONTROL | KBDEXT },
  34. { 0x10, SCANCODE_ALT, VK_LMENU },
  35. { 0x20, SCANCODE_ALT, VK_RMENU | KBDEXT },
  36. { 0x40, SCANCODE_LWIN, VK_LWIN },
  37. { 0x80, SCANCODE_RWIN, VK_RWIN | KBDEXT}
  38. };
  39. /*
  40. * The ausMouseVKey array provides a translation from the virtual key
  41. * value to an index. The index is used to select the appropriate
  42. * routine to process the virtual key, as well as to select extra
  43. * information that is used by this routine during its processing.
  44. */
  45. CONST USHORT ausMouseVKey[] = {
  46. VK_CLEAR,
  47. VK_PRIOR,
  48. VK_NEXT,
  49. VK_END,
  50. VK_HOME,
  51. VK_LEFT,
  52. VK_UP,
  53. VK_RIGHT,
  54. VK_DOWN,
  55. VK_INSERT,
  56. VK_DELETE,
  57. VK_MULTIPLY,
  58. VK_ADD,
  59. VK_SUBTRACT,
  60. VK_DIVIDE | KBDEXT,
  61. VK_NUMLOCK | KBDEXT
  62. };
  63. CONST int cMouseVKeys = sizeof(ausMouseVKey) / sizeof(ausMouseVKey[0]);
  64. /*
  65. * aMouseKeyEvent is an array of function pointers. The routine to call
  66. * is selected using the index created by scanning the ausMouseVKey array.
  67. */
  68. CONST MOUSEPROC aMouseKeyEvent[] = {
  69. xxxMKButtonClick, // Numpad 5 (Clear)
  70. xxxMKMouseMove, // Numpad 9 (PgUp)
  71. xxxMKMouseMove, // Numpad 3 (PgDn)
  72. xxxMKMouseMove, // Numpad 1 (End)
  73. xxxMKMouseMove, // Numpad 7 (Home)
  74. xxxMKMouseMove, // Numpad 4 (Left)
  75. xxxMKMouseMove, // Numpad 8 (Up)
  76. xxxMKMouseMove, // Numpad 6 (Right)
  77. xxxMKMouseMove, // Numpad 2 (Down)
  78. xxxMKButtonSetState, // Numpad 0 (Ins)
  79. xxxMKButtonSetState, // Numpad . (Del)
  80. MKButtonSelect, // Numpad * (Multiply)
  81. xxxMKButtonDoubleClick,// Numpad + (Add)
  82. MKButtonSelect, // Numpad - (Subtract)
  83. MKButtonSelect, // Numpad / (Divide)
  84. xxxMKToggleMouseKeys // Num Lock
  85. };
  86. /*
  87. * ausMouseKeyData contains useful data for the routines that process
  88. * the virtual mousekeys. This array is indexed using the index created
  89. * by scanning the ausMouseVKey array.
  90. */
  91. CONST USHORT ausMouseKeyData[] = {
  92. 0, // Numpad 5: Click active button
  93. MK_UP | MK_RIGHT, // Numpad 9: Up & Right
  94. MK_DOWN | MK_RIGHT, // Numpad 3: Down & Right
  95. MK_DOWN | MK_LEFT, // Numpad 1: Down & Left
  96. MK_UP | MK_LEFT, // Numpad 7: Up & Left
  97. MK_LEFT, // Numpad 4: Left
  98. MK_UP, // Numpad 8: Up
  99. MK_RIGHT, // Numpad 6: Right
  100. MK_DOWN, // Numpad 2: Down
  101. FALSE, // Numpad 0: Active button down
  102. TRUE, // Numpad .: Active button up
  103. MOUSE_BUTTON_LEFT | MOUSE_BUTTON_RIGHT, // Numpad *: Select both buttons
  104. 0, // Numpad +: Double click active button
  105. MOUSE_BUTTON_RIGHT, // Numpad -: Select right button
  106. MOUSE_BUTTON_LEFT, // Numpad /: Select left button
  107. 0
  108. };
  109. __inline void
  110. PostAccessNotification(UINT accessKeyType)
  111. {
  112. if (gspwndLogonNotify != NULL)
  113. {
  114. glinp.ptiLastWoken = GETPTI(gspwndLogonNotify);
  115. _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY,
  116. LOGON_ACCESSNOTIFY, accessKeyType);
  117. }
  118. }
  119. void PostRitSound(PTERMINAL pTerm, UINT message) {
  120. PostEventMessage(
  121. pTerm->ptiDesktop,
  122. pTerm->ptiDesktop->pq,
  123. QEVENT_RITSOUND,
  124. NULL,
  125. message, 0, 0);
  126. return;
  127. }
  128. void PostAccessibility( LPARAM lParam )
  129. {
  130. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  131. PostEventMessage(
  132. pTerm->ptiDesktop,
  133. pTerm->ptiDesktop->pq,
  134. QEVENT_RITACCESSIBILITY,
  135. NULL,
  136. 0, HSHELL_ACCESSIBILITYSTATE, lParam);
  137. }
  138. /***************************************************************************\
  139. * AccessProceduresStream
  140. *
  141. * This function controls the order in which the access functions are called.
  142. * All key events pass through this routine. If an access function returns
  143. * FALSE then none of the other access functions in the stream are called.
  144. * This routine is called initially from KeyboardApcProcedure(), but then
  145. * can be called any number of times by the access functions as they process
  146. * the current key event or add more key events.
  147. *
  148. * Return value:
  149. * TRUE All access functions returned TRUE, the key event can be
  150. * processed.
  151. * FALSE An access function returned FALSE, the key event should be
  152. * discarded.
  153. *
  154. * History:
  155. * 11 Feb 93 GregoryW Created.
  156. \***************************************************************************/
  157. BOOL AccessProceduresStream(PKE pKeyEvent, ULONG ExtraInformation, int dwProcIndex)
  158. {
  159. int index;
  160. CheckCritIn();
  161. for (index = dwProcIndex; index < ARRAY_SIZE(aAccessibilityProc); index++) {
  162. if (!aAccessibilityProc[index](pKeyEvent, ExtraInformation, index+1)) {
  163. return FALSE;
  164. }
  165. }
  166. return TRUE;
  167. }
  168. /***************************************************************************\
  169. * FKActivationTimer
  170. *
  171. * If the hot key (right shift key) is held down this routine is called after
  172. * 4, 8, 12 and 16 seconds. This routine is only called at the 12 and 16
  173. * second time points if we're in the process of enabling FilterKeys. If at
  174. * 8 seconds FilterKeys is disabled then this routine will not be called again
  175. * until the hot key is released and then pressed.
  176. *
  177. * This routine is called with the critical section already locked.
  178. *
  179. * Return value:
  180. * 0
  181. *
  182. * History:
  183. * 11 Feb 93 GregoryW Created.
  184. \***************************************************************************/
  185. VOID FKActivationTimer(
  186. PWND pwnd,
  187. UINT message,
  188. UINT_PTR nID,
  189. LPARAM lParam)
  190. {
  191. UINT TimerDelta;
  192. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  193. UNREFERENCED_PARAMETER(pwnd);
  194. UNREFERENCED_PARAMETER(lParam);
  195. UNREFERENCED_PARAMETER(message);
  196. CheckCritIn();
  197. switch (gFilterKeysState) {
  198. case FKFIRSTWARNING:
  199. //
  200. // The audible feedback cannot be disabled for this warning.
  201. //
  202. TimerDelta = FKACTIVATIONDELTA;
  203. break;
  204. case FKTOGGLE:
  205. if (TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)) {
  206. //
  207. // Disable Filter Keys
  208. //
  209. CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON);
  210. if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) {
  211. PostRitSound(pTerm, RITSOUND_DOWNSIREN);
  212. }
  213. PostAccessibility(ACCESS_FILTERKEYS);
  214. //
  215. // Stop all timers that are currently running.
  216. //
  217. if (gtmridFKResponse != 0) {
  218. KILLRITTIMER(NULL, gtmridFKResponse);
  219. gtmridFKResponse = 0;
  220. }
  221. if (gtmridFKAcceptanceDelay != 0) {
  222. KILLRITTIMER(NULL, gtmridFKAcceptanceDelay);
  223. gtmridFKAcceptanceDelay = 0;
  224. }
  225. //
  226. // Don't reset activation timer. Emergency levels are only
  227. // activated after enabling Filter Keys.
  228. //
  229. return;
  230. } else {
  231. if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) {
  232. PostRitSound(pTerm, RITSOUND_UPSIREN);
  233. }
  234. PostAccessNotification(ACCESS_FILTERKEYS);
  235. }
  236. TimerDelta = FKEMERGENCY1DELTA;
  237. break;
  238. case FKFIRSTLEVELEMERGENCY:
  239. //
  240. // First level emergency settings:
  241. // Repeat Rate OFF
  242. // SlowKeys OFF (Acceptance Delay of 0)
  243. // BounceKeys Debounce Time of 1 second
  244. //
  245. if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) {
  246. PostEventMessage(pTerm->ptiDesktop,
  247. pTerm->ptiDesktop->pq,
  248. QEVENT_RITSOUND,
  249. NULL,
  250. RITSOUND_DOBEEP,
  251. RITSOUND_UPSIREN,
  252. 2);
  253. }
  254. gFilterKeys.iRepeatMSec = 0;
  255. gFilterKeys.iWaitMSec = 0;
  256. gFilterKeys.iBounceMSec = 1000;
  257. TimerDelta = FKEMERGENCY2DELTA;
  258. break;
  259. case FKSECONDLEVELEMERGENCY:
  260. //
  261. // Second level emergency settings:
  262. // Repeat Rate OFF
  263. // SlowKeys Acceptance Delay of 2 seconds
  264. // BounceKeys OFF (Debounce Time of 0)
  265. //
  266. gFilterKeys.iRepeatMSec = 0;
  267. gFilterKeys.iWaitMSec = 2000;
  268. gFilterKeys.iBounceMSec = 0;
  269. if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) {
  270. PostEventMessage(
  271. pTerm->ptiDesktop,
  272. pTerm->ptiDesktop->pq,
  273. QEVENT_RITSOUND,
  274. NULL,
  275. RITSOUND_DOBEEP, RITSOUND_UPSIREN, 3);
  276. }
  277. return;
  278. break;
  279. default:
  280. return;
  281. }
  282. gFilterKeysState++;
  283. gtmridFKActivation = InternalSetTimer(NULL,
  284. nID,
  285. TimerDelta,
  286. FKActivationTimer,
  287. TMRF_RIT | TMRF_ONESHOT);
  288. }
  289. /***************************************************************************\
  290. * FKBounceKeyTimer
  291. *
  292. * If BounceKeys is active this routine is called after the debounce time
  293. * has expired. Until then, the last key released will not be accepted as
  294. * input if it is pressed again.
  295. *
  296. * Return value:
  297. * 0
  298. *
  299. * History:
  300. * 11 Feb 93 GregoryW Created.
  301. \***************************************************************************/
  302. VOID FKBounceKeyTimer(
  303. PWND pwnd,
  304. UINT message,
  305. UINT_PTR nID,
  306. LPARAM lParam)
  307. {
  308. UNREFERENCED_PARAMETER(pwnd);
  309. UNREFERENCED_PARAMETER(lParam);
  310. UNREFERENCED_PARAMETER(nID);
  311. UNREFERENCED_PARAMETER(message);
  312. CheckCritIn();
  313. //
  314. // All we need to do is clear gBounceVk to allow this key as the
  315. // next keystroke.
  316. //
  317. gBounceVk = 0;
  318. }
  319. /***************************************************************************\
  320. * xxxFKRepeatRateTimer
  321. *
  322. * If FilterKeys is active and a repeat rate is set, this routine controls
  323. * the rate at which the last key pressed repeats. The hardware keyboard
  324. * typematic repeat is ignored in this case.
  325. *
  326. * This routine is called with the critical section already locked.
  327. *
  328. * Return value:
  329. * 0
  330. *
  331. * History:
  332. * 11 Feb 93 GregoryW Created.
  333. \***************************************************************************/
  334. VOID xxxFKRepeatRateTimer(
  335. PWND pwnd,
  336. UINT message,
  337. UINT_PTR nID,
  338. LPARAM lParam)
  339. {
  340. UNREFERENCED_PARAMETER(pwnd);
  341. UNREFERENCED_PARAMETER(lParam);
  342. UNREFERENCED_PARAMETER(message);
  343. CheckCritIn();
  344. if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) {
  345. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  346. PostRitSound(pTerm, RITSOUND_KEYCLICK);
  347. }
  348. UserAssert(gtmridFKAcceptanceDelay == 0);
  349. gtmridFKResponse = InternalSetTimer(NULL,
  350. nID,
  351. gFilterKeys.iRepeatMSec,
  352. xxxFKRepeatRateTimer,
  353. TMRF_RIT | TMRF_ONESHOT);
  354. if (AccessProceduresStream(gpFKKeyEvent, gFKExtraInformation, gFKNextProcIndex)) {
  355. xxxProcessKeyEvent(gpFKKeyEvent, gFKExtraInformation, FALSE);
  356. }
  357. }
  358. /***************************************************************************\
  359. * xxxFKAcceptanceDelayTimer
  360. *
  361. * If FilterKeys is active and an acceptance delay is set, this routine
  362. * is called after the key has been held down for the acceptance delay
  363. * period.
  364. *
  365. * This routine is called with the critical section already locked.
  366. *
  367. * Return value:
  368. * 0
  369. *
  370. * History:
  371. * 11 Feb 93 GregoryW Created.
  372. \***************************************************************************/
  373. VOID xxxFKAcceptanceDelayTimer(
  374. PWND pwnd,
  375. UINT message,
  376. UINT_PTR nID,
  377. LPARAM lParam)
  378. {
  379. UNREFERENCED_PARAMETER(lParam);
  380. UNREFERENCED_PARAMETER(message);
  381. UNREFERENCED_PARAMETER(pwnd);
  382. CheckCritIn();
  383. //
  384. // The key has been held down long enough. Send it on...
  385. //
  386. if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) {
  387. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  388. PostRitSound(pTerm, RITSOUND_KEYCLICK);
  389. }
  390. if (AccessProceduresStream(gpFKKeyEvent, gFKExtraInformation, gFKNextProcIndex)) {
  391. xxxProcessKeyEvent(gpFKKeyEvent, gFKExtraInformation, FALSE);
  392. }
  393. if (!gFilterKeys.iRepeatMSec) {
  394. //
  395. // gptmrFKAcceptanceDelay needs to be released, but we can't do it while
  396. // in a RIT timer routine. Set a global to indicate that the subsequent
  397. // break of this key should be passed on and the timer freed.
  398. //
  399. SET_ACCF(ACCF_FKMAKECODEPROCESSED);
  400. return;
  401. }
  402. UserAssert(gtmridFKResponse == 0);
  403. if (gFilterKeys.iDelayMSec) {
  404. gtmridFKResponse = InternalSetTimer(NULL,
  405. nID,
  406. gFilterKeys.iDelayMSec,
  407. xxxFKRepeatRateTimer,
  408. TMRF_RIT | TMRF_ONESHOT);
  409. } else {
  410. gtmridFKResponse = InternalSetTimer(NULL,
  411. nID,
  412. gFilterKeys.iRepeatMSec,
  413. xxxFKRepeatRateTimer,
  414. TMRF_RIT | TMRF_ONESHOT);
  415. }
  416. //
  417. // gptmrFKAcceptanceDelay timer structure was reused so set handle to
  418. // NULL.
  419. //
  420. gtmridFKAcceptanceDelay = 0;
  421. }
  422. /***************************************************************************\
  423. * FilterKeys
  424. *
  425. * History:
  426. * 11 Feb 93 GregoryW Created.
  427. \***************************************************************************/
  428. BOOL FilterKeys(
  429. PKE pKeyEvent,
  430. ULONG ExtraInformation,
  431. int NextProcIndex)
  432. {
  433. int fBreak;
  434. BYTE Vk;
  435. CheckCritIn();
  436. Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff);
  437. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  438. //
  439. // Check for Filter Keys hot key (right shift key).
  440. //
  441. if (Vk == VK_RSHIFT) {
  442. if (fBreak) {
  443. if (gtmridFKActivation != 0) {
  444. KILLRITTIMER(NULL, gtmridFKActivation);
  445. gtmridFKActivation = 0;
  446. }
  447. gFilterKeysState = FKIDLE;
  448. } else if (ONLYRIGHTSHIFTDOWN(gPhysModifierState)) {
  449. //
  450. // Verify that activation via hotkey is allowed.
  451. //
  452. if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYACTIVE)) {
  453. if ((gtmridFKActivation == 0) && (gFilterKeysState != FKMOUSEMOVE)) {
  454. gFilterKeysState = FKFIRSTWARNING;
  455. gtmridFKActivation = InternalSetTimer(NULL,
  456. 0,
  457. FKFIRSTWARNINGTIME,
  458. FKActivationTimer,
  459. TMRF_RIT | TMRF_ONESHOT);
  460. }
  461. }
  462. }
  463. }
  464. //
  465. // If another key is pressed while the hot key is down, kill
  466. // the timer.
  467. //
  468. if (Vk != VK_RSHIFT && gtmridFKActivation != 0) {
  469. gFilterKeysState = FKIDLE;
  470. KILLRITTIMER(NULL, gtmridFKActivation);
  471. gtmridFKActivation = 0;
  472. }
  473. //
  474. // If Filter Keys not enabled send the key event on.
  475. //
  476. if (!TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)) {
  477. return TRUE;
  478. }
  479. if (fBreak) {
  480. //
  481. // Kill the current timer and activate bounce key timer (if this is
  482. // a break of the last key down).
  483. //
  484. if (Vk == gLastVkDown) {
  485. KILLRITTIMER(NULL, gtmridFKResponse);
  486. gtmridFKResponse = 0;
  487. gLastVkDown = 0;
  488. if (gtmridFKAcceptanceDelay != 0) {
  489. KILLRITTIMER(NULL, gtmridFKAcceptanceDelay);
  490. gtmridFKAcceptanceDelay = 0;
  491. if (!TEST_ACCF(ACCF_FKMAKECODEPROCESSED)) {
  492. //
  493. // This key was released before accepted. Don't pass on the
  494. // break.
  495. //
  496. return FALSE;
  497. } else {
  498. CLEAR_ACCF(ACCF_FKMAKECODEPROCESSED);
  499. }
  500. }
  501. if (gFilterKeys.iBounceMSec) {
  502. gBounceVk = Vk;
  503. gtmridFKResponse = InternalSetTimer(NULL,
  504. 0,
  505. gFilterKeys.iBounceMSec,
  506. FKBounceKeyTimer,
  507. TMRF_RIT | TMRF_ONESHOT);
  508. if (TEST_ACCF(ACCF_IGNOREBREAKCODE)) {
  509. return FALSE;
  510. }
  511. }
  512. }
  513. } else {
  514. //
  515. // Make key processing
  516. //
  517. // First check to see if this is a typematic repeat. If so, we
  518. // can ignore this key event. Our timer will handle any repeats.
  519. // LastVkDown is cleared during processing of the break.
  520. //
  521. if (Vk == gLastVkDown) {
  522. return FALSE;
  523. }
  524. //
  525. // Remember current Virtual Key down for typematic repeat check.
  526. //
  527. gLastVkDown = Vk;
  528. if (gBounceVk) {
  529. //
  530. // BounceKeys is active. If this is a make of the last
  531. // key pressed we ignore it. Only when the BounceKey
  532. // timer expires or another key is pressed will we accept
  533. // this key.
  534. //
  535. if (Vk == gBounceVk) {
  536. //
  537. // Ignore this make event and the subsequent break
  538. // code. BounceKey timer will be reset on break.
  539. //
  540. SET_ACCF(ACCF_IGNOREBREAKCODE);
  541. return FALSE;
  542. } else {
  543. //
  544. // We have a make of a new key. Kill the BounceKey
  545. // timer and clear gBounceVk.
  546. //
  547. UserAssert(gtmridFKResponse);
  548. if (gtmridFKResponse != 0) {
  549. KILLRITTIMER(NULL, gtmridFKResponse);
  550. gtmridFKResponse = 0;
  551. }
  552. gBounceVk = 0;
  553. }
  554. }
  555. CLEAR_ACCF(ACCF_IGNOREBREAKCODE);
  556. //
  557. // Give audible feedback that key was pressed.
  558. //
  559. if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) {
  560. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  561. PostRitSound(
  562. pTerm,
  563. RITSOUND_KEYCLICK);
  564. }
  565. //
  566. // If gptmrFKAcceptanceDelay is non-NULL the previous key was
  567. // not held down long enough to be accepted. Kill the current
  568. // timer. A new timer will be started below for the key we're
  569. // processing now.
  570. //
  571. if (gtmridFKAcceptanceDelay != 0) {
  572. KILLRITTIMER(NULL, gtmridFKAcceptanceDelay);
  573. gtmridFKAcceptanceDelay = 0;
  574. }
  575. //
  576. // If gptmrFKResponse is non-NULL a repeat rate timer is active
  577. // on the previous key. Kill the timer as we have a new make key.
  578. //
  579. if (gtmridFKResponse != 0) {
  580. KILLRITTIMER(NULL, gtmridFKResponse);
  581. gtmridFKResponse = 0;
  582. }
  583. //
  584. // Save the current key event for later use if we process an
  585. // acceptance delay or key repeat.
  586. //
  587. *gpFKKeyEvent = *pKeyEvent;
  588. gFKExtraInformation = ExtraInformation;
  589. gFKNextProcIndex = NextProcIndex;
  590. //
  591. // If there is an acceptance delay, set timer and ignore current
  592. // key event. When timer expires, saved key event will be sent.
  593. //
  594. if (gFilterKeys.iWaitMSec) {
  595. gtmridFKAcceptanceDelay = InternalSetTimer(NULL,
  596. 0,
  597. gFilterKeys.iWaitMSec,
  598. xxxFKAcceptanceDelayTimer,
  599. TMRF_RIT | TMRF_ONESHOT);
  600. CLEAR_ACCF(ACCF_FKMAKECODEPROCESSED);
  601. return FALSE;
  602. }
  603. //
  604. // No acceptance delay. Before sending this key event on the
  605. // timer routine must be set to either the delay until repeat value
  606. // or the repeat rate value. If repeat rate is 0 then ignore
  607. // delay until repeat.
  608. //
  609. if (!gFilterKeys.iRepeatMSec) {
  610. return TRUE;
  611. }
  612. UserAssert(gtmridFKResponse == 0);
  613. if (gFilterKeys.iDelayMSec) {
  614. gtmridFKResponse = InternalSetTimer(NULL,
  615. 0,
  616. gFilterKeys.iDelayMSec,
  617. xxxFKRepeatRateTimer,
  618. TMRF_RIT | TMRF_ONESHOT);
  619. } else {
  620. gtmridFKResponse = InternalSetTimer(NULL,
  621. 0,
  622. gFilterKeys.iRepeatMSec,
  623. xxxFKRepeatRateTimer,
  624. TMRF_RIT | TMRF_ONESHOT);
  625. }
  626. }
  627. return TRUE;
  628. }
  629. /***************************************************************************\
  630. * StopFilterKeysTimers
  631. *
  632. * Called from SystemParametersInfo on SPI_SETFILTERKEYS if FKF_FILTERKEYSON
  633. * is not set. Timers must be stopped if user turns FilterKeys off.
  634. *
  635. * History:
  636. * 18 Jul 94 GregoryW Created.
  637. \***************************************************************************/
  638. VOID StopFilterKeysTimers(VOID)
  639. {
  640. if (gtmridFKResponse != 0) {
  641. KILLRITTIMER(NULL, gtmridFKResponse);
  642. gtmridFKResponse = 0;
  643. }
  644. if (gtmridFKAcceptanceDelay) {
  645. KILLRITTIMER(NULL, gtmridFKAcceptanceDelay);
  646. gtmridFKAcceptanceDelay = 0;
  647. }
  648. gLastVkDown = 0;
  649. gBounceVk = 0;
  650. }
  651. /***************************************************************************\
  652. * xxxStickyKeys
  653. *
  654. * History:
  655. * 11 Feb 93 GregoryW Created.
  656. \***************************************************************************/
  657. BOOL xxxStickyKeys(PKE pKeyEvent, ULONG ExtraInformation, int NextProcIndex)
  658. {
  659. int fBreak;
  660. BYTE NewLockBits, NewLatchBits;
  661. int BitPositions;
  662. BOOL bChange;
  663. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  664. CheckCritIn();
  665. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  666. if (gCurrentModifierBit) {
  667. //
  668. // Process modifier key
  669. //
  670. //
  671. // One method of activating StickyKeys is to press either the
  672. // left shift key or the right shift key five times without
  673. // pressing any other keys. We don't want the typematic shift
  674. // (make code) to enable/disable StickyKeys so we perform a
  675. // special test for them.
  676. //
  677. if (!fBreak) {
  678. if (gCurrentModifierBit & gPrevModifierState) {
  679. //
  680. // This is a typematic make of a modifier key. Don't do
  681. // any further processing. Just pass it along.
  682. //
  683. gPrevModifierState = gPhysModifierState;
  684. return TRUE;
  685. }
  686. }
  687. gPrevModifierState = gPhysModifierState;
  688. if (LEFTSHIFTKEY(pKeyEvent->usFlaggedVk) &&
  689. ((gPhysModifierState & ~gCurrentModifierBit) == 0)) {
  690. gStickyKeysLeftShiftCount++;
  691. } else {
  692. gStickyKeysLeftShiftCount = 0;
  693. }
  694. if (RIGHTSHIFTKEY(pKeyEvent->usFlaggedVk) &&
  695. ((gPhysModifierState & ~gCurrentModifierBit) == 0)) {
  696. gStickyKeysRightShiftCount++;
  697. } else {
  698. gStickyKeysRightShiftCount = 0;
  699. }
  700. //
  701. // Check to see if StickyKeys should be toggled on/off
  702. //
  703. if ((gStickyKeysLeftShiftCount == (TOGGLE_STICKYKEYS_COUNT * 2)) ||
  704. (gStickyKeysRightShiftCount == (TOGGLE_STICKYKEYS_COUNT * 2))) {
  705. if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYACTIVE)) {
  706. if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) {
  707. xxxTurnOffStickyKeys();
  708. if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) {
  709. PostRitSound(
  710. pTerm,
  711. RITSOUND_DOWNSIREN);
  712. }
  713. } else {
  714. if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) {
  715. PostRitSound(
  716. pTerm,
  717. RITSOUND_UPSIREN);
  718. }
  719. // To make the notification window get the focus
  720. // The same is done other places where WM_LOGONNOTIFY message is
  721. // sent : a-anilk
  722. PostAccessNotification(ACCESS_STICKYKEYS);
  723. }
  724. }
  725. gStickyKeysLeftShiftCount = 0;
  726. gStickyKeysRightShiftCount = 0;
  727. return TRUE;
  728. }
  729. //
  730. // If StickyKeys is enabled process the modifier key, otherwise
  731. // just pass on the modifier key.
  732. //
  733. if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) {
  734. if (fBreak) {
  735. //
  736. // If either locked or latched bit set for this key then
  737. // don't pass the break on.
  738. //
  739. if (UNION(gLatchBits, gLockBits) & gCurrentModifierBit) {
  740. return FALSE;
  741. } else {
  742. return TRUE;
  743. }
  744. } else{
  745. if (gPhysModifierState != gCurrentModifierBit) {
  746. //
  747. // More than one modifier key down at the same time.
  748. // This condition may signal sticky keys to turn off.
  749. // The routine xxxTwoKeysDown will return the new value
  750. // of fStickyKeysOn. If sticky keys is turned off
  751. // (return value 0), the key event should be passed
  752. // on without further processing here.
  753. //
  754. if (!xxxTwoKeysDown(NextProcIndex)) {
  755. return TRUE;
  756. }
  757. //
  758. // Modifier states were set to physical state by
  759. // xxxTwoKeysDown. The modifier keys currently in
  760. // the down position will be latched by updating
  761. // gLatchBits. No more processing for this key
  762. // event is needed.
  763. //
  764. bChange = gLockBits ||
  765. (gLatchBits != gPhysModifierState);
  766. gLatchBits = gPhysModifierState;
  767. gLockBits = 0;
  768. if (bChange) {
  769. PostAccessibility( ACCESS_STICKYKEYS );
  770. }
  771. //
  772. // Provide sound feedback, if enabled, before returning.
  773. //
  774. if (TEST_ACCESSFLAG(StickyKeys, SKF_AUDIBLEFEEDBACK)) {
  775. PostRitSound(
  776. pTerm,
  777. RITSOUND_LOWBEEP);
  778. PostRitSound(
  779. pTerm,
  780. RITSOUND_HIGHBEEP);
  781. }
  782. return FALSE;
  783. }
  784. //
  785. // Figure out which bits (Shift, Ctrl or Alt key bits) to
  786. // examine. Also set up default values for NewLatchBits
  787. // and NewLockBits in case they're not set later.
  788. //
  789. // See the depiction of the bit pattern in KeyboardApcProcedure.
  790. //
  791. // Bit 0 -- L SHIFT
  792. // Bit 1 -- R SHIFT
  793. // Bit 2 -- L CTL
  794. // Bit 3 -- R CTL
  795. // Bit 4 -- L ALT
  796. // Bit 5 -- R RLT
  797. // Bit 6 -- L WIN
  798. // Bit 7 -- R WIN
  799. switch(pKeyEvent->usFlaggedVk) {
  800. case VK_LSHIFT:
  801. case VK_RSHIFT:
  802. BitPositions = 0x3;
  803. break;
  804. case VK_LCONTROL:
  805. case VK_RCONTROL:
  806. BitPositions = 0xc;
  807. break;
  808. case VK_LMENU:
  809. case VK_RMENU:
  810. BitPositions = 0x30;
  811. break;
  812. case VK_LWIN:
  813. case VK_RWIN:
  814. BitPositions = 0xc0;
  815. break;
  816. }
  817. NewLatchBits = gLatchBits;
  818. NewLockBits = gLockBits;
  819. //
  820. // If either left or right modifier is locked clear latched
  821. // and locked states and send appropriate break/make messages.
  822. //
  823. if (gLockBits & BitPositions) {
  824. NewLockBits = gLockBits & ~BitPositions;
  825. NewLatchBits = gLatchBits & ~BitPositions;
  826. xxxUpdateModifierState(
  827. NewLockBits | NewLatchBits | gCurrentModifierBit,
  828. NextProcIndex
  829. );
  830. } else {
  831. //
  832. // If specific lock bit (left or right) not
  833. // previously set then toggle latch bits.
  834. //
  835. if (!(gLockBits & gCurrentModifierBit)) {
  836. NewLatchBits = gLatchBits ^ gCurrentModifierBit;
  837. }
  838. //
  839. // If locked mode (tri-state) enabled then if latch or lock
  840. // bit previously set, toggle lock bit.
  841. //
  842. if (TEST_ACCESSFLAG(StickyKeys, SKF_TRISTATE)) {
  843. if (UNION(gLockBits, gLatchBits) & gCurrentModifierBit) {
  844. NewLockBits = gLockBits ^ gCurrentModifierBit;
  845. }
  846. }
  847. }
  848. //
  849. // Update globals
  850. //
  851. bChange = ((gLatchBits != NewLatchBits) ||
  852. (gLockBits != NewLockBits));
  853. gLatchBits = NewLatchBits;
  854. gLockBits = NewLockBits;
  855. if (bChange) {
  856. PostAccessibility( ACCESS_STICKYKEYS );
  857. }
  858. //
  859. // Now provide sound feedback if enabled. For the transition
  860. // to LATCH mode issue a low beep then a high beep. For the
  861. // transition to LOCKED mode issue a high beep. For the
  862. // transition out of LOCKED mode (or LATCH mode if tri-state
  863. // not enabled) issue a low beep.
  864. //
  865. if (TEST_ACCESSFLAG(StickyKeys, SKF_AUDIBLEFEEDBACK)) {
  866. if (!(gLockBits & gCurrentModifierBit)) {
  867. PostRitSound(
  868. pTerm,
  869. RITSOUND_LOWBEEP);
  870. }
  871. if ((gLatchBits | gLockBits) & gCurrentModifierBit) {
  872. PostRitSound(
  873. pTerm,
  874. RITSOUND_HIGHBEEP);
  875. }
  876. }
  877. //
  878. // Pass key on if shift bit is set (e.g., if transitioning
  879. // from shift to lock mode don't pass on make).
  880. //
  881. if (gLatchBits & gCurrentModifierBit) {
  882. return TRUE;
  883. } else {
  884. return FALSE;
  885. }
  886. }
  887. }
  888. } else {
  889. //
  890. // Non-shift key processing here...
  891. //
  892. gStickyKeysLeftShiftCount = 0;
  893. gStickyKeysRightShiftCount = 0;
  894. if (!TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) {
  895. return TRUE;
  896. }
  897. //
  898. // If no modifier keys are down, or this is a break, pass the key event
  899. // on and clear any latch states.
  900. //
  901. if (!gPhysModifierState || fBreak) {
  902. if (AccessProceduresStream(pKeyEvent, ExtraInformation, NextProcIndex)) {
  903. xxxProcessKeyEvent(pKeyEvent, ExtraInformation, FALSE);
  904. }
  905. xxxUpdateModifierState(gLockBits, NextProcIndex);
  906. bChange = gLatchBits != 0;
  907. gLatchBits = 0;
  908. if (bChange) {
  909. PostAccessibility( ACCESS_STICKYKEYS );
  910. }
  911. return FALSE;
  912. } else {
  913. //
  914. // This is a make of a non-modifier key and there is a modifier key
  915. // down. Update the states and pass the key event on.
  916. //
  917. xxxTwoKeysDown(NextProcIndex);
  918. return TRUE;
  919. }
  920. }
  921. return TRUE;
  922. }
  923. /***************************************************************************\
  924. * xxxUpdateModifierState
  925. *
  926. * Starting from the current modifier keys state, send the necessary key
  927. * events (make or break) to end up with the NewModifierState passed in.
  928. *
  929. * Return value:
  930. * None.
  931. *
  932. * History:
  933. * 11 Feb 93 GregoryW Created.
  934. \***************************************************************************/
  935. VOID xxxUpdateModifierState(int NewModifierState, int NextProcIndex)
  936. {
  937. KE ke;
  938. int CurrentModState;
  939. int CurrentModBit, NewModBit;
  940. int i;
  941. CheckCritIn();
  942. CurrentModState = gLockBits | gLatchBits;
  943. for (i = 0; i < ARRAY_SIZE(aModBit); i++) {
  944. CurrentModBit = CurrentModState & aModBit[i].BitPosition;
  945. NewModBit = NewModifierState & aModBit[i].BitPosition;
  946. if (CurrentModBit != NewModBit) {
  947. ke.bScanCode = (BYTE)aModBit[i].ScanCode;
  948. ke.usFlaggedVk = aModBit[i].Vk;
  949. if (CurrentModBit) { // if it's currently on, send break
  950. ke.usFlaggedVk |= KBDBREAK;
  951. }
  952. if (AccessProceduresStream(&ke, 0L, NextProcIndex)) {
  953. xxxProcessKeyEvent(&ke, 0L, FALSE);
  954. }
  955. }
  956. }
  957. }
  958. /***************************************************************************\
  959. * xxxTurnOffStickyKeys
  960. *
  961. * The user either pressed the appropriate key sequence or used the
  962. * access utility to turn StickyKeys off. Update modifier states and
  963. * reset globals.
  964. *
  965. * Return value:
  966. * None.
  967. *
  968. * History:
  969. * 11 Feb 93 GregoryW Created.
  970. \***************************************************************************/
  971. VOID xxxTurnOffStickyKeys(VOID)
  972. {
  973. INT index;
  974. CheckCritIn();
  975. for (index = 0; index < ARRAY_SIZE(aAccessibilityProc); index++) {
  976. if (aAccessibilityProc[index] == xxxStickyKeys) {
  977. xxxUpdateModifierState(gPhysModifierState, index+1);
  978. gLockBits = gLatchBits = 0;
  979. CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON);
  980. PostAccessibility( ACCESS_STICKYKEYS );
  981. break;
  982. }
  983. }
  984. }
  985. /***************************************************************************\
  986. * xxxUnlatchStickyKeys
  987. *
  988. * This routine releases any sticky keys that are latched. This routine
  989. * is called during mouse up event processing.
  990. *
  991. * Return value:
  992. * None.
  993. *
  994. * History:
  995. * 21 Jun 93 GregoryW Created.
  996. \***************************************************************************/
  997. VOID xxxUnlatchStickyKeys(VOID)
  998. {
  999. INT index;
  1000. BOOL bChange;
  1001. if (!gLatchBits) {
  1002. return;
  1003. }
  1004. for (index = 0; index < ARRAY_SIZE(aAccessibilityProc); index++) {
  1005. if (aAccessibilityProc[index] == xxxStickyKeys) {
  1006. xxxUpdateModifierState(gLockBits, index+1);
  1007. bChange = gLatchBits != 0;
  1008. gLatchBits = 0;
  1009. if (bChange) {
  1010. PostAccessibility( ACCESS_STICKYKEYS );
  1011. }
  1012. break;
  1013. }
  1014. }
  1015. }
  1016. /***************************************************************************\
  1017. * xxxHardwareMouseKeyUp
  1018. *
  1019. * This routine is called during a mouse button up event. If MouseKeys is
  1020. * on and the button up event corresponds to a mouse key that's locked down,
  1021. * the mouse key must be released.
  1022. *
  1023. * If StickyKeys is on, all latched keys are released.
  1024. *
  1025. * Return value:
  1026. * None.
  1027. *
  1028. * History:
  1029. * 17 Jun 94 GregoryW Created.
  1030. \***************************************************************************/
  1031. VOID xxxHardwareMouseKeyUp(DWORD dwButton)
  1032. {
  1033. CheckCritIn();
  1034. if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) {
  1035. gwMKButtonState &= ~dwButton;
  1036. }
  1037. // Not required to post a setting change
  1038. //PostAccessibility( SPI_SETMOUSEKEYS );
  1039. if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) {
  1040. xxxUnlatchStickyKeys();
  1041. }
  1042. }
  1043. /***************************************************************************\
  1044. * xxxTwoKeysDown
  1045. *
  1046. * Two keys are down simultaneously. Check to see if StickyKeys should be
  1047. * turned off. In all cases update the modifier key state to reflect the
  1048. * physical key state and clear latched and locked modes.
  1049. *
  1050. * Return value:
  1051. * 1 if StickyKeys is enabled.
  1052. * 0 if StickyKeys is disabled.
  1053. *
  1054. * History:
  1055. * 11 Feb 93 GregoryW Created.
  1056. \***************************************************************************/
  1057. BOOL xxxTwoKeysDown(int NextProcIndex)
  1058. {
  1059. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1060. if (TEST_ACCESSFLAG(StickyKeys, SKF_TWOKEYSOFF)) {
  1061. CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON);
  1062. if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) {
  1063. PostRitSound(
  1064. pTerm,
  1065. RITSOUND_DOWNSIREN);
  1066. }
  1067. gStickyKeysLeftShiftCount = 0;
  1068. gStickyKeysRightShiftCount = 0;
  1069. }
  1070. xxxUpdateModifierState(gPhysModifierState, NextProcIndex);
  1071. gLockBits = gLatchBits = 0;
  1072. PostAccessibility( ACCESS_STICKYKEYS );
  1073. return TEST_BOOL_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON);
  1074. }
  1075. /***************************************************************************\
  1076. * SetGlobalCursorLevel
  1077. *
  1078. * Set the cursor level of all threads running on the visible
  1079. * windowstation.
  1080. *
  1081. * History:
  1082. * 04-17-95 JimA Created.
  1083. \***************************************************************************/
  1084. VOID SetGlobalCursorLevel(
  1085. INT iCursorLevel)
  1086. {
  1087. /*
  1088. * LATER
  1089. * We have other code which assumes that the
  1090. * iCursorLevel of a queue is the sum of the iCursorLevel values for the
  1091. * threads attached to the queue. But this code, if you set iCursorLevel to
  1092. * -1 (to indicate no mouse) will set the queue iCursorLevel to -1, no matter
  1093. * how many threads are attached to the queue. This needs to be revisited.
  1094. * See the function AttachToQueue.
  1095. * FritzS
  1096. */
  1097. PDESKTOP pdesk;
  1098. PTHREADINFO pti;
  1099. PLIST_ENTRY pHead, pEntry;
  1100. TAGMSG1(DBGTAG_PNP, "SetGlobalCursorLevel %x", iCursorLevel);
  1101. if (grpdeskRitInput) {
  1102. for (pdesk = grpdeskRitInput->rpwinstaParent->rpdeskList;
  1103. pdesk != NULL; pdesk = pdesk->rpdeskNext) {
  1104. pHead = &pdesk->PtiList;
  1105. for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
  1106. pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink);
  1107. pti->iCursorLevel = iCursorLevel;
  1108. pti->pq->iCursorLevel = iCursorLevel;
  1109. }
  1110. }
  1111. }
  1112. /*
  1113. * CSRSS doesn't seem to be on the list, so fix it up now.
  1114. */
  1115. for (pti = PpiFromProcess(gpepCSRSS)->ptiList;
  1116. pti != NULL; pti = pti->ptiSibling) {
  1117. if (pti->iCursorLevel != iCursorLevel) {
  1118. TAGMSG3(DBGTAG_PNP, "pti %#p has cursorlevel %x, should be %x",
  1119. pti, pti->iCursorLevel, iCursorLevel);
  1120. }
  1121. if (pti->pq->iCursorLevel != iCursorLevel) {
  1122. TAGMSG4(DBGTAG_PNP, "pti->pq %#p->%#p has cursorlevel %x, should be %x",
  1123. pti, pti->pq, pti->pq->iCursorLevel, iCursorLevel);
  1124. }
  1125. pti->iCursorLevel = iCursorLevel;
  1126. pti->pq->iCursorLevel = iCursorLevel;
  1127. }
  1128. }
  1129. /***************************************************************************\
  1130. * MKShowMouseCursor
  1131. *
  1132. * If no hardware mouse is installed and MouseKeys is enabled, we need
  1133. * to fix up the system metrics, the oem information and the queue
  1134. * information. The mouse cursor then gets displayed.
  1135. *
  1136. * Return value:
  1137. * None.
  1138. *
  1139. * History:
  1140. * 11 Feb 93 GregoryW Created.
  1141. \***************************************************************************/
  1142. VOID MKShowMouseCursor()
  1143. {
  1144. TAGMSG1(DBGTAG_PNP, "MKShowMouseCursor (gpDeviceInfoList == %#p)", gpDeviceInfoList);
  1145. //
  1146. // If TEST_GTERMF(GTERMF_MOUSE) is TRUE then we either have a hardware mouse
  1147. // or we're already pretending a mouse is installed. In either case,
  1148. // there's nothing to do so just return.
  1149. //
  1150. if (TEST_GTERMF(GTERMF_MOUSE)) {
  1151. TAGMSG0(DBGTAG_PNP, "MKShowMouseCursor just returns");
  1152. return;
  1153. }
  1154. SET_GTERMF(GTERMF_MOUSE);
  1155. SET_ACCF(ACCF_MKVIRTUALMOUSE);
  1156. SYSMET(MOUSEPRESENT) = TRUE;
  1157. SYSMET(CMOUSEBUTTONS) = 2;
  1158. /*
  1159. * HACK: CreateQueue() uses oemInfo.fMouse to determine if a mouse is
  1160. * present and thus whether to set the iCursorLevel field in the
  1161. * THREADINFO structure to 0 or -1. Unfortunately some queues have
  1162. * already been created at this point. Since oemInfo.fMouse is
  1163. * initialized to FALSE, we need to go back through any queues already
  1164. * around and set their iCursorLevel field to the correct value when
  1165. * mousekeys is enabled.
  1166. */
  1167. SetGlobalCursorLevel(0);
  1168. }
  1169. /***************************************************************************\
  1170. * MKHideMouseCursor
  1171. *
  1172. * If no hardware mouse is installed and MouseKeys is disabled, we need
  1173. * to fix up the system metrics, the oem information and the queue
  1174. * information. The mouse cursor then disappears.
  1175. *
  1176. * Return value:
  1177. * None.
  1178. *
  1179. * History:
  1180. * 11 Feb 93 GregoryW Created.
  1181. \***************************************************************************/
  1182. VOID MKHideMouseCursor()
  1183. {
  1184. TAGMSG1(DBGTAG_PNP, "MKHideMouseCursor (gpDeviceInfoList == %#p)", gpDeviceInfoList);
  1185. //
  1186. // If a hardware mouse is present we don't need to do anything.
  1187. //
  1188. if (!TEST_ACCF(ACCF_MKVIRTUALMOUSE)) {
  1189. return;
  1190. }
  1191. CLEAR_ACCF(ACCF_MKVIRTUALMOUSE);
  1192. CLEAR_GTERMF(GTERMF_MOUSE);
  1193. SYSMET(MOUSEPRESENT) = FALSE;
  1194. SYSMET(CMOUSEBUTTONS) = 0;
  1195. SetGlobalCursorLevel(-1);
  1196. }
  1197. /***************************************************************************\
  1198. * xxxMKToggleMouseKeys
  1199. *
  1200. * This routine is called when the NumLock key is pressed and MouseKeys is
  1201. * active. If the left shift key and the left alt key are down then MouseKeys
  1202. * is turned off. If just the NumLock key is pressed then we toggle between
  1203. * MouseKeys active and the state of the number pad before MouseKeys was
  1204. * activated.
  1205. *
  1206. * Return value:
  1207. * TRUE - key should be passed on in the input stream.
  1208. * FALSE - key should not be passed on.
  1209. *
  1210. * History:
  1211. \***************************************************************************/
  1212. BOOL xxxMKToggleMouseKeys(
  1213. USHORT NotUsed)
  1214. {
  1215. BOOL bRetVal = TRUE;
  1216. BOOL bNewPassThrough;
  1217. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1218. UNREFERENCED_PARAMETER(NotUsed);
  1219. //
  1220. // If this is a typematic repeat of NumLock we just pass it on.
  1221. //
  1222. if (TEST_ACCF(ACCF_MKREPEATVK)) {
  1223. return bRetVal;
  1224. }
  1225. //
  1226. // This is a make of NumLock. Check for disable sequence.
  1227. //
  1228. if ((gLockBits | gLatchBits | gPhysModifierState) == MOUSEKEYMODBITS) {
  1229. if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE)) {
  1230. if (!gbMKMouseMode) {
  1231. //
  1232. // User wants to turn MouseKeys off. If we're currently in
  1233. // pass through mode then the NumLock key is in the same state
  1234. // (on or off) as it was when the user invoked MouseKeys. We
  1235. // want to leave it in that state, so don't pass the NumLock
  1236. // key on.
  1237. //
  1238. bRetVal = FALSE;
  1239. }
  1240. TurnOffMouseKeys();
  1241. }
  1242. return bRetVal;
  1243. }
  1244. /*
  1245. * This is a NumLock with no modifiers. Toggle current state and
  1246. * provide audible feedback.
  1247. *
  1248. * Note -- this test is the reverse of other ones because it tests the
  1249. * state of VK_NUMLOCK before the keypress flips the state of NUMLOCK.
  1250. * So the code checks for what the state will be.
  1251. */
  1252. bNewPassThrough =
  1253. #ifdef FE_SB // MouseKeys()
  1254. (TestAsyncKeyStateToggle(gNumLockVk) != 0) ^
  1255. #else // FE_SB
  1256. (TestAsyncKeyStateToggle(VK_NUMLOCK) != 0) ^
  1257. #endif // FE_SB
  1258. (TEST_ACCESSFLAG(MouseKeys, MKF_REPLACENUMBERS) != 0);
  1259. if (!bNewPassThrough) {
  1260. gbMKMouseMode = TRUE;
  1261. PostRitSound(
  1262. pTerm,
  1263. RITSOUND_HIGHBEEP);
  1264. } else {
  1265. WORD SaveCurrentActiveButton;
  1266. //
  1267. // User wants keys to be passed on. Release all buttons currently
  1268. // down.
  1269. //
  1270. gbMKMouseMode = FALSE;
  1271. PostRitSound(
  1272. pTerm,
  1273. RITSOUND_LOWBEEP);
  1274. SaveCurrentActiveButton = gwMKCurrentButton;
  1275. gwMKCurrentButton = MOUSE_BUTTON_LEFT | MOUSE_BUTTON_RIGHT;
  1276. xxxMKButtonSetState(TRUE);
  1277. gwMKCurrentButton = SaveCurrentActiveButton;
  1278. }
  1279. PostAccessibility( ACCESS_MOUSEKEYS );
  1280. return bRetVal;
  1281. }
  1282. /***************************************************************************\
  1283. * xxxMKButtonClick
  1284. *
  1285. * Click the active mouse button.
  1286. *
  1287. * Return value:
  1288. * Always FALSE - key should not be passed on.
  1289. *
  1290. * History:
  1291. \***************************************************************************/
  1292. BOOL xxxMKButtonClick(USHORT NotUsed)
  1293. {
  1294. UNREFERENCED_PARAMETER(NotUsed);
  1295. //
  1296. // The button click only happens on initial make of key. If this is a
  1297. // typematic repeat we just ignore it.
  1298. //
  1299. if (TEST_ACCF(ACCF_MKREPEATVK)) {
  1300. return FALSE;
  1301. }
  1302. //
  1303. // Ensure active button is UP before the click
  1304. //
  1305. xxxMKButtonSetState(TRUE);
  1306. //
  1307. // Now push the button DOWN
  1308. //
  1309. xxxMKButtonSetState(FALSE);
  1310. //
  1311. // Now release the button
  1312. //
  1313. xxxMKButtonSetState(TRUE);
  1314. return FALSE;
  1315. }
  1316. /***************************************************************************\
  1317. * xxxMKMoveConstCursorTimer
  1318. *
  1319. * Timer routine that handles constant speed mouse movement. This routine
  1320. * is called 20 times per second and uses information from
  1321. * gMouseCursor.bConstantTable[] to determine how many pixels to move the
  1322. * mouse cursor on each tick.
  1323. *
  1324. * Return value:
  1325. * None.
  1326. *
  1327. * History:
  1328. \***************************************************************************/
  1329. VOID xxxMKMoveConstCursorTimer(
  1330. PWND pwnd,
  1331. UINT message,
  1332. UINT_PTR nID,
  1333. LPARAM lParam)
  1334. {
  1335. LONG MovePixels;
  1336. UNREFERENCED_PARAMETER(pwnd);
  1337. UNREFERENCED_PARAMETER(lParam);
  1338. UNREFERENCED_PARAMETER(nID);
  1339. UNREFERENCED_PARAMETER(message);
  1340. CheckCritIn();
  1341. if (TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS)) {
  1342. if ((gLockBits | gLatchBits | gPhysModifierState) & LRSHIFT) {
  1343. MovePixels = 1;
  1344. goto MoveIt;
  1345. }
  1346. if ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL) {
  1347. MovePixels = gMouseCursor.bConstantTable[0] * MK_CONTROL_SPEED;
  1348. goto MoveIt;
  1349. }
  1350. }
  1351. giMouseMoveTable %= gMouseCursor.bConstantTableLen;
  1352. MovePixels = gMouseCursor.bConstantTable[giMouseMoveTable++];
  1353. if (MovePixels == 0) {
  1354. return;
  1355. }
  1356. MoveIt:
  1357. //
  1358. // We're inside the critical section - leave before calling MoveEvent.
  1359. // Set gbMouseMoved to TRUE so RawInputThread wakes up the appropriate
  1360. // user thread (if any) to receive this event.
  1361. //
  1362. LeaveCrit();
  1363. xxxMoveEvent(MovePixels * gMKDeltaX, MovePixels * gMKDeltaY, 0, 0,
  1364. #ifdef GENERIC_INPUT
  1365. NULL,
  1366. NULL,
  1367. #endif
  1368. 0, FALSE);
  1369. QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(),
  1370. #ifdef GENERIC_INPUT
  1371. /*
  1372. * There's no real mouse related to this mouse message.
  1373. */
  1374. NULL,
  1375. NULL,
  1376. #endif
  1377. FALSE, TRUE);
  1378. EnterCrit();
  1379. }
  1380. /***************************************************************************\
  1381. * xxxMKMoveAccelCursorTimer
  1382. *
  1383. * Timer routine that handles mouse acceleration. It gets called 20 times
  1384. * per second and uses information from gMouseCursor.bAccelTable[] to determine
  1385. * how many pixels to move the mouse cursor on each tick.
  1386. *
  1387. * Return value:
  1388. * None.
  1389. *
  1390. * History:
  1391. \***************************************************************************/
  1392. VOID xxxMKMoveAccelCursorTimer(
  1393. PWND pwnd,
  1394. UINT message,
  1395. UINT_PTR nID,
  1396. LPARAM lParam)
  1397. {
  1398. LONG MovePixels;
  1399. UNREFERENCED_PARAMETER(pwnd);
  1400. UNREFERENCED_PARAMETER(message);
  1401. UNREFERENCED_PARAMETER(nID);
  1402. UNREFERENCED_PARAMETER(lParam);
  1403. CheckCritIn();
  1404. if (TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS)) {
  1405. if ((gLockBits | gLatchBits | gPhysModifierState) & LRSHIFT) {
  1406. MovePixels = 1;
  1407. goto MoveIt;
  1408. }
  1409. if ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL) {
  1410. MovePixels = gMouseCursor.bConstantTable[0] * MK_CONTROL_SPEED;
  1411. goto MoveIt;
  1412. }
  1413. }
  1414. if (giMouseMoveTable < gMouseCursor.bAccelTableLen) {
  1415. MovePixels = gMouseCursor.bAccelTable[giMouseMoveTable++];
  1416. } else {
  1417. //
  1418. // We've reached maximum cruising speed. Switch to constant table.
  1419. //
  1420. MovePixels = gMouseCursor.bConstantTable[0];
  1421. giMouseMoveTable = 1;
  1422. gtmridMKMoveCursor = InternalSetTimer(NULL,
  1423. gtmridMKMoveCursor,
  1424. MOUSETIMERRATE,
  1425. xxxMKMoveConstCursorTimer,
  1426. TMRF_RIT);
  1427. }
  1428. if (MovePixels == 0) {
  1429. return;
  1430. }
  1431. MoveIt:
  1432. //
  1433. // We're inside the critical section - leave before calling xxxMoveEvent.
  1434. // Set gbMouseMoved to TRUE so RawInputThread wakes up the appropriate
  1435. // user thread (if any) to receive this event.
  1436. //
  1437. LeaveCrit();
  1438. xxxMoveEvent(MovePixels * gMKDeltaX, MovePixels * gMKDeltaY, 0, 0,
  1439. #ifdef GENERIC_INPUT
  1440. NULL,
  1441. NULL,
  1442. #endif
  1443. 0, FALSE);
  1444. QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(),
  1445. #ifdef GENERIC_INPUT
  1446. NULL,
  1447. NULL,
  1448. #endif
  1449. FALSE, TRUE);
  1450. EnterCrit();
  1451. }
  1452. /***************************************************************************\
  1453. * xxxMKMouseMove
  1454. *
  1455. * Send a mouse move event. A timer routine is set to handle the mouse
  1456. * cursor acceleration. The timer will be set on the first make of a
  1457. * mouse move key if FilterKeys repeat rate is OFF. Otherwise, the timer
  1458. * is set on the first repeat (typematic make) of the mouse move key.
  1459. * Once the timer is set the timer routine handles all mouse movement
  1460. * until the key is released or a new key is pressed.
  1461. *
  1462. * Return value:
  1463. * Always FALSE - key should not be passed on.
  1464. *
  1465. * History:
  1466. \***************************************************************************/
  1467. BOOL xxxMKMouseMove(USHORT Data)
  1468. {
  1469. /*
  1470. * Let the mouse acceleration timer routine handle repeats.
  1471. */
  1472. if (TEST_ACCF(ACCF_MKREPEATVK) && (gtmridMKMoveCursor != 0)) {
  1473. return FALSE;
  1474. }
  1475. gMKDeltaX = (LONG)((CHAR)LOBYTE(Data)); // Force sign extension
  1476. gMKDeltaY = (LONG)((CHAR)HIBYTE(Data)); // Force sign extension
  1477. LeaveCrit();
  1478. if ((TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS) && ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL))) {
  1479. xxxMoveEvent(gMKDeltaX * MK_CONTROL_SPEED * gMouseCursor.bConstantTable[0], gMKDeltaY * MK_CONTROL_SPEED * gMouseCursor.bConstantTable[0], 0, 0,
  1480. #ifdef GENERIC_INPUT
  1481. NULL,
  1482. NULL,
  1483. #endif
  1484. 0, FALSE);
  1485. } else {
  1486. xxxMoveEvent(gMKDeltaX, gMKDeltaY, 0, 0,
  1487. #ifdef GENERIC_INPUT
  1488. NULL,
  1489. NULL,
  1490. #endif
  1491. 0, FALSE);
  1492. }
  1493. QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(),
  1494. #ifdef GENERIC_INPUT
  1495. NULL,
  1496. NULL,
  1497. #endif
  1498. FALSE, TRUE);
  1499. EnterCrit();
  1500. /*
  1501. * If the repeat rate is zero we'll start the mouse acceleration
  1502. * immediately. Otherwise we wait until after the first repeat
  1503. * of the mouse movement key.
  1504. */
  1505. if (!gFilterKeys.iRepeatMSec || TEST_ACCF(ACCF_MKREPEATVK)) {
  1506. giMouseMoveTable = 0;
  1507. gtmridMKMoveCursor = InternalSetTimer(NULL,
  1508. gtmridMKMoveCursor,
  1509. MOUSETIMERRATE,
  1510. (gMouseCursor.bAccelTableLen) ?
  1511. xxxMKMoveAccelCursorTimer :
  1512. xxxMKMoveConstCursorTimer,
  1513. TMRF_RIT);
  1514. }
  1515. return FALSE;
  1516. }
  1517. /***************************************************************************\
  1518. * xxxMKButtonSetState
  1519. *
  1520. * Set the active mouse button(s) to the state specified by fButtonUp
  1521. * (if fButtonUp is TRUE then the button is released, o.w. the button
  1522. * is pressed).
  1523. *
  1524. * Return value:
  1525. * Always FALSE - key should not be passed on.
  1526. *
  1527. * History:
  1528. \***************************************************************************/
  1529. BOOL xxxMKButtonSetState(USHORT fButtonUp)
  1530. {
  1531. WORD NewButtonState;
  1532. CheckCritIn();
  1533. if (fButtonUp) {
  1534. NewButtonState = gwMKButtonState & ~gwMKCurrentButton;
  1535. } else {
  1536. NewButtonState = gwMKButtonState | gwMKCurrentButton;
  1537. }
  1538. if ((NewButtonState & MOUSE_BUTTON_LEFT) != (gwMKButtonState & MOUSE_BUTTON_LEFT)) {
  1539. xxxButtonEvent(MOUSE_BUTTON_LEFT,
  1540. gptCursorAsync,
  1541. fButtonUp,
  1542. NtGetTickCount(),
  1543. 0L,
  1544. #ifdef GENERIC_INPUT
  1545. NULL,
  1546. NULL,
  1547. #endif
  1548. FALSE,
  1549. FALSE);
  1550. }
  1551. if ((NewButtonState & MOUSE_BUTTON_RIGHT) != (gwMKButtonState & MOUSE_BUTTON_RIGHT)) {
  1552. xxxButtonEvent(MOUSE_BUTTON_RIGHT,
  1553. gptCursorAsync,
  1554. fButtonUp,
  1555. NtGetTickCount(),
  1556. 0L,
  1557. #ifdef GENERIC_INPUT
  1558. NULL,
  1559. NULL,
  1560. #endif
  1561. FALSE,
  1562. FALSE);
  1563. }
  1564. gwMKButtonState = NewButtonState;
  1565. PostAccessibility( ACCESS_MOUSEKEYS );
  1566. return FALSE;
  1567. }
  1568. /***************************************************************************\
  1569. * MKButtonSelect
  1570. *
  1571. * Mark ThisButton as the active mouse button. It's possible to select both
  1572. * the left and right mouse buttons as active simultaneously.
  1573. *
  1574. * Return value:
  1575. * Always FALSE - key should not be passed on.
  1576. *
  1577. * History:
  1578. \***************************************************************************/
  1579. BOOL MKButtonSelect(WORD ThisButton)
  1580. {
  1581. gwMKCurrentButton = ThisButton;
  1582. PostAccessibility( ACCESS_MOUSEKEYS );
  1583. return FALSE;
  1584. }
  1585. /***************************************************************************\
  1586. * xxxMKButtonDoubleClick
  1587. *
  1588. * Double click the active mouse button.
  1589. *
  1590. * Return value:
  1591. * Always FALSE - key should not be passed on.
  1592. *
  1593. * History:
  1594. \***************************************************************************/
  1595. BOOL xxxMKButtonDoubleClick(
  1596. USHORT NotUsed)
  1597. {
  1598. UNREFERENCED_PARAMETER(NotUsed);
  1599. xxxMKButtonClick(0);
  1600. xxxMKButtonClick(0);
  1601. return FALSE;
  1602. }
  1603. BOOL HighContrastHotKey(
  1604. PKE pKeyEvent,
  1605. ULONG ExtraInformation,
  1606. int NotUsed)
  1607. {
  1608. int CurrentModState;
  1609. int fBreak;
  1610. BYTE Vk;
  1611. UNREFERENCED_PARAMETER(NotUsed);
  1612. UNREFERENCED_PARAMETER(ExtraInformation);
  1613. CheckCritIn();
  1614. Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff);
  1615. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  1616. CurrentModState = gLockBits | gLatchBits | gPhysModifierState;
  1617. if (!TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON)) {
  1618. if (TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) && Vk == VK_SNAPSHOT && !fBreak && CurrentModState == MOUSEKEYMODBITS) {
  1619. if (TEST_ACCESSFLAG(HighContrast, MKF_HOTKEYSOUND)) {
  1620. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1621. PostRitSound(
  1622. pTerm,
  1623. RITSOUND_UPSIREN);
  1624. }
  1625. PostAccessNotification(ACCESS_HIGHCONTRAST);
  1626. return FALSE;
  1627. }
  1628. } else {
  1629. if (TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) && Vk == VK_SNAPSHOT && !fBreak && CurrentModState == MOUSEKEYMODBITS) {
  1630. CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON);
  1631. if (TEST_ACCESSFLAG(HighContrast, MKF_HOTKEYSOUND)) {
  1632. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1633. PostRitSound(
  1634. pTerm,
  1635. RITSOUND_DOWNSIREN);
  1636. }
  1637. if (gspwndLogonNotify != NULL) {
  1638. _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY,
  1639. LOGON_ACCESSNOTIFY, ACCESS_HIGHCONTRASTOFF);
  1640. }
  1641. }
  1642. }
  1643. return TRUE; // send key event to next accessibility routine.
  1644. }
  1645. /***************************************************************************\
  1646. * MouseKeys
  1647. *
  1648. * This is the strategy routine that gets called as part of the input stream
  1649. * processing. MouseKeys enabling/disabling is handled here. All MouseKeys
  1650. * helper routines are called from this routine.
  1651. *
  1652. * Return value:
  1653. * TRUE - key event should be passed on to the next access routine.
  1654. * FALSE - key event was processed and should not be passed on.
  1655. *
  1656. * History:
  1657. \***************************************************************************/
  1658. BOOL MouseKeys(
  1659. PKE pKeyEvent,
  1660. ULONG ExtraInformation,
  1661. int NotUsed)
  1662. {
  1663. int CurrentModState;
  1664. int fBreak;
  1665. BYTE Vk;
  1666. USHORT FlaggedVk;
  1667. int i;
  1668. UNREFERENCED_PARAMETER(ExtraInformation);
  1669. UNREFERENCED_PARAMETER(NotUsed);
  1670. CheckCritIn();
  1671. Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff);
  1672. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  1673. CurrentModState = gLockBits | gLatchBits | gPhysModifierState;
  1674. if (!TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) {
  1675. //
  1676. // MouseKeys currently disabled. Check for enabling sequence:
  1677. // left Shift + left Alt + Num Lock.
  1678. //
  1679. #ifdef FE_SB // MouseKeys()
  1680. if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) && Vk == gNumLockVk && !fBreak && CurrentModState == MOUSEKEYMODBITS) {
  1681. #else // FE_SB
  1682. if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) && Vk == VK_NUMLOCK && !fBreak && CurrentModState == MOUSEKEYMODBITS) {
  1683. #endif // FE_SB
  1684. gMKPreviousVk = Vk;
  1685. if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYSOUND)) {
  1686. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1687. PostRitSound(
  1688. pTerm,
  1689. RITSOUND_UPSIREN);
  1690. }
  1691. PostAccessNotification(ACCESS_MOUSEKEYS);
  1692. return FALSE;
  1693. }
  1694. } else {
  1695. //
  1696. // Is this a MouseKey key?
  1697. //
  1698. //
  1699. FlaggedVk = Vk | (pKeyEvent->usFlaggedVk & KBDEXT);
  1700. for (i = 0; i < cMouseVKeys; i++) {
  1701. #ifdef FE_SB // MouseKeys()
  1702. if (FlaggedVk == gpusMouseVKey[i]) {
  1703. #else // FE_SB
  1704. if (FlaggedVk == ausMouseVKey[i]) {
  1705. #endif // FE_SB
  1706. break;
  1707. }
  1708. }
  1709. if (i == cMouseVKeys) {
  1710. return TRUE; // not a mousekey
  1711. }
  1712. //
  1713. // Check to see if we should pass on key events until Num Lock is
  1714. // entered.
  1715. //
  1716. if (!gbMKMouseMode) {
  1717. #ifdef FE_SB // MouseKeys()
  1718. if (Vk != gNumLockVk) {
  1719. #else // FE_SB
  1720. if (Vk != VK_NUMLOCK) {
  1721. #endif // FE_SB
  1722. return TRUE;
  1723. }
  1724. }
  1725. //
  1726. // Check for Ctrl-Alt-Numpad Del. Pass key event on if sequence
  1727. // detected.
  1728. //
  1729. if (Vk == VK_DELETE && CurrentModState & LRALT && CurrentModState & LRCONTROL) {
  1730. return TRUE;
  1731. }
  1732. if (fBreak) {
  1733. //
  1734. // If this is a break of the key that we're accelerating then
  1735. // kill the timer.
  1736. //
  1737. if (gMKPreviousVk == Vk) {
  1738. if (gtmridMKMoveCursor != 0) {
  1739. KILLRITTIMER(NULL, gtmridMKMoveCursor);
  1740. gtmridMKMoveCursor = 0;
  1741. }
  1742. CLEAR_ACCF(ACCF_MKREPEATVK);
  1743. gMKPreviousVk = 0;
  1744. }
  1745. //
  1746. // Pass break of Numlock along. Other mousekeys stop here.
  1747. //
  1748. #ifdef FE_SB // MouseKeys()
  1749. if (Vk == gNumLockVk) {
  1750. #else // FE_SB
  1751. if (Vk == VK_NUMLOCK) {
  1752. #endif // FE_SB
  1753. return TRUE;
  1754. } else {
  1755. return FALSE;
  1756. }
  1757. } else {
  1758. SET_OR_CLEAR_ACCF(ACCF_MKREPEATVK,
  1759. (gMKPreviousVk == Vk));
  1760. //
  1761. // If this is not a typematic repeat, kill the mouse acceleration
  1762. // timer.
  1763. //
  1764. if ((!TEST_ACCF(ACCF_MKREPEATVK)) && (gtmridMKMoveCursor)) {
  1765. KILLRITTIMER(NULL, gtmridMKMoveCursor);
  1766. gtmridMKMoveCursor = 0;
  1767. }
  1768. gMKPreviousVk = Vk;
  1769. }
  1770. return aMouseKeyEvent[i](ausMouseKeyData[i]);
  1771. }
  1772. return TRUE;
  1773. }
  1774. /***************************************************************************\
  1775. * TurnOffMouseKeys
  1776. *
  1777. * Return value:
  1778. * None.
  1779. *
  1780. * History:
  1781. * 11 Feb 93 GregoryW Created.
  1782. \***************************************************************************/
  1783. VOID TurnOffMouseKeys(VOID)
  1784. {
  1785. CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON);
  1786. // gMKPassThrough = 0;
  1787. CLEAR_ACCF(ACCF_MKREPEATVK);
  1788. MKHideMouseCursor();
  1789. if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYSOUND)) {
  1790. PostRitSound(
  1791. grpdeskRitInput->rpwinstaParent->pTerm,
  1792. RITSOUND_DOWNSIREN);
  1793. }
  1794. PostAccessibility( ACCESS_MOUSEKEYS );
  1795. }
  1796. /*
  1797. * Let's assert at the compile time if those values are
  1798. * defined unexpectedly.
  1799. */
  1800. #if (MAXSPEED_MIN >= MAXSPEED_MAX) || (MAXSPEED_MIN <= 0) || (TIMETOMAXSPEED_MIN >= TIMETOMAXSPEED_MAX) || (TIMETOMAXSPEED_MIN <= 0)
  1801. #error The mousekey min/max values are not as expected.
  1802. #endif
  1803. /***************************************************************************\
  1804. * CalculateMouseTable
  1805. *
  1806. * Set mouse table based on time to max speed and max speed. This routine
  1807. * is called during user logon (after the registry entries for the access
  1808. * features are read).
  1809. *
  1810. * Return value:
  1811. * None.
  1812. *
  1813. * History:
  1814. * Taken from access utility.
  1815. *
  1816. ****************************************************************************/
  1817. VOID CalculateMouseTable(VOID)
  1818. {
  1819. long Total_Distance; /* in 1000th of pixel */
  1820. long Accel_Per_Tick; /* in 1000th of pixel/tick */
  1821. long Current_Speed; /* in 1000th of pixel/tick */
  1822. long Max_Speed; /* in 1000th of pixel/tick */
  1823. long Real_Total_Distance; /* in pixels */
  1824. long Real_Delta_Distance; /* in pixels */
  1825. int i;
  1826. int Num_Constant_Table,Num_Accel_Table;
  1827. UserAssert(gMouseKeys.iMaxSpeed >= MAXSPEED_MIN && gMouseKeys.iMaxSpeed <= MAXSPEED_MAX);
  1828. UserAssert(gMouseKeys.iTimeToMaxSpeed >= TIMETOMAXSPEED_MIN && gMouseKeys.iTimeToMaxSpeed <= TIMETOMAXSPEED_MAX);
  1829. UserAssert(gMouseKeys.iTimeToMaxSpeed != 0);
  1830. Max_Speed = gMouseKeys.iMaxSpeed;
  1831. Max_Speed *= 1000 / MOUSETICKS;
  1832. Accel_Per_Tick = Max_Speed * 1000 / (gMouseKeys.iTimeToMaxSpeed * MOUSETICKS);
  1833. Current_Speed = 0;
  1834. Total_Distance = 0;
  1835. Real_Total_Distance = 0;
  1836. Num_Constant_Table = 0;
  1837. Num_Accel_Table = 0;
  1838. for(i=0; i<= 255; i++) {
  1839. Current_Speed = Current_Speed + Accel_Per_Tick;
  1840. if (Current_Speed > Max_Speed) {
  1841. Current_Speed = Max_Speed;
  1842. }
  1843. Total_Distance += Current_Speed;
  1844. //
  1845. // Calculate how many pixels to move on this tick
  1846. //
  1847. Real_Delta_Distance = ((Total_Distance - (Real_Total_Distance * 1000)) + 500) / 1000 ;
  1848. //
  1849. // Calculate total distance moved up to this point
  1850. //
  1851. Real_Total_Distance = Real_Total_Distance + Real_Delta_Distance;
  1852. if ((Current_Speed < Max_Speed) && (Num_Accel_Table < 128)) {
  1853. gMouseCursor.bAccelTable[Num_Accel_Table++] = (BYTE)Real_Delta_Distance;
  1854. }
  1855. if ((Current_Speed == Max_Speed) && (Num_Constant_Table < 128)) {
  1856. gMouseCursor.bConstantTable[Num_Constant_Table++] = (BYTE)Real_Delta_Distance;
  1857. }
  1858. }
  1859. gMouseCursor.bAccelTableLen = (BYTE)Num_Accel_Table;
  1860. gMouseCursor.bConstantTableLen = (BYTE)Num_Constant_Table;
  1861. }
  1862. /***************************************************************************\
  1863. * xxxToggleKeysTimer
  1864. *
  1865. * Enable ToggleKeys if it is currently disabled. Disable ToggleKeys if it
  1866. * is currently enabled.
  1867. *
  1868. * This routine is called only when the NumLock key is held down for 5 seconds.
  1869. *
  1870. * Return value:
  1871. * 0
  1872. *
  1873. * History:
  1874. * 11 Feb 93 GregoryW Created.
  1875. \***************************************************************************/
  1876. VOID xxxToggleKeysTimer(
  1877. PWND pwnd,
  1878. UINT message,
  1879. UINT_PTR nID,
  1880. LPARAM lParam)
  1881. {
  1882. KE ToggleKeyEvent;
  1883. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  1884. UNREFERENCED_PARAMETER(pwnd);
  1885. UNREFERENCED_PARAMETER(message);
  1886. UNREFERENCED_PARAMETER(nID);
  1887. UNREFERENCED_PARAMETER(lParam);
  1888. CheckCritIn();
  1889. //
  1890. // Toggle ToggleKeys and provide audible feedback if appropriate.
  1891. //
  1892. if (TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON)) {
  1893. CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON);
  1894. if (TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYSOUND)) {
  1895. PostRitSound(
  1896. pTerm,
  1897. RITSOUND_DOWNSIREN);
  1898. }
  1899. } else {
  1900. if (TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYSOUND)) {
  1901. PostRitSound(
  1902. pTerm,
  1903. RITSOUND_UPSIREN);
  1904. }
  1905. PostAccessNotification(ACCESS_TOGGLEKEYS);
  1906. }
  1907. //
  1908. // Send a fake break/make combination so state of numlock key remains
  1909. // the same as it was before user pressed it to activate/deactivate
  1910. // ToggleKeys.
  1911. //
  1912. ToggleKeyEvent.bScanCode = gTKScanCode;
  1913. #ifdef FE_SB // ToggleKeysTimer()
  1914. ToggleKeyEvent.usFlaggedVk = gNumLockVk | KBDBREAK;
  1915. #else
  1916. ToggleKeyEvent.usFlaggedVk = VK_NUMLOCK | KBDBREAK;
  1917. #endif // FE_SB
  1918. if (AccessProceduresStream(&ToggleKeyEvent, gTKExtraInformation, gTKNextProcIndex)) {
  1919. xxxProcessKeyEvent(&ToggleKeyEvent, gTKExtraInformation, FALSE);
  1920. }
  1921. #ifdef FE_SB // ToggleKeysTimer()
  1922. ToggleKeyEvent.usFlaggedVk = gNumLockVk;
  1923. #else
  1924. ToggleKeyEvent.usFlaggedVk = VK_NUMLOCK;
  1925. #endif // FE_SB
  1926. if (AccessProceduresStream(&ToggleKeyEvent, gTKExtraInformation, gTKNextProcIndex)) {
  1927. xxxProcessKeyEvent(&ToggleKeyEvent, gTKExtraInformation, FALSE);
  1928. }
  1929. }
  1930. /***************************************************************************\
  1931. * ToggleKeys
  1932. *
  1933. * This is the strategy routine that gets called as part of the input stream
  1934. * processing. Keys of interest are Num Lock, Scroll Lock and Caps Lock.
  1935. *
  1936. * Return value:
  1937. * TRUE - key event should be passed on to the next access routine.
  1938. * FALSE - key event was processed and should not be passed on.
  1939. *
  1940. * History:
  1941. \***************************************************************************/
  1942. BOOL ToggleKeys(PKE pKeyEvent, ULONG ExtraInformation, int NextProcIndex)
  1943. {
  1944. int fBreak;
  1945. BYTE Vk;
  1946. CheckCritIn();
  1947. Vk = (BYTE)pKeyEvent->usFlaggedVk;
  1948. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  1949. //
  1950. // Check for Numlock key. On the first make set the ToggleKeys timer.
  1951. // The timer is killed on the break of the Numlock key.
  1952. //
  1953. switch (Vk) {
  1954. case VK_NUMLOCK:
  1955. #ifdef FE_SB // ToggleKeys()
  1956. NumLockProc:
  1957. #endif // FE_SB
  1958. /*
  1959. * Don't handle NUMLOCK toggles if the user is doing MouseKey
  1960. * toggling.
  1961. */
  1962. if ((gLockBits | gLatchBits | gPhysModifierState) == MOUSEKEYMODBITS &&
  1963. TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE)) {
  1964. break;
  1965. }
  1966. if (fBreak)
  1967. {
  1968. //
  1969. // Only reset gptmrToggleKeys on the break of NumLock. This
  1970. // prevents cycling the toggle keys state by continually
  1971. // holding down the NumLock key.
  1972. //
  1973. KILLRITTIMER(NULL, gtmridToggleKeys);
  1974. gtmridToggleKeys = 0;
  1975. gTKExtraInformation = 0;
  1976. gTKScanCode = 0;
  1977. }
  1978. else
  1979. {
  1980. if (gtmridToggleKeys == 0 &&
  1981. TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYACTIVE))
  1982. {
  1983. //
  1984. // Remember key information to be used by timer routine.
  1985. //
  1986. gTKExtraInformation = ExtraInformation;
  1987. gTKScanCode = pKeyEvent->bScanCode;
  1988. gTKNextProcIndex = NextProcIndex;
  1989. gtmridToggleKeys = InternalSetTimer(NULL,
  1990. 0,
  1991. TOGGLEKEYTOGGLETIME,
  1992. xxxToggleKeysTimer,
  1993. TMRF_RIT | TMRF_ONESHOT);
  1994. }
  1995. }
  1996. //
  1997. // If MouseKeys is on, audible feedback has already occurred for this
  1998. // keystroke. Skip the rest of the processing.
  1999. //
  2000. if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) {
  2001. break;
  2002. }
  2003. // fall through
  2004. case VK_SCROLL:
  2005. case VK_CAPITAL:
  2006. #ifdef FE_SB // ToggleKeys()
  2007. CapitalProc:
  2008. #endif // FE_SB
  2009. if (TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) && !fBreak) {
  2010. if (!TestAsyncKeyStateDown(Vk)) {
  2011. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  2012. if (!TestAsyncKeyStateToggle(Vk)) {
  2013. PostRitSound(
  2014. pTerm,
  2015. RITSOUND_HIGHBEEP);
  2016. } else {
  2017. PostRitSound(
  2018. pTerm,
  2019. RITSOUND_LOWBEEP);
  2020. }
  2021. }
  2022. }
  2023. break;
  2024. default:
  2025. #ifdef FE_SB // ToggleKeys()
  2026. if (Vk == gNumLockVk) goto NumLockProc;
  2027. if (Vk == gOemScrollVk) goto CapitalProc;
  2028. #endif // FE_SB
  2029. if (gtmridToggleKeys != 0) {
  2030. KILLRITTIMER(NULL, gtmridToggleKeys);
  2031. }
  2032. }
  2033. return TRUE;
  2034. }
  2035. /***************************************************************************\
  2036. * AccessTimeOutTimer
  2037. *
  2038. * This routine is called if no keyboard activity takes place for the
  2039. * user configured amount of time. All access related functions are
  2040. * disabled.
  2041. *
  2042. * This routine is called with the critical section already locked.
  2043. *
  2044. * Return value:
  2045. * 0
  2046. *
  2047. * History:
  2048. \***************************************************************************/
  2049. VOID xxxAccessTimeOutTimer(
  2050. PWND pwnd,
  2051. UINT message,
  2052. UINT_PTR nID,
  2053. LPARAM lParam)
  2054. {
  2055. UNREFERENCED_PARAMETER(pwnd);
  2056. UNREFERENCED_PARAMETER(message);
  2057. UNREFERENCED_PARAMETER(nID);
  2058. UNREFERENCED_PARAMETER(lParam);
  2059. CheckCritIn();
  2060. /*
  2061. * The timeout timer will remain on (if so configured) as long as
  2062. * TEST_ACCF(ACCF_ACCESSENABLED) is TRUE. This means we might get timeouts when
  2063. * only hot keys are enabled, but no features are actually on. Don't
  2064. * provide any audible feedback in this case.
  2065. */
  2066. if ( TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) ||
  2067. TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) ||
  2068. TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) ||
  2069. TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) ||
  2070. TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON) ||
  2071. TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON) ||
  2072. TEST_ACCF(ACCF_SHOWSOUNDSON)) {
  2073. PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm;
  2074. CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON);
  2075. xxxTurnOffStickyKeys();
  2076. CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON);
  2077. CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON);
  2078. CLEAR_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON);
  2079. CLEAR_ACCF(ACCF_SHOWSOUNDSON);
  2080. CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON);
  2081. if (gspwndLogonNotify != NULL) {
  2082. _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY,
  2083. LOGON_ACCESSNOTIFY, ACCESS_HIGHCONTRASTOFF);
  2084. }
  2085. if (TEST_ACCESSFLAG(AccessTimeOut, ATF_ONOFFFEEDBACK)) {
  2086. PostRitSound(
  2087. pTerm,
  2088. RITSOUND_DOWNSIREN);
  2089. }
  2090. PostAccessibility( ACCESS_MOUSEKEYS );
  2091. PostAccessibility( ACCESS_FILTERKEYS );
  2092. PostAccessibility( ACCESS_STICKYKEYS );
  2093. }
  2094. SetAccessEnabledFlag();
  2095. }
  2096. /***************************************************************************\
  2097. * AccessTimeOutReset
  2098. *
  2099. * This routine resets the timeout timer.
  2100. *
  2101. * Return value:
  2102. * 0
  2103. *
  2104. * History:
  2105. \***************************************************************************/
  2106. VOID AccessTimeOutReset(
  2107. VOID)
  2108. {
  2109. if (gtmridAccessTimeOut != 0) {
  2110. KILLRITTIMER(NULL, gtmridAccessTimeOut);
  2111. }
  2112. if (TEST_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON)) {
  2113. gtmridAccessTimeOut = InternalSetTimer(NULL,
  2114. 0,
  2115. (UINT)gAccessTimeOut.iTimeOutMSec,
  2116. xxxAccessTimeOutTimer,
  2117. TMRF_RIT | TMRF_ONESHOT);
  2118. }
  2119. }
  2120. /***************************************************************************\
  2121. * xxxUpdatePerUserAccessPackSettings
  2122. *
  2123. * Sets the initial access pack features according to the user's profile.
  2124. *
  2125. * 02-14-93 GregoryW Created.
  2126. \***************************************************************************/
  2127. VOID xxxUpdatePerUserAccessPackSettings(
  2128. PUNICODE_STRING pProfileUserName)
  2129. {
  2130. LUID luidCaller;
  2131. NTSTATUS Status;
  2132. BOOL fSystem;
  2133. BOOL fRegFilterKeysOn;
  2134. BOOL fRegStickyKeysOn;
  2135. BOOL fRegMouseKeysOn;
  2136. BOOL fRegToggleKeysOn;
  2137. BOOL fRegTimeOutOn;
  2138. BOOL fRegKeyboardPref;
  2139. BOOL fRegScreenReader;
  2140. BOOL fRegHighContrastOn;
  2141. DWORD dwDefFlags;
  2142. WCHAR wcHighContrastScheme[MAX_SCHEME_NAME_SIZE];
  2143. Status = GetProcessLuid(NULL, &luidCaller);
  2144. //
  2145. // If we're called in the system context no one is logged on.
  2146. // We want to read the current .DEFAULT settings for the access
  2147. // features. Later when we're called in the user context (e.g.,
  2148. // someone has successfully logged on) we check to see if the
  2149. // current access state is the same as the default setting. If
  2150. // not, the user has enabled/disabled one or more access features
  2151. // from the keyboard. These changes will be propagated across
  2152. // the logon into the user's intial state (overriding the settings
  2153. // in the user's profile).
  2154. //
  2155. if (NT_SUCCESS(Status) && RtlEqualLuid(&luidCaller, &luidSystem)) {
  2156. fSystem = TRUE;
  2157. } else {
  2158. fSystem = FALSE;
  2159. }
  2160. FastGetProfileIntW(pProfileUserName,
  2161. PMAP_KEYBOARDRESPONSE,
  2162. TEXT("Flags"),
  2163. 0,
  2164. &dwDefFlags,
  2165. 0);
  2166. fRegFilterKeysOn = (dwDefFlags & FKF_FILTERKEYSON) != 0;
  2167. FastGetProfileIntW(pProfileUserName,
  2168. PMAP_STICKYKEYS,
  2169. TEXT("Flags"),
  2170. 0,
  2171. &dwDefFlags,
  2172. 0);
  2173. fRegStickyKeysOn = (dwDefFlags & SKF_STICKYKEYSON) != 0;
  2174. FastGetProfileIntW(pProfileUserName,
  2175. PMAP_MOUSEKEYS,
  2176. TEXT("Flags"),
  2177. 0,
  2178. &dwDefFlags,
  2179. 0);
  2180. fRegMouseKeysOn = (dwDefFlags & MKF_MOUSEKEYSON) != 0;
  2181. FastGetProfileIntW(pProfileUserName,
  2182. PMAP_TOGGLEKEYS,
  2183. TEXT("Flags"),
  2184. 0,
  2185. &dwDefFlags,
  2186. 0);
  2187. fRegToggleKeysOn = (dwDefFlags & TKF_TOGGLEKEYSON) != 0;
  2188. FastGetProfileIntW(pProfileUserName,
  2189. PMAP_KEYBOARDPREF,
  2190. TEXT("On"),
  2191. 0,
  2192. &dwDefFlags,
  2193. 0);
  2194. fRegKeyboardPref = !!dwDefFlags;
  2195. FastGetProfileIntW(pProfileUserName,
  2196. PMAP_SCREENREADER,
  2197. TEXT("On"),
  2198. 0,
  2199. &dwDefFlags,
  2200. 0);
  2201. fRegScreenReader = !!dwDefFlags;
  2202. FastGetProfileIntW(pProfileUserName,
  2203. PMAP_TIMEOUT,
  2204. TEXT("Flags"),
  2205. 0,
  2206. &dwDefFlags,
  2207. 0);
  2208. fRegTimeOutOn = (dwDefFlags & ATF_TIMEOUTON) != 0;
  2209. FastGetProfileIntW(pProfileUserName,
  2210. PMAP_HIGHCONTRAST,
  2211. TEXT("Flags"),
  2212. 0,
  2213. &dwDefFlags,
  2214. 0);
  2215. fRegHighContrastOn = (dwDefFlags & HCF_HIGHCONTRASTON) != 0;
  2216. if (fSystem) {
  2217. //
  2218. // We're in system mode (e.g., no one is logged in). Remember
  2219. // the .DEFAULT state for comparison during the next user logon
  2220. // and set the current state to the .DEFAULT state.
  2221. //
  2222. if (fRegFilterKeysOn) {
  2223. SET_ACCF(ACCF_DEFAULTFILTERKEYSON);
  2224. SET_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON);
  2225. } else {
  2226. CLEAR_ACCF(ACCF_DEFAULTFILTERKEYSON);
  2227. CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON);
  2228. }
  2229. //
  2230. // If StickyKeys is currently on and we're about to turn it
  2231. // off we need to make sure the latch keys and lock keys are
  2232. // released.
  2233. //
  2234. if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) && (fRegFilterKeysOn == 0)) {
  2235. xxxTurnOffStickyKeys();
  2236. }
  2237. if (fRegStickyKeysOn) {
  2238. SET_ACCF(ACCF_DEFAULTSTICKYKEYSON);
  2239. SET_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON);
  2240. } else {
  2241. CLEAR_ACCF(ACCF_DEFAULTSTICKYKEYSON);
  2242. CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON);
  2243. }
  2244. if (fRegMouseKeysOn) {
  2245. SET_ACCF(ACCF_DEFAULTMOUSEKEYSON);
  2246. SET_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON);
  2247. } else {
  2248. CLEAR_ACCF(ACCF_DEFAULTMOUSEKEYSON);
  2249. CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON);
  2250. }
  2251. if (fRegToggleKeysOn) {
  2252. SET_ACCF(ACCF_DEFAULTTOGGLEKEYSON);
  2253. SET_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON);
  2254. } else {
  2255. CLEAR_ACCF(ACCF_DEFAULTTOGGLEKEYSON);
  2256. CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON);
  2257. }
  2258. if (fRegTimeOutOn) {
  2259. SET_ACCF(ACCF_DEFAULTTIMEOUTON);
  2260. SET_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON);
  2261. } else {
  2262. CLEAR_ACCF(ACCF_DEFAULTTIMEOUTON);
  2263. CLEAR_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON);
  2264. }
  2265. if (fRegKeyboardPref) {
  2266. SET_ACCF(ACCF_DEFAULTKEYBOARDPREF);
  2267. SET_ACCF(ACCF_KEYBOARDPREF);
  2268. SET_SRVIF(SRVIF_KEYBOARDPREF);
  2269. } else {
  2270. CLEAR_ACCF(ACCF_DEFAULTKEYBOARDPREF);
  2271. CLEAR_ACCF(ACCF_KEYBOARDPREF);
  2272. CLEAR_SRVIF(SRVIF_KEYBOARDPREF);
  2273. }
  2274. if (fRegScreenReader) {
  2275. SET_ACCF(ACCF_DEFAULTSCREENREADER);
  2276. SET_ACCF(ACCF_SCREENREADER);
  2277. } else {
  2278. CLEAR_ACCF(ACCF_DEFAULTSCREENREADER);
  2279. CLEAR_ACCF(ACCF_SCREENREADER);
  2280. }
  2281. if (fRegHighContrastOn) {
  2282. SET_ACCF(ACCF_DEFAULTHIGHCONTRASTON);
  2283. SET_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON);
  2284. } else {
  2285. CLEAR_ACCF(ACCF_DEFAULTHIGHCONTRASTON);
  2286. CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON);
  2287. }
  2288. } else {
  2289. //
  2290. // A user has successfully logged on. If the current state is
  2291. // different from the default state stored earlier then we know
  2292. // the user has modified the state via the keyboard (at the logon
  2293. // dialog). This state will override whatever on/off state the
  2294. // user has set in their profile. If the current state is the
  2295. // same as the default state then the on/off setting from the
  2296. // user profile is used.
  2297. //
  2298. if ( TEST_BOOL_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) ==
  2299. TEST_BOOL_ACCF(ACCF_DEFAULTFILTERKEYSON)) {
  2300. //
  2301. // Current state and default state are the same. Use the
  2302. // user's profile setting.
  2303. //
  2304. SET_OR_CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON, fRegFilterKeysOn);
  2305. }
  2306. if ( TEST_BOOL_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) ==
  2307. TEST_BOOL_ACCF(ACCF_DEFAULTSTICKYKEYSON)) {
  2308. //
  2309. // If StickyKeys is currently on and we're about to turn it
  2310. // off we need to make sure the latch keys and lock keys are
  2311. // released.
  2312. //
  2313. if ( TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) &&
  2314. (fRegStickyKeysOn == 0)) {
  2315. xxxTurnOffStickyKeys();
  2316. }
  2317. SET_OR_CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON, fRegStickyKeysOn);
  2318. }
  2319. if ( TEST_BOOL_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) ==
  2320. TEST_BOOL_ACCF(ACCF_DEFAULTMOUSEKEYSON)) {
  2321. //
  2322. // Current state and default state are the same. Use the user's
  2323. // profile setting.
  2324. //
  2325. SET_OR_CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON, fRegMouseKeysOn);
  2326. }
  2327. if ( TEST_BOOL_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) ==
  2328. TEST_BOOL_ACCF(ACCF_DEFAULTTOGGLEKEYSON)) {
  2329. //
  2330. // Current state and default state are the same. Use the user's
  2331. // profile setting.
  2332. //
  2333. SET_OR_CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON, fRegToggleKeysOn);
  2334. }
  2335. if ( TEST_BOOL_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON) ==
  2336. TEST_BOOL_ACCF(ACCF_DEFAULTTIMEOUTON)) {
  2337. //
  2338. // Current state and default state are the same. Use the user's
  2339. // profile setting.
  2340. //
  2341. SET_OR_CLEAR_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON, fRegTimeOutOn);
  2342. }
  2343. if ( TEST_BOOL_ACCF(ACCF_KEYBOARDPREF) ==
  2344. TEST_BOOL_ACCF(ACCF_DEFAULTKEYBOARDPREF)) {
  2345. //
  2346. // Current state and default state are the same. Use the user's
  2347. // profile setting.
  2348. //
  2349. SET_OR_CLEAR_ACCF(ACCF_KEYBOARDPREF, fRegKeyboardPref);
  2350. }
  2351. if ( TEST_BOOL_ACCF(ACCF_SCREENREADER) ==
  2352. TEST_BOOL_ACCF(ACCF_DEFAULTSCREENREADER)) {
  2353. //
  2354. // Current state and default state are the same. Use the user's
  2355. // profile setting.
  2356. //
  2357. SET_OR_CLEAR_ACCF(ACCF_SCREENREADER, fRegScreenReader);
  2358. }
  2359. if ( TEST_BOOL_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON) ==
  2360. TEST_BOOL_ACCF(ACCF_DEFAULTHIGHCONTRASTON)) {
  2361. //
  2362. // Current state and default state are the same. Use the user's
  2363. // profile setting.
  2364. //
  2365. SET_OR_CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON, fRegHighContrastOn);
  2366. }
  2367. }
  2368. //
  2369. // Get the default FilterKeys state.
  2370. //
  2371. // -------- flag --------------- value --------- default ------
  2372. // #define FKF_FILTERKEYSON 0x00000001 0
  2373. // #define FKF_AVAILABLE 0x00000002 2
  2374. // #define FKF_HOTKEYACTIVE 0x00000004 0
  2375. // #define FKF_CONFIRMHOTKEY 0x00000008 0
  2376. // #define FKF_HOTKEYSOUND 0x00000010 10
  2377. // #define FKF_INDICATOR 0x00000020 0
  2378. // #define FKF_CLICKON 0x00000040 40
  2379. // ----------------------------------------- total = 0x52 = 82
  2380. //
  2381. FastGetProfileIntW(pProfileUserName,
  2382. PMAP_KEYBOARDRESPONSE,
  2383. TEXT("Flags"),
  2384. 82,
  2385. &dwDefFlags,
  2386. 0);
  2387. SET_OR_CLEAR_FLAG(
  2388. dwDefFlags,
  2389. FKF_FILTERKEYSON,
  2390. TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON));
  2391. gFilterKeys.dwFlags = dwDefFlags;
  2392. FastGetProfileIntW(pProfileUserName,
  2393. PMAP_KEYBOARDRESPONSE,
  2394. TEXT("DelayBeforeAcceptance"),
  2395. 1000,
  2396. &gFilterKeys.iWaitMSec,
  2397. 0);
  2398. FastGetProfileIntW(pProfileUserName,
  2399. PMAP_KEYBOARDRESPONSE,
  2400. TEXT("AutoRepeatRate"),
  2401. 500,
  2402. &gFilterKeys.iRepeatMSec,
  2403. 0);
  2404. FastGetProfileIntW(pProfileUserName,
  2405. PMAP_KEYBOARDRESPONSE,
  2406. TEXT("AutoRepeatDelay"),
  2407. 1000,
  2408. &gFilterKeys.iDelayMSec,
  2409. 0);
  2410. FastGetProfileIntW(pProfileUserName,
  2411. PMAP_KEYBOARDRESPONSE,
  2412. TEXT("BounceTime"),
  2413. 0,
  2414. &gFilterKeys.iBounceMSec,
  2415. 0);
  2416. //
  2417. // Fill in the SoundSentry state. This release of the
  2418. // accessibility features only supports iWindowsEffect.
  2419. //
  2420. // -------- flag --------------- value --------- default ------
  2421. // #define SSF_SOUNDSENTRYON 0x00000001 0
  2422. // #define SSF_AVAILABLE 0x00000002 1
  2423. // #define SSF_INDICATOR 0x00000004 0
  2424. // ----------------------------------------- total = 0x2 = 2
  2425. //
  2426. FastGetProfileIntW(pProfileUserName,
  2427. PMAP_SOUNDSENTRY,
  2428. TEXT("Flags"),
  2429. 2,
  2430. &gSoundSentry.dwFlags,
  2431. 0);
  2432. FastGetProfileIntW(pProfileUserName,
  2433. PMAP_SOUNDSENTRY,
  2434. TEXT("FSTextEffect"),
  2435. 0,
  2436. &gSoundSentry.iFSTextEffect,
  2437. 0);
  2438. FastGetProfileIntW(pProfileUserName,
  2439. PMAP_SOUNDSENTRY,
  2440. TEXT("WindowsEffect"),
  2441. 0,
  2442. &gSoundSentry.iWindowsEffect,
  2443. 0);
  2444. /*
  2445. * Set ShowSounds flag.
  2446. */
  2447. FastGetProfileIntW(pProfileUserName,
  2448. PMAP_SHOWSOUNDS,
  2449. TEXT("On"),
  2450. 0,
  2451. &dwDefFlags,
  2452. 0);
  2453. SET_OR_CLEAR_ACCF(ACCF_SHOWSOUNDSON, dwDefFlags);
  2454. /*
  2455. * Bug 17210. Update the System Metrics Info.
  2456. */
  2457. SYSMET(SHOWSOUNDS) = TEST_BOOL_ACCF(ACCF_SHOWSOUNDSON);
  2458. //
  2459. // Get the default StickyKeys state.
  2460. //
  2461. // -------- flag --------------- value --------- default ------
  2462. // #define SKF_STICKYKEYSON 0x00000001 0
  2463. // #define SKF_AVAILABLE 0x00000002 2
  2464. // #define SKF_HOTKEYACTIVE 0x00000004 0
  2465. // #define SKF_CONFIRMHOTKEY 0x00000008 0
  2466. // #define SKF_HOTKEYSOUND 0x00000010 10
  2467. // #define SKF_INDICATOR 0x00000020 0
  2468. // #define SKF_AUDIBLEFEEDBACK 0x00000040 40
  2469. // #define SKF_TRISTATE 0x00000080 80
  2470. // #define SKF_TWOKEYSOFF 0x00000100 100
  2471. // ----------------------------------------- total = 0x1d2 = 466
  2472. //
  2473. FastGetProfileIntW(pProfileUserName,
  2474. PMAP_STICKYKEYS,
  2475. TEXT("Flags"),
  2476. 466,
  2477. &dwDefFlags,
  2478. 0);
  2479. SET_OR_CLEAR_FLAG(
  2480. dwDefFlags,
  2481. SKF_STICKYKEYSON,
  2482. TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON));
  2483. gStickyKeys.dwFlags = dwDefFlags;
  2484. //
  2485. // Get the default MouseKeys state.
  2486. //
  2487. // -------- flag --------------- value --------- default ------
  2488. // #define MKF_MOUSEKEYSON 0x00000001 0
  2489. // #define MKF_AVAILABLE 0x00000002 2
  2490. // #define MKF_HOTKEYACTIVE 0x00000004 0
  2491. // #define MKF_CONFIRMHOTKEY 0x00000008 0
  2492. // #define MKF_HOTKEYSOUND 0x00000010 10
  2493. // #define MKF_INDICATOR 0x00000020 0
  2494. // #define MKF_MODIFIERS 0x00000040 0
  2495. // #define MKF_REPLACENUMBERS 0x00000080 0
  2496. // ----------------------------------------- total = 0x12 = 18
  2497. //
  2498. FastGetProfileIntW(pProfileUserName,
  2499. PMAP_MOUSEKEYS,
  2500. TEXT("Flags"),
  2501. 18,
  2502. &dwDefFlags,
  2503. 0);
  2504. SET_OR_CLEAR_FLAG(
  2505. dwDefFlags,
  2506. MKF_MOUSEKEYSON,
  2507. TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON));
  2508. gMouseKeys.dwFlags = dwDefFlags;
  2509. FastGetProfileIntW(pProfileUserName,
  2510. PMAP_MOUSEKEYS,
  2511. TEXT("MaximumSpeed"),
  2512. MAXSPEED_DEF,
  2513. &gMouseKeys.iMaxSpeed,
  2514. 0);
  2515. FastGetProfileIntW(pProfileUserName,
  2516. PMAP_MOUSEKEYS,
  2517. TEXT("TimeToMaximumSpeed"),
  2518. TIMETOMAXSPEED_DEF,
  2519. &gMouseKeys.iTimeToMaxSpeed,
  2520. 0);
  2521. /*
  2522. * Avoid unexpected values, like when the migration from previous OS has set bogus values
  2523. * or when the registry is simply broken...
  2524. */
  2525. if (gMouseKeys.iMaxSpeed < MAXSPEED_MIN || gMouseKeys.iMaxSpeed > MAXSPEED_MAX) {
  2526. gMouseKeys.iMaxSpeed = MAXSPEED_DEF;
  2527. }
  2528. if (gMouseKeys.iTimeToMaxSpeed < TIMETOMAXSPEED_MIN || gMouseKeys.iTimeToMaxSpeed > TIMETOMAXSPEED_MAX) {
  2529. gMouseKeys.iTimeToMaxSpeed = TIMETOMAXSPEED_DEF;
  2530. }
  2531. CalculateMouseTable();
  2532. gbMKMouseMode =
  2533. #ifdef FE_SB
  2534. (TestAsyncKeyStateToggle(gNumLockVk) != 0) ^
  2535. #else // FE_SB
  2536. (TestAsyncKeyStateToggle(VK_NUMLOCK) != 0) ^
  2537. #endif // FE_SB
  2538. (TEST_ACCESSFLAG(MouseKeys, MKF_REPLACENUMBERS) != 0);
  2539. //
  2540. // If the system does not have a hardware mouse:
  2541. // If MouseKeys is enabled show the mouse cursor,
  2542. // o.w. hide the mouse cursor.
  2543. //
  2544. if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) {
  2545. MKShowMouseCursor();
  2546. } else {
  2547. MKHideMouseCursor();
  2548. }
  2549. //
  2550. // Get the default ToggleKeys state.
  2551. //
  2552. // -------- flag --------------- value --------- default ------
  2553. // #define TKF_TOGGLEKEYSON 0x00000001 0
  2554. // #define TKF_AVAILABLE 0x00000002 2
  2555. // #define TKF_HOTKEYACTIVE 0x00000004 0
  2556. // #define TKF_CONFIRMHOTKEY 0x00000008 0
  2557. // #define TKF_HOTKEYSOUND 0x00000010 10
  2558. // #define TKF_INDICATOR 0x00000020 0
  2559. // ----------------------------------------- total = 0x12 = 18
  2560. //
  2561. FastGetProfileIntW(pProfileUserName,
  2562. PMAP_TOGGLEKEYS,
  2563. TEXT("Flags"),
  2564. 18,
  2565. &dwDefFlags,
  2566. 0);
  2567. SET_OR_CLEAR_FLAG(
  2568. dwDefFlags,
  2569. TKF_TOGGLEKEYSON,
  2570. TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON));
  2571. gToggleKeys.dwFlags = dwDefFlags;
  2572. //
  2573. // Get the default Timeout state.
  2574. //
  2575. // -------- flag --------------- value --------- default ------
  2576. // #define ATF_TIMEOUTON 0x00000001 0
  2577. // #define ATF_ONOFFFEEDBACK 0x00000002 2
  2578. // ----------------------------------------- total = 0x2 = 2
  2579. //
  2580. FastGetProfileIntW(pProfileUserName,
  2581. PMAP_TIMEOUT,
  2582. TEXT("Flags"),
  2583. 2,
  2584. &dwDefFlags,
  2585. 0);
  2586. SET_OR_CLEAR_FLAG(
  2587. dwDefFlags,
  2588. ATF_TIMEOUTON,
  2589. TEST_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON));
  2590. gAccessTimeOut.dwFlags = dwDefFlags;
  2591. #ifdef FE_SB //
  2592. if (gpKbdNlsTbl) {
  2593. //
  2594. // Is there any alternative MouseVKey table in KBDNLSTABLE ?
  2595. //
  2596. if ((gpKbdNlsTbl->NumOfMouseVKey == cMouseVKeys) &&
  2597. (gpKbdNlsTbl->pusMouseVKey != NULL)) {
  2598. //
  2599. // Overwite the pointer.
  2600. //
  2601. gpusMouseVKey = gpKbdNlsTbl->pusMouseVKey;
  2602. }
  2603. //
  2604. // Is there any remapping flag for VK_NUMLOCK/VK_SCROLL ?
  2605. //
  2606. if (gpKbdNlsTbl->LayoutInformation & NLSKBD_INFO_ACCESSIBILITY_KEYMAP) {
  2607. //
  2608. // Overwrite default.
  2609. //
  2610. gNumLockVk = VK_HOME;
  2611. gOemScrollVk = VK_KANA;
  2612. }
  2613. }
  2614. #endif // FE_SB
  2615. FastGetProfileIntW(pProfileUserName,
  2616. PMAP_TIMEOUT,
  2617. TEXT("TimeToWait"),
  2618. 300000,
  2619. &gAccessTimeOut.iTimeOutMSec,
  2620. 0); // default is 5 minutes
  2621. /*
  2622. * Get High Contrast state
  2623. */
  2624. FastGetProfileIntW(pProfileUserName,
  2625. PMAP_HIGHCONTRAST,
  2626. TEXT("Flags"),
  2627. HCF_AVAILABLE | HCF_HOTKEYSOUND | HCF_HOTKEYAVAILABLE,
  2628. &dwDefFlags,
  2629. 0);
  2630. SET_OR_CLEAR_FLAG(
  2631. dwDefFlags,
  2632. HCF_HIGHCONTRASTON,
  2633. TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON));
  2634. gHighContrast.dwFlags = dwDefFlags;
  2635. /*
  2636. * Get scheme -- set up buffer
  2637. */
  2638. if (FastGetProfileStringW(pProfileUserName,
  2639. PMAP_HIGHCONTRAST,
  2640. TEXT("High Contrast Scheme"),
  2641. NULL,
  2642. wcHighContrastScheme,
  2643. MAX_SCHEME_NAME_SIZE,
  2644. 0)) {
  2645. /*
  2646. * copy data
  2647. */
  2648. wcscpy(gHighContrastDefaultScheme, wcHighContrastScheme);
  2649. }
  2650. AccessTimeOutReset();
  2651. SetAccessEnabledFlag();
  2652. }
  2653. /***************************************************************************\
  2654. * SetAccessEnabledFlag
  2655. *
  2656. * Sets the global flag ACCF_ACCESSENABLED to non-zero if any accessibility
  2657. * function is on or hot key activation is enabled. When TEST_ACCF(ACCF_ACCESSENABLED)
  2658. * is zero keyboard input is processed directly. When TEST_ACCF(ACCF_ACCESSENABLED) is
  2659. * non-zero keyboard input is filtered through AccessProceduresStream().
  2660. * See KeyboardApcProcedure in ntinput.c.
  2661. *
  2662. * History:
  2663. * 01-19-94 GregoryW Created.
  2664. \***************************************************************************/
  2665. VOID SetAccessEnabledFlag(VOID)
  2666. {
  2667. SET_OR_CLEAR_ACCF(ACCF_ACCESSENABLED,
  2668. TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) ||
  2669. TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYACTIVE) ||
  2670. TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) ||
  2671. TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYACTIVE) ||
  2672. TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) ||
  2673. TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) ||
  2674. TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) ||
  2675. TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) ||
  2676. TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYACTIVE) ||
  2677. TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON)||
  2678. TEST_ACCF(ACCF_SHOWSOUNDSON));
  2679. }
  2680. VOID SoundSentryTimer(
  2681. PWND pwnd,
  2682. UINT message,
  2683. UINT_PTR idTimer,
  2684. LPARAM lParam)
  2685. {
  2686. TL tlpwndT;
  2687. PWND pwndSoundSentry;
  2688. UNREFERENCED_PARAMETER(pwnd);
  2689. UNREFERENCED_PARAMETER(message);
  2690. UNREFERENCED_PARAMETER(lParam);
  2691. if (pwndSoundSentry = RevalidateHwnd(ghwndSoundSentry)) {
  2692. ThreadLock(pwndSoundSentry, &tlpwndT);
  2693. xxxFlashWindow(pwndSoundSentry,
  2694. (TEST_BOOL_ACCF(ACCF_FIRSTTICK) ? FLASHW_ALL : FLASHW_STOP),
  2695. 0);
  2696. ThreadUnlock(&tlpwndT);
  2697. }
  2698. if (TEST_ACCF(ACCF_FIRSTTICK)) {
  2699. gtmridSoundSentry = InternalSetTimer(NULL,
  2700. idTimer,
  2701. 5,
  2702. SoundSentryTimer,
  2703. TMRF_RIT | TMRF_ONESHOT);
  2704. CLEAR_ACCF(ACCF_FIRSTTICK);
  2705. } else {
  2706. ghwndSoundSentry = NULL;
  2707. gtmridSoundSentry = 0;
  2708. SET_ACCF(ACCF_FIRSTTICK);
  2709. }
  2710. }
  2711. /***************************************************************************\
  2712. * _UserSoundSentryWorker
  2713. *
  2714. * This is the worker routine that provides the visual feedback requested
  2715. * by the user.
  2716. *
  2717. * History:
  2718. * 08-02-93 GregoryW Created.
  2719. \***************************************************************************/
  2720. BOOL
  2721. _UserSoundSentryWorker(VOID)
  2722. {
  2723. PWND pwndActive;
  2724. TL tlpwndT;
  2725. CheckCritIn();
  2726. //
  2727. // Check to see if SoundSentry is on.
  2728. //
  2729. if (!TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON)) {
  2730. return TRUE;
  2731. }
  2732. if ((gpqForeground != NULL) && (gpqForeground->spwndActive != NULL)) {
  2733. pwndActive = gpqForeground->spwndActive;
  2734. } else {
  2735. return TRUE;
  2736. }
  2737. switch (gSoundSentry.iWindowsEffect) {
  2738. case SSWF_NONE:
  2739. break;
  2740. case SSWF_TITLE:
  2741. //
  2742. // Flash the active caption bar.
  2743. //
  2744. if (gtmridSoundSentry) {
  2745. break;
  2746. }
  2747. ThreadLock(pwndActive, &tlpwndT);
  2748. xxxFlashWindow(pwndActive, FLASHW_ALL, 0);
  2749. ThreadUnlock(&tlpwndT);
  2750. ghwndSoundSentry = HWq(pwndActive);
  2751. gtmridSoundSentry = InternalSetTimer(NULL,
  2752. 0,
  2753. gpsi->dtCaretBlink,
  2754. SoundSentryTimer,
  2755. TMRF_RIT | TMRF_ONESHOT);
  2756. break;
  2757. case SSWF_WINDOW:
  2758. {
  2759. //
  2760. // Flash the active window.
  2761. //
  2762. HDC hdc;
  2763. RECT rc;
  2764. hdc = _GetWindowDC(pwndActive);
  2765. _GetWindowRect(pwndActive, &rc);
  2766. //
  2767. // _GetWindowRect returns screen coordinates. First adjust them
  2768. // to window (display) coordinates and then map them to logical
  2769. // coordinates before calling InvertRect.
  2770. //
  2771. OffsetRect(&rc, -rc.left, -rc.top);
  2772. GreDPtoLP(hdc, (LPPOINT)&rc, 2);
  2773. InvertRect(hdc, &rc);
  2774. InvertRect(hdc, &rc);
  2775. _ReleaseDC(hdc);
  2776. break;
  2777. }
  2778. case SSWF_DISPLAY:
  2779. {
  2780. //
  2781. // Flash the entire display.
  2782. //
  2783. HDC hdc;
  2784. RECT rc;
  2785. hdc = _GetDCEx(PWNDDESKTOP(pwndActive), NULL, DCX_WINDOW | DCX_CACHE);
  2786. rc.left = rc.top = 0;
  2787. rc.right = SYSMET(CXVIRTUALSCREEN);
  2788. rc.bottom = SYSMET(CYVIRTUALSCREEN);
  2789. InvertRect(hdc, &rc);
  2790. InvertRect(hdc, &rc);
  2791. _ReleaseDC(hdc);
  2792. break;
  2793. }
  2794. }
  2795. return TRUE;
  2796. }
  2797. /***************************************************************************\
  2798. * UtilityManager
  2799. *
  2800. * This is the strategy routine that gets called as part of the input stream
  2801. * processing. Utility Manager launching happens here.
  2802. *
  2803. * Return value:
  2804. * TRUE - key event should be passed on to the next access routine.
  2805. * FALSE - key event was processed and should not be passed on.
  2806. *
  2807. * History: 10-28-98 a-anilk created
  2808. \***************************************************************************/
  2809. BOOL UtilityManager(
  2810. PKE pKeyEvent,
  2811. ULONG ExtraInformation,
  2812. int NotUsed)
  2813. {
  2814. int CurrentModState;
  2815. int fBreak;
  2816. BYTE Vk;
  2817. UNREFERENCED_PARAMETER(NotUsed);
  2818. UNREFERENCED_PARAMETER(ExtraInformation);
  2819. CheckCritIn();
  2820. Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff);
  2821. fBreak = pKeyEvent->usFlaggedVk & KBDBREAK;
  2822. CurrentModState = gLockBits | gLatchBits | gPhysModifierState;
  2823. // the hot key to launch the utility manager is WinKey + U
  2824. if (Vk == VK_U && !fBreak && (CurrentModState & LRWIN)) {
  2825. PostAccessNotification(ACCESS_UTILITYMANAGER);
  2826. return FALSE;
  2827. }
  2828. return TRUE; // send key event to next accessibility routine.
  2829. }