winebus.sys: Convert the product strings to Unicode on the Unix-side.

This avoids keeping two copies of each string.

It also fixes a regression on macOS from commit 9d4b70473c
that incorrectly treated a CFStringRef as a char ptr.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2021-10-05 09:55:50 +01:00 committed by Alexandre Julliard
parent e9178864a7
commit 43cd5d8a2d
6 changed files with 64 additions and 48 deletions

View File

@ -130,6 +130,13 @@ static struct iohid_device *find_device_from_iohid(IOHIDDeviceRef IOHIDDevice)
return NULL;
}
static void CFStringToWSTR(CFStringRef cstr, LPWSTR wstr, int length)
{
int len = min(CFStringGetLength(cstr), length - 1);
CFStringGetCharacters(cstr, CFRangeMake(0, len), (UniChar*)wstr);
wstr[len] = 0;
}
static DWORD CFNumberToDWORD(CFNumberRef num)
{
int dwNum = 0;
@ -265,10 +272,10 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
struct device_desc desc =
{
.input = -1,
.serialnumber = {"0000"},
.serialnumber = {'0','0','0','0',0},
};
struct iohid_device *impl;
CFStringRef str = NULL;
CFStringRef str;
desc.vid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDVendorIDKey)));
desc.pid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDProductIDKey)));
@ -283,11 +290,11 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
IOHIDDeviceScheduleWithRunLoop(IOHIDDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
str = IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDManufacturerKey));
if (str) lstrcpynA(desc.manufacturer, str, sizeof(desc.manufacturer));
if (str) CFStringToWSTR(str, desc.manufacturer, ARRAY_SIZE(desc.manufacturer));
str = IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDProductKey));
if (str) lstrcpynA(desc.product, str, sizeof(desc.product));
if (str) CFStringToWSTR(str, desc.product, ARRAY_SIZE(desc.product));
str = IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDSerialNumberKey));
if (str) lstrcpynA(desc.serialnumber, str, sizeof(desc.serialnumber));
if (str) CFStringToWSTR(str, desc.serialnumber, ARRAY_SIZE(desc.serialnumber));
if (IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad) ||
IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))

View File

@ -51,6 +51,7 @@
#include "wine/debug.h"
#include "wine/hid.h"
#include "wine/unixlib.h"
#include "unix_private.h"
@ -693,8 +694,8 @@ static void sdl_add_device(unsigned int index)
struct device_desc desc =
{
.input = -1,
.manufacturer = {"SDL"},
.serialnumber = {"0000"},
.manufacturer = {'S','D','L',0},
.serialnumber = {'0','0','0','0',0},
};
struct sdl_device *impl;
@ -702,6 +703,8 @@ static void sdl_add_device(unsigned int index)
SDL_JoystickID id;
SDL_JoystickGUID guid;
SDL_GameController *controller = NULL;
const char *str;
char guid_str[33];
if ((joystick = pSDL_JoystickOpen(index)) == NULL)
{
@ -712,8 +715,9 @@ static void sdl_add_device(unsigned int index)
if (options.map_controllers && pSDL_IsGameController(index))
controller = pSDL_GameControllerOpen(index);
if (controller) lstrcpynA(desc.product, pSDL_GameControllerName(controller), sizeof(desc.product));
else lstrcpynA(desc.product, pSDL_JoystickName(joystick), sizeof(desc.product));
if (controller) str = pSDL_GameControllerName(controller);
else str = pSDL_JoystickName(joystick);
if (str) ntdll_umbstowcs(str, strlen(str) + 1, desc.product, ARRAY_SIZE(desc.product));
id = pSDL_JoystickInstanceID(joystick);
@ -730,7 +734,8 @@ static void sdl_add_device(unsigned int index)
}
guid = pSDL_JoystickGetGUID(joystick);
pSDL_JoystickGetGUIDString(guid, desc.serialnumber, sizeof(desc.serialnumber));
pSDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
ntdll_umbstowcs(guid_str, strlen(guid_str) + 1, desc.serialnumber, ARRAY_SIZE(desc.serialnumber));
if (controller) desc.is_gamepad = TRUE;
else

View File

