4 * Copyright 2012 Henri Verbeet
5 * Copyright 2018 Zebediah Figura for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
33 #include "ddk/hidsdi.h"
34 #include "wine/debug.h"
35 #include "wine/server.h"
38 #include "user_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(rawinput
);
50 PHIDP_PREPARSED_DATA data
;
53 static struct device
*rawinput_devices
;
54 static unsigned int rawinput_devices_count
, rawinput_devices_max
;
56 static CRITICAL_SECTION rawinput_devices_cs
;
57 static CRITICAL_SECTION_DEBUG rawinput_devices_cs_debug
=
59 0, 0, &rawinput_devices_cs
,
60 { &rawinput_devices_cs_debug
.ProcessLocksList
, &rawinput_devices_cs_debug
.ProcessLocksList
},
61 0, 0, { (DWORD_PTR
)(__FILE__
": rawinput_devices_cs") }
63 static CRITICAL_SECTION rawinput_devices_cs
= { &rawinput_devices_cs_debug
, -1, 0, 0, 0, 0 };
65 static BOOL
array_reserve(void **elements
, unsigned int *capacity
, unsigned int count
, unsigned int size
)
67 unsigned int new_capacity
, max_capacity
;
70 if (count
<= *capacity
)
73 max_capacity
= ~(SIZE_T
)0 / size
;
74 if (count
> max_capacity
)
77 new_capacity
= max(4, *capacity
);
78 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
80 if (new_capacity
< count
)
81 new_capacity
= max_capacity
;
83 if (!(new_elements
= heap_realloc(*elements
, new_capacity
* size
)))
86 *elements
= new_elements
;
87 *capacity
= new_capacity
;
92 static struct device
*add_device(HDEVINFO set
, SP_DEVICE_INTERFACE_DATA
*iface
)
94 SP_DEVICE_INTERFACE_DETAIL_DATA_W
*detail
;
95 struct device
*device
;
100 SetupDiGetDeviceInterfaceDetailW(set
, iface
, NULL
, 0, &size
, NULL
);
101 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
103 ERR("Failed to get device path, error %#x.\n", GetLastError());
106 if (!(detail
= heap_alloc(size
)))
108 ERR("Failed to allocate memory.\n");
111 detail
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
112 SetupDiGetDeviceInterfaceDetailW(set
, iface
, detail
, size
, NULL
, NULL
);
114 TRACE("Found HID device %s.\n", debugstr_w(detail
->DevicePath
));
116 if (!(path
= heap_strdupW(detail
->DevicePath
)))
118 ERR("Failed to allocate memory.\n");
124 file
= CreateFileW(path
, GENERIC_READ
| GENERIC_WRITE
,
125 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
126 if (file
== INVALID_HANDLE_VALUE
)
128 ERR("Failed to open device file %s, error %u.\n", debugstr_w(path
), GetLastError());
133 if (!array_reserve((void **)&rawinput_devices
, &rawinput_devices_max
,
134 rawinput_devices_count
+ 1, sizeof(*rawinput_devices
)))
136 ERR("Failed to allocate memory.\n");
142 device
= &rawinput_devices
[rawinput_devices_count
++];
145 device
->info
.cbSize
= sizeof(RID_DEVICE_INFO
);
150 static void find_devices(void)
152 static ULONGLONG last_check
;
154 SP_DEVICE_INTERFACE_DATA iface
= { sizeof(iface
) };
155 struct device
*device
;
156 HIDD_ATTRIBUTES attr
;
162 if (GetTickCount64() - last_check
< 2000)
164 last_check
= GetTickCount64();
166 HidD_GetHidGuid(&hid_guid
);
168 EnterCriticalSection(&rawinput_devices_cs
);
170 /* destroy previous list */
171 for (idx
= 0; idx
< rawinput_devices_count
; ++idx
)
173 CloseHandle(rawinput_devices
[idx
].file
);
174 heap_free(rawinput_devices
[idx
].path
);
176 rawinput_devices_count
= 0;
178 set
= SetupDiGetClassDevsW(&hid_guid
, NULL
, NULL
, DIGCF_DEVICEINTERFACE
| DIGCF_PRESENT
);
180 for (idx
= 0; SetupDiEnumDeviceInterfaces(set
, NULL
, &hid_guid
, idx
, &iface
); ++idx
)
182 if (!(device
= add_device(set
, &iface
)))
185 attr
.Size
= sizeof(HIDD_ATTRIBUTES
);
186 if (!HidD_GetAttributes(device
->file
, &attr
))
187 WARN("Failed to get attributes.\n");
189 device
->info
.dwType
= RIM_TYPEHID
;
190 device
->info
.u
.hid
.dwVendorId
= attr
.VendorID
;
191 device
->info
.u
.hid
.dwProductId
= attr
.ProductID
;
192 device
->info
.u
.hid
.dwVersionNumber
= attr
.VersionNumber
;
194 if (!HidD_GetPreparsedData(device
->file
, &device
->data
))
195 WARN("Failed to get preparsed data.\n");
197 if (!HidP_GetCaps(device
->data
, &caps
))
198 WARN("Failed to get caps.\n");
200 device
->info
.u
.hid
.usUsagePage
= caps
.UsagePage
;
201 device
->info
.u
.hid
.usUsage
= caps
.Usage
;
204 SetupDiDestroyDeviceInfoList(set
);
206 set
= SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MOUSE
, NULL
, NULL
, DIGCF_DEVICEINTERFACE
| DIGCF_PRESENT
);
208 for (idx
= 0; SetupDiEnumDeviceInterfaces(set
, NULL
, &GUID_DEVINTERFACE_MOUSE
, idx
, &iface
); ++idx
)
210 static const RID_DEVICE_INFO_MOUSE mouse_info
= {1, 5, 0, FALSE
};
212 if (!(device
= add_device(set
, &iface
)))
215 device
->info
.dwType
= RIM_TYPEMOUSE
;
216 device
->info
.u
.mouse
= mouse_info
;
219 SetupDiDestroyDeviceInfoList(set
);
221 LeaveCriticalSection(&rawinput_devices_cs
);
225 struct rawinput_thread_data
*rawinput_thread_data(void)
227 struct user_thread_info
*thread_info
= get_user_thread_info();
228 struct rawinput_thread_data
*data
= thread_info
->rawinput
;
229 if (data
) return data
;
230 data
= thread_info
->rawinput
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
231 RAWINPUT_BUFFER_SIZE
+ sizeof(struct user_thread_info
) );
236 BOOL
rawinput_from_hardware_message(RAWINPUT
*rawinput
, const struct hardware_msg_data
*msg_data
)
238 rawinput
->header
.dwType
= msg_data
->rawinput
.type
;
239 if (msg_data
->rawinput
.type
== RIM_TYPEMOUSE
)
241 static const unsigned int button_flags
[] =
243 0, /* MOUSEEVENTF_MOVE */
244 RI_MOUSE_LEFT_BUTTON_DOWN
, /* MOUSEEVENTF_LEFTDOWN */
245 RI_MOUSE_LEFT_BUTTON_UP
, /* MOUSEEVENTF_LEFTUP */
246 RI_MOUSE_RIGHT_BUTTON_DOWN
, /* MOUSEEVENTF_RIGHTDOWN */
247 RI_MOUSE_RIGHT_BUTTON_UP
, /* MOUSEEVENTF_RIGHTUP */
248 RI_MOUSE_MIDDLE_BUTTON_DOWN
, /* MOUSEEVENTF_MIDDLEDOWN */
249 RI_MOUSE_MIDDLE_BUTTON_UP
, /* MOUSEEVENTF_MIDDLEUP */
253 rawinput
->header
.dwSize
= FIELD_OFFSET(RAWINPUT
, data
) + sizeof(RAWMOUSE
);
254 rawinput
->header
.hDevice
= WINE_MOUSE_HANDLE
;
255 rawinput
->header
.wParam
= 0;
257 rawinput
->data
.mouse
.usFlags
= MOUSE_MOVE_RELATIVE
;
258 rawinput
->data
.mouse
.u
.s
.usButtonFlags
= 0;
259 rawinput
->data
.mouse
.u
.s
.usButtonData
= 0;
260 for (i
= 1; i
< ARRAY_SIZE(button_flags
); ++i
)
262 if (msg_data
->flags
& (1 << i
))
263 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= button_flags
[i
];
265 if (msg_data
->flags
& MOUSEEVENTF_WHEEL
)
267 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_WHEEL
;
268 rawinput
->data
.mouse
.u
.s
.usButtonData
= msg_data
->rawinput
.mouse
.data
;
270 if (msg_data
->flags
& MOUSEEVENTF_HWHEEL
)
272 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_HORIZONTAL_WHEEL
;
273 rawinput
->data
.mouse
.u
.s
.usButtonData
= msg_data
->rawinput
.mouse
.data
;
275 if (msg_data
->flags
& MOUSEEVENTF_XDOWN
)
277 if (msg_data
->rawinput
.mouse
.data
== XBUTTON1
)
278 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_BUTTON_4_DOWN
;
279 else if (msg_data
->rawinput
.mouse
.data
== XBUTTON2
)
280 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_BUTTON_5_DOWN
;
282 if (msg_data
->flags
& MOUSEEVENTF_XUP
)
284 if (msg_data
->rawinput
.mouse
.data
== XBUTTON1
)
285 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_BUTTON_4_UP
;
286 else if (msg_data
->rawinput
.mouse
.data
== XBUTTON2
)
287 rawinput
->data
.mouse
.u
.s
.usButtonFlags
|= RI_MOUSE_BUTTON_5_UP
;
290 rawinput
->data
.mouse
.ulRawButtons
= 0;
291 rawinput
->data
.mouse
.lLastX
= msg_data
->rawinput
.mouse
.x
;
292 rawinput
->data
.mouse
.lLastY
= msg_data
->rawinput
.mouse
.y
;
293 rawinput
->data
.mouse
.ulExtraInformation
= msg_data
->info
;
295 else if (msg_data
->rawinput
.type
== RIM_TYPEKEYBOARD
)
297 rawinput
->header
.dwSize
= FIELD_OFFSET(RAWINPUT
, data
) + sizeof(RAWKEYBOARD
);
298 rawinput
->header
.hDevice
= WINE_KEYBOARD_HANDLE
;
299 rawinput
->header
.wParam
= 0;
301 rawinput
->data
.keyboard
.MakeCode
= msg_data
->rawinput
.kbd
.scan
;
302 rawinput
->data
.keyboard
.Flags
= msg_data
->flags
& KEYEVENTF_KEYUP
? RI_KEY_BREAK
: RI_KEY_MAKE
;
303 if (msg_data
->flags
& KEYEVENTF_EXTENDEDKEY
) rawinput
->data
.keyboard
.Flags
|= RI_KEY_E0
;
304 rawinput
->data
.keyboard
.Reserved
= 0;
306 switch (msg_data
->rawinput
.kbd
.vkey
)
310 rawinput
->data
.keyboard
.VKey
= VK_SHIFT
;
311 rawinput
->data
.keyboard
.Flags
&= ~RI_KEY_E0
;
315 rawinput
->data
.keyboard
.VKey
= VK_CONTROL
;
319 rawinput
->data
.keyboard
.VKey
= VK_MENU
;
322 rawinput
->data
.keyboard
.VKey
= msg_data
->rawinput
.kbd
.vkey
;
326 rawinput
->data
.keyboard
.Message
= msg_data
->rawinput
.kbd
.message
;
327 rawinput
->data
.keyboard
.ExtraInformation
= msg_data
->info
;
331 FIXME("Unhandled rawinput type %#x.\n", msg_data
->rawinput
.type
);
339 /***********************************************************************
340 * GetRawInputDeviceList (USER32.@)
342 UINT WINAPI
GetRawInputDeviceList(RAWINPUTDEVICELIST
*devices
, UINT
*device_count
, UINT size
)
346 TRACE("devices %p, device_count %p, size %u.\n", devices
, device_count
, size
);
348 if (size
!= sizeof(*devices
))
350 SetLastError(ERROR_INVALID_PARAMETER
);
356 SetLastError(ERROR_NOACCESS
);
364 *device_count
= 2 + rawinput_devices_count
;
368 if (*device_count
< 2 + rawinput_devices_count
)
370 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
371 *device_count
= 2 + rawinput_devices_count
;
375 devices
[0].hDevice
= WINE_MOUSE_HANDLE
;
376 devices
[0].dwType
= RIM_TYPEMOUSE
;
377 devices
[1].hDevice
= WINE_KEYBOARD_HANDLE
;
378 devices
[1].dwType
= RIM_TYPEKEYBOARD
;
380 for (i
= 0; i
< rawinput_devices_count
; ++i
)
382 devices
[2 + i
].hDevice
= &rawinput_devices
[i
];
383 devices
[2 + i
].dwType
= rawinput_devices
[i
].info
.dwType
;
386 return 2 + rawinput_devices_count
;
389 /***********************************************************************
390 * RegisterRawInputDevices (USER32.@)
392 BOOL WINAPI DECLSPEC_HOTPATCH
RegisterRawInputDevices(RAWINPUTDEVICE
*devices
, UINT device_count
, UINT size
)
394 struct rawinput_device
*d
;
398 TRACE("devices %p, device_count %u, size %u.\n", devices
, device_count
, size
);
400 if (size
!= sizeof(*devices
))
402 WARN("Invalid structure size %u.\n", size
);
403 SetLastError(ERROR_INVALID_PARAMETER
);
407 for (i
= 0; i
< device_count
; ++i
)
409 if ((devices
[i
].dwFlags
& RIDEV_INPUTSINK
) &&
410 (devices
[i
].hwndTarget
== NULL
))
412 SetLastError(ERROR_INVALID_PARAMETER
);
416 if ((devices
[i
].dwFlags
& RIDEV_REMOVE
) &&
417 (devices
[i
].hwndTarget
!= NULL
))
419 SetLastError(ERROR_INVALID_PARAMETER
);
424 if (!(d
= HeapAlloc( GetProcessHeap(), 0, device_count
* sizeof(*d
) ))) return FALSE
;
426 for (i
= 0; i
< device_count
; ++i
)
428 TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
429 i
, devices
[i
].usUsagePage
, devices
[i
].usUsage
,
430 devices
[i
].dwFlags
, devices
[i
].hwndTarget
);
431 if (devices
[i
].dwFlags
& ~(RIDEV_REMOVE
|RIDEV_NOLEGACY
|RIDEV_INPUTSINK
))
432 FIXME("Unhandled flags %#x for device %u.\n", devices
[i
].dwFlags
, i
);
434 d
[i
].usage_page
= devices
[i
].usUsagePage
;
435 d
[i
].usage
= devices
[i
].usUsage
;
436 d
[i
].flags
= devices
[i
].dwFlags
;
437 d
[i
].target
= wine_server_user_handle( devices
[i
].hwndTarget
);
440 SERVER_START_REQ( update_rawinput_devices
)
442 wine_server_add_data( req
, d
, device_count
* sizeof(*d
) );
443 ret
= !wine_server_call( req
);
447 HeapFree( GetProcessHeap(), 0, d
);
452 /***********************************************************************
453 * GetRawInputData (USER32.@)
455 UINT WINAPI
GetRawInputData(HRAWINPUT rawinput
, UINT command
, void *data
, UINT
*data_size
, UINT header_size
)
457 struct rawinput_thread_data
*thread_data
= rawinput_thread_data();
460 TRACE("rawinput %p, command %#x, data %p, data_size %p, header_size %u.\n",
461 rawinput
, command
, data
, data_size
, header_size
);
463 if (!rawinput
|| thread_data
->hw_id
!= (UINT_PTR
)rawinput
)
465 SetLastError(ERROR_INVALID_HANDLE
);
469 if (header_size
!= sizeof(RAWINPUTHEADER
))
471 WARN("Invalid structure size %u.\n", header_size
);
472 SetLastError(ERROR_INVALID_PARAMETER
);
479 size
= thread_data
->buffer
->header
.dwSize
;
482 size
= sizeof(RAWINPUTHEADER
);
485 SetLastError(ERROR_INVALID_PARAMETER
);
495 if (*data_size
< size
)
497 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
500 memcpy(data
, thread_data
->buffer
, size
);
505 typedef RAWINPUT RAWINPUT64
;
509 RAWINPUTHEADER header
;
513 RAWKEYBOARD keyboard
;
519 /***********************************************************************
520 * GetRawInputBuffer (USER32.@)
522 UINT WINAPI DECLSPEC_HOTPATCH
GetRawInputBuffer(RAWINPUT
*data
, UINT
*data_size
, UINT header_size
)
524 struct hardware_msg_data
*msg_data
;
525 struct rawinput_thread_data
*thread_data
;
527 UINT count
= 0, rawinput_size
, next_size
, overhead
;
531 if (IsWow64Process( GetCurrentProcess(), &is_wow64
) && is_wow64
)
532 rawinput_size
= sizeof(RAWINPUT64
);
534 rawinput_size
= sizeof(RAWINPUT
);
535 overhead
= rawinput_size
- sizeof(RAWINPUT
);
537 if (header_size
!= sizeof(RAWINPUTHEADER
))
539 WARN("Invalid structure size %u.\n", header_size
);
540 SetLastError(ERROR_INVALID_PARAMETER
);
546 SetLastError(ERROR_INVALID_PARAMETER
);
552 TRACE("data %p, data_size %p (%u), header_size %u\n", data
, data_size
, *data_size
, header_size
);
553 SERVER_START_REQ( get_rawinput_buffer
)
555 req
->rawinput_size
= rawinput_size
;
556 req
->buffer_size
= 0;
557 if (wine_server_call( req
)) return ~0U;
558 *data_size
= reply
->next_size
;
564 if (!(thread_data
= rawinput_thread_data())) return ~0U;
565 rawinput
= thread_data
->buffer
;
567 /* first RAWINPUT block in the buffer is used for WM_INPUT message data */
568 msg_data
= (struct hardware_msg_data
*)NEXTRAWINPUTBLOCK(rawinput
);
569 SERVER_START_REQ( get_rawinput_buffer
)
571 req
->rawinput_size
= rawinput_size
;
572 req
->buffer_size
= *data_size
;
573 wine_server_set_reply( req
, msg_data
, RAWINPUT_BUFFER_SIZE
- rawinput
->header
.dwSize
);
574 if (wine_server_call( req
)) return ~0U;
575 next_size
= reply
->next_size
;
576 count
= reply
->count
;
580 for (i
= 0; i
< count
; ++i
)
582 rawinput_from_hardware_message(data
, msg_data
);
583 if (overhead
) memmove((char *)&data
->data
+ overhead
, &data
->data
,
584 data
->header
.dwSize
- sizeof(RAWINPUTHEADER
));
585 data
->header
.dwSize
+= overhead
;
586 data
= NEXTRAWINPUTBLOCK(data
);
590 if (count
== 0 && next_size
== 0) *data_size
= 0;
591 else if (next_size
== 0) next_size
= rawinput_size
;
593 if (next_size
&& *data_size
<= next_size
)
595 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
596 *data_size
= next_size
;
600 if (count
) TRACE("data %p, data_size %p (%u), header_size %u, count %u\n", data
, data_size
, *data_size
, header_size
, count
);
604 /***********************************************************************
605 * GetRawInputDeviceInfoA (USER32.@)
607 UINT WINAPI
GetRawInputDeviceInfoA(HANDLE device
, UINT command
, void *data
, UINT
*data_size
)
609 TRACE("device %p, command %#x, data %p, data_size %p.\n",
610 device
, command
, data
, data_size
);
612 /* RIDI_DEVICENAME data_size is in chars, not bytes */
613 if (command
== RIDI_DEVICENAME
)
618 if (!data_size
) return ~0U;
620 nameW_sz
= *data_size
;
622 if (data
&& nameW_sz
> 0)
623 nameW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * nameW_sz
);
627 ret
= GetRawInputDeviceInfoW(device
, command
, nameW
, &nameW_sz
);
629 if (ret
&& ret
!= ~0U)
630 WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, data
, *data_size
, NULL
, NULL
);
632 *data_size
= nameW_sz
;
634 HeapFree(GetProcessHeap(), 0, nameW
);
639 return GetRawInputDeviceInfoW(device
, command
, data
, data_size
);
642 /***********************************************************************
643 * GetRawInputDeviceInfoW (USER32.@)
645 UINT WINAPI
GetRawInputDeviceInfoW(HANDLE handle
, UINT command
, void *data
, UINT
*data_size
)
647 /* FIXME: Most of this is made up. */
648 static const RID_DEVICE_INFO_KEYBOARD keyboard_info
= {0, 0, 1, 12, 3, 101};
649 static const RID_DEVICE_INFO_MOUSE mouse_info
= {1, 5, 0, FALSE
};
651 RID_DEVICE_INFO info
;
652 struct device
*device
= handle
;
654 UINT to_copy_bytes
, avail_bytes
;
656 TRACE("handle %p, command %#x, data %p, data_size %p.\n",
657 handle
, command
, data
, data_size
);
659 if (!data_size
) return ~0U;
661 /* each case below must set:
662 * *data_size: length (meaning defined by command) of data we want to copy
663 * avail_bytes: number of bytes available in user buffer
664 * to_copy_bytes: number of bytes we want to copy into user buffer
665 * to_copy: pointer to data we want to copy into user buffer
669 case RIDI_DEVICENAME
:
670 /* for RIDI_DEVICENAME, data_size is in characters, not bytes */
671 avail_bytes
= *data_size
* sizeof(WCHAR
);
672 if (handle
== WINE_MOUSE_HANDLE
)
674 *data_size
= ARRAY_SIZE(L
"\\\\?\\WINE_MOUSE");
675 to_copy
= L
"\\\\?\\WINE_MOUSE";
677 else if (handle
== WINE_KEYBOARD_HANDLE
)
679 *data_size
= ARRAY_SIZE(L
"\\\\?\\WINE_KEYBOARD");
680 to_copy
= L
"\\\\?\\WINE_KEYBOARD";
684 *data_size
= lstrlenW(device
->path
) + 1;
685 to_copy
= device
->path
;
687 to_copy_bytes
= *data_size
* sizeof(WCHAR
);
690 case RIDI_DEVICEINFO
:
691 avail_bytes
= *data_size
;
692 info
.cbSize
= sizeof(info
);
693 if (handle
== WINE_MOUSE_HANDLE
)
695 info
.dwType
= RIM_TYPEMOUSE
;
696 info
.u
.mouse
= mouse_info
;
698 else if (handle
== WINE_KEYBOARD_HANDLE
)
700 info
.dwType
= RIM_TYPEKEYBOARD
;
701 info
.u
.keyboard
= keyboard_info
;
707 to_copy_bytes
= sizeof(info
);
708 *data_size
= to_copy_bytes
;
712 case RIDI_PREPARSEDDATA
:
713 avail_bytes
= *data_size
;
714 if (handle
== WINE_MOUSE_HANDLE
|| handle
== WINE_KEYBOARD_HANDLE
||
715 device
->info
.dwType
!= RIM_TYPEHID
)
723 to_copy_bytes
= ((WINE_HIDP_PREPARSED_DATA
*)device
->data
)->dwSize
;
724 *data_size
= to_copy_bytes
;
725 to_copy
= device
->data
;
730 FIXME("command %#x not supported\n", command
);
737 if (avail_bytes
< to_copy_bytes
)
740 memcpy(data
, to_copy
, to_copy_bytes
);
745 static int __cdecl
compare_raw_input_devices(const void *ap
, const void *bp
)
747 const RAWINPUTDEVICE a
= *(const RAWINPUTDEVICE
*)ap
;
748 const RAWINPUTDEVICE b
= *(const RAWINPUTDEVICE
*)bp
;
750 if (a
.usUsagePage
!= b
.usUsagePage
) return a
.usUsagePage
- b
.usUsagePage
;
751 if (a
.usUsage
!= b
.usUsage
) return a
.usUsage
- b
.usUsage
;
755 /***********************************************************************
756 * GetRegisteredRawInputDevices (USER32.@)
758 UINT WINAPI DECLSPEC_HOTPATCH
GetRegisteredRawInputDevices(RAWINPUTDEVICE
*devices
, UINT
*device_count
, UINT size
)
760 struct rawinput_device
*buffer
= NULL
;
761 unsigned int i
, status
, count
= ~0U, buffer_size
;
763 TRACE("devices %p, device_count %p, size %u\n", devices
, device_count
, size
);
765 if (size
!= sizeof(RAWINPUTDEVICE
) || !device_count
|| (devices
&& !*device_count
))
767 SetLastError(ERROR_INVALID_PARAMETER
);
771 buffer_size
= *device_count
* sizeof(*buffer
);
772 if (devices
&& !(buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
)))
775 SERVER_START_REQ(get_rawinput_devices
)
777 if (buffer
) wine_server_set_reply(req
, buffer
, buffer_size
);
778 status
= wine_server_call_err(req
);
779 *device_count
= reply
->device_count
;
783 if (buffer
&& !status
)
785 for (i
= 0, count
= *device_count
; i
< count
; ++i
)
787 devices
[i
].usUsagePage
= buffer
[i
].usage_page
;
788 devices
[i
].usUsage
= buffer
[i
].usage
;
789 devices
[i
].dwFlags
= buffer
[i
].flags
;
790 devices
[i
].hwndTarget
= wine_server_ptr_handle(buffer
[i
].target
);
793 qsort(devices
, count
, sizeof(*devices
), compare_raw_input_devices
);
796 if (buffer
) HeapFree(GetProcessHeap(), 0, buffer
);
802 /***********************************************************************
803 * DefRawInputProc (USER32.@)
805 LRESULT WINAPI
DefRawInputProc(RAWINPUT
**data
, INT data_count
, UINT header_size
)
807 FIXME("data %p, data_count %d, header_size %u stub!\n", data
, data_count
, header_size
);