Minor changes for ATAPI Srb Functions
[reactos.git] / base / setup / usetup / native / utils / keytrans.c
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/native/utils/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,
53 VK_LMENU, VK_SPACE, VK_CAPITAL, VK_F1,
54 VK_F2, VK_F3, VK_F4, VK_F5,
55 /* 0x40 */
56 VK_F6, VK_F7, VK_F8, VK_F9,
57 VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
58 VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT,
59 0, VK_RIGHT, VK_ADD, VK_END,
60 /* 0x50 */
61 VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE,
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 */
104 VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE,
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 /*
121 * Note how the keyboard lights are not handled, so while NUMLOCK_ON can
122 * be on, the light will never be. If this starts to be a problem it can be
123 * fixed, but it's too much work for too little gain to do now.
124 * Look in win32k/ntuser/input.c for an example.
125 */
126
127 static WORD KeyTableNumlock[] = {
128 /* 0x00 */
129 0, 0, 0, 0,
130 0, 0, 0, 0,
131 0, 0, 0, 0,
132 0, 0, 0, 0,
133 /* 0x10 */
134 0, 0, 0, 0,
135 0, 0, 0, 0,
136 0, 0, 0, 0,
137 0, 0, 0, 0,
138 /* 0x20 */
139 0, 0, 0, 0,
140 0, 0, 0, 0,
141 0, 0, 0, 0,
142 0, 0, 0, 0,
143 /* 0x30 */
144 0, 0, 0, 0,
145 0, 0, 0, 0,
146 0, 0, 0, 0,
147 0, 0, 0, 0,
148 /* 0x40 */
149 0, 0, 0, 0,
150 0, 0, 0, VK_NUMPAD7,
151 VK_NUMPAD8, VK_NUMPAD9, 0, VK_NUMPAD4,
152 VK_NUMPAD5, VK_NUMPAD6, 0, VK_NUMPAD1,
153 /* 0x50 */
154 VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, 0,
155 0, 0, 0, 0,
156 0, 0, 0, 0,
157 0, 0, 0, 0,
158 /* 0x60 */
159 0, 0, 0, 0,
160 0, 0, 0, 0,
161 0, 0, 0, 0,
162 0, 0, 0, 0,
163 /* 0x70 */
164 0, 0, 0, 0,
165 0, 0, 0, 0,
166 0, 0, 0, 0,
167 0, 0, 0, 0
168 };
169
170 typedef struct _SCANTOASCII {
171 USHORT ScanCode;
172 USHORT Enhanced;
173 UCHAR Normal;
174 UCHAR Shift;
175 UCHAR NumLock;
176 } SCANTOASCII, *PSCANTOASCII;
177
178 SCANTOASCII ScanToAscii[] = {
179 { 0x1e, 0, 'a', 'A', 0 },
180 { 0x30, 0, 'b', 'B', 0 },
181 { 0x2e, 0, 'c', 'C', 0 },
182 { 0x20, 0, 'd', 'D', 0 },
183 { 0x12, 0, 'e', 'E', 0 },
184 { 0x21, 0, 'f', 'F', 0 },
185 { 0x22, 0, 'g', 'G', 0 },
186 { 0x23, 0, 'h', 'H', 0 },
187 { 0x17, 0, 'i', 'I', 0 },
188 { 0x24, 0, 'j', 'J', 0 },
189 { 0x25, 0, 'k', 'K', 0 },
190 { 0x26, 0, 'l', 'L', 0 },
191 { 0x32, 0, 'm', 'M', 0 },
192 { 0x31, 0, 'n', 'N', 0 },
193 { 0x18, 0, 'o', 'O', 0 },
194 { 0x19, 0, 'p', 'P', 0 },
195 { 0x10, 0, 'q', 'Q', 0 },
196 { 0x13, 0, 'r', 'R', 0 },
197 { 0x1f, 0, 's', 'S', 0 },
198 { 0x14, 0, 't', 'T', 0 },
199 { 0x16, 0, 'u', 'U', 0 },
200 { 0x2f, 0, 'v', 'V', 0 },
201 { 0x11, 0, 'w', 'W', 0 },
202 { 0x2d, 0, 'x', 'X', 0 },
203 { 0x15, 0, 'y', 'Y', 0 },
204 { 0x2c, 0, 'z', 'Z', 0 },
205
206 { 0x02, 0, '1', '!', 0 },
207 { 0x03, 0, '2', '@', 0 },
208 { 0x04, 0, '3', '#', 0 },
209 { 0x05, 0, '4', '$', 0 },
210 { 0x06, 0, '5', '%', 0 },
211 { 0x07, 0, '6', '^', 0 },
212 { 0x08, 0, '7', '&', 0 },
213 { 0x09, 0, '8', '*', 0 },
214 { 0x0a, 0, '9', '(', 0 },
215 { 0x0b, 0, '0', ')', 0 },
216
217 { 0x29, 0, '\'', '~', 0 },
218 { 0x0c, 0, '-', '_', 0 },
219 { 0x0d, 0, '=', '+', 0 },
220 { 0x1a, 0, '[', '{', 0 },
221 { 0x1b, 0, ']', '}', 0 },
222 { 0x2b, 0, '\\', '|', 0 },
223 { 0x27, 0, ';', ':', 0 },
224 { 0x28, 0, '\'', '"', 0 },
225 { 0x33, 0, ',', '<', 0 },
226 { 0x34, 0, '.', '>', 0 },
227 { 0x35, 0, '/', '?', 0 },
228
229 { 0x4f, 0, 0, 0, '1' },
230 { 0x50, 0, 0, 0, '2' },
231 { 0x51, 0, 0, 0, '3' },
232 { 0x4b, 0, 0, 0, '4' },
233 { 0x4c, 0, 0, 0, '5' },
234 { 0x4d, 0, 0, 0, '6' },
235 { 0x47, 0, 0, 0, '7' },
236 { 0x48, 0, 0, 0, '8' },
237 { 0x49, 0, 0, 0, '9' },
238 { 0x52, 0, 0, 0, '0' },
239
240 { 0x4a, 0, '-', '-', 0 },
241 { 0x4e, 0, '+', '+', 0 },
242 { 0x37, 0, '*', '*', 0 },
243 { 0x35, 1, '/', '/', 0 },
244 { 0x53, 0, 0, 0, '.' },
245
246 { 0x39, 0, ' ', ' ', 0 },
247
248 { 0x1c, 0, '\r', '\r', 0 },
249 { 0x1c, 1, '\r', '\r', 0 },
250 { 0x0e, 0, 0x08, 0x08, 0 }, /* backspace */
251
252 { 0, 0, 0, 0, 0 }
253 };
254
255
256 static void
257 IntUpdateControlKeyState(LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
258 {
259 DWORD Value = 0;
260
261 if (InputData->Flags & KEY_E1) /* Only the pause key has E1 */
262 return;
263
264 if (!(InputData->Flags & KEY_E0)) {
265 switch (InputData->MakeCode) {
266 case 0x2a:
267 case 0x36:
268 Value = SHIFT_PRESSED;
269 break;
270
271 case 0x1d:
272 Value = LEFT_CTRL_PRESSED;
273 break;
274
275 case 0x38:
276 Value = LEFT_ALT_PRESSED;
277 break;
278
279 case 0x45:
280 Value = NUMLOCK_ON;
281 if (!(InputData->Flags & KEY_BREAK))
282 *State ^= Value;
283 return;
284 default:
285 return;
286 }
287 } else {
288 switch (InputData->MakeCode) {
289 case 0x1d:
290 Value = RIGHT_CTRL_PRESSED;
291 break;
292
293 case 0x38:
294 Value = RIGHT_ALT_PRESSED;
295 break;
296
297 default:
298 return;
299 }
300 }
301
302 if (InputData->Flags & KEY_BREAK)
303 *State &= ~Value;
304 else
305 *State |= Value;
306 }
307
308 static DWORD
309 IntVKFromKbdInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
310 {
311 if (!(KeyState & ENHANCED_KEY)) {
312 if ((KeyState & NUMLOCK_ON) &&
313 KeyTableNumlock[InputData->MakeCode & 0x7f]) {
314 DPRINT("Numlock, using %x\n",
315 InputData->MakeCode & 0x7f);
316 return KeyTableNumlock[InputData->MakeCode & 0x7f];
317 }
318 DPRINT("Not enhanced, using %x\n", InputData->MakeCode & 0x7f);
319 return KeyTable[InputData->MakeCode & 0x7f];
320 }
321
322 DPRINT("Enhanced, using %x\n", InputData->MakeCode & 0x7f);
323 return KeyTableEnhanced[InputData->MakeCode & 0x7f];
324 }
325
326 static UCHAR
327 IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
328 {
329 UINT Counter = 0;
330 USHORT Enhanced = 0;
331
332 if (KeyState & ENHANCED_KEY) Enhanced = 1;
333
334 while (ScanToAscii[Counter].ScanCode != 0) {
335 if ((ScanToAscii[Counter].ScanCode == InputData->MakeCode) &&
336 (ScanToAscii[Counter].Enhanced == Enhanced)) {
337 if (ScanToAscii[Counter].NumLock) {
338 if ((KeyState & NUMLOCK_ON) &&
339 !(KeyState & SHIFT_PRESSED)) {
340 return ScanToAscii[Counter].NumLock;
341 } else {
342 return ScanToAscii[Counter].Normal;
343 }
344 }
345 if (KeyState & SHIFT_PRESSED)
346 return ScanToAscii[Counter].Shift;
347
348 return ScanToAscii[Counter].Normal;
349 }
350 Counter++;
351 }
352
353 return 0;
354 }
355
356 /* This is going to be quick and messy. The usetup app runs in native mode
357 * so it cannot use the translation routines in win32k which means it'll have
358 * to be done here too.
359 *
360 * Only the bKeyDown, AsciiChar and wVirtualKeyCode members are used
361 * in the app so I'll just fill the others with somewhat sane values
362 */
363 NTSTATUS
364 IntTranslateKey(PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
365 {
366 static DWORD dwControlKeyState;
367
368 RtlZeroMemory(Event, sizeof(KEY_EVENT_RECORD));
369
370 if (!(InputData->Flags & KEY_BREAK))
371 Event->bKeyDown = TRUE;
372 else
373 Event->bKeyDown = FALSE;
374
375 Event->wRepeatCount = 1;
376 Event->wVirtualScanCode = InputData->MakeCode;
377
378 DPRINT("Translating: %x\n", InputData->MakeCode);
379
380 IntUpdateControlKeyState(&dwControlKeyState, InputData);
381 Event->dwControlKeyState = dwControlKeyState;
382
383 if (InputData->Flags & KEY_E0)
384 Event->dwControlKeyState |= ENHANCED_KEY;
385
386 Event->wVirtualKeyCode = IntVKFromKbdInput(InputData,
387 Event->dwControlKeyState);
388
389 DPRINT("Result: %x\n", Event->wVirtualKeyCode);
390
391 if (Event->bKeyDown) {
392 Event->uChar.AsciiChar =
393 IntAsciiFromInput(InputData,
394 Event->dwControlKeyState);
395 DPRINT("Char: %x\n", Event->uChar.AsciiChar);
396 } else {
397 Event->uChar.AsciiChar = 0;
398 }
399
400 return STATUS_SUCCESS;
401 }