@ -73,6 +73,7 @@
#include "wine/debug.h"
#include "wine/hid.h"
#include "wine/unixlib.h"
#ifdef HAS_PROPER_INPUT_HEADER
# include "hidusage.h"
@ -1061,8 +1062,10 @@ static void get_device_subsystem_info(struct udev_device *dev, char const *subsy
if (!strncmp(ptr, "HID_UNIQ=", 9))
{
char buffer[MAX_PATH];
if (desc->serialnumber[0]) continue;
sscanf(ptr, "HID_UNIQ=%256s\n", desc->serialnumber);
if (sscanf(ptr, "HID_UNIQ=%256s\n", buffer) == 1)
ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc->serialnumber, ARRAY_SIZE(desc->serialnumber));
}
if (!strncmp(ptr, "HID_PHYS=", 9) || !strncmp(ptr, "PHYS=\"", 6))
{
@ -1086,13 +1089,13 @@ static void get_device_subsystem_info(struct udev_device *dev, char const *subsy
}
if (!desc->manufacturer[0] && (tmp = udev_device_get_sysattr_value(dev, "manufacturer")))
lstrcpynA(desc->manufacturer, tmp, sizeof(desc->manufacturer));
ntdll_umbstowcs(tmp, strlen(tmp) + 1, desc->manufacturer, ARRAY_SIZE(desc->manufacturer));
if (!desc->product[0] && (tmp = udev_device_get_sysattr_value(dev, "product")))
lstrcpynA(desc->product, tmp, sizeof(desc->product));
ntdll_umbstowcs(tmp, strlen(tmp) + 1, desc->product, ARRAY_SIZE(desc->product));
if (!desc->serialnumber[0] && (tmp = udev_device_get_sysattr_value(dev, "serial")))
lstrcpynA(desc->serialnumber, tmp, sizeof(desc->serialnumber));
ntdll_umbstowcs(tmp, strlen(tmp) + 1, desc->serialnumber, ARRAY_SIZE(desc->serialnumber));
}
static void udev_add_device(struct udev_device *dev)
@ -1133,17 +1136,22 @@ static void udev_add_device(struct udev_device *dev)
subsystem = udev_device_get_subsystem(dev);
if (!strcmp(subsystem, "hidraw"))
{
if (!desc.manufacturer[0]) strcpy(desc.manufacturer, "hidraw");
static const WCHAR hidraw[] = {'h','i','d','r','a','w',0};
char product[MAX_PATH];
if (!desc.manufacturer[0]) memcpy(desc.manufacturer, hidraw, sizeof(hidraw));
#ifdef HAVE_LINUX_HIDRAW_H
if (!desc.product[0] && ioctl(fd, HIDIOCGRAWNAME(sizeof(desc.product) - 1), desc.product) < 0)
desc.product[0] = 0;
if (!desc.product[0] && ioctl(fd, HIDIOCGRAWNAME(sizeof(product) - 1), product) >= 0)
ntdll_umbstowcs(product, strlen(product) + 1, desc.product, ARRAY_SIZE(desc.product));
#endif
}
#ifdef HAS_PROPER_INPUT_HEADER
else if (!strcmp(subsystem, "input"))
{
static const WCHAR evdev[] = {'e','v','d','e','v',0};
struct input_id device_id = {0};
char buffer[MAX_PATH];
if (ioctl(fd, EVIOCGID, &device_id) < 0)
WARN("ioctl(EVIOCGID) failed: %d %s\n", errno, strerror(errno));
@ -1154,17 +1162,21 @@ static void udev_add_device(struct udev_device *dev)
desc.version = device_id.version;
}
if (!desc.manufacturer[0]) strcpy(desc.manufacturer, "evdev");
if (!desc.manufacturer[0]) memcpy(desc.manufacturer, evdev, sizeof(evdev));
if (!desc.product[0] && ioctl(fd, EVIOCGNAME(sizeof(desc.product) - 1), desc.product) <= 0)
desc.product[0] = 0;
if (!desc.product[0] && ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), buffer) > 0)
ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.product, ARRAY_SIZE(desc.product));
if (!desc.serialnumber[0] && ioctl(fd, EVIOCGUNIQ(sizeof(desc.serialnumber)), desc.serialnumber) < 0)
desc.serialnumber[0] = 0;
if (!desc.serialnumber[0] && ioctl(fd, EVIOCGUNIQ(sizeof(buffer)), buffer) >= 0)
ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.serialnumber, ARRAY_SIZE(desc.serialnumber));
}
#endif
if (!desc.serialnumber[0]) strcpy(desc.serialnumber, "0000");
if (!desc.serialnumber[0])
{
static const WCHAR zeros[] = {'0','0','0','0',0};
memcpy(desc.serialnumber, zeros, sizeof(zeros));
}
if (is_xbox_gamepad(desc.vid, desc.pid))
desc.is_gamepad = TRUE;

View File

