Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winexinput.sys/main.c | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
diff --git a/dlls/winexinput.sys/main.c b/dlls/winexinput.sys/main.c index 3832c97ef26..667ce867269 100644 --- a/dlls/winexinput.sys/main.c +++ b/dlls/winexinput.sys/main.c @@ -32,6 +32,7 @@ #include "ddk/wdm.h" #include "ddk/hidport.h" #include "ddk/hidpddi.h" +#include "ddk/hidtypes.h"
#include "wine/asm.h" #include "wine/debug.h" @@ -314,17 +315,76 @@ static NTSTATUS try_complete_pending_read(DEVICE_OBJECT *device, IRP *irp) return IoCallDriver(fdo->bus_device, xinput_irp); }
+struct device_strings +{ + const WCHAR *id; + const WCHAR *product; +}; + +static const struct device_strings device_strings[] = +{ + { .id = L"VID_045E&PID_028E&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, + { .id = L"VID_045E&PID_028F&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, + { .id = L"VID_045E&PID_02D1&IG_00", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02DD&IG_00", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02E3&IG_00", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02EA&IG_00", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02FD&IG_00", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_0719&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, +}; + +static const WCHAR *find_product_string(const WCHAR *device_id) +{ + const WCHAR *match_id = wcsrchr(device_id, '\') + 1; + DWORD i; + + for (i = 0; i < ARRAY_SIZE(device_strings); ++i) + if (!wcsicmp(device_strings[i].id, match_id)) + return device_strings[i].product; + + return NULL; +} + static NTSTATUS WINAPI gamepad_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); ULONG output_len = stack->Parameters.DeviceIoControl.OutputBufferLength; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; struct func_device *fdo = fdo_from_DEVICE_OBJECT(device); + struct device *impl = impl_from_DEVICE_OBJECT(device); + const WCHAR *str = NULL;
TRACE("device %p, irp %p, code %#x, bus_device %p.\n", device, irp, code, fdo->bus_device);
switch (code) { + case IOCTL_HID_GET_STRING: + switch ((ULONG_PTR)stack->Parameters.DeviceIoControl.Type3InputBuffer) + { + case HID_STRING_ID_IPRODUCT: + str = find_product_string(impl->device_id); + break; + } + + if (!str) + { + IoSkipCurrentIrpStackLocation(irp); + return IoCallDriver(fdo->bus_device, irp); + } + + irp->IoStatus.Information = (wcslen(str) + 1) * sizeof(WCHAR); + if (output_len < irp->IoStatus.Information) + { + irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_BUFFER_TOO_SMALL; + } + + wcscpy(irp->UserBuffer, str); + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + case IOCTL_HID_GET_DEVICE_DESCRIPTOR: { HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer;