From 43cd5d8a2d54fe6dc5f4c21e9e9e57b2c0ed255b Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 5 Oct 2021 09:55:50 +0100 Subject: [PATCH] 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 9d4b70473c147b that incorrectly treated a CFStringRef as a char ptr. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/winebus.sys/bus_iohid.c | 17 +++++++++++----- dlls/winebus.sys/bus_sdl.c | 15 +++++++++----- dlls/winebus.sys/bus_udev.c | 38 ++++++++++++++++++++++++------------ dlls/winebus.sys/main.c | 24 ++++++++--------------- dlls/winebus.sys/unixlib.c | 12 ++++++------ dlls/winebus.sys/unixlib.h | 6 +++--- 6 files changed, 64 insertions(+), 48 deletions(-) diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index a450402e87b..4412a4bf6dd 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -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)) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index de1aa2363fd..4eab51b5cb2 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -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 diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 08ca8435d31..0aade2fd104 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -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; diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index b5130a7908e..6a4695cd3be 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -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; } diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 790becf4bc3..ea26094049e 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -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) diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index 317599571c2..e3996838c61 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -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