@ -70,10 +70,6 @@ struct device_extension
struct device_desc desc;
DWORD index;
WCHAR manufacturer[MAX_PATH];
WCHAR product[MAX_PATH];
WCHAR serialnumber[MAX_PATH];
BYTE *last_report;
DWORD last_report_size;
BOOL last_report_read;
@ -180,11 +176,11 @@ static DWORD get_device_index(struct device_desc *desc)
static WCHAR *get_instance_id(DEVICE_OBJECT *device)
{
struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
DWORD len = wcslen(ext->serialnumber) + 33;
DWORD len = wcslen(ext->desc.serialnumber) + 33;
WCHAR *dst;
if ((dst = ExAllocatePool(PagedPool, len * sizeof(WCHAR))))
swprintf(dst, len, L"%i&%s&%x&%i", ext->desc.version, ext->serialnumber, ext->desc.uid, ext->index);
swprintf(dst, len, L"%i&%s&%x&%i", ext->desc.version, ext->desc.serialnumber, ext->desc.uid, ext->index);
return dst;
}
@ -299,10 +295,6 @@ static DEVICE_OBJECT *bus_create_hid_device(struct device_desc *desc, struct uni
ext->buffer_size = 0;
ext->unix_device = unix_device;
MultiByteToWideChar(CP_UNIXCP, 0, ext->desc.manufacturer, -1, ext->manufacturer, MAX_PATH);
MultiByteToWideChar(CP_UNIXCP, 0, ext->desc.product, -1, ext->product, MAX_PATH);
MultiByteToWideChar(CP_UNIXCP, 0, ext->desc.serialnumber, -1, ext->serialnumber, MAX_PATH);
InitializeListHead(&ext->irp_queue);
InitializeCriticalSection(&ext->cs);
ext->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
@ -894,19 +886,19 @@ static NTSTATUS hid_get_device_string(DEVICE_OBJECT *device, DWORD index, WCHAR
switch (index)
{
case HID_STRING_ID_IMANUFACTURER:
len = (wcslen(ext->manufacturer) + 1) * sizeof(WCHAR);
len = (wcslen(ext->desc.manufacturer) + 1) * sizeof(WCHAR);
if (len > buffer_len) return STATUS_BUFFER_TOO_SMALL;
else memcpy(buffer, ext->manufacturer, len);
else memcpy(buffer, ext->desc.manufacturer, len);
return STATUS_SUCCESS;
case HID_STRING_ID_IPRODUCT:
len = (wcslen(ext->product) + 1) * sizeof(WCHAR);
len = (wcslen(ext->desc.product) + 1) * sizeof(WCHAR);
if (len > buffer_len) return STATUS_BUFFER_TOO_SMALL;
else memcpy(buffer, ext->product, len);
else memcpy(buffer, ext->desc.product, len);
return STATUS_SUCCESS;
case HID_STRING_ID_ISERIALNUMBER:
len = (wcslen(ext->serialnumber) + 1) * sizeof(WCHAR);
len = (wcslen(ext->desc.serialnumber) + 1) * sizeof(WCHAR);
if (len > buffer_len) return STATUS_BUFFER_TOO_SMALL;
else memcpy(buffer, ext->serialnumber, len);
else memcpy(buffer, ext->desc.serialnumber, len);
return STATUS_SUCCESS;
}

View File

@ -125,9 +125,9 @@ static const struct device_desc mouse_device_desc =
.vid = 0x845e,
.pid = 0x0001,
.input = -1,
.manufacturer = {"The Wine Project"},
.product = {"Wine HID mouse"},
.serialnumber = {"0000"},
.manufacturer = {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0},
.product = {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0},
.serialnumber = {'0','0','0','0',0},
};
static NTSTATUS mouse_device_create(void *args)
@ -202,9 +202,9 @@ static const struct device_desc keyboard_device_desc =
.vid = 0x845e,
.pid = 0x0002,
.input = -1,
.manufacturer = {"The Wine Project"},
.product = {"Wine HID keyboard"},
.serialnumber = {"0000"},
.manufacturer = {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0},
.product = {'W','i','n','e',' ','H','I','D',' ','k','e','y','b','o','a','r','d',0},
.serialnumber = {'0','0','0','0',0},
};
static NTSTATUS keyboard_device_create(void *args)

View File

@ -39,9 +39,9 @@ struct device_desc
DWORD uid;
BOOL is_gamepad;
char manufacturer[MAX_PATH];
char product[MAX_PATH];
char serialnumber[MAX_PATH];
WCHAR manufacturer[MAX_PATH];
WCHAR product[MAX_PATH];
WCHAR serialnumber[MAX_PATH];
};
struct sdl_bus_options