ReactOS 0.4.15-dev-7924-g5949c20
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
34static 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,
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 */
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
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,
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,
96 VK_RMENU, 0, 0, 0,
97 0, 0, 0, 0,
98/* 0x40 */
99 0, 0, 0, 0,
100 0, 0, 0, VK_HOME,
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
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
163typedef 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
250static 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,
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
357static 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
375static 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)) {
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 */
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}
UINT ScanCode
Definition: VirtualKey.c:24
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
Status
Definition: gdiplustypes.h:25
static void IntUpdateControlKeyState(HANDLE hConsoleInput, LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
Definition: keytrans.c:251
static WORD KeyTable[]
Definition: keytrans.c:34
struct _SCANTOASCII * PSCANTOASCII
struct _SCANTOASCII SCANTOASCII
NTSTATUS IntTranslateKey(HANDLE hConsoleInput, PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
Definition: keytrans.c:417
static WORD KeyTableEnhanced[]
Definition: keytrans.c:77
static UCHAR IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
Definition: keytrans.c:376
static DWORD IntVKFromKbdInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
Definition: keytrans.c:358
static WORD KeyTableNumlock[]
Definition: keytrans.c:120
SCANTOASCII ScanToAscii[]
Definition: keytrans.c:172
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int UINT
Definition: ndis.h:50
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 KEY_BREAK
Definition: ntddkbd.h:71
#define IOCTL_KEYBOARD_SET_INDICATORS
Definition: ntddkbd.h:47
#define KEYBOARD_SCROLL_LOCK_ON
Definition: ntddkbd.h:83
#define KEY_E1
Definition: ntddkbd.h:73
#define KEY_E0
Definition: ntddkbd.h:72
#define KEYBOARD_NUM_LOCK_ON
Definition: ntddkbd.h:82
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
USHORT Enhanced
Definition: keytrans.c:165
UCHAR NumLock
Definition: keytrans.c:168
UCHAR Shift
Definition: keytrans.c:167
UCHAR bCAPS
Definition: keytrans.c:169
USHORT ScanCode
Definition: keytrans.c:164
UCHAR Normal
Definition: keytrans.c:166
static LARGE_INTEGER Counter
Definition: clock.c:43
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define CAPSLOCK_ON
Definition: wincon.h:144
#define LEFT_CTRL_PRESSED
Definition: wincon.h:140
#define SHIFT_PRESSED
Definition: wincon.h:141
#define NUMLOCK_ON
Definition: wincon.h:142
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define RIGHT_ALT_PRESSED
Definition: wincon.h:137
#define ENHANCED_KEY
Definition: wincon.h:145
#define SCROLLLOCK_ON
Definition: wincon.h:143
#define LEFT_ALT_PRESSED
Definition: wincon.h:138
#define VK_OEM_5
Definition: winuser.h:2318
#define VK_NUMPAD3
Definition: winuser.h:2242
#define VK_SNAPSHOT
Definition: winuser.h:2231
#define VK_F12
Definition: winuser.h:2266
#define VK_TAB
Definition: winuser.h:2199
#define VK_F9
Definition: winuser.h:2263
#define VK_MULTIPLY
Definition: winuser.h:2249
#define VK_NUMPAD1
Definition: winuser.h:2240
#define VK_F10
Definition: winuser.h:2264
#define VK_OEM_7
Definition: winuser.h:2320
#define VK_NUMPAD2
Definition: winuser.h:2241
#define VK_SPACE
Definition: winuser.h:2219
#define VK_CAPITAL
Definition: winuser.h:2206
#define VK_OEM_4
Definition: winuser.h:2317
#define VK_NUMPAD4
Definition: winuser.h:2243
#define VK_SCROLL
Definition: winuser.h:2280
#define VK_CONTROL
Definition: winuser.h:2203
#define VK_RSHIFT
Definition: winuser.h:2283
#define VK_UP
Definition: winuser.h:2225
#define VK_LSHIFT
Definition: winuser.h:2282
#define VK_NUMPAD0
Definition: winuser.h:2239
#define VK_F1
Definition: winuser.h:2255
#define VK_F6
Definition: winuser.h:2260
#define VK_NUMPAD6
Definition: winuser.h:2245
#define VK_NEXT
Definition: winuser.h:2221
#define VK_RCONTROL
Definition: winuser.h:2285
#define VK_RETURN
Definition: winuser.h:2201
#define VK_OEM_6
Definition: winuser.h:2319
#define VK_F5
Definition: winuser.h:2259
#define VK_F11
Definition: winuser.h:2265
#define VK_F8
Definition: winuser.h:2262
#define VK_RMENU
Definition: winuser.h:2287
#define VK_NUMPAD9
Definition: winuser.h:2248
#define VK_END
Definition: winuser.h:2222
#define VK_HOME
Definition: winuser.h:2223
#define VK_ADD
Definition: winuser.h:2250
#define VK_OEM_2
Definition: winuser.h:2315
#define VK_BACK
Definition: winuser.h:2198
#define VK_F3
Definition: winuser.h:2257
#define VK_F4
Definition: winuser.h:2258
#define VK_NUMPAD5
Definition: winuser.h:2244
#define VK_LEFT
Definition: winuser.h:2224
#define VK_NUMPAD7
Definition: winuser.h:2246
#define VK_RIGHT
Definition: winuser.h:2226
#define VK_OEM_1
Definition: winuser.h:2308
#define VK_DOWN
Definition: winuser.h:2227
#define VK_NUMLOCK
Definition: winuser.h:2279
#define VK_PRIOR
Definition: winuser.h:2220
#define VK_DELETE
Definition: winuser.h:2233
#define VK_DIVIDE
Definition: winuser.h:2254
#define VK_NUMPAD8
Definition: winuser.h:2247
#define VK_ESCAPE
Definition: winuser.h:2214
#define VK_F7
Definition: winuser.h:2261
#define VK_INSERT
Definition: winuser.h:2232
#define VK_SUBTRACT
Definition: winuser.h:2252
#define VK_LMENU
Definition: winuser.h:2286
#define VK_F2
Definition: winuser.h:2256
unsigned char UCHAR
Definition: xmlstorage.h:181