[PATCH] winebus.sys: Convert the product strings to unicode on the unix-side.

Huw Davies huw at codeweavers.com
Tue Oct 5 03:55:50 CDT 2021


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 <huw at codeweavers.com>
---
 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 33386a80a34..4e4f275fbc9 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"
 
@@ -589,8 +590,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;
 
@@ -598,6 +599,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)
     {
@@ -608,8 +611,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);
 
@@ -626,7 +630,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 3db261b2404..90213b7cd5b 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"
@@ -945,8 +946,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))
             {
@@ -970,13 +973,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)
@@ -1017,17 +1020,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));
@@ -1038,17 +1046,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 29537170df7..d14fb30d917 100644
--- a/dlls/winebus.sys/unixlib.c
+++ b/dlls/winebus.sys/unixlib.c
@@ -114,9 +114,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)
@@ -184,9 +184,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
-- 
2.25.1




More information about the wine-devel mailing list