- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / base / applications / testsets / user32 / kbdlayout / kbdlayout.c
1 /*
2 * PROJECT: ReactOS
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/testset/user32/kbdlayout/kbdlayout.c
5 * PURPOSE: Keyboard layout testapp
6 * COPYRIGHT: Copyright 2007 Saveliy Tretiakov
7 */
8
9 #define UNICODE
10 #include<wchar.h>
11 #include <windows.h>
12 #include "resource.h"
13
14
15
16 LRESULT MainDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
17
18
19 HINSTANCE hInst;
20 HWND hMainDlg;
21
22
23 typedef struct {
24 WNDPROC OrigProc;
25 WCHAR WndName[25];
26 } WND_DATA;
27
28 DWORD WINAPI ThreadProc(LPVOID lpParam)
29 {
30
31 DialogBoxParam(hInst,
32 MAKEINTRESOURCE(IDD_MAINDIALOG),
33 NULL,
34 (DLGPROC)MainDialogProc,
35 (LPARAM)NULL);
36
37 return 0;
38 }
39
40 INT WINAPI WinMain(HINSTANCE hInstance,
41 HINSTANCE hPrevInstance,
42 LPSTR lpCmdLine,
43 int nCmdShow)
44 {
45
46
47 hInst = hInstance;
48
49 ThreadProc(0);
50
51 return 0;
52 }
53
54
55 int GetKlList(HKL **list)
56 {
57 HKL *ret;
58 int n;
59
60 n = GetKeyboardLayoutList(0, NULL);
61 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(HKL)*n);
62 GetKeyboardLayoutList(n, ret);
63 *list = ret;
64 return n;
65 }
66
67 void FreeKlList(HKL *list)
68 {
69 HeapFree(GetProcessHeap(), 0, list);
70 }
71
72
73 void UpdateData(HWND hDlg)
74 {
75 WCHAR buf[KL_NAMELENGTH];
76 WCHAR buf2[512];
77
78 HWND hList;
79 HKL *klList, hKl;
80 int n, i,j;
81
82 GetKeyboardLayoutName(buf);
83 swprintf(buf2, L"Active: %s (%x)", buf, GetKeyboardLayout(0));
84 SetWindowText(GetDlgItem(hDlg, IDC_ACTIVE), buf2);
85
86 hList = GetDlgItem(hDlg, IDC_LIST);
87 SendMessage(hList, LB_RESETCONTENT, 0, 0);
88
89 n = GetKlList(&klList);
90 hKl = GetKeyboardLayout(0);
91 for(i = 0; i < n; i++)
92 {
93 swprintf(buf, L"%x", klList[i] );
94 j = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM) buf);
95 SendMessage(hList, LB_SETITEMDATA, j, (LPARAM) klList[i]);
96 if(klList[i] == hKl) SendMessage(hList, LB_SETCURSEL, j, 0);
97 }
98
99 FreeKlList(klList);
100 }
101
102 void FormatMsg(WCHAR *format, ...)
103 {
104 WCHAR buf[255];
105 va_list argptr;
106 va_start(argptr, format);
107 _vsnwprintf(buf, sizeof(buf)-1, format, argptr);
108 MessageBox(0, buf, L"msg", 0);
109 va_end(argptr);
110 }
111
112 void FormatBox(HWND hWnd, DWORD Flags, WCHAR *Caption, WCHAR *Format, ...)
113 {
114 WCHAR buf[255];
115 va_list argptr;
116 va_start(argptr, Format);
117 _vsnwprintf(buf, sizeof(buf)-1, Format, argptr);
118 MessageBox(hWnd, buf, Caption, Flags);
119 va_end(argptr);
120 }
121
122
123 LRESULT CALLBACK WndSubclassProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
124 {
125 WND_DATA *data = (WND_DATA*)GetWindowLong(hwnd, GWL_USERDATA);
126
127 if(uMsg == WM_INPUTLANGCHANGE)
128 {
129 FormatMsg(L"%s: WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", data->WndName, lParam, wParam);
130 UpdateData(hMainDlg);
131 //Pass message to defwindowproc
132 }
133 else if(uMsg == WM_INPUTLANGCHANGEREQUEST)
134 {
135 FormatMsg(L"%s: WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", data->WndName, lParam, wParam);
136 UpdateData(hMainDlg);
137 //Pass message to defwindowproc
138 }
139
140 return ( CallWindowProc( data->OrigProc, hwnd, uMsg, wParam, lParam) );
141 }
142
143 void SubclassWnd(HWND hWnd, WCHAR* Name)
144 {
145 WND_DATA *data = HeapAlloc(GetProcessHeap(), 0, sizeof(WND_DATA));
146 data->OrigProc = (WNDPROC)SetWindowLong( hWnd, GWL_WNDPROC, (LONG)WndSubclassProc);
147 wcsncpy(data->WndName, Name, 25);
148 SetWindowLong(hWnd, GWL_USERDATA, (LONG)data);
149 return;
150 }
151
152 DWORD GetActivateFlags(HWND hDlg)
153 {
154 DWORD ret = 0;
155
156 if(IsDlgButtonChecked(hDlg, IDC_KLF_REORDER))
157 ret |= KLF_REORDER;
158
159 if(IsDlgButtonChecked(hDlg, IDC_KLF_RESET))
160 ret |= KLF_RESET;
161
162 if(IsDlgButtonChecked(hDlg, IDC_KLF_SHIFTLOCK))
163 ret |= KLF_SHIFTLOCK;
164
165 if(IsDlgButtonChecked(hDlg, IDC_KLF_SETFORPROCESS))
166 ret |= KLF_SETFORPROCESS;
167
168 return ret;
169
170 }
171
172 DWORD GetLoadFlags(HWND hDlg)
173 {
174 DWORD ret = 0;
175
176 if(IsDlgButtonChecked(hDlg, IDL_KLF_ACTIVATE))
177 ret |= KLF_ACTIVATE;
178
179 if(IsDlgButtonChecked(hDlg, IDL_KLF_NOTELLSHELL))
180 ret |= KLF_NOTELLSHELL;
181
182 if(IsDlgButtonChecked(hDlg, IDL_KLF_REORDER))
183 ret |= KLF_REORDER;
184
185 if(IsDlgButtonChecked(hDlg, IDL_KLF_REPLACELANG))
186 ret |= KLF_REPLACELANG;
187
188 if(IsDlgButtonChecked(hDlg, IDL_KLF_SUBSTITUTE_OK))
189 ret |= KLF_SUBSTITUTE_OK;
190
191 if(IsDlgButtonChecked(hDlg, IDL_KLF_SETFORPROCESS))
192 ret |= KLF_SETFORPROCESS;
193
194 return ret;
195 }
196
197 UINT GetDelayMilliseconds(HWND hDlg)
198 {
199 WCHAR Buf[255];
200 UINT ret;
201
202 GetWindowText(GetDlgItem(hDlg, IDC_DELAY), Buf, sizeof(Buf));
203
204 swscanf(Buf, L"%d", &ret);
205
206 return ret*1000;
207 }
208
209 HKL GetSelectedLayout(HWND hDlg)
210 {
211 int n;
212 HWND hList;
213 hList = GetDlgItem(hDlg, IDC_LIST);
214 if((n = SendMessage(hList, LB_GETCURSEL, 0, 0)) != LB_ERR)
215 return (HKL) SendMessage(hList, LB_GETITEMDATA, n, 0);
216 else return INVALID_HANDLE_VALUE;
217 }
218
219 HKL GetActivateHandle(HWND hDlg)
220 {
221
222 if(IsDlgButtonChecked(hDlg, IDC_FROMLIST))
223 return GetSelectedLayout(hDlg);
224 else if(IsDlgButtonChecked(hDlg, IDC_HKL_NEXT))
225 return (HKL)HKL_NEXT;
226
227 return (HKL)HKL_PREV;
228
229 }
230
231
232 /***************************************************
233 * MainDialogProc *
234 ***************************************************/
235
236 LRESULT MainDialogProc(HWND hDlg,
237 UINT Msg,
238 WPARAM wParam,
239 LPARAM lParam)
240 {
241 HKL hKl;
242
243 switch (Msg)
244 {
245 case WM_INITDIALOG:
246 {
247 WCHAR Buf[255];
248 UpdateData(hDlg);
249 hMainDlg = hDlg;
250
251 SubclassWnd(GetDlgItem(hDlg, IDC_LIST), L"List");
252 SubclassWnd(GetDlgItem(hDlg, IDC_EDIT1), L"Edit1");
253 SubclassWnd(GetDlgItem(hDlg, IDC_KLID), L"Klid");
254 SubclassWnd(GetDlgItem(hDlg, ID_CANCEL), L"CancelB");
255 SubclassWnd(GetDlgItem(hDlg, IDC_ACTIVATE), L"ActivateB");
256 SubclassWnd(GetDlgItem(hDlg, IDC_REFRESH), L"RefreshB");
257 SubclassWnd(GetDlgItem(hDlg, IDC_UNLOAD), L"UnloadB");
258 SubclassWnd(GetDlgItem(hDlg, IDC_LOAD), L"LoadB");
259
260 CheckRadioButton(hDlg, IDC_FROMLIST, IDC_FROMEDIT, IDC_FROMLIST);
261 SetWindowText(GetDlgItem(hDlg, IDC_KLID), L"00000419");
262
263 swprintf(Buf, L"Current thread id: %d", GetCurrentThreadId());
264 SetWindowText(GetDlgItem(hDlg, IDC_CURTHREAD), Buf);
265
266 SetWindowText(GetDlgItem(hDlg, IDC_DELAY), L"0");
267
268 return 0;
269 } /* WM_INITDIALOG */
270
271 case WM_COMMAND:
272 {
273 switch(LOWORD(wParam))
274 {
275 case ID_CANCEL:
276 {
277 EndDialog(hDlg, ERROR_CANCELLED);
278 break;
279 }
280
281 case IDC_ACTIVATE:
282 {
283 if((hKl = GetActivateHandle(hDlg)) != INVALID_HANDLE_VALUE)
284 {
285 Sleep(GetDelayMilliseconds(hDlg));
286 if(!(hKl = ActivateKeyboardLayout(hKl, GetActivateFlags(hDlg))))
287 FormatBox(hDlg, MB_ICONERROR, L"Error",
288 L"ActivateKeyboardLayout() failed. %d", GetLastError());
289 else UpdateData(hDlg);
290 //FormatBox(hDlg, 0, L"Activated", L"Prev - %x, err - %d.", hKl,
291 // GetLastError());
292 }
293 else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR);
294 break;
295 }
296
297 case IDC_UNLOAD:
298 {
299 if((hKl = GetSelectedLayout(hDlg)) != INVALID_HANDLE_VALUE)
300 {
301 Sleep(GetDelayMilliseconds(hDlg));
302 if(!UnloadKeyboardLayout(hKl))
303 FormatBox(hDlg, MB_ICONERROR, L"Error",
304 L"UnloadKeyboardLayout() failed. %d",
305 GetLastError());
306 else UpdateData(hDlg);
307 }
308 else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR);
309 break;
310 }
311
312 case IDC_LOAD:
313 {
314 WCHAR buf[255];
315 GetWindowText(GetDlgItem(hDlg, IDC_KLID), buf, sizeof(buf));
316 Sleep(GetDelayMilliseconds(hDlg));
317 if(!LoadKeyboardLayout(buf, GetLoadFlags(hDlg)))
318 FormatBox(hDlg, MB_ICONERROR, L"Error",
319 L"LoadKeyboardLayout() failed. %d",
320 GetLastError());
321 else UpdateData(hDlg);
322 break;
323 }
324
325 case IDC_REFRESH:
326 {
327 UpdateData(hDlg);
328 break;
329 }
330
331 case IDC_NEWTHREAD:
332 {
333 if(!CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL))
334 {
335 FormatBox(hDlg, MB_ICONERROR, L"Error!",
336 L"Can not create thread (%d).", GetLastError());
337 }
338 }
339
340 case IDC_LIST:
341 {
342 if(HIWORD(wParam) == LBN_SELCHANGE)
343 {
344 WCHAR buf[25];
345 if((hKl = GetSelectedLayout(hDlg)) != NULL)
346 {
347 swprintf(buf, L"%x", hKl);
348 SetWindowText(GetDlgItem(hDlg, IDC_HANDLE), buf);
349 }
350 }
351 break;
352 }
353
354 }
355
356 return TRUE;
357 } /* WM_COMMAND */
358
359
360 case WM_INPUTLANGCHANGE:
361 {
362 FormatMsg(L"dlg WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", lParam, wParam);
363 return FALSE;
364 }
365
366 case WM_INPUTLANGCHANGEREQUEST:
367 {
368 FormatMsg(L"dlg WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", lParam, wParam);
369 UpdateData(hDlg);
370 return FALSE;
371 }
372
373 case WM_CLOSE:
374 {
375 EndDialog(hDlg, ERROR_CANCELLED);
376 return TRUE;
377 } /* WM_CLOSE */
378
379 default:
380 return FALSE;
381 }
382
383 }
384
385
386
387