gameux: Loading of game statistics implemented.
[wine] / dlls / user32 / input.c
1 /*
2  * USER Input processing
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <assert.h>
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41 #include "winnls.h"
42 #include "winternl.h"
43 #include "winerror.h"
44 #include "win.h"
45 #include "user_private.h"
46 #include "wine/server.h"
47 #include "wine/debug.h"
48 #include "wine/unicode.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(win);
51 WINE_DECLARE_DEBUG_CHANNEL(keyboard);
52
53
54 /***********************************************************************
55  *           get_key_state
56  */
57 static WORD get_key_state(void)
58 {
59     WORD ret = 0;
60
61     if (GetSystemMetrics( SM_SWAPBUTTON ))
62     {
63         if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
64         if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
65     }
66     else
67     {
68         if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
69         if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
70     }
71     if (GetAsyncKeyState(VK_MBUTTON) & 0x80)  ret |= MK_MBUTTON;
72     if (GetAsyncKeyState(VK_SHIFT) & 0x80)    ret |= MK_SHIFT;
73     if (GetAsyncKeyState(VK_CONTROL) & 0x80)  ret |= MK_CONTROL;
74     if (GetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
75     if (GetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
76     return ret;
77 }
78
79
80 /**********************************************************************
81  *              set_capture_window
82  */
83 BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
84 {
85     HWND previous = 0;
86     UINT flags = 0;
87     BOOL ret;
88
89     if (gui_flags & GUI_INMENUMODE) flags |= CAPTURE_MENU;
90     if (gui_flags & GUI_INMOVESIZE) flags |= CAPTURE_MOVESIZE;
91
92     SERVER_START_REQ( set_capture_window )
93     {
94         req->handle = wine_server_user_handle( hwnd );
95         req->flags  = flags;
96         if ((ret = !wine_server_call_err( req )))
97         {
98             previous = wine_server_ptr_handle( reply->previous );
99             hwnd = wine_server_ptr_handle( reply->full_handle );
100         }
101     }
102     SERVER_END_REQ;
103
104     if (ret)
105     {
106         USER_Driver->pSetCapture( hwnd, gui_flags );
107
108         if (previous && previous != hwnd)
109             SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
110
111         if (prev_ret) *prev_ret = previous;
112     }
113     return ret;
114 }
115
116
117 /***********************************************************************
118  *              SendInput  (USER32.@)
119  */
120 UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
121 {
122     if (TRACE_ON(win))
123     {
124         UINT i;
125
126         for (i = 0; i < count; i++)
127         {
128             switch(inputs[i].type)
129             {
130             case INPUT_MOUSE:
131                 TRACE("mouse: dx %d, dy %d, data %x, flags %x, time %u, info %lx\n",
132                       inputs[i].u.mi.dx, inputs[i].u.mi.dy, inputs[i].u.mi.mouseData,
133                       inputs[i].u.mi.dwFlags, inputs[i].u.mi.time, inputs[i].u.mi.dwExtraInfo);
134                 break;
135
136             case INPUT_KEYBOARD:
137                 TRACE("keyboard: vk %X, scan %x, flags %x, time %u, info %lx\n",
138                       inputs[i].u.ki.wVk, inputs[i].u.ki.wScan, inputs[i].u.ki.dwFlags,
139                       inputs[i].u.ki.time, inputs[i].u.ki.dwExtraInfo);
140                 break;
141
142             case INPUT_HARDWARE:
143                 TRACE("hardware: msg %d, wParamL %x, wParamH %x\n",
144                       inputs[i].u.hi.uMsg, inputs[i].u.hi.wParamL, inputs[i].u.hi.wParamH);
145                 break;
146
147             default:
148                 FIXME("unknown input type %u\n", inputs[i].type);
149                 break;
150             }
151         }
152     }
153
154     return USER_Driver->pSendInput( count, inputs, size );
155 }
156
157
158 /***********************************************************************
159  *              keybd_event (USER32.@)
160  */
161 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
162                          DWORD dwFlags, ULONG_PTR dwExtraInfo )
163 {
164     INPUT input;
165
166     input.type = INPUT_KEYBOARD;
167     input.u.ki.wVk = bVk;
168     input.u.ki.wScan = bScan;
169     input.u.ki.dwFlags = dwFlags;
170     input.u.ki.time = 0;
171     input.u.ki.dwExtraInfo = dwExtraInfo;
172     SendInput( 1, &input, sizeof(input) );
173 }
174
175
176 /***********************************************************************
177  *              mouse_event (USER32.@)
178  */
179 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
180                          DWORD dwData, ULONG_PTR dwExtraInfo )
181 {
182     INPUT input;
183
184     input.type = INPUT_MOUSE;
185     input.u.mi.dx = dx;
186     input.u.mi.dy = dy;
187     input.u.mi.mouseData = dwData;
188     input.u.mi.dwFlags = dwFlags;
189     input.u.mi.time = 0;
190     input.u.mi.dwExtraInfo = dwExtraInfo;
191     SendInput( 1, &input, sizeof(input) );
192 }
193
194
195 /***********************************************************************
196  *              GetCursorPos (USER32.@)
197  */
198 BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
199 {
200     if (!pt) return FALSE;
201     return USER_Driver->pGetCursorPos( pt );
202 }
203
204
205 /***********************************************************************
206  *              GetCursorInfo (USER32.@)
207  */
208 BOOL WINAPI GetCursorInfo( PCURSORINFO pci )
209 {
210     BOOL ret;
211
212     if (!pci) return 0;
213
214     SERVER_START_REQ( get_thread_input )
215     {
216         req->tid = 0;
217         if ((ret = !wine_server_call( req )))
218         {
219             pci->hCursor = wine_server_ptr_handle( reply->cursor );
220             pci->flags = (reply->show_count >= 0) ? CURSOR_SHOWING : 0;
221         }
222     }
223     SERVER_END_REQ;
224     GetCursorPos(&pci->ptScreenPos);
225     return ret;
226 }
227
228
229 /***********************************************************************
230  *              SetCursorPos (USER32.@)
231  */
232 BOOL WINAPI DECLSPEC_HOTPATCH SetCursorPos( INT x, INT y )
233 {
234     return USER_Driver->pSetCursorPos( x, y );
235 }
236
237
238 /**********************************************************************
239  *              SetCapture (USER32.@)
240  */
241 HWND WINAPI DECLSPEC_HOTPATCH SetCapture( HWND hwnd )
242 {
243     HWND previous = 0;
244
245     set_capture_window( hwnd, 0, &previous );
246     return previous;
247 }
248
249
250 /**********************************************************************
251  *              ReleaseCapture (USER32.@)
252  */
253 BOOL WINAPI DECLSPEC_HOTPATCH ReleaseCapture(void)
254 {
255     BOOL ret = set_capture_window( 0, 0, NULL );
256
257     /* Somebody may have missed some mouse movements */
258     if (ret) mouse_event( MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
259
260     return ret;
261 }
262
263
264 /**********************************************************************
265  *              GetCapture (USER32.@)
266  */
267 HWND WINAPI GetCapture(void)
268 {
269     HWND ret = 0;
270
271     SERVER_START_REQ( get_thread_input )
272     {
273         req->tid = GetCurrentThreadId();
274         if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->capture );
275     }
276     SERVER_END_REQ;
277     return ret;
278 }
279
280
281 /**********************************************************************
282  *              GetAsyncKeyState (USER32.@)
283  *
284  *      Determine if a key is or was pressed.  retval has high-order
285  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
286  * been pressed.
287  */
288 SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState(INT nKey)
289 {
290     if (nKey < 0 || nKey > 256)
291         return 0;
292     return USER_Driver->pGetAsyncKeyState( nKey );
293 }
294
295
296 /***********************************************************************
297  *              GetQueueStatus (USER32.@)
298  */
299 DWORD WINAPI GetQueueStatus( UINT flags )
300 {
301     DWORD ret = 0;
302
303     if (flags & ~(QS_ALLINPUT | QS_ALLPOSTMESSAGE | QS_SMRESULT))
304     {
305         SetLastError( ERROR_INVALID_FLAGS );
306         return 0;
307     }
308
309     /* check for pending X events */
310     USER_Driver->pMsgWaitForMultipleObjectsEx( 0, NULL, 0, flags, 0 );
311
312     SERVER_START_REQ( get_queue_status )
313     {
314         req->clear = 1;
315         wine_server_call( req );
316         ret = MAKELONG( reply->changed_bits & flags, reply->wake_bits & flags );
317     }
318     SERVER_END_REQ;
319     return ret;
320 }
321
322
323 /***********************************************************************
324  *              GetInputState   (USER32.@)
325  */
326 BOOL WINAPI GetInputState(void)
327 {
328     DWORD ret = 0;
329
330     /* check for pending X events */
331     USER_Driver->pMsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_INPUT, 0 );
332
333     SERVER_START_REQ( get_queue_status )
334     {
335         req->clear = 0;
336         wine_server_call( req );
337         ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
338     }
339     SERVER_END_REQ;
340     return ret;
341 }
342
343
344 /******************************************************************
345  *              GetLastInputInfo (USER32.@)
346  */
347 BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii)
348 {
349     BOOL ret;
350
351     TRACE("%p\n", plii);
352
353     if (plii->cbSize != sizeof (*plii) )
354     {
355         SetLastError(ERROR_INVALID_PARAMETER);
356         return FALSE;
357     }
358
359     SERVER_START_REQ( get_last_input_time )
360     {
361         ret = !wine_server_call_err( req );
362         if (ret)
363             plii->dwTime = reply->time;
364     }
365     SERVER_END_REQ;
366     return ret;
367 }
368
369
370 /******************************************************************
371 *               GetRawInputDeviceList (USER32.@)
372 */
373 UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize)
374 {
375     FIXME("(pRawInputDeviceList=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDeviceList, puiNumDevices, cbSize);
376
377     if(pRawInputDeviceList)
378         memset(pRawInputDeviceList, 0, sizeof *pRawInputDeviceList);
379     *puiNumDevices = 0;
380     return 0;
381 }
382
383
384 /******************************************************************
385 *               RegisterRawInputDevices (USER32.@)
386 */
387 BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
388 {
389     FIXME("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d) stub!\n", pRawInputDevices, uiNumDevices, cbSize);
390
391     return TRUE;
392 }
393
394
395 /******************************************************************
396 *               GetRawInputData (USER32.@)
397 */
398 UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader)
399 {
400     FIXME("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n",
401             hRawInput, uiCommand, pData, pcbSize, cbSizeHeader);
402
403     return 0;
404 }
405
406
407 /******************************************************************
408 *               GetRawInputBuffer (USER32.@)
409 */
410 UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader)
411 {
412     FIXME("(pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", pData, pcbSize, cbSizeHeader);
413
414     return 0;
415 }
416
417
418 /******************************************************************
419 *               GetRawInputDeviceInfoA (USER32.@)
420 */
421 UINT WINAPI GetRawInputDeviceInfoA(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize)
422 {
423     FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize);
424
425     return 0;
426 }
427
428
429 /******************************************************************
430 *               GetRawInputDeviceInfoW (USER32.@)
431 */
432 UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize)
433 {
434     FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize);
435
436     return 0;
437 }
438
439
440 /******************************************************************
441 *               GetRegisteredRawInputDevices (USER32.@)
442 */
443 UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize)
444 {
445     FIXME("(pRawInputDevices=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDevices, puiNumDevices, cbSize);
446
447     return 0;
448 }
449
450
451 /******************************************************************
452 *               DefRawInputProc (USER32.@)
453 */
454 LRESULT WINAPI DefRawInputProc(PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader)
455 {
456     FIXME("(paRawInput=%p, nInput=%d, cbSizeHeader=%d) stub!\n", *paRawInput, nInput, cbSizeHeader);
457
458     return 0;
459 }
460
461
462 /**********************************************************************
463  *              AttachThreadInput (USER32.@)
464  *
465  * Attaches the input processing mechanism of one thread to that of
466  * another thread.
467  */
468 BOOL WINAPI AttachThreadInput( DWORD from, DWORD to, BOOL attach )
469 {
470     BOOL ret;
471
472     SERVER_START_REQ( attach_thread_input )
473     {
474         req->tid_from = from;
475         req->tid_to   = to;
476         req->attach   = attach;
477         ret = !wine_server_call_err( req );
478     }
479     SERVER_END_REQ;
480     return ret;
481 }
482
483
484 /**********************************************************************
485  *              GetKeyState (USER32.@)
486  *
487  * An application calls the GetKeyState function in response to a
488  * keyboard-input message.  This function retrieves the state of the key
489  * at the time the input message was generated.
490  */
491 SHORT WINAPI DECLSPEC_HOTPATCH GetKeyState(INT vkey)
492 {
493     SHORT retval = 0;
494
495     SERVER_START_REQ( get_key_state )
496     {
497         req->tid = GetCurrentThreadId();
498         req->key = vkey;
499         if (!wine_server_call( req )) retval = (signed char)reply->state;
500     }
501     SERVER_END_REQ;
502     TRACE("key (0x%x) -> %x\n", vkey, retval);
503     return retval;
504 }
505
506
507 /**********************************************************************
508  *              GetKeyboardState (USER32.@)
509  */
510 BOOL WINAPI DECLSPEC_HOTPATCH GetKeyboardState( LPBYTE state )
511 {
512     BOOL ret;
513
514     TRACE("(%p)\n", state);
515
516     memset( state, 0, 256 );
517     SERVER_START_REQ( get_key_state )
518     {
519         req->tid = GetCurrentThreadId();
520         req->key = -1;
521         wine_server_set_reply( req, state, 256 );
522         ret = !wine_server_call_err( req );
523     }
524     SERVER_END_REQ;
525     return ret;
526 }
527
528
529 /**********************************************************************
530  *              SetKeyboardState (USER32.@)
531  */
532 BOOL WINAPI SetKeyboardState( LPBYTE state )
533 {
534     BOOL ret;
535
536     SERVER_START_REQ( set_key_state )
537     {
538         req->tid = GetCurrentThreadId();
539         wine_server_add_data( req, state, 256 );
540         ret = !wine_server_call_err( req );
541     }
542     SERVER_END_REQ;
543     return ret;
544 }
545
546
547 /**********************************************************************
548  *              VkKeyScanA (USER32.@)
549  *
550  * VkKeyScan translates an ANSI character to a virtual-key and shift code
551  * for the current keyboard.
552  * high-order byte yields :
553  *      0       Unshifted
554  *      1       Shift
555  *      2       Ctrl
556  *      3-5     Shift-key combinations that are not used for characters
557  *      6       Ctrl-Alt
558  *      7       Ctrl-Alt-Shift
559  *      I.e. :  Shift = 1, Ctrl = 2, Alt = 4.
560  * FIXME : works ok except for dead chars :
561  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
562  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
563  */
564 SHORT WINAPI VkKeyScanA(CHAR cChar)
565 {
566     WCHAR wChar;
567
568     if (IsDBCSLeadByte(cChar)) return -1;
569
570     MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
571     return VkKeyScanW(wChar);
572 }
573
574 /******************************************************************************
575  *              VkKeyScanW (USER32.@)
576  */
577 SHORT WINAPI VkKeyScanW(WCHAR cChar)
578 {
579     return VkKeyScanExW(cChar, GetKeyboardLayout(0));
580 }
581
582 /**********************************************************************
583  *              VkKeyScanExA (USER32.@)
584  */
585 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
586 {
587     WCHAR wChar;
588
589     if (IsDBCSLeadByte(cChar)) return -1;
590
591     MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
592     return VkKeyScanExW(wChar, dwhkl);
593 }
594
595 /******************************************************************************
596  *              VkKeyScanExW (USER32.@)
597  */
598 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
599 {
600     return USER_Driver->pVkKeyScanEx(cChar, dwhkl);
601 }
602
603 /**********************************************************************
604  *              OemKeyScan (USER32.@)
605  */
606 DWORD WINAPI OemKeyScan(WORD wOemChar)
607 {
608     return wOemChar;
609 }
610
611 /******************************************************************************
612  *              GetKeyboardType (USER32.@)
613  */
614 INT WINAPI GetKeyboardType(INT nTypeFlag)
615 {
616     TRACE_(keyboard)("(%d)\n", nTypeFlag);
617     switch(nTypeFlag)
618     {
619     case 0:      /* Keyboard type */
620         return 4;    /* AT-101 */
621     case 1:      /* Keyboard Subtype */
622         return 0;    /* There are no defined subtypes */
623     case 2:      /* Number of F-keys */
624         return 12;   /* We're doing an 101 for now, so return 12 F-keys */
625     default:
626         WARN_(keyboard)("Unknown type\n");
627         return 0;    /* The book says 0 here, so 0 */
628     }
629 }
630
631 /******************************************************************************
632  *              MapVirtualKeyA (USER32.@)
633  */
634 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
635 {
636     return MapVirtualKeyExA( code, maptype, GetKeyboardLayout(0) );
637 }
638
639 /******************************************************************************
640  *              MapVirtualKeyW (USER32.@)
641  */
642 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
643 {
644     return MapVirtualKeyExW(code, maptype, GetKeyboardLayout(0));
645 }
646
647 /******************************************************************************
648  *              MapVirtualKeyExA (USER32.@)
649  */
650 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
651 {
652     UINT ret;
653
654     ret = MapVirtualKeyExW( code, maptype, hkl );
655     if (maptype == MAPVK_VK_TO_CHAR)
656     {
657         BYTE ch = 0;
658         WCHAR wch = ret;
659
660         WideCharToMultiByte( CP_ACP, 0, &wch, 1, (LPSTR)&ch, 1, NULL, NULL );
661         ret = ch;
662     }
663     return ret;
664 }
665
666 /******************************************************************************
667  *              MapVirtualKeyExW (USER32.@)
668  */
669 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
670 {
671     TRACE_(keyboard)("(%X, %d, %p)\n", code, maptype, hkl);
672
673     return USER_Driver->pMapVirtualKeyEx(code, maptype, hkl);
674 }
675
676 /****************************************************************************
677  *              GetKBCodePage (USER32.@)
678  */
679 UINT WINAPI GetKBCodePage(void)
680 {
681     return GetOEMCP();
682 }
683
684 /***********************************************************************
685  *              GetKeyboardLayout (USER32.@)
686  *
687  *        - device handle for keyboard layout defaulted to
688  *          the language id. This is the way Windows default works.
689  *        - the thread identifier (dwLayout) is also ignored.
690  */
691 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
692 {
693     return USER_Driver->pGetKeyboardLayout(dwLayout);
694 }
695
696 /****************************************************************************
697  *              GetKeyboardLayoutNameA (USER32.@)
698  */
699 BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID)
700 {
701     WCHAR buf[KL_NAMELENGTH];
702
703     if (GetKeyboardLayoutNameW(buf))
704         return WideCharToMultiByte( CP_ACP, 0, buf, -1, pszKLID, KL_NAMELENGTH, NULL, NULL ) != 0;
705     return FALSE;
706 }
707
708 /****************************************************************************
709  *              GetKeyboardLayoutNameW (USER32.@)
710  */
711 BOOL WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
712 {
713     return USER_Driver->pGetKeyboardLayoutName(pwszKLID);
714 }
715
716 /****************************************************************************
717  *              GetKeyNameTextA (USER32.@)
718  */
719 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
720 {
721     WCHAR buf[256];
722     INT ret;
723
724     if (!GetKeyNameTextW(lParam, buf, 256))
725     {
726         lpBuffer[0] = 0;
727         return 0;
728     }
729     ret = WideCharToMultiByte(CP_ACP, 0, buf, -1, lpBuffer, nSize, NULL, NULL);
730     if (!ret && nSize)
731     {
732         ret = nSize - 1;
733         lpBuffer[ret] = 0;
734     }
735     return ret;
736 }
737
738 /****************************************************************************
739  *              GetKeyNameTextW (USER32.@)
740  */
741 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
742 {
743     return USER_Driver->pGetKeyNameText( lParam, lpBuffer, nSize );
744 }
745
746 /****************************************************************************
747  *              ToUnicode (USER32.@)
748  */
749 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
750                      LPWSTR lpwStr, int size, UINT flags)
751 {
752     return ToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, GetKeyboardLayout(0));
753 }
754
755 /****************************************************************************
756  *              ToUnicodeEx (USER32.@)
757  */
758 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
759                        LPWSTR lpwStr, int size, UINT flags, HKL hkl)
760 {
761     return USER_Driver->pToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, hkl);
762 }
763
764 /****************************************************************************
765  *              ToAscii (USER32.@)
766  */
767 INT WINAPI ToAscii( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
768                     LPWORD lpChar, UINT flags )
769 {
770     return ToAsciiEx(virtKey, scanCode, lpKeyState, lpChar, flags, GetKeyboardLayout(0));
771 }
772
773 /****************************************************************************
774  *              ToAsciiEx (USER32.@)
775  */
776 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
777                       LPWORD lpChar, UINT flags, HKL dwhkl )
778 {
779     WCHAR uni_chars[2];
780     INT ret, n_ret;
781
782     ret = ToUnicodeEx(virtKey, scanCode, lpKeyState, uni_chars, 2, flags, dwhkl);
783     if (ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
784     else n_ret = ret;
785     WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
786     return ret;
787 }
788
789 /**********************************************************************
790  *              ActivateKeyboardLayout (USER32.@)
791  */
792 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
793 {
794     TRACE_(keyboard)("(%p, %d)\n", hLayout, flags);
795
796     return USER_Driver->pActivateKeyboardLayout(hLayout, flags);
797 }
798
799 /**********************************************************************
800  *              BlockInput (USER32.@)
801  */
802 BOOL WINAPI BlockInput(BOOL fBlockIt)
803 {
804     FIXME_(keyboard)("(%d): stub\n", fBlockIt);
805     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
806
807     return FALSE;
808 }
809
810 /***********************************************************************
811  *              GetKeyboardLayoutList (USER32.@)
812  *
813  * Return number of values available if either input parm is
814  *  0, per MS documentation.
815  */
816 UINT WINAPI GetKeyboardLayoutList(INT nBuff, HKL *layouts)
817 {
818     HKEY hKeyKeyboard;
819     DWORD rc;
820     INT count = 0;
821     ULONG_PTR baselayout;
822     LANGID langid;
823     static const WCHAR szKeyboardReg[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s',0};
824
825     TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
826
827     baselayout = GetUserDefaultLCID();
828     langid = PRIMARYLANGID(LANGIDFROMLCID(baselayout));
829     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
830         baselayout |= 0xe001 << 16; /* IME */
831     else
832         baselayout |= baselayout << 16;
833
834     /* Enumerate the Registry */
835     rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,szKeyboardReg,&hKeyKeyboard);
836     if (rc == ERROR_SUCCESS)
837     {
838         do {
839             WCHAR szKeyName[9];
840             HKL layout;
841             rc = RegEnumKeyW(hKeyKeyboard, count, szKeyName, 9);
842             if (rc == ERROR_SUCCESS)
843             {
844                 layout = (HKL)strtoulW(szKeyName,NULL,16);
845                 if (baselayout != 0 && layout == (HKL)baselayout)
846                     baselayout = 0; /* found in the registry do not add again */
847                 if (nBuff && layouts)
848                 {
849                     if (count >= nBuff ) break;
850                     layouts[count] = layout;
851                 }
852                 count ++;
853             }
854         } while (rc == ERROR_SUCCESS);
855         RegCloseKey(hKeyKeyboard);
856     }
857
858     /* make sure our base layout is on the list */
859     if (baselayout != 0)
860     {
861         if (nBuff && layouts)
862         {
863             if (count < nBuff)
864             {
865                 layouts[count] = (HKL)baselayout;
866                 count++;
867             }
868         }
869         else
870             count++;
871     }
872
873     return count;
874 }
875
876
877 /***********************************************************************
878  *              RegisterHotKey (USER32.@)
879  */
880 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk)
881 {
882     static int once;
883     if (!once++) FIXME_(keyboard)("(%p,%d,0x%08x,%X): stub\n",hwnd,id,modifiers,vk);
884     return TRUE;
885 }
886
887 /***********************************************************************
888  *              UnregisterHotKey (USER32.@)
889  */
890 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id)
891 {
892     static int once;
893     if (!once++) FIXME_(keyboard)("(%p,%d): stub\n",hwnd,id);
894     return TRUE;
895 }
896
897 /***********************************************************************
898  *              LoadKeyboardLayoutW (USER32.@)
899  */
900 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
901 {
902     TRACE_(keyboard)("(%s, %d)\n", debugstr_w(pwszKLID), Flags);
903
904     return USER_Driver->pLoadKeyboardLayout(pwszKLID, Flags);
905 }
906
907 /***********************************************************************
908  *              LoadKeyboardLayoutA (USER32.@)
909  */
910 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
911 {
912     HKL ret;
913     UNICODE_STRING pwszKLIDW;
914
915     if (pwszKLID) RtlCreateUnicodeStringFromAsciiz(&pwszKLIDW, pwszKLID);
916     else pwszKLIDW.Buffer = NULL;
917
918     ret = LoadKeyboardLayoutW(pwszKLIDW.Buffer, Flags);
919     RtlFreeUnicodeString(&pwszKLIDW);
920     return ret;
921 }
922
923
924 /***********************************************************************
925  *              UnloadKeyboardLayout (USER32.@)
926  */
927 BOOL WINAPI UnloadKeyboardLayout(HKL hkl)
928 {
929     TRACE_(keyboard)("(%p)\n", hkl);
930
931     return USER_Driver->pUnloadKeyboardLayout(hkl);
932 }
933
934 typedef struct __TRACKINGLIST {
935     TRACKMOUSEEVENT tme;
936     POINT pos; /* center of hover rectangle */
937 } _TRACKINGLIST;
938
939 /* FIXME: move tracking stuff into a per thread data */
940 static _TRACKINGLIST tracking_info;
941 static UINT_PTR timer;
942
943 static void check_mouse_leave(HWND hwnd, int hittest)
944 {
945     if (tracking_info.tme.hwndTrack != hwnd)
946     {
947         if (tracking_info.tme.dwFlags & TME_NONCLIENT)
948             PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
949         else
950             PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
951
952         /* remove the TME_LEAVE flag */
953         tracking_info.tme.dwFlags &= ~TME_LEAVE;
954     }
955     else
956     {
957         if (hittest == HTCLIENT)
958         {
959             if (tracking_info.tme.dwFlags & TME_NONCLIENT)
960             {
961                 PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
962                 /* remove the TME_LEAVE flag */
963                 tracking_info.tme.dwFlags &= ~TME_LEAVE;
964             }
965         }
966         else
967         {
968             if (!(tracking_info.tme.dwFlags & TME_NONCLIENT))
969             {
970                 PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
971                 /* remove the TME_LEAVE flag */
972                 tracking_info.tme.dwFlags &= ~TME_LEAVE;
973             }
974         }
975     }
976 }
977
978 static void CALLBACK TrackMouseEventProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent,
979                                          DWORD dwTime)
980 {
981     POINT pos;
982     INT hoverwidth = 0, hoverheight = 0, hittest;
983
984     TRACE("hwnd %p, msg %04x, id %04lx, time %u\n", hwnd, uMsg, idEvent, dwTime);
985
986     GetCursorPos(&pos);
987     hwnd = WINPOS_WindowFromPoint(hwnd, pos, &hittest);
988
989     TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
990
991     SystemParametersInfoW(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
992     SystemParametersInfoW(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
993
994     TRACE("tracked pos %s, current pos %s, hover width %d, hover height %d\n",
995            wine_dbgstr_point(&tracking_info.pos), wine_dbgstr_point(&pos),
996            hoverwidth, hoverheight);
997
998     /* see if this tracking event is looking for TME_LEAVE and that the */
999     /* mouse has left the window */
1000     if (tracking_info.tme.dwFlags & TME_LEAVE)
1001     {
1002         check_mouse_leave(hwnd, hittest);
1003     }
1004
1005     if (tracking_info.tme.hwndTrack != hwnd)
1006     {
1007         /* mouse is gone, stop tracking mouse hover */
1008         tracking_info.tme.dwFlags &= ~TME_HOVER;
1009     }
1010
1011     /* see if we are tracking hovering for this hwnd */
1012     if (tracking_info.tme.dwFlags & TME_HOVER)
1013     {
1014         /* has the cursor moved outside the rectangle centered around pos? */
1015         if ((abs(pos.x - tracking_info.pos.x) > (hoverwidth / 2)) ||
1016             (abs(pos.y - tracking_info.pos.y) > (hoverheight / 2)))
1017         {
1018             /* record this new position as the current position */
1019             tracking_info.pos = pos;
1020         }
1021         else
1022         {
1023             if (hittest == HTCLIENT)
1024             {
1025                 ScreenToClient(hwnd, &pos);
1026                 TRACE("client cursor pos %s\n", wine_dbgstr_point(&pos));
1027
1028                 PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSEHOVER,
1029                              get_key_state(), MAKELPARAM( pos.x, pos.y ));
1030             }
1031             else
1032             {
1033                 if (tracking_info.tme.dwFlags & TME_NONCLIENT)
1034                     PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSEHOVER,
1035                                  hittest, MAKELPARAM( pos.x, pos.y ));
1036             }
1037
1038             /* stop tracking mouse hover */
1039             tracking_info.tme.dwFlags &= ~TME_HOVER;
1040         }
1041     }
1042
1043     /* stop the timer if the tracking list is empty */
1044     if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
1045     {
1046         KillSystemTimer(tracking_info.tme.hwndTrack, timer);
1047         timer = 0;
1048         tracking_info.tme.hwndTrack = 0;
1049         tracking_info.tme.dwFlags = 0;
1050         tracking_info.tme.dwHoverTime = 0;
1051     }
1052 }
1053
1054
1055 /***********************************************************************
1056  * TrackMouseEvent [USER32]
1057  *
1058  * Requests notification of mouse events
1059  *
1060  * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1061  * to the hwnd specified in the ptme structure.  After the event message
1062  * is posted to the hwnd, the entry in the queue is removed.
1063  *
1064  * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1065  * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1066  * immediately and the TME_LEAVE flag being ignored.
1067  *
1068  * PARAMS
1069  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1070  *
1071  * RETURNS
1072  *     Success: non-zero
1073  *     Failure: zero
1074  *
1075  */
1076
1077 BOOL WINAPI
1078 TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1079 {
1080     HWND hwnd;
1081     POINT pos;
1082     DWORD hover_time;
1083     INT hittest;
1084
1085     TRACE("%x, %x, %p, %u\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1086
1087     if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1088         WARN("wrong TRACKMOUSEEVENT size from app\n");
1089         SetLastError(ERROR_INVALID_PARAMETER);
1090         return FALSE;
1091     }
1092
1093     /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1094     if (ptme->dwFlags & TME_QUERY )
1095     {
1096         *ptme = tracking_info.tme;
1097         /* set cbSize in the case it's not initialized yet */
1098         ptme->cbSize = sizeof(TRACKMOUSEEVENT);
1099
1100         return TRUE; /* return here, TME_QUERY is retrieving information */
1101     }
1102
1103     if (!IsWindow(ptme->hwndTrack))
1104     {
1105         SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1106         return FALSE;
1107     }
1108
1109     hover_time = ptme->dwHoverTime;
1110
1111     /* if HOVER_DEFAULT was specified replace this with the systems current value.
1112      * TME_LEAVE doesn't need to specify hover time so use default */
1113     if (hover_time == HOVER_DEFAULT || hover_time == 0 || !(ptme->dwHoverTime&TME_HOVER))
1114         SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0);
1115
1116     GetCursorPos(&pos);
1117     hwnd = WINPOS_WindowFromPoint(ptme->hwndTrack, pos, &hittest);
1118     TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
1119
1120     if (ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT))
1121         FIXME("Unknown flag(s) %08x\n", ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT));
1122
1123     if (ptme->dwFlags & TME_CANCEL)
1124     {
1125         if (tracking_info.tme.hwndTrack == ptme->hwndTrack)
1126         {
1127             tracking_info.tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1128
1129             /* if we aren't tracking on hover or leave remove this entry */
1130             if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
1131             {
1132                 KillSystemTimer(tracking_info.tme.hwndTrack, timer);
1133                 timer = 0;
1134                 tracking_info.tme.hwndTrack = 0;
1135                 tracking_info.tme.dwFlags = 0;
1136                 tracking_info.tme.dwHoverTime = 0;
1137             }
1138         }
1139     } else {
1140         /* In our implementation it's possible that another window will receive a
1141          * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is
1142          * called. In such a situation post the WM_MOUSELEAVE now */
1143         if (tracking_info.tme.dwFlags & TME_LEAVE && tracking_info.tme.hwndTrack != NULL)
1144             check_mouse_leave(hwnd, hittest);
1145
1146         if (timer)
1147         {
1148             KillSystemTimer(tracking_info.tme.hwndTrack, timer);
1149             timer = 0;
1150             tracking_info.tme.hwndTrack = 0;
1151             tracking_info.tme.dwFlags = 0;
1152             tracking_info.tme.dwHoverTime = 0;
1153         }
1154
1155         if (ptme->hwndTrack == hwnd)
1156         {
1157             /* Adding new mouse event to the tracking list */
1158             tracking_info.tme = *ptme;
1159             tracking_info.tme.dwHoverTime = hover_time;
1160
1161             /* Initialize HoverInfo variables even if not hover tracking */
1162             tracking_info.pos = pos;
1163
1164             timer = SetSystemTimer(tracking_info.tme.hwndTrack, (UINT_PTR)&tracking_info.tme, hover_time, TrackMouseEventProc);
1165         }
1166     }
1167
1168     return TRUE;
1169 }
1170
1171 /***********************************************************************
1172  * GetMouseMovePointsEx [USER32]
1173  *
1174  * RETURNS
1175  *     Success: count of point set in the buffer
1176  *     Failure: -1
1177  */
1178 int WINAPI GetMouseMovePointsEx(UINT size, LPMOUSEMOVEPOINT ptin, LPMOUSEMOVEPOINT ptout, int count, DWORD res) {
1179
1180     if((size != sizeof(MOUSEMOVEPOINT)) || (count < 0) || (count > 64)) {
1181         SetLastError(ERROR_INVALID_PARAMETER);
1182         return -1;
1183     }
1184
1185     if(!ptin || (!ptout && count)) {
1186         SetLastError(ERROR_NOACCESS);
1187         return -1;
1188     }
1189
1190     FIXME("(%d %p %p %d %d) stub\n", size, ptin, ptout, count, res);
1191
1192     SetLastError(ERROR_POINT_NOT_FOUND);
1193     return -1;
1194 }