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.

423 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: keyboard.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * History:
  7. * 11-11-90 DavidPe Created.
  8. * 13-Feb-1991 mikeke Added Revalidation code (None)
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. /***************************************************************************\
  13. * _GetKeyState (API)
  14. *
  15. * This API returns the up/down and toggle state of the specified VK based
  16. * on the input synchronized keystate in the current queue. The toggle state
  17. * is mainly for 'state' keys like Caps-Lock that are toggled each time you
  18. * press them.
  19. *
  20. * History:
  21. * 11-11-90 DavidPe Created.
  22. \***************************************************************************/
  23. SHORT _GetKeyState(
  24. int vk)
  25. {
  26. UINT wKeyState;
  27. PTHREADINFO pti;
  28. if ((UINT)vk >= CVKKEYSTATE) {
  29. RIPERR1(ERROR_INVALID_PARAMETER,
  30. RIP_WARNING,
  31. "Invalid parameter \"vk\" (%ld) to _GetKeyState",
  32. vk);
  33. return 0;
  34. }
  35. pti = PtiCurrentShared();
  36. #ifdef LATER
  37. //
  38. // note - anything that accesses the pq structure is a bad idea since it
  39. // can be changed between any two instructions.
  40. //
  41. #endif
  42. wKeyState = 0;
  43. /*
  44. * Set the toggle bit.
  45. */
  46. if (TestKeyStateToggle(pti->pq, vk))
  47. wKeyState = 0x0001;
  48. /*
  49. * Set the keyup/down bit.
  50. */
  51. if (TestKeyStateDown(pti->pq, vk)) {
  52. /*
  53. * Used to be wKeyState|= 0x8000.Fix for bug 28820; Ctrl-Enter
  54. * accelerator doesn't work on Nestscape Navigator Mail 2.0
  55. */
  56. wKeyState |= 0xff80; // This is what 3.1 returned!!!!
  57. }
  58. return (SHORT)wKeyState;
  59. }
  60. /***************************************************************************\
  61. * _GetAsyncKeyState (API)
  62. *
  63. * This function is similar to GetKeyState except it returns what could be
  64. * considered the 'hardware' keystate or what state the key is in at the
  65. * moment the function is called, rather than based on what key events the
  66. * application has processed. Also, rather than returning the toggle bit,
  67. * it has a bit telling whether the key was pressed since the last call to
  68. * GetAsyncKeyState().
  69. *
  70. * History:
  71. * 11-11-90 DavidPe Created.
  72. \***************************************************************************/
  73. SHORT _GetAsyncKeyState(
  74. int vk)
  75. {
  76. SHORT sKeyState;
  77. if ((UINT)vk >= CVKKEYSTATE) {
  78. RIPERR1(ERROR_INVALID_PARAMETER,
  79. RIP_WARNING,
  80. "Invalid parameter \"vk\" (%ld) to _GetAsyncKeyState",
  81. vk);
  82. return 0;
  83. }
  84. /*
  85. * See if this key went down since the last time state for it was
  86. * read. Clear the flag if so.
  87. */
  88. sKeyState = 0;
  89. if (TestAsyncKeyStateRecentDown(vk)) {
  90. ClearAsyncKeyStateRecentDown(vk);
  91. sKeyState = 1;
  92. }
  93. /*
  94. * Set the keyup/down bit.
  95. */
  96. if (TestAsyncKeyStateDown(vk))
  97. sKeyState |= 0x8000;
  98. /*
  99. * Don't return the toggle bit since it's a new bit and might
  100. * cause compatibility problems.
  101. */
  102. return sKeyState;
  103. }
  104. /***************************************************************************\
  105. * _SetKeyboardState (API)
  106. *
  107. * This function allows the app to set the current keystate. This is mainly
  108. * useful for setting the toggle bit, particularly for the keys associated
  109. * with the LEDs on the physical keyboard.
  110. *
  111. * History:
  112. * 11-11-90 DavidPe Created.
  113. * 16-May-1991 mikeke Changed to return BOOL
  114. \***************************************************************************/
  115. BOOL _SetKeyboardState(
  116. CONST BYTE *pb)
  117. {
  118. int i;
  119. PQ pq;
  120. PTHREADINFO ptiCurrent = PtiCurrent();
  121. pq = ptiCurrent->pq;
  122. /*
  123. * Copy in the new state table.
  124. */
  125. for (i = 0; i < 256; i++, pb++) {
  126. if (*pb & 0x80) {
  127. SetKeyStateDown(pq, i);
  128. } else {
  129. ClearKeyStateDown(pq, i);
  130. }
  131. if (*pb & 0x01) {
  132. SetKeyStateToggle(pq, i);
  133. } else {
  134. ClearKeyStateToggle(pq, i);
  135. }
  136. }
  137. /*
  138. * Update the key cache index.
  139. */
  140. gpsi->dwKeyCache++;
  141. #ifdef LATER
  142. // scottlu 6-9-91
  143. // I don't think we ought to do this unless someone really complains. This
  144. // could have bad side affects, especially considering that terminal
  145. // apps will want to do this, and terminal apps could easily not respond
  146. // to input for awhile, causing this state to change unexpectedly while
  147. // a user is using some other application. - scottlu.
  148. /* DavidPe 02/05/92
  149. * How about if we only do it when the calling app is foreground?
  150. */
  151. /*
  152. * Propagate the toggle bits for the keylight keys to the
  153. * async keystate table and update the keylights.
  154. *
  155. * THIS could be evil in a de-synced environment, but to do this
  156. * in a totally "synchronous" way is hard.
  157. */
  158. if (pb[VK_CAPITAL] & 0x01) {
  159. SetAsyncKeyStateToggle(VK_CAPITAL);
  160. } else {
  161. ClearAsyncKeyStateToggle(VK_CAPITAL);
  162. }
  163. if (pb[VK_NUMLOCK] & 0x01) {
  164. SetAsyncKeyStateToggle(VK_NUMLOCK);
  165. } else {
  166. ClearAsyncKeyStateToggle(VK_NUMLOCK);
  167. }
  168. if (pb[VK_SCROLL] & 0x01) {
  169. SetAsyncKeyStateToggle(VK_SCROLL);
  170. } else {
  171. ClearAsyncKeyStateToggle(VK_SCROLL);
  172. }
  173. UpdateKeyLights(TRUE);
  174. #endif
  175. return TRUE;
  176. }
  177. /***************************************************************************\
  178. * RegisterPerUserKeyboardIndicators
  179. *
  180. * Saves the current keyboard indicators in the user's profile.
  181. *
  182. * ASSUMPTIONS:
  183. *
  184. * 10-14-92 IanJa Created.
  185. \***************************************************************************/
  186. static CONST WCHAR wszInitialKeyboardIndicators[] = L"InitialKeyboardIndicators";
  187. VOID
  188. RegisterPerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName)
  189. {
  190. WCHAR wszInitKbdInd[2] = L"0";
  191. /*
  192. * Initial Keyboard state (Num-Lock only)
  193. */
  194. /*
  195. * For HYDRA we do not want to save this.
  196. */
  197. if (gbRemoteSession) {
  198. return;
  199. }
  200. wszInitKbdInd[0] += TestAsyncKeyStateToggle(VK_NUMLOCK) ? 2 : 0;
  201. FastWriteProfileStringW(pProfileUserName,
  202. PMAP_KEYBOARD,
  203. wszInitialKeyboardIndicators,
  204. wszInitKbdInd);
  205. }
  206. /***************************************************************************\
  207. * UpdatePerUserKeyboardIndicators
  208. *
  209. * Sets the initial keyboard indicators according to the user's profile.
  210. *
  211. * ASSUMPTIONS:
  212. *
  213. * 10-14-92 IanJa Created.
  214. \***************************************************************************/
  215. VOID
  216. UpdatePerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName)
  217. {
  218. DWORD dw = 0x80000000;
  219. PQ pq;
  220. PTHREADINFO ptiCurrent = PtiCurrent();
  221. pq = ptiCurrent->pq;
  222. /*
  223. * For terminal server, the client is responsible for synchronizing the
  224. * keyboard state.
  225. */
  226. if (IsRemoteConnection()) {
  227. return;
  228. }
  229. /*
  230. * Initial Keyboard state (Num-Lock only)
  231. */
  232. FastGetProfileIntW(pProfileUserName,
  233. PMAP_KEYBOARD,
  234. wszInitialKeyboardIndicators,
  235. 0x80000000,
  236. &dw,
  237. 0);
  238. dw &= 0x80000002;
  239. /*
  240. * The special value 0x80000000 in the registry indicates that the BIOS
  241. * settings are to be used as the initial LED state. (This is undocumented)
  242. */
  243. if (dw == 0x80000000) {
  244. dw = gklpBootTime.LedFlags;
  245. }
  246. if (dw & KEYBOARD_NUM_LOCK_ON) {
  247. SetKeyStateToggle(pq, VK_NUMLOCK);
  248. SetAsyncKeyStateToggle(VK_NUMLOCK);
  249. SetRawKeyToggle(VK_NUMLOCK);
  250. } else {
  251. ClearKeyStateToggle(pq, VK_NUMLOCK);
  252. ClearAsyncKeyStateToggle(VK_NUMLOCK);
  253. ClearRawKeyToggle(VK_NUMLOCK);
  254. }
  255. /*
  256. * Initialize KANA Toggle status
  257. */
  258. gfKanaToggle = FALSE;
  259. ClearKeyStateToggle(pq, VK_KANA);
  260. ClearAsyncKeyStateToggle(VK_KANA);
  261. ClearRawKeyToggle(VK_KANA);
  262. UpdateKeyLights(FALSE);
  263. }
  264. /***************************************************************************\
  265. * UpdateAsyncKeyState
  266. *
  267. * Based on a VK and a make/break flag, this function will update the async
  268. * keystate table.
  269. *
  270. * History:
  271. * 06-09-91 ScottLu Added keystate synchronization across threads.
  272. * 11-12-90 DavidPe Created.
  273. \***************************************************************************/
  274. void UpdateAsyncKeyState(
  275. PQ pqOwner,
  276. UINT wVK,
  277. BOOL fBreak)
  278. {
  279. PQ pqT;
  280. PLIST_ENTRY pHead, pEntry;
  281. PTHREADINFO pti;
  282. CheckCritIn();
  283. /*
  284. * First check to see if the queue this key is going to has a pending
  285. * key state event. If it does, post it because we need to copy the
  286. * async key state into this event as it is before we modify
  287. * this key's state, or else we'll generate a key state event with
  288. * the wrong key state in it.
  289. */
  290. if (pqOwner != NULL && pqOwner->QF_flags & QF_UPDATEKEYSTATE) {
  291. PostUpdateKeyStateEvent(pqOwner);
  292. }
  293. if (!fBreak) {
  294. /*
  295. * This key has gone down - update the "recent down" bit in the
  296. * async key state table.
  297. */
  298. SetAsyncKeyStateRecentDown(wVK);
  299. /*
  300. * This is a key make. If the key was not already down, update the
  301. * toggle bit.
  302. */
  303. if (!TestAsyncKeyStateDown(wVK)) {
  304. if (TestAsyncKeyStateToggle(wVK)) {
  305. ClearAsyncKeyStateToggle(wVK);
  306. } else {
  307. SetAsyncKeyStateToggle(wVK);
  308. }
  309. }
  310. /*
  311. * This is a make, so turn on the key down bit.
  312. */
  313. SetAsyncKeyStateDown(wVK);
  314. } else {
  315. /*
  316. * This is a break, so turn off the key down bit.
  317. */
  318. ClearAsyncKeyStateDown(wVK);
  319. }
  320. /*
  321. * If this is one of the keys we cache, update the async key cache index.
  322. */
  323. if (wVK < CVKASYNCKEYCACHE) {
  324. gpsi->dwAsyncKeyCache++;
  325. }
  326. /*
  327. * A key has changed state. Update all queues not receiving this input so
  328. * they know that this key has changed state. This lets us know which keys to
  329. * update in the thread specific key state table to keep it in sync
  330. * with the user. Walking down the thread list may mean that an
  331. * individual queue may by updated more than once, but it is cheaper
  332. * than maintaining a list of queues on the desktop.
  333. */
  334. UserAssert(grpdeskRitInput != NULL);
  335. pHead = &grpdeskRitInput->PtiList;
  336. for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
  337. pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink);
  338. /*
  339. * Don't update the queue this message is going to - it'll be
  340. * in sync because it is receiving this message.
  341. */
  342. pqT = pti->pq;
  343. if (pqT == pqOwner)
  344. continue;
  345. /*
  346. * Set the "recent down" bit. In this case this doesn't really mean
  347. * "recent down", it means "recent change" (since the last time
  348. * we synced this queue), either up or down. This tells us which
  349. * keys went down since the last time this thread synced with key
  350. * state. Set the "update key state" flag so we know that later
  351. * we need to sync with these keys.
  352. */
  353. SetKeyRecentDownBit(pqT->afKeyRecentDown, wVK);
  354. pqT->QF_flags |= QF_UPDATEKEYSTATE;
  355. }
  356. /*
  357. * Update the key cache index.
  358. */
  359. gpsi->dwKeyCache++;
  360. }