ReactOS  0.4.13-dev-100-gc8611ae
keytrans.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2002 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * COPYRIGHT: See COPYING in the top level directory
21  * PROJECT: ReactOS text-mode setup
22  * FILE: base/setup/usetup/keytrans.c
23  * PURPOSE: Console support functions: keyboard translation
24  * PROGRAMMER: Tinus
25  *
26  * NB: Hardcoded to US keyboard
27  */
28 #include <usetup.h>
29 #include "keytrans.h"
30 
31 #define NDEBUG
32 #include <debug.h>
33 
34 static WORD KeyTable[] = {
35 /* 0x00 */
36  0x00, VK_ESCAPE, 0x31, 0x32,
37  0x33, 0x34, 0x35, 0x36,
38  0x37, 0x38, 0x39, 0x30,
39  VK_OEM_MINUS, VK_OEM_PLUS, VK_BACK, VK_TAB,
40 /* 0x10 */
41  0x51, 0x57, 0x45, 0x52,
42  0x54, 0x59, 0x55, 0x49,
43  0x4f, 0x50, VK_OEM_4, VK_OEM_6,
44  VK_RETURN, VK_CONTROL, 0x41, 0x53,
45 /* 0x20 */
46  0x44, 0x46, 0x47, 0x48,
47  0x4a, 0x4b, 0x4c, VK_OEM_1,
48  VK_OEM_7, 0xc0, VK_LSHIFT, VK_OEM_5,
49  0x5a, 0x58, 0x43, 0x56,
50 /* 0x30 */
51  0x42, 0x4e, 0x4d, VK_OEM_COMMA,
52  VK_OEM_PERIOD, VK_OEM_2, VK_RSHIFT, VK_MULTIPLY,
55 /* 0x40 */
59  0, VK_RIGHT, VK_ADD, VK_END,
60 /* 0x50 */
62  0, 0, 0, VK_F11,
63  VK_F12, 0, 0, 0,
64  0, 0, 0, 0,
65 /* 0x60 */
66  0, 0, 0, 0,
67  0, 0, 0, 0,
68  0, 0, 0, 0,
69  0, 0, 0, 0,
70 /* 0x70 */
71  0, 0, 0, 0,
72  0, 0, 0, 0,
73  0, 0, 0, 0,
74  0, 0, 0, 0
75 };
76 
77 static WORD KeyTableEnhanced[] = {
78 /* 0x00 */
79  0, 0, 0, 0,
80  0, 0, 0, 0,
81  0, 0, 0, 0,
82  0, 0, 0, 0,
83 /* 0x10 */
84  0, 0, 0, 0,
85  0, 0, 0, 0,
86  0, 0, 0, 0,
87  VK_RETURN, VK_RCONTROL, 0, 0,
88 /* 0x20 */
89  0, 0, 0, 0,
90  0, 0, 0, 0,
91  0, 0, 0, 0,
92  0, 0, 0, 0,
93 /* 0x30 */
94  0, 0, 0, 0,
95  0, VK_DIVIDE, 0, VK_SNAPSHOT,
96  VK_RMENU, 0, 0, 0,
97  0, 0, 0, 0,
98 /* 0x40 */
99  0, 0, 0, 0,
100  0, 0, 0, VK_HOME,
101  VK_UP, VK_PRIOR, 0, VK_LEFT,
102  0, VK_RIGHT, 0, VK_END,
103 /* 0x50 */
105  0, 0, 0, 0,
106  0, 0, 0, 0,
107  0, 0, 0, 0,
108 /* 0x60 */
109  0, 0, 0, 0,
110  0, 0, 0, 0,
111  0, 0, 0, 0,
112  0, 0, 0, 0,
113 /* 0x70 */
114  0, 0, 0, 0,
115  0, 0, 0, 0,
116  0, 0, 0, 0,
117  0, 0, 0, 0
118 };
119 
120 static WORD KeyTableNumlock[] = {
121 /* 0x00 */
122  0, 0, 0, 0,
123  0, 0, 0, 0,
124  0, 0, 0, 0,
125  0, 0, 0, 0,
126 /* 0x10 */
127  0, 0, 0, 0,
128  0, 0, 0, 0,
129  0, 0, 0, 0,
130  0, 0, 0, 0,
131 /* 0x20 */
132  0, 0, 0, 0,
133  0, 0, 0, 0,
134  0, 0, 0, 0,
135  0, 0, 0, 0,
136 /* 0x30 */
137  0, 0, 0, 0,
138  0, 0, 0, 0,
139  0, 0, 0, 0,
140  0, 0, 0, 0,
141 /* 0x40 */
142  0, 0, 0, 0,
143  0, 0, 0, VK_NUMPAD7,
146 /* 0x50 */
148  0, 0, 0, 0,
149  0, 0, 0, 0,
150  0, 0, 0, 0,
151 /* 0x60 */
152  0, 0, 0, 0,
153  0, 0, 0, 0,
154  0, 0, 0, 0,
155  0, 0, 0, 0,
156 /* 0x70 */
157  0, 0, 0, 0,
158  0, 0, 0, 0,
159  0, 0, 0, 0,
160  0, 0, 0, 0
161 };
162 
163 typedef struct _SCANTOASCII {
171 
173 { 0x1e, 0, 'a', 'A', 0, TRUE },
174 { 0x30, 0, 'b', 'B', 0, TRUE },
175 { 0x2e, 0, 'c', 'C', 0, TRUE },
176 { 0x20, 0, 'd', 'D', 0, TRUE },
177 { 0x12, 0, 'e', 'E', 0, TRUE },
178 { 0x21, 0, 'f', 'F', 0, TRUE },
179 { 0x22, 0, 'g', 'G', 0, TRUE },
180 { 0x23, 0, 'h', 'H', 0, TRUE },
181 { 0x17, 0, 'i', 'I', 0, TRUE },
182 { 0x24, 0, 'j', 'J', 0, TRUE },
183 { 0x25, 0, 'k', 'K', 0, TRUE },
184 { 0x26, 0, 'l', 'L', 0, TRUE },
185 { 0x32, 0, 'm', 'M', 0, TRUE },
186 { 0x31, 0, 'n', 'N', 0, TRUE },
187 { 0x18, 0, 'o', 'O', 0, TRUE },
188 { 0x19, 0, 'p', 'P', 0, TRUE },
189 { 0x10, 0, 'q', 'Q', 0, TRUE },
190 { 0x13, 0, 'r', 'R', 0, TRUE },
191 { 0x1f, 0, 's', 'S', 0, TRUE },
192 { 0x14, 0, 't', 'T', 0, TRUE },
193 { 0x16, 0, 'u', 'U', 0, TRUE },
194 { 0x2f, 0, 'v', 'V', 0, TRUE },
195 { 0x11, 0, 'w', 'W', 0, TRUE },
196 { 0x2d, 0, 'x', 'X', 0, TRUE },
197 { 0x15, 0, 'y', 'Y', 0, TRUE },
198 { 0x2c, 0, 'z', 'Z', 0, TRUE },
199 
200 { 0x02, 0, '1', '!', 0, FALSE },
201 { 0x03, 0, '2', '@', 0, FALSE },
202 { 0x04, 0, '3', '#', 0, FALSE },
203 { 0x05, 0, '4', '$', 0, FALSE },
204 { 0x06, 0, '5', '%', 0, FALSE },
205 { 0x07, 0, '6', '^', 0, FALSE },
206 { 0x08, 0, '7', '&', 0, FALSE },
207 { 0x09, 0, '8', '*', 0, FALSE },
208 { 0x0a, 0, '9', '(', 0, FALSE },
209 { 0x0b, 0, '0', ')', 0, FALSE },
210 
211 { 0x29, 0, '\'', '~', 0, FALSE },
212 { 0x0c, 0, '-', '_', 0, FALSE },
213 { 0x0d, 0, '=', '+', 0, FALSE },
214 { 0x1a, 0, '[', '{', 0, FALSE },
215 { 0x1b, 0, ']', '}', 0, FALSE },
216 { 0x2b, 0, '\\', '|', 0, FALSE },
217 { 0x27, 0, ';', ':', 0, FALSE },
218 { 0x28, 0, '\'', '"', 0, FALSE },
219 { 0x33, 0, ',', '<', 0, FALSE },
220 { 0x34, 0, '.', '>', 0, FALSE },
221 { 0x35, 0, '/', '?', 0, FALSE },
222 
223 { 0x4f, 0, 0, 0, '1', FALSE },
224 { 0x50, 0, 0, 0, '2', FALSE },
225 { 0x51, 0, 0, 0, '3', FALSE },
226 { 0x4b, 0, 0, 0, '4', FALSE },
227 { 0x4c, 0, 0, 0, '5', FALSE },
228 { 0x4d, 0, 0, 0, '6', FALSE },
229 { 0x47, 0, 0, 0, '7', FALSE },
230 { 0x48, 0, 0, 0, '8', FALSE },
231 { 0x49, 0, 0, 0, '9', FALSE },
232 { 0x52, 0, 0, 0, '0', FALSE },
233 
234 { 0x4a, 0, '-', '-', 0, FALSE },
235 { 0x4e, 0, '+', '+', 0, FALSE },
236 { 0x37, 0, '*', '*', 0, FALSE },
237 { 0x35, 1, '/', '/', 0, FALSE },
238 { 0x53, 0, 0, 0, '.', FALSE },
239 
240 { 0x39, 0, ' ', ' ', 0, FALSE },
241 
242 { 0x1c, 0, '\r', '\r', 0, FALSE },
243 { 0x1c, 1, '\r', '\r', 0, FALSE },
244 { 0x0e, 0, 0x08, 0x08, 0, FALSE }, /* backspace */
245 
246 { 0, 0, 0, 0, 0, FALSE }
247 };
248 
249 
250 static void
252 {
253  DWORD Value = 0;
254  DWORD oldState, newState;
255 
256  if (InputData->Flags & KEY_E1) /* Only the pause key has E1 */
257  return;
258 
259  oldState = newState = *State;
260 
261  if (!(InputData->Flags & KEY_E0)) {
262  switch (InputData->MakeCode) {
263  case 0x2a:
264  case 0x36:
266  break;
267 
268  case 0x1d:
270  break;
271 
272  case 0x38:
274  break;
275 
276  case 0x3A:
277  if (!(InputData->Flags & KEY_BREAK))
278  newState ^= CAPSLOCK_ON;
279  break;
280 
281  case 0x45:
282  if (!(InputData->Flags & KEY_BREAK))
283  newState ^= NUMLOCK_ON;
284  break;
285 
286  case 0x46:
287  if (!(InputData->Flags & KEY_BREAK))
288  newState ^= SCROLLLOCK_ON;
289  break;
290 
291  default:
292  return;
293  }
294  } else {
295  switch (InputData->MakeCode) {
296  case 0x1d:
298  break;
299 
300  case 0x38:
302  break;
303 
304  default:
305  return;
306  }
307  }
308 
309  /* Check if the state of the indicators has been changed */
310  if ((oldState ^ newState) & (NUMLOCK_ON | CAPSLOCK_ON | SCROLLLOCK_ON))
311  {
315 
316  kip.LedFlags = 0;
317  kip.UnitId = 0;
318 
319  if ((newState & NUMLOCK_ON))
321 
322  if ((newState & CAPSLOCK_ON))
324 
325  if ((newState & SCROLLLOCK_ON))
327 
328  /* Update the state of the leds on primary keyboard */
329  DPRINT("NtDeviceIoControlFile dwLeds=%x\n", kip.LedFlags);
330 
332  hConsoleInput,
333  NULL,
334  NULL,
335  NULL,
336  &IoStatusBlock,
338  &kip,
339  sizeof(kip),
340  NULL,
341  0);
342 
343  if (!NT_SUCCESS(Status))
344  {
345  DPRINT1("NtDeviceIoControlFile(IOCTL_KEYBOARD_SET_INDICATORS) failed (Status %lx)\n", Status);
346  }
347  } else
348  /* Normal press/release state handling */
349  if (InputData->Flags & KEY_BREAK)
350  newState &= ~Value;
351  else
352  newState |= Value;
353 
354  *State = newState;
355 }
356 
357 static DWORD
359 {
360  if (!(KeyState & ENHANCED_KEY)) {
361  if ((KeyState & NUMLOCK_ON) &&
362  KeyTableNumlock[InputData->MakeCode & 0x7f]) {
363  DPRINT("Numlock, using %x\n",
364  InputData->MakeCode & 0x7f);
365  return KeyTableNumlock[InputData->MakeCode & 0x7f];
366  }
367  DPRINT("Not enhanced, using %x\n", InputData->MakeCode & 0x7f);
368  return KeyTable[InputData->MakeCode & 0x7f];
369  }
370 
371  DPRINT("Enhanced, using %x\n", InputData->MakeCode & 0x7f);
372  return KeyTableEnhanced[InputData->MakeCode & 0x7f];
373 }
374 
375 static UCHAR
377 {
378  UINT Counter = 0;
379  USHORT Enhanced = 0;
380 
381  if (KeyState & ENHANCED_KEY) Enhanced = 1;
382 
383  while (ScanToAscii[Counter].ScanCode != 0) {
384  if ((ScanToAscii[Counter].ScanCode == InputData->MakeCode) &&
385  (ScanToAscii[Counter].Enhanced == Enhanced)) {
386  if (ScanToAscii[Counter].NumLock) {
387  if ((KeyState & NUMLOCK_ON) &&
388  !(KeyState & SHIFT_PRESSED)) {
389  return ScanToAscii[Counter].NumLock;
390  } else {
391  return ScanToAscii[Counter].Normal;
392  }
393  }
394 
395  if ((KeyState & CAPSLOCK_ON) && ScanToAscii[Counter].bCAPS)
396  KeyState ^= SHIFT_PRESSED;
397 
398  if (KeyState & SHIFT_PRESSED)
399  return ScanToAscii[Counter].Shift;
400 
401  return ScanToAscii[Counter].Normal;
402  }
403  Counter++;
404  }
405 
406  return 0;
407 }
408 
409 /* This is going to be quick and messy. The usetup app runs in native mode
410  * so it cannot use the translation routines in win32k which means it'll have
411  * to be done here too.
412  *
413  * Only the bKeyDown, AsciiChar and wVirtualKeyCode members are used
414  * in the app so I'll just fill the others with somewhat sane values
415  */
416 NTSTATUS
418 {
419  static DWORD dwControlKeyState;
420 
422 
423  if (!(InputData->Flags & KEY_BREAK))
424  Event->bKeyDown = TRUE;
425  else
426  Event->bKeyDown = FALSE;
427 
428  Event->wRepeatCount = 1;
429  Event->wVirtualScanCode = InputData->MakeCode;
430 
431  DPRINT("Translating: %x\n", InputData->MakeCode);
432 
433  IntUpdateControlKeyState(hConsoleInput, &dwControlKeyState, InputData);
434  Event->dwControlKeyState = dwControlKeyState;
435 
436  if (InputData->Flags & KEY_E0)
437  Event->dwControlKeyState |= ENHANCED_KEY;
438 
439  Event->wVirtualKeyCode = IntVKFromKbdInput(InputData,
440  Event->dwControlKeyState);
441 
442  DPRINT("Result: %x\n", Event->wVirtualKeyCode);
443 
444  if (Event->bKeyDown) {
445  Event->uChar.AsciiChar =
446  IntAsciiFromInput(InputData,
447  Event->dwControlKeyState);
448  DPRINT("Char: %x\n", Event->uChar.AsciiChar);
449  } else {
450  Event->uChar.AsciiChar = 0;
451  }
452 
453  return STATUS_SUCCESS;
454 }
#define VK_SUBTRACT
Definition: winuser.h:2206
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
#define SCROLLLOCK_ON
Definition: wincon.h:137
#define VK_NUMPAD8
Definition: winuser.h:2201
static void IntUpdateControlKeyState(HANDLE hConsoleInput, LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
Definition: keytrans.c:251
#define VK_NUMPAD0
Definition: winuser.h:2193
struct _SCANTOASCII * PSCANTOASCII
#define TRUE
Definition: types.h:120
ULONG ScanCode
Definition: api.c:39
#define VK_F5
Definition: winuser.h:2213
#define VK_F6
Definition: winuser.h:2214
#define VK_NUMPAD6
Definition: winuser.h:2199
#define VK_RMENU
Definition: winuser.h:2241
#define VK_LSHIFT
Definition: winuser.h:2236
LONG NTSTATUS
Definition: precomp.h:26
#define VK_NUMPAD5
Definition: winuser.h:2198
#define VK_F9
Definition: winuser.h:2217
struct _SCANTOASCII SCANTOASCII
#define VK_ADD
Definition: winuser.h:2204
#define VK_LEFT
Definition: winuser.h:2178
static UCHAR IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
Definition: keytrans.c:376
#define VK_OEM_5
Definition: winuser.h:2272
#define VK_TAB
Definition: winuser.h:2153
#define VK_DOWN
Definition: winuser.h:2181
#define VK_INSERT
Definition: winuser.h:2186
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define KEYBOARD_CAPS_LOCK_ON
Definition: ntddkbd.h:81
#define VK_PRIOR
Definition: winuser.h:2174
#define SHIFT_PRESSED
Definition: wincon.h:135
#define KEY_BREAK
Definition: ntddkbd.h:71
#define VK_ESCAPE
Definition: winuser.h:2168
#define VK_NUMPAD9
Definition: winuser.h:2202
#define VK_RETURN
Definition: winuser.h:2155
#define VK_NEXT
Definition: winuser.h:2175
#define VK_F10
Definition: winuser.h:2218
USHORT Enhanced
Definition: keytrans.c:165
#define VK_OEM_4
Definition: winuser.h:2271
#define VK_HOME
Definition: winuser.h:2177
#define VK_UP
Definition: winuser.h:2179
UCHAR Shift
Definition: keytrans.c:167
NTSTATUS IntTranslateKey(HANDLE hConsoleInput, PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
Definition: keytrans.c:417
#define VK_F4
Definition: winuser.h:2212
#define VK_F2
Definition: winuser.h:2210
smooth NULL
Definition: ftsmooth.c:416
#define VK_MULTIPLY
Definition: winuser.h:2203
#define VK_NUMPAD3
Definition: winuser.h:2196
#define VK_OEM_6
Definition: winuser.h:2273
void DPRINT(...)
Definition: polytest.cpp:61
#define VK_DELETE
Definition: winuser.h:2187
#define LEFT_ALT_PRESSED
Definition: wincon.h:132
#define VK_OEM_7
Definition: winuser.h:2274
#define VK_F7
Definition: winuser.h:2215
#define ENHANCED_KEY
Definition: wincon.h:139
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define VK_F12
Definition: winuser.h:2220
unsigned short WORD
Definition: ntddk_ex.h:93
UCHAR Normal
Definition: keytrans.c:166
unsigned long DWORD
Definition: ntddk_ex.h:95
#define VK_NUMPAD4
Definition: winuser.h:2197
#define VK_F3
Definition: winuser.h:2211
unsigned char UCHAR
Definition: xmlstorage.h:181
#define VK_F8
Definition: winuser.h:2216
#define LEFT_CTRL_PRESSED
Definition: wincon.h:134
#define VK_RCONTROL
Definition: winuser.h:2239
#define VK_LMENU
Definition: winuser.h:2240
#define VK_RSHIFT
Definition: winuser.h:2237
#define VK_BACK
Definition: winuser.h:2152
#define KEY_E1
Definition: ntddkbd.h:73
Status
Definition: gdiplustypes.h:24
#define VK_RIGHT
Definition: winuser.h:2180
#define VK_NUMPAD7
Definition: winuser.h:2200
static WORD KeyTable[]
Definition: keytrans.c:34
enum State_ State
Definition: pofuncs.h:54
SCANTOASCII ScanToAscii[]
Definition: keytrans.c:172
#define VK_SCROLL
Definition: winuser.h:2234
#define VK_NUMLOCK
Definition: winuser.h:2233
unsigned short USHORT
Definition: pedump.c:61
#define KEY_E0
Definition: ntddkbd.h:72
static WORD KeyTableNumlock[]
Definition: keytrans.c:120
UCHAR NumLock
Definition: keytrans.c:168
#define KEYBOARD_SCROLL_LOCK_ON
Definition: ntddkbd.h:83
#define VK_CAPITAL
Definition: winuser.h:2160
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define VK_NUMPAD2
Definition: winuser.h:2195
unsigned int UINT
Definition: ndis.h:50
#define VK_SPACE
Definition: winuser.h:2173
#define VK_F1
Definition: winuser.h:2209
#define VK_CONTROL
Definition: winuser.h:2157
#define DPRINT1
Definition: precomp.h:8
static LARGE_INTEGER Counter
Definition: clock.c:43
#define VK_DIVIDE
Definition: winuser.h:2208
UCHAR bCAPS
Definition: keytrans.c:169
#define VK_F11
Definition: winuser.h:2219
uint32_t * LPDWORD
Definition: typedefs.h:57
#define KEYBOARD_NUM_LOCK_ON
Definition: ntddkbd.h:82
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
static WORD KeyTableEnhanced[]
Definition: keytrans.c:77
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:133
#define IOCTL_KEYBOARD_SET_INDICATORS
Definition: ntddkbd.h:47
static DWORD IntVKFromKbdInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
Definition: keytrans.c:358
#define VK_NUMPAD1
Definition: winuser.h:2194
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define VK_SNAPSHOT
Definition: winuser.h:2185
#define VK_END
Definition: winuser.h:2176
#define VK_OEM_2
Definition: winuser.h:2269
#define VK_OEM_1
Definition: winuser.h:2262
#define NUMLOCK_ON
Definition: wincon.h:136
USHORT ScanCode
Definition: keytrans.c:164
#define RIGHT_ALT_PRESSED
Definition: wincon.h:131
#define CAPSLOCK_ON
Definition: wincon.h:138