FreeRDP
Loading...
Searching...
No Matches
scancode.c
1
20#include <float.h>
21#include <math.h>
22
23#include <winpr/config.h>
24#include <winpr/assert.h>
25#include <winpr/crt.h>
26#include <winpr/path.h>
27#include <winpr/json.h>
28
29#include <winpr/input.h>
30
31#include "../log.h"
32#define TAG WINPR_TAG("input.scancode")
33
34#define KBD_ARRAY_SIZE 256
35
36#ifndef MIN
37#define MIN(x, y) (((x) < (y)) ? (x) : (y))
38#endif
39
40typedef struct
41{
42 DWORD multivk[KBD_ARRAY_SIZE];
43 DWORD kbdext[KBD_ARRAY_SIZE];
44 DWORD normal[KBD_ARRAY_SIZE];
45} ScancodeToVKMap_t;
46
47static const char KEYBOARD_CONFIG_FILE_NAME[] = "KeyboardMapping.json";
48static INIT_ONCE VKmapInitialized = INIT_ONCE_STATIC_INIT;
49static ScancodeToVKMap_t VKmap[8];
50
62static const DWORD KBD4T[KBD_ARRAY_SIZE] = {
63 KBD4_T00, KBD4_T01, KBD4_T02, KBD4_T03, KBD4_T04, KBD4_T05, KBD4_T06, KBD4_T07, KBD4_T08,
64 KBD4_T09, KBD4_T0A, KBD4_T0B, KBD4_T0C, KBD4_T0D, KBD4_T0E, KBD4_T0F, KBD4_T10, KBD4_T11,
65 KBD4_T12, KBD4_T13, KBD4_T14, KBD4_T15, KBD4_T16, KBD4_T17, KBD4_T18, KBD4_T19, KBD4_T1A,
66 KBD4_T1B, KBD4_T1C, KBD4_T1D, KBD4_T1E, KBD4_T1F, KBD4_T20, KBD4_T21, KBD4_T22, KBD4_T23,
67 KBD4_T24, KBD4_T25, KBD4_T26, KBD4_T27, KBD4_T28, KBD4_T29, KBD4_T2A, KBD4_T2B, KBD4_T2C,
68 KBD4_T2D, KBD4_T2E, KBD4_T2F, KBD4_T30, KBD4_T31, KBD4_T32, KBD4_T33, KBD4_T34, KBD4_T35,
69 KBD4_T36, KBD4_T37, KBD4_T38, KBD4_T39, KBD4_T3A, KBD4_T3B, KBD4_T3C, KBD4_T3D, KBD4_T3E,
70 KBD4_T3F, KBD4_T40, KBD4_T41, KBD4_T42, KBD4_T43, KBD4_T44, KBD4_T45, KBD4_T46, KBD4_T47,
71 KBD4_T48, KBD4_T49, KBD4_T4A, KBD4_T4B, KBD4_T4C, KBD4_T4D, KBD4_T4E, KBD4_T4F, KBD4_T50,
72 KBD4_T51, KBD4_T52, KBD4_T53, KBD4_T54, KBD4_T55, KBD4_T56, KBD4_T57, KBD4_T58, KBD4_T59,
73 KBD4_T5A, KBD4_T5B, KBD4_T5C, KBD4_T5D, KBD4_T5E, KBD4_T5F, KBD4_T60, KBD4_T61, KBD4_T62,
74 KBD4_T63, KBD4_T64, KBD4_T65, KBD4_T66, KBD4_T67, KBD4_T68, KBD4_T69, KBD4_T6A, KBD4_T6B,
75 KBD4_T6C, KBD4_T6D, KBD4_T6E, KBD4_T6F, KBD4_T70, KBD4_T71, KBD4_T72, KBD4_T73, KBD4_T74,
76 KBD4_T75, KBD4_T76, KBD4_T77, KBD4_T78, KBD4_T79, KBD4_T7A, KBD4_T7B, KBD4_T7C, KBD4_T7D,
77 KBD4_T7E, KBD4_T7F
78};
79
80static const DWORD KBD4X[KBD_ARRAY_SIZE] = {
81 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
82 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, KBD4_X10, VK_NONE,
83 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, KBD4_X19, VK_NONE,
84 VK_NONE, KBD4_X1C, KBD4_X1D, VK_NONE, VK_NONE, KBD4_X20, KBD4_X21, KBD4_X22, VK_NONE,
85 KBD4_X24, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
86 VK_NONE, KBD4_X2E, VK_NONE, KBD4_X30, VK_NONE, KBD4_X32, VK_NONE, VK_NONE, KBD4_X35,
87 VK_NONE, KBD4_X37, KBD4_X38, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
88 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, KBD4_X46, KBD4_X47,
89 KBD4_X48, KBD4_X49, VK_NONE, KBD4_X4B, VK_NONE, KBD4_X4D, VK_NONE, KBD4_X4F, KBD4_X50,
90 KBD4_X51, KBD4_X52, KBD4_X53, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
91 VK_NONE, KBD4_X5B, KBD4_X5C, KBD4_X5D, KBD4_X5E, KBD4_X5F, VK_NONE, VK_NONE, VK_NONE,
92 VK_NONE, VK_NONE, KBD4_X65, KBD4_X66, KBD4_X67, KBD4_X68, KBD4_X69, KBD4_X6A, KBD4_X6B,
93 KBD4_X6C, KBD4_X6D, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
94 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
95 VK_NONE, VK_NONE,
96};
97
98static const DWORD KBD4X_1[KBD_ARRAY_SIZE] = {
99 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
100 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
101 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_PAUSE,
102 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
103 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
104 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
105 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
106 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
107 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
108 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
109 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
110 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
111 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE
112};
113
121static const DWORD KBD7T[KBD_ARRAY_SIZE] = {
122 KBD7_T00, KBD7_T01, KBD7_T02, KBD7_T03, KBD7_T04, KBD7_T05, KBD7_T06, KBD7_T07, KBD7_T08,
123 KBD7_T09, KBD7_T0A, KBD7_T0B, KBD7_T0C, KBD7_T0D, KBD7_T0E, KBD7_T0F, KBD7_T10, KBD7_T11,
124 KBD7_T12, KBD7_T13, KBD7_T14, KBD7_T15, KBD7_T16, KBD7_T17, KBD7_T18, KBD7_T19, KBD7_T1A,
125 KBD7_T1B, KBD7_T1C, KBD7_T1D, KBD7_T1E, KBD7_T1F, KBD7_T20, KBD7_T21, KBD7_T22, KBD7_T23,
126 KBD7_T24, KBD7_T25, KBD7_T26, KBD7_T27, KBD7_T28, KBD7_T29, KBD7_T2A, KBD7_T2B, KBD7_T2C,
127 KBD7_T2D, KBD7_T2E, KBD7_T2F, KBD7_T30, KBD7_T31, KBD7_T32, KBD7_T33, KBD7_T34, KBD7_T35,
128 KBD7_T36, KBD7_T37, KBD7_T38, KBD7_T39, KBD7_T3A, KBD7_T3B, KBD7_T3C, KBD7_T3D, KBD7_T3E,
129 KBD7_T3F, KBD7_T40, KBD7_T41, KBD7_T42, KBD7_T43, KBD7_T44, KBD7_T45, KBD7_T46, KBD7_T47,
130 KBD7_T48, KBD7_T49, KBD7_T4A, KBD7_T4B, KBD7_T4C, KBD7_T4D, KBD7_T4E, KBD7_T4F, KBD7_T50,
131 KBD7_T51, KBD7_T52, KBD7_T53, KBD7_T54, KBD7_T55, KBD7_T56, KBD7_T57, KBD7_T58, KBD7_T59,
132 KBD7_T5A, KBD7_T5B, KBD7_T5C, KBD7_T5D, KBD7_T5E, KBD7_T5F, KBD7_T60, KBD7_T61, KBD7_T62,
133 KBD7_T63, KBD7_T64, KBD7_T65, KBD7_T66, KBD7_T67, KBD7_T68, KBD7_T69, KBD7_T6A, KBD7_T6B,
134 KBD7_T6C, KBD7_T6D, KBD7_T6E, KBD7_T6F, KBD7_T70, KBD7_T71, KBD7_T72, KBD7_T73, KBD7_T74,
135 KBD7_T75, KBD7_T76, KBD7_T77, KBD7_T78, KBD7_T79, KBD7_T7A, KBD7_T7B, KBD7_T7C, KBD7_T7D,
136 KBD7_T7E, KBD7_T7F
137};
138
139static const DWORD KBD7X[KBD_ARRAY_SIZE] = {
140 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
141 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, KBD7_X10, VK_NONE,
142 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, KBD7_X19, VK_NONE,
143 VK_NONE, KBD7_X1C, KBD7_X1D, VK_NONE, VK_NONE, KBD7_X20, KBD7_X21, KBD7_X22, VK_NONE,
144 KBD7_X24, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
145 VK_NONE, KBD7_X2E, VK_NONE, KBD7_X30, VK_NONE, KBD7_X32, KBD7_X33, VK_NONE, KBD7_X35,
146 VK_NONE, KBD7_X37, KBD7_X38, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
147 VK_NONE, VK_NONE, VK_NONE, KBD7_X42, KBD7_X43, KBD7_X44, VK_NONE, KBD7_X46, KBD7_X47,
148 KBD7_X48, KBD7_X49, VK_NONE, KBD7_X4B, VK_NONE, KBD7_X4D, VK_NONE, KBD7_X4F, KBD7_X50,
149 KBD7_X51, KBD7_X52, KBD7_X53, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
150 VK_NONE, KBD7_X5B, KBD7_X5C, KBD7_X5D, KBD7_X5E, KBD7_X5F, VK_NONE, VK_NONE, VK_NONE,
151 VK_NONE, VK_NONE, KBD7_X65, KBD7_X66, KBD7_X67, KBD7_X68, KBD7_X69, KBD7_X6A, KBD7_X6B,
152 KBD7_X6C, KBD7_X6D, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
153 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
154 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
155 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
156 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
157 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
158 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
159 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
160 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
161 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
162 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
163 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
164 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
165 KBD7_XF1, KBD7_XF2, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
166 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE
167};
168
169static const DWORD KBD7X_1[KBD_ARRAY_SIZE] = {
170 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
171 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
172 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_PAUSE,
173 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
174 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
175 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
176 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
177 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
178 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
179 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
180 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
181 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
182 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE
183};
184
191static const DWORD KBD8T[KBD_ARRAY_SIZE] = { // break here
192 VK_NONE, VK_ESCAPE,
193 VK_KEY_1, VK_KEY_2,
194 VK_KEY_3, VK_KEY_4,
195 VK_KEY_5, VK_KEY_6,
196 VK_KEY_7, VK_KEY_8,
197 VK_KEY_9, VK_KEY_0,
198 VK_OEM_MINUS, VK_OEM_PLUS,
199 VK_BACK, VK_TAB,
200 VK_KEY_Q, VK_KEY_W,
201 VK_KEY_E, VK_KEY_R,
202 VK_KEY_T, VK_KEY_Y,
203 VK_KEY_U, VK_KEY_I,
204 VK_KEY_O, VK_KEY_P,
205 VK_OEM_4, VK_OEM_6,
206 VK_RETURN, VK_LCONTROL,
207 VK_KEY_A, VK_KEY_S,
208 VK_KEY_D, VK_KEY_F,
209 VK_KEY_G, VK_KEY_H,
210 VK_KEY_J, VK_KEY_K,
211 VK_KEY_L, VK_OEM_1,
212 VK_OEM_7, VK_OEM_3,
213 VK_LSHIFT, VK_OEM_5,
214 VK_KEY_Z, VK_KEY_X,
215 VK_KEY_C, VK_KEY_V,
216 VK_KEY_B, VK_KEY_N,
217 VK_KEY_M, VK_OEM_COMMA,
218 VK_OEM_PERIOD, VK_OEM_2,
219 VK_RSHIFT, VK_MULTIPLY,
220 VK_LMENU, VK_SPACE,
221 VK_CAPITAL, VK_F1,
222 VK_F2, VK_F3,
223 VK_F4, VK_F5,
224 VK_F6, VK_F7,
225 VK_F8, VK_F9,
226 VK_F10, VK_NUMLOCK,
227 VK_SCROLL, VK_HOME,
228 VK_UP, VK_PRIOR,
229 VK_SUBTRACT, VK_LEFT,
230 VK_CLEAR, VK_RIGHT,
231 VK_ADD, VK_END,
232 VK_DOWN, VK_NEXT,
233 VK_INSERT, VK_DELETE,
234 VK_SNAPSHOT, VK_NONE,
235 VK_OEM_102, VK_F11,
236 VK_F12, VK_CLEAR,
237 VK_OEM_WSCTRL, VK_DBE_KATAKANA,
238 VK_OEM_JUMP, VK_DBE_FLUSHSTRING,
239 VK_OEM_BACKTAB, VK_OEM_AUTO,
240 VK_NONE, VK_DBE_NOCODEINPUT,
241 VK_HELP, VK_NONE,
242 VK_F13, VK_F14,
243 VK_F15, VK_F16,
244 VK_F17, VK_F18,
245 VK_F19, VK_F20,
246 VK_F21, VK_F22,
247 VK_F23, VK_OEM_PA3,
248 VK_NONE, VK_OEM_RESET,
249 VK_NONE, VK_ABNT_C1,
250 VK_NONE, VK_NONE,
251 VK_F24, VK_NONE,
252 VK_NONE, VK_NONE,
253 VK_NONE, VK_OEM_PA1,
254 VK_TAB, VK_NONE,
255 VK_ABNT_C2, VK_OEM_PA2
256};
257
258static const DWORD KBD8X[KBD_ARRAY_SIZE] = { // break here
259 VK_NONE,
260 VK_NONE,
261 VK_NONE,
262 VK_NONE,
263 VK_NONE,
264 VK_NONE,
265 VK_NONE,
266 VK_NONE,
267 VK_NONE,
268 VK_NONE,
269 VK_NONE,
270 VK_NONE,
271 VK_NONE,
272 VK_NONE,
273 VK_NONE,
274 VK_NONE,
275 VK_MEDIA_PREV_TRACK,
276 VK_NONE,
277 VK_NONE,
278 VK_NONE,
279 VK_NONE,
280 VK_NONE,
281 VK_NONE,
282 VK_NONE,
283 VK_NONE,
284 VK_MEDIA_NEXT_TRACK,
285 VK_NONE,
286 VK_NONE,
287 VK_RETURN,
288 VK_HANJA,
289 VK_NONE,
290 VK_NONE,
291 VK_VOLUME_MUTE,
292 VK_LAUNCH_APP2,
293 VK_MEDIA_PLAY_PAUSE,
294 VK_NONE,
295 VK_MEDIA_STOP,
296 VK_NONE,
297 VK_NONE,
298 VK_NONE,
299 VK_NONE,
300 VK_NONE,
301 VK_NONE,
302 VK_NONE,
303 VK_NONE,
304 VK_NONE,
305 VK_VOLUME_DOWN,
306 VK_NONE,
307 VK_VOLUME_UP,
308 VK_NONE,
309 VK_BROWSER_HOME,
310 VK_NONE,
311 VK_NONE,
312 VK_DIVIDE,
313 VK_NONE,
314 VK_SNAPSHOT,
315 VK_KANA,
316 VK_NONE,
317 VK_NONE,
318 VK_NONE,
319 VK_NONE,
320 VK_NONE,
321 VK_NONE,
322 VK_NONE,
323 VK_NONE,
324 VK_NONE,
325 VK_NONE,
326 VK_NONE,
327 VK_NONE,
328 VK_NONE,
329 VK_CANCEL,
330 VK_HOME,
331 VK_UP,
332 VK_PRIOR,
333 VK_NONE,
334 VK_LEFT,
335 VK_NONE,
336 VK_RIGHT,
337 VK_NONE,
338 VK_END,
339 VK_DOWN,
340 VK_NEXT,
341 VK_INSERT,
342 VK_DELETE,
343 VK_NONE,
344 VK_NONE,
345 VK_NONE,
346 VK_NONE,
347 VK_NONE,
348 VK_NONE,
349 VK_NONE,
350 VK_LWIN,
351 VK_RWIN,
352 VK_APPS,
353 VK_NONE,
354 VK_SLEEP,
355 VK_NONE,
356 VK_NONE,
357 VK_NONE,
358 VK_NONE,
359 VK_NONE,
360 VK_BROWSER_SEARCH,
361 VK_BROWSER_FAVORITES,
362 VK_BROWSER_REFRESH,
363 VK_BROWSER_STOP,
364 VK_BROWSER_FORWARD,
365 VK_BROWSER_BACK,
366 VK_LAUNCH_APP1,
367 VK_LAUNCH_MAIL,
368 VK_LAUNCH_MEDIA_SELECT,
369 VK_NONE,
370 VK_NONE,
371 VK_NONE,
372 VK_NONE,
373 VK_NONE,
374 VK_NONE,
375 VK_NONE,
376 VK_NONE,
377 VK_NONE,
378 VK_NONE,
379 VK_NONE,
380 VK_NONE,
381 VK_NONE,
382 VK_NONE,
383 VK_NONE,
384 VK_NONE,
385 VK_NONE,
386 VK_NONE,
387 VK_NONE,
388 VK_NONE,
389 VK_NONE,
390 VK_NONE,
391 VK_NONE,
392 VK_NONE,
393 VK_NONE,
394 VK_NONE,
395 VK_NONE,
396 VK_NONE,
397 VK_NONE,
398 VK_NONE,
399 VK_NONE,
400 VK_NONE,
401 VK_NONE,
402 VK_NONE,
403 VK_NONE,
404 VK_NONE,
405 VK_NONE,
406 VK_NONE,
407 VK_NONE,
408 VK_NONE,
409 VK_NONE,
410 VK_NONE,
411 VK_NONE,
412 VK_NONE,
413 VK_NONE,
414 VK_NONE,
415 VK_NONE,
416 VK_NONE,
417 VK_NONE,
418 VK_NONE,
419 VK_NONE,
420 VK_NONE,
421 VK_NONE,
422 VK_NONE,
423 VK_NONE,
424 VK_NONE,
425 VK_NONE,
426 VK_NONE,
427 VK_NONE,
428 VK_NONE,
429 VK_NONE,
430 VK_NONE,
431 VK_NONE,
432 VK_NONE,
433 VK_NONE,
434 VK_NONE,
435 VK_NONE,
436 VK_NONE,
437 VK_NONE,
438 VK_NONE,
439 VK_NONE,
440 VK_NONE,
441 VK_NONE,
442 VK_NONE,
443 VK_NONE,
444 VK_NONE,
445 VK_NONE,
446 VK_NONE,
447 VK_NONE,
448 VK_NONE,
449 VK_NONE,
450 VK_NONE,
451 VK_NONE,
452 VK_NONE,
453 VK_NONE,
454 VK_NONE,
455 VK_NONE,
456 VK_NONE,
457 VK_NONE,
458 VK_NONE,
459 VK_NONE,
460 VK_NONE,
461 VK_NONE,
462 VK_NONE,
463 VK_NONE,
464 VK_NONE,
465 VK_NONE,
466 VK_NONE,
467 VK_NONE,
468 VK_NONE,
469 VK_NONE,
470 VK_NONE,
471 VK_NONE,
472 VK_NONE,
473 VK_NONE,
474 VK_NONE,
475 VK_NONE,
476 VK_NONE,
477 VK_NONE,
478 VK_NONE,
479 VK_NONE,
480 VK_NONE,
481 VK_NONE,
482 VK_NONE,
483 VK_NONE,
484 VK_NONE,
485 VK_HANJA,
486 VK_KANA,
487 VK_NONE,
488 VK_NONE,
489 VK_NONE,
490 VK_NONE,
491 VK_NONE,
492 VK_NONE,
493 VK_NONE,
494 VK_NONE,
495 VK_NONE,
496 VK_NONE,
497 VK_NONE,
498 VK_NONE,
499 VK_NONE
500};
501
502static const DWORD KBD8X_1[KBD_ARRAY_SIZE] = {
503 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
504 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
505 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_PAUSE,
506 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
507 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
508 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
509 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
510 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
511 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
512 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
513 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
514 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE,
515 VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE, VK_NONE
516};
517
518WINPR_ATTR_NODISCARD
519static BOOL setup(void);
520
521WINPR_ATTR_NODISCARD
522static DWORD GetVirtualKeyCodeFromVirtualScanCodeMap(DWORD scancode, const ScancodeToVKMap_t* map)
523{
524 WINPR_ASSERT(map);
525 const DWORD codeIndex = scancode & 0xFF;
526
527 if (codeIndex > 127)
528 return VK_NONE;
529 if (scancode & KBDMULTIVK)
530 return map->multivk[codeIndex];
531 if (scancode & KBDEXT)
532 return map->kbdext[codeIndex];
533 return map->normal[codeIndex];
534}
535
536DWORD GetVirtualKeyCodeFromVirtualScanCode(DWORD scancode, DWORD dwKeyboardType)
537{
538 if (!setup())
539 return VK_NONE;
540
541 switch (dwKeyboardType)
542 {
543 /* IBM and compatible */
544 case WINPR_KBD_TYPE_IBM_PC_XT:
545 case WINPR_KBD_TYPE_OLIVETTI_ICO:
546 case WINPR_KBD_TYPE_IBM_PC_AT:
547 case WINPR_KBD_TYPE_IBM_ENHANCED:
548 case WINPR_KBD_TYPE_JAPANESE:
549 case WINPR_KBD_TYPE_KOREAN:
550 case WINPR_KBD_TYPE_NOKIA_1050:
551 case WINPR_KBD_TYPE_NOKIA_9140:
552 return GetVirtualKeyCodeFromVirtualScanCodeMap(scancode, &VKmap[dwKeyboardType - 1]);
553 default:
554 WLog_ERR(TAG, "dwKeyboardType=0x%08" PRIx32 " not supported", dwKeyboardType);
555 return VK_NONE;
556 }
557}
558
559WINPR_ATTR_NODISCARD
560static DWORD get_scancode(size_t offset, DWORD vkcode, const DWORD* array, size_t arraysize,
561 DWORD flag)
562{
563 WINPR_ASSERT(array);
564 for (size_t x = offset; x < arraysize; x++)
565 {
566 const DWORD cur = array[x];
567 if (cur == vkcode)
568 {
569 const DWORD sc = WINPR_ASSERTING_INT_CAST(DWORD, x);
570 if (sc == 0)
571 return 0;
572 return sc | flag;
573 }
574 }
575 return 0;
576}
577
578WINPR_ATTR_NODISCARD
579static DWORD get_scancodes(DWORD vkcode, const DWORD* array, size_t arraysize, DWORD flag,
580 DWORD* pdwScanCodeBuffer, size_t ScanCodeBufferSize)
581{
582 WINPR_ASSERT(array);
583 size_t offset = 0;
584 DWORD count = 0;
585
586 DWORD sc = 0;
587 const BOOL nobuffer = ScanCodeBufferSize == 0;
588 do
589 {
590 sc = get_scancode(offset, vkcode, array, arraysize, flag);
591 if (sc != 0)
592 {
593 if (!nobuffer)
594 {
595 if (count < ScanCodeBufferSize)
596 pdwScanCodeBuffer[count] = sc;
597 }
598 count++;
599 offset = (sc & ~flag) + 1;
600 }
601 } while ((sc != 0) && ((count < ScanCodeBufferSize) || nobuffer));
602
603 return count;
604}
605
606DWORD GetVirtualScanCodeFromVirtualKeyCode(DWORD vkcode, DWORD dwKeyboardType)
607{
608 DWORD scancodes[1] = WINPR_C_ARRAY_INIT;
609 const DWORD count = GetVirtualScanCodesFromVirtualKeyCode(vkcode, dwKeyboardType, scancodes,
610 ARRAYSIZE(scancodes));
611 if (count == 0)
612 return 0;
613 return scancodes[0];
614}
615
616WINPR_ATTR_NODISCARD
617static const char* kbdTypeStr(enum WINPR_KBD_TYPE type)
618{
619#define EVCASE(x) \
620 case x: \
621 return #x
622
623 switch (type)
624 {
625 EVCASE(WINPR_KBD_TYPE_IBM_PC_XT);
626 EVCASE(WINPR_KBD_TYPE_OLIVETTI_ICO);
627 EVCASE(WINPR_KBD_TYPE_IBM_PC_AT);
628 EVCASE(WINPR_KBD_TYPE_IBM_ENHANCED);
629 EVCASE(WINPR_KBD_TYPE_NOKIA_1050);
630 EVCASE(WINPR_KBD_TYPE_NOKIA_9140);
631 EVCASE(WINPR_KBD_TYPE_JAPANESE);
632 EVCASE(WINPR_KBD_TYPE_KOREAN);
633 default:
634 WLog_WARN(TAG, "Unsupported WINPR_KBD_TYPE %08" PRIx32, type);
635 return nullptr;
636 }
637#undef EVCASE
638}
639
640WINPR_ATTR_NODISCARD
641static DWORD VKStrToInteger(WINPR_JSON* val, size_t pos, const char* section)
642{
643 WINPR_ASSERT(section);
644
645 if (!val)
646 {
647 WLog_WARN(TAG, "[%s:%s at %" PRIuz "] invalid array entry, NULL value",
648 KEYBOARD_CONFIG_FILE_NAME, section, pos);
649 return VK_NONE;
650 }
651
652 if (WINPR_JSON_IsNumber(val))
653 {
654 const double nr = WINPR_JSON_GetNumberValue(val);
655 if (isnan(nr) || isinf(nr))
656 {
657 WLog_WARN(TAG, "[%s:%s at %" PRIuz "] invalid array entry, floating NaN/INF value %lf",
658 KEYBOARD_CONFIG_FILE_NAME, section, pos, nr);
659 return VK_NONE;
660 }
661 if (nr < 0.0)
662 {
663 WLog_WARN(TAG, "[%s:%s at %" PRIuz "] invalid array entry, negative value %lf",
664 KEYBOARD_CONFIG_FILE_NAME, section, pos, nr);
665 return VK_NONE;
666 }
667 return (DWORD)nr;
668 }
669
670 if (!WINPR_JSON_IsString(val))
671 {
672 WLog_WARN(TAG, "[%s:%s at %" PRIuz "] invalid array entry, not a string value",
673 KEYBOARD_CONFIG_FILE_NAME, section, pos);
674 return VK_NONE;
675 }
676
677 const char* strval = WINPR_JSON_GetStringValue(val);
678
679#define EVCASE(str, x) \
680 if (strcmp(#x, str) == 0) \
681 return x
682
683 EVCASE(strval, VK_LBUTTON);
684 EVCASE(strval, VK_RBUTTON);
685 EVCASE(strval, VK_CANCEL);
686 EVCASE(strval, VK_MBUTTON);
687 EVCASE(strval, VK_XBUTTON1);
688 EVCASE(strval, VK_XBUTTON2);
689 EVCASE(strval, VK_BACK);
690 EVCASE(strval, VK_TAB);
691 EVCASE(strval, VK_CLEAR);
692 EVCASE(strval, VK_RETURN);
693 EVCASE(strval, VK_SHIFT);
694 EVCASE(strval, VK_CONTROL);
695 EVCASE(strval, VK_MENU);
696 EVCASE(strval, VK_PAUSE);
697 EVCASE(strval, VK_CAPITAL);
698 EVCASE(strval, VK_KANA);
699 EVCASE(strval, VK_HANGUEL);
700 EVCASE(strval, VK_HANGUL);
701 EVCASE(strval, VK_IME_ON);
702 EVCASE(strval, VK_JUNJA);
703 EVCASE(strval, VK_FINAL);
704 EVCASE(strval, VK_HANJA);
705 EVCASE(strval, VK_KANJI);
706 EVCASE(strval, VK_HKTG);
707 EVCASE(strval, VK_IME_OFF);
708 EVCASE(strval, VK_ESCAPE);
709 EVCASE(strval, VK_CONVERT);
710 EVCASE(strval, VK_NONCONVERT);
711 EVCASE(strval, VK_ACCEPT);
712 EVCASE(strval, VK_MODECHANGE);
713 EVCASE(strval, VK_SPACE);
714 EVCASE(strval, VK_PRIOR);
715 EVCASE(strval, VK_NEXT);
716 EVCASE(strval, VK_END);
717 EVCASE(strval, VK_HOME);
718 EVCASE(strval, VK_LEFT);
719 EVCASE(strval, VK_UP);
720 EVCASE(strval, VK_RIGHT);
721 EVCASE(strval, VK_DOWN);
722 EVCASE(strval, VK_SELECT);
723 EVCASE(strval, VK_PRINT);
724 EVCASE(strval, VK_EXECUTE);
725 EVCASE(strval, VK_SNAPSHOT);
726 EVCASE(strval, VK_INSERT);
727 EVCASE(strval, VK_DELETE);
728 EVCASE(strval, VK_HELP);
729 EVCASE(strval, VK_KEY_0);
730 EVCASE(strval, VK_KEY_1);
731 EVCASE(strval, VK_KEY_2);
732 EVCASE(strval, VK_KEY_3);
733 EVCASE(strval, VK_KEY_4);
734 EVCASE(strval, VK_KEY_5);
735 EVCASE(strval, VK_KEY_6);
736 EVCASE(strval, VK_KEY_7);
737 EVCASE(strval, VK_KEY_8);
738 EVCASE(strval, VK_KEY_9);
739 EVCASE(strval, VK_KEY_A);
740 EVCASE(strval, VK_KEY_B);
741 EVCASE(strval, VK_KEY_C);
742 EVCASE(strval, VK_KEY_D);
743 EVCASE(strval, VK_KEY_E);
744 EVCASE(strval, VK_KEY_F);
745 EVCASE(strval, VK_KEY_G);
746 EVCASE(strval, VK_KEY_H);
747 EVCASE(strval, VK_KEY_I);
748 EVCASE(strval, VK_KEY_J);
749 EVCASE(strval, VK_KEY_K);
750 EVCASE(strval, VK_KEY_L);
751 EVCASE(strval, VK_KEY_M);
752 EVCASE(strval, VK_KEY_N);
753 EVCASE(strval, VK_KEY_O);
754 EVCASE(strval, VK_KEY_P);
755 EVCASE(strval, VK_KEY_Q);
756 EVCASE(strval, VK_KEY_R);
757 EVCASE(strval, VK_KEY_S);
758 EVCASE(strval, VK_KEY_T);
759 EVCASE(strval, VK_KEY_U);
760 EVCASE(strval, VK_KEY_V);
761 EVCASE(strval, VK_KEY_W);
762 EVCASE(strval, VK_KEY_X);
763 EVCASE(strval, VK_KEY_Y);
764 EVCASE(strval, VK_KEY_Z);
765 EVCASE(strval, VK_LWIN);
766 EVCASE(strval, VK_RWIN);
767 EVCASE(strval, VK_APPS);
768 EVCASE(strval, VK_POWER);
769 EVCASE(strval, VK_SLEEP);
770 EVCASE(strval, VK_NUMPAD0);
771 EVCASE(strval, VK_NUMPAD1);
772 EVCASE(strval, VK_NUMPAD2);
773 EVCASE(strval, VK_NUMPAD3);
774 EVCASE(strval, VK_NUMPAD4);
775 EVCASE(strval, VK_NUMPAD5);
776 EVCASE(strval, VK_NUMPAD6);
777 EVCASE(strval, VK_NUMPAD7);
778 EVCASE(strval, VK_NUMPAD8);
779 EVCASE(strval, VK_NUMPAD9);
780 EVCASE(strval, VK_MULTIPLY);
781 EVCASE(strval, VK_ADD);
782 EVCASE(strval, VK_SEPARATOR);
783 EVCASE(strval, VK_SUBTRACT);
784 EVCASE(strval, VK_DECIMAL);
785 EVCASE(strval, VK_DIVIDE);
786 EVCASE(strval, VK_F1);
787 EVCASE(strval, VK_F2);
788 EVCASE(strval, VK_F3);
789 EVCASE(strval, VK_F4);
790 EVCASE(strval, VK_F5);
791 EVCASE(strval, VK_F6);
792 EVCASE(strval, VK_F7);
793 EVCASE(strval, VK_F8);
794 EVCASE(strval, VK_F9);
795 EVCASE(strval, VK_F10);
796 EVCASE(strval, VK_F11);
797 EVCASE(strval, VK_F12);
798 EVCASE(strval, VK_F13);
799 EVCASE(strval, VK_F14);
800 EVCASE(strval, VK_F15);
801 EVCASE(strval, VK_F16);
802 EVCASE(strval, VK_F17);
803 EVCASE(strval, VK_F18);
804 EVCASE(strval, VK_F19);
805 EVCASE(strval, VK_F20);
806 EVCASE(strval, VK_F21);
807 EVCASE(strval, VK_F22);
808 EVCASE(strval, VK_F23);
809 EVCASE(strval, VK_F24);
810 EVCASE(strval, VK_NUMLOCK);
811 EVCASE(strval, VK_SCROLL);
812 EVCASE(strval, VK_LSHIFT);
813 EVCASE(strval, VK_RSHIFT);
814 EVCASE(strval, VK_LCONTROL);
815 EVCASE(strval, VK_RCONTROL);
816 EVCASE(strval, VK_LMENU);
817 EVCASE(strval, VK_RMENU);
818 EVCASE(strval, VK_BROWSER_BACK);
819 EVCASE(strval, VK_BROWSER_FORWARD);
820 EVCASE(strval, VK_BROWSER_REFRESH);
821 EVCASE(strval, VK_BROWSER_STOP);
822 EVCASE(strval, VK_BROWSER_SEARCH);
823 EVCASE(strval, VK_BROWSER_FAVORITES);
824 EVCASE(strval, VK_BROWSER_HOME);
825 EVCASE(strval, VK_VOLUME_MUTE);
826 EVCASE(strval, VK_VOLUME_DOWN);
827 EVCASE(strval, VK_VOLUME_UP);
828 EVCASE(strval, VK_MEDIA_NEXT_TRACK);
829 EVCASE(strval, VK_MEDIA_PREV_TRACK);
830 EVCASE(strval, VK_MEDIA_STOP);
831 EVCASE(strval, VK_MEDIA_PLAY_PAUSE);
832 EVCASE(strval, VK_LAUNCH_MAIL);
833 EVCASE(strval, VK_MEDIA_SELECT);
834 EVCASE(strval, VK_LAUNCH_MEDIA_SELECT);
835 EVCASE(strval, VK_LAUNCH_APP1);
836 EVCASE(strval, VK_LAUNCH_APP2);
837 EVCASE(strval, VK_OEM_1);
838 EVCASE(strval, VK_OEM_PLUS);
839 EVCASE(strval, VK_OEM_COMMA);
840 EVCASE(strval, VK_OEM_MINUS);
841 EVCASE(strval, VK_OEM_PERIOD);
842 EVCASE(strval, VK_OEM_2);
843 EVCASE(strval, VK_OEM_3);
844 EVCASE(strval, VK_ABNT_C1);
845 EVCASE(strval, VK_ABNT_C2);
846 EVCASE(strval, VK_OEM_4);
847 EVCASE(strval, VK_OEM_5);
848 EVCASE(strval, VK_OEM_6);
849 EVCASE(strval, VK_OEM_7);
850 EVCASE(strval, VK_OEM_8);
851 EVCASE(strval, VK_OEM_AX);
852 EVCASE(strval, VK_OEM_102);
853 EVCASE(strval, VK_PROCESSKEY);
854 EVCASE(strval, VK_PACKET);
855 EVCASE(strval, VK_OEM_RESET);
856 EVCASE(strval, VK_OEM_JUMP);
857 EVCASE(strval, VK_OEM_PA1);
858 EVCASE(strval, VK_OEM_PA2);
859 EVCASE(strval, VK_OEM_PA3);
860 EVCASE(strval, VK_OEM_WSCTRL);
861 EVCASE(strval, VK_OEM_CUSEL);
862 EVCASE(strval, VK_OEM_ATTN);
863 EVCASE(strval, VK_OEM_FINISH);
864 EVCASE(strval, VK_OEM_COPY);
865 EVCASE(strval, VK_OEM_AUTO);
866 EVCASE(strval, VK_OEM_ENLW);
867 EVCASE(strval, VK_OEM_BACKTAB);
868 EVCASE(strval, VK_ATTN);
869 EVCASE(strval, VK_CRSEL);
870 EVCASE(strval, VK_EXSEL);
871 EVCASE(strval, VK_EREOF);
872 EVCASE(strval, VK_PLAY);
873 EVCASE(strval, VK_ZOOM);
874 EVCASE(strval, VK_NONAME);
875 EVCASE(strval, VK_PA1);
876 EVCASE(strval, VK_OEM_CLEAR);
877 EVCASE(strval, VK_NONE);
878 EVCASE(strval, VK_DBE_ALPHANUMERIC);
879 EVCASE(strval, VK_DBE_KATAKANA);
880 EVCASE(strval, VK_DBE_HIRAGANA);
881 EVCASE(strval, VK_DBE_SBCSCHAR);
882 EVCASE(strval, VK_DBE_DBCSCHAR);
883 EVCASE(strval, VK_DBE_ROMAN);
884 EVCASE(strval, VK_DBE_NOROMAN);
885 EVCASE(strval, VK_DBE_ENTERWORDREGISTERMODE);
886 EVCASE(strval, VK_DBE_ENTERIMECONFIGMODE);
887 EVCASE(strval, VK_DBE_FLUSHSTRING);
888 EVCASE(strval, VK_DBE_CODEINPUT);
889 EVCASE(strval, VK_DBE_NOCODEINPUT);
890
891 WLog_WARN(TAG, "[%s:%s at %" PRIuz "] invalid array entry, unknown value '%s'",
892 KEYBOARD_CONFIG_FILE_NAME, section, pos, strval);
893 return VK_NONE;
894}
895
896static void loadKeyboardTypeArray(WINPR_JSON* json, const char* section, DWORD* array, size_t count)
897{
898 WINPR_ASSERT(section);
899
900 if (!json || !WINPR_JSON_IsArray(json))
901 {
902 WLog_WARN(TAG, "[%s:%s] invalid section entry, NULL or not a JSON array",
903 KEYBOARD_CONFIG_FILE_NAME, section);
904 return;
905 }
906
907 WINPR_ASSERT(array || (count == 0));
908
909 for (size_t x = 0; x < MIN(WINPR_JSON_GetArraySize(json), count); x++)
910 {
911 WINPR_JSON* vk = WINPR_JSON_GetArrayItem(json, x);
912 const DWORD val = VKStrToInteger(vk, x, section);
913 array[x] = val;
914 }
915}
916
917static void loadKeyboardType(WINPR_JSON* json, enum WINPR_KBD_TYPE type)
918{
919 WINPR_ASSERT(json);
920 WINPR_ASSERT(WINPR_JSON_IsObject(json));
921
922 WINPR_JSON* entry = WINPR_JSON_GetObjectItemCaseSensitive(json, kbdTypeStr(type));
923 if (!entry || !WINPR_JSON_IsObject(entry))
924 {
925 WLog_WARN(
926 TAG,
927 "[%s] configuration file, no entry for keyboard type '%s' or element not a JSON Object",
928 KEYBOARD_CONFIG_FILE_NAME, kbdTypeStr(type));
929 return;
930 }
931
932 ScancodeToVKMap_t* cur = &VKmap[type - 1];
933
934 WINPR_JSON* multivk = WINPR_JSON_GetObjectItemCaseSensitive(entry, "multivk");
935 loadKeyboardTypeArray(multivk, "multivk", cur->multivk, ARRAYSIZE(cur->multivk));
936
937 WINPR_JSON* kbdext = WINPR_JSON_GetObjectItemCaseSensitive(entry, "kbdext");
938 loadKeyboardTypeArray(kbdext, "kbdext", cur->kbdext, ARRAYSIZE(cur->kbdext));
939
940 WINPR_JSON* normal = WINPR_JSON_GetObjectItemCaseSensitive(entry, "normal");
941 loadKeyboardTypeArray(normal, "normal", cur->normal, ARRAYSIZE(cur->normal));
942}
943
944WINPR_ATTR_NODISCARD
945static BOOL CALLBACK loadFromSettings(WINPR_ATTR_UNUSED PINIT_ONCE InitOnce,
946 WINPR_ATTR_UNUSED PVOID Parameter,
947 WINPR_ATTR_UNUSED PVOID* Context)
948{
949 WINPR_STATIC_ASSERT(ARRAYSIZE(VKmap) >= WINPR_KBD_TYPE_KOREAN);
950 {
951 ScancodeToVKMap_t* cur = &VKmap[WINPR_KBD_TYPE_IBM_PC_XT - 1];
952
953 WINPR_STATIC_ASSERT(sizeof(KBD4X_1) == sizeof(cur->multivk));
954 WINPR_STATIC_ASSERT(sizeof(KBD4X) == sizeof(cur->kbdext));
955 WINPR_STATIC_ASSERT(sizeof(KBD4T) == sizeof(cur->normal));
956 WINPR_STATIC_ASSERT(sizeof(ScancodeToVKMap_t) == sizeof(VKmap[0]));
957
958 memcpy(cur->multivk, KBD4X_1, sizeof(KBD4X_1));
959 memcpy(cur->kbdext, KBD4X, sizeof(KBD4X));
960 memcpy(cur->normal, KBD4T, sizeof(KBD4T));
961
962 memcpy(&VKmap[WINPR_KBD_TYPE_OLIVETTI_ICO - 1], cur, sizeof(ScancodeToVKMap_t));
963 memcpy(&VKmap[WINPR_KBD_TYPE_IBM_PC_AT - 1], cur, sizeof(ScancodeToVKMap_t));
964 memcpy(&VKmap[WINPR_KBD_TYPE_IBM_ENHANCED - 1], cur, sizeof(ScancodeToVKMap_t));
965 }
966 {
967 ScancodeToVKMap_t* cur = &VKmap[WINPR_KBD_TYPE_NOKIA_1050 - 1];
968 for (size_t x = 0; x < ARRAYSIZE(cur->multivk); x++)
969 cur->multivk[x] = VK_NONE;
970 for (size_t x = 0; x < ARRAYSIZE(cur->kbdext); x++)
971 cur->kbdext[x] = VK_NONE;
972 for (size_t x = 0; x < ARRAYSIZE(cur->normal); x++)
973 cur->normal[x] = VK_NONE;
974
975 memcpy(&VKmap[WINPR_KBD_TYPE_NOKIA_9140 - 1], cur, sizeof(ScancodeToVKMap_t));
976 }
977 {
978 ScancodeToVKMap_t* cur = &VKmap[WINPR_KBD_TYPE_JAPANESE - 1];
979
980 WINPR_STATIC_ASSERT(sizeof(KBD7X_1) == sizeof(cur->multivk));
981 WINPR_STATIC_ASSERT(sizeof(KBD7X) == sizeof(cur->kbdext));
982 WINPR_STATIC_ASSERT(sizeof(KBD7T) == sizeof(cur->normal));
983
984 memcpy(cur->multivk, KBD7X_1, sizeof(KBD7X_1));
985 memcpy(cur->kbdext, KBD7X, sizeof(KBD7X));
986 memcpy(cur->normal, KBD7T, sizeof(KBD7T));
987 }
988 {
989 ScancodeToVKMap_t* cur = &VKmap[WINPR_KBD_TYPE_KOREAN - 1];
990
991 WINPR_STATIC_ASSERT(sizeof(KBD8X_1) == sizeof(cur->multivk));
992 WINPR_STATIC_ASSERT(sizeof(KBD8X) == sizeof(cur->kbdext));
993 WINPR_STATIC_ASSERT(sizeof(KBD8T) == sizeof(cur->normal));
994
995 memcpy(cur->multivk, KBD8X_1, sizeof(KBD8X_1));
996 memcpy(cur->kbdext, KBD8X, sizeof(KBD8X));
997 memcpy(cur->normal, KBD8T, sizeof(KBD8T));
998 }
999
1000 char* filename = GetCombinedPath(WINPR_RESOURCE_ROOT, KEYBOARD_CONFIG_FILE_NAME);
1001 if (!filename || !winpr_PathFileExists(filename))
1002 {
1003 WLog_DBG(TAG, "[%s] configuration file does not exist at %s, skipping...",
1004 KEYBOARD_CONFIG_FILE_NAME, filename);
1005 free(filename);
1006 return TRUE;
1007 }
1008 WINPR_JSON* json = WINPR_JSON_ParseFromFile(filename);
1009 free(filename);
1010 if (!json || !WINPR_JSON_IsObject(json))
1011 {
1012 WLog_WARN(TAG,
1013 "[%s] invalid JSON configuration at top level, element NULL or not a JSON Object",
1014 KEYBOARD_CONFIG_FILE_NAME);
1015 }
1016 else
1017 {
1018 loadKeyboardType(json, WINPR_KBD_TYPE_IBM_PC_XT);
1019 loadKeyboardType(json, WINPR_KBD_TYPE_OLIVETTI_ICO);
1020 loadKeyboardType(json, WINPR_KBD_TYPE_IBM_PC_AT);
1021 loadKeyboardType(json, WINPR_KBD_TYPE_IBM_ENHANCED);
1022 loadKeyboardType(json, WINPR_KBD_TYPE_NOKIA_1050);
1023 loadKeyboardType(json, WINPR_KBD_TYPE_NOKIA_9140);
1024 loadKeyboardType(json, WINPR_KBD_TYPE_JAPANESE);
1025 loadKeyboardType(json, WINPR_KBD_TYPE_KOREAN);
1026 }
1027 WINPR_JSON_Delete(json);
1028 return TRUE;
1029}
1030
1031BOOL setup(void)
1032{
1033 return InitOnceExecuteOnce(&VKmapInitialized, loadFromSettings, nullptr, nullptr);
1034}
1035
1036WINPR_ATTR_NODISCARD
1037static DWORD GetVirtualScanCodesFromVirtualKeyCodeMap(DWORD vkcode, const ScancodeToVKMap_t* map,
1038 DWORD* pdwScanCodeBuffer,
1039 size_t ScanCodeBufferSize)
1040{
1041 WINPR_ASSERT(map);
1042 DWORD codeIndex = vkcode & 0xFF;
1043 if (codeIndex == VK_NONE)
1044 return 0;
1045
1046 if (vkcode & KBDMULTIVK)
1047 return get_scancodes(codeIndex, map->multivk, ARRAYSIZE(map->multivk), KBDMULTIVK,
1048 pdwScanCodeBuffer, ScanCodeBufferSize);
1049 if (vkcode & KBDEXT)
1050 return get_scancodes(codeIndex, map->kbdext, ARRAYSIZE(map->kbdext), KBDEXT,
1051 pdwScanCodeBuffer, ScanCodeBufferSize);
1052
1053 return get_scancodes(codeIndex, map->normal, ARRAYSIZE(map->normal), 0, pdwScanCodeBuffer,
1054 ScanCodeBufferSize);
1055}
1056
1057DWORD GetVirtualScanCodesFromVirtualKeyCode(DWORD vkcode, DWORD /* WINPR_KBD_TYPE */ dwKeyboardType,
1058 DWORD* pdwScanCodeBuffer, size_t ScanCodeBufferSize)
1059{
1060 if (!setup())
1061 return 0;
1062
1063 switch (dwKeyboardType)
1064 {
1065 case WINPR_KBD_TYPE_IBM_PC_XT:
1066 case WINPR_KBD_TYPE_OLIVETTI_ICO:
1067 case WINPR_KBD_TYPE_IBM_PC_AT:
1068 case WINPR_KBD_TYPE_IBM_ENHANCED:
1069 case WINPR_KBD_TYPE_JAPANESE:
1070 case WINPR_KBD_TYPE_KOREAN:
1071 case WINPR_KBD_TYPE_NOKIA_1050:
1072 case WINPR_KBD_TYPE_NOKIA_9140:
1073 return GetVirtualScanCodesFromVirtualKeyCodeMap(vkcode, &VKmap[dwKeyboardType - 1],
1074 pdwScanCodeBuffer, ScanCodeBufferSize);
1075 default:
1076 WLog_ERR(TAG, "dwKeyboardType=0x%08" PRIx32 " not supported", dwKeyboardType);
1077 return 0;
1078 }
1079}
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsNumber(const WINPR_JSON *item)
Check if JSON item is of type Number.
Definition c-json.c:177
WINPR_ATTR_NODISCARD WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
Definition c-json.c:114
WINPR_API WINPR_JSON * WINPR_JSON_ParseFromFile(const char *filename)
Parse a JSON string read from a file filename.
Definition json.c:27
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON *object, const char *string)
Same as WINPR_JSON_GetObjectItem but with case sensitive matching.
Definition c-json.c:127
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
Definition c-json.c:182
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
Definition c-json.c:108
WINPR_ATTR_NODISCARD WINPR_API double WINPR_JSON_GetNumberValue(const WINPR_JSON *item)
Return the Number value of a JSON item.
Definition c-json.c:147
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
Definition c-json.c:187
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
Definition c-json.c:192
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
Definition c-json.c:103
WINPR_ATTR_NODISCARD WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
Definition c-json.c:142