wineconsole: Try harder to get a scalable font.
[wine.git] / dlls / user32 / rawinput.c
blobcf3028a4ec19678eb9a094c5f236b0c06e8afaf8
1 /*
2 * Raw Input
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
22 #include "config.h"
23 #include <stdarg.h>
25 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winnls.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "setupapi.h"
33 #include "ddk/hidsdi.h"
34 #include "wine/debug.h"
35 #include "wine/server.h"
37 #include "user_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
41 struct hid_device
43 WCHAR *path;
44 HANDLE file;
45 RID_DEVICE_INFO_HID info;
46 PHIDP_PREPARSED_DATA data;
49 static struct hid_device *hid_devices;
50 static unsigned int hid_devices_count, hid_devices_max;
52 static CRITICAL_SECTION hid_devices_cs;
53 static CRITICAL_SECTION_DEBUG hid_devices_cs_debug =
55 0, 0, &hid_devices_cs,
56 { &hid_devices_cs_debug.ProcessLocksList, &hid_devices_cs_debug.ProcessLocksList },
57 0, 0, { (DWORD_PTR)(__FILE__ ": hid_devices_cs") }
59 static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 };
61 static void find_hid_devices(void)
63 static ULONGLONG last_check;
65 SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) };
66 SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
67 DWORD detail_size, needed;
68 HIDD_ATTRIBUTES attr;
69 DWORD idx, didx;
70 HIDP_CAPS caps;
71 GUID hid_guid;
72 HDEVINFO set;
73 HANDLE file;
74 WCHAR *path;
76 if (GetTickCount64() - last_check < 2000)
77 return;
78 last_check = GetTickCount64();
80 HidD_GetHidGuid(&hid_guid);
82 set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
84 detail_size = sizeof(*detail) + (MAX_PATH * sizeof(WCHAR));
85 if (!(detail = heap_alloc(detail_size)))
86 return;
87 detail->cbSize = sizeof(*detail);
89 EnterCriticalSection(&hid_devices_cs);
91 /* destroy previous list */
92 for (didx = 0; didx < hid_devices_count; ++didx)
94 CloseHandle(hid_devices[didx].file);
95 heap_free(hid_devices[didx].path);
98 didx = 0;
99 for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx)
101 if (!SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, detail_size, &needed, NULL))
103 if (!(detail = heap_realloc(detail, needed)))
105 ERR("Failed to allocate memory.\n");
106 goto done;
108 detail_size = needed;
110 SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, detail_size, NULL, NULL);
113 if (!(path = heap_strdupW(detail->DevicePath)))
115 ERR("Failed to allocate memory.\n");
116 goto done;
119 file = CreateFileW(path, GENERIC_READ | GENERIC_WRITE,
120 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
121 if (file == INVALID_HANDLE_VALUE)
123 ERR("Failed to open device file %s, error %u.\n", debugstr_w(path), GetLastError());
124 heap_free(path);
125 continue;
128 if (didx >= hid_devices_max)
130 if (hid_devices)
132 hid_devices_max *= 2;
133 hid_devices = heap_realloc(hid_devices,
134 hid_devices_max * sizeof(hid_devices[0]));
136 else
138 hid_devices_max = 8;
139 hid_devices = heap_alloc(hid_devices_max * sizeof(hid_devices[0]));
141 if (!hid_devices)
143 ERR("Failed to allocate memory.\n");
144 goto done;
148 TRACE("Found HID device %s.\n", debugstr_w(path));
150 hid_devices[didx].path = path;
151 hid_devices[didx].file = file;
153 attr.Size = sizeof(HIDD_ATTRIBUTES);
154 if (!HidD_GetAttributes(file, &attr))
155 WARN_(rawinput)("Failed to get attributes.\n");
156 hid_devices[didx].info.dwVendorId = attr.VendorID;
157 hid_devices[didx].info.dwProductId = attr.ProductID;
158 hid_devices[didx].info.dwVersionNumber = attr.VersionNumber;
160 if (!HidD_GetPreparsedData(file, &hid_devices[didx].data))
161 WARN_(rawinput)("Failed to get preparsed data.\n");
163 if (!HidP_GetCaps(hid_devices[didx].data, &caps))
164 WARN_(rawinput)("Failed to get caps.\n");
166 hid_devices[didx].info.usUsagePage = caps.UsagePage;
167 hid_devices[didx].info.usUsage = caps.Usage;
169 didx++;
171 hid_devices_count = didx;
173 done:
174 LeaveCriticalSection(&hid_devices_cs);
175 heap_free(detail);
178 /***********************************************************************
179 * GetRawInputDeviceList (USER32.@)
181 UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size)
183 UINT i;
185 TRACE("devices %p, device_count %p, size %u.\n", devices, device_count, size);
187 if (size != sizeof(*devices))
189 SetLastError(ERROR_INVALID_PARAMETER);
190 return ~0U;
193 if (!device_count)
195 SetLastError(ERROR_NOACCESS);
196 return ~0U;
199 find_hid_devices();
201 if (!devices)
203 *device_count = 2 + hid_devices_count;
204 return 0;
207 if (*device_count < 2 + hid_devices_count)
209 SetLastError(ERROR_INSUFFICIENT_BUFFER);
210 *device_count = 2 + hid_devices_count;
211 return ~0U;
214 devices[0].hDevice = WINE_MOUSE_HANDLE;
215 devices[0].dwType = RIM_TYPEMOUSE;
216 devices[1].hDevice = WINE_KEYBOARD_HANDLE;
217 devices[1].dwType = RIM_TYPEKEYBOARD;
219 for (i = 0; i < hid_devices_count; ++i)
221 devices[2 + i].hDevice = &hid_devices[i];
222 devices[2 + i].dwType = RIM_TYPEHID;
225 return 2 + hid_devices_count;
228 /***********************************************************************
229 * RegisterRawInputDevices (USER32.@)
231 BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, UINT device_count, UINT size)
233 struct rawinput_device *d;
234 BOOL ret;
235 UINT i;
237 TRACE("devices %p, device_count %u, size %u.\n", devices, device_count, size);
239 if (size != sizeof(*devices))
241 WARN("Invalid structure size %u.\n", size);
242 return FALSE;
245 if (!(d = HeapAlloc( GetProcessHeap(), 0, device_count * sizeof(*d) ))) return FALSE;
247 for (i = 0; i < device_count; ++i)
249 TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
250 i, devices[i].usUsagePage, devices[i].usUsage,
251 devices[i].dwFlags, devices[i].hwndTarget);
252 if (devices[i].dwFlags & ~RIDEV_REMOVE)
253 FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
255 d[i].usage_page = devices[i].usUsagePage;
256 d[i].usage = devices[i].usUsage;
257 d[i].flags = devices[i].dwFlags;
258 d[i].target = wine_server_user_handle( devices[i].hwndTarget );
261 SERVER_START_REQ( update_rawinput_devices )
263 wine_server_add_data( req, d, device_count * sizeof(*d) );
264 ret = !wine_server_call( req );
266 SERVER_END_REQ;
268 HeapFree( GetProcessHeap(), 0, d );
270 return ret;
273 /***********************************************************************
274 * GetRawInputData (USER32.@)
276 UINT WINAPI GetRawInputData(HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size)
278 RAWINPUT *ri = (RAWINPUT *)rawinput;
279 UINT s;
281 TRACE("rawinput %p, command %#x, data %p, data_size %p, header_size %u.\n",
282 rawinput, command, data, data_size, header_size);
284 if (header_size != sizeof(RAWINPUTHEADER))
286 WARN("Invalid structure size %u.\n", header_size);
287 return ~0U;
290 switch (command)
292 case RID_INPUT:
293 s = ri->header.dwSize;
294 break;
295 case RID_HEADER:
296 s = sizeof(RAWINPUTHEADER);
297 break;
298 default:
299 return ~0U;
302 if (!data)
304 *data_size = s;
305 return 0;
308 if (*data_size < s) return ~0U;
309 memcpy(data, ri, s);
310 return s;
313 /***********************************************************************
314 * GetRawInputBuffer (USER32.@)
316 UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, UINT header_size)
318 FIXME("data %p, data_size %p, header_size %u stub!\n", data, data_size, header_size);
320 return 0;
323 /***********************************************************************
324 * GetRawInputDeviceInfoA (USER32.@)
326 UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT *data_size)
328 UINT ret;
330 TRACE("device %p, command %#x, data %p, data_size %p.\n",
331 device, command, data, data_size);
333 ret = GetRawInputDeviceInfoW(device, command, data, data_size);
334 if (command == RIDI_DEVICENAME && ret && ret != ~0U)
335 ret = WideCharToMultiByte(CP_ACP, 0, data, -1, data, *data_size, NULL, NULL);
337 return ret;
340 /***********************************************************************
341 * GetRawInputDeviceInfoW (USER32.@)
343 UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT *data_size)
345 /* FIXME: Most of this is made up. */
346 static const WCHAR keyboard_name[] = {'\\','\\','?','\\','W','I','N','E','_','K','E','Y','B','O','A','R','D',0};
347 static const WCHAR mouse_name[] = {'\\','\\','?','\\','W','I','N','E','_','M','O','U','S','E',0};
348 static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101};
349 static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE};
350 struct hid_device *hid_device;
351 const WCHAR *name = NULL;
352 RID_DEVICE_INFO *info;
353 UINT s;
355 TRACE("device %p, command %#x, data %p, data_size %p.\n",
356 device, command, data, data_size);
358 if (!data_size) return ~0U;
360 switch (command)
362 case RIDI_DEVICENAME:
363 if (device == WINE_MOUSE_HANDLE)
365 s = sizeof(mouse_name);
366 name = mouse_name;
368 else if (device == WINE_KEYBOARD_HANDLE)
370 s = sizeof(keyboard_name);
371 name = keyboard_name;
373 else
375 hid_device = device;
376 s = (strlenW(hid_device->path) + 1) * sizeof(WCHAR);
377 name = hid_device->path;
379 break;
380 case RIDI_DEVICEINFO:
381 s = sizeof(*info);
382 break;
383 default:
384 return ~0U;
387 if (!data)
389 *data_size = s;
390 return 0;
393 if (*data_size < s)
395 *data_size = s;
396 return ~0U;
399 if (command == RIDI_DEVICENAME)
401 memcpy(data, name, s);
402 return s;
405 info = data;
406 info->cbSize = sizeof(*info);
407 if (device == WINE_MOUSE_HANDLE)
409 info->dwType = RIM_TYPEMOUSE;
410 info->u.mouse = mouse_info;
412 else if (device == WINE_KEYBOARD_HANDLE)
414 info->dwType = RIM_TYPEKEYBOARD;
415 info->u.keyboard = keyboard_info;
417 else
419 hid_device = device;
420 info->dwType = RIM_TYPEHID;
421 info->u.hid = hid_device->info;
423 return s;
426 /***********************************************************************
427 * GetRegisteredRawInputDevices (USER32.@)
429 UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(RAWINPUTDEVICE *devices, UINT *device_count, UINT size)
431 FIXME("devices %p, device_count %p, size %u stub!\n", devices, device_count, size);
433 return 0;
437 /***********************************************************************
438 * DefRawInputProc (USER32.@)
440 LRESULT WINAPI DefRawInputProc(RAWINPUT **data, INT data_count, UINT header_size)
442 FIXME("data %p, data_count %d, header_size %u stub!\n", data, data_count, header_size);
444 return 0;