Преглед изворни кода

fixed serial port name encoding - fixes #6200

Eugene Pankov пре 3 година
родитељ
комит
4c242fdca4
1 измењених фајлова са 327 додато и 0 уклоњено
  1. 327 0
      app/patches/@serialport+bindings-cpp+10.7.0.patch

+ 327 - 0
app/patches/@serialport+bindings-cpp+10.7.0.patch

@@ -0,0 +1,327 @@
+diff --git a/node_modules/@serialport/bindings-cpp/src/serialport_win.cpp b/node_modules/@serialport/bindings-cpp/src/serialport_win.cpp
+index b11c07f..910023e 100644
+--- a/node_modules/@serialport/bindings-cpp/src/serialport_win.cpp
++++ b/node_modules/@serialport/bindings-cpp/src/serialport_win.cpp
+@@ -10,6 +10,7 @@
+ #include <initguid.h>
+ #include <devpkey.h>
+ #include <devguid.h>
++#include <wchar.h>
+ #pragma comment(lib, "setupapi.lib")
+ 
+ #define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))
+@@ -25,6 +26,29 @@ typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
+ 
+ std::list<int> g_closingHandles;
+ 
++void ErrorCodeToString(const wchar_t* prefix, int errorCode, wchar_t *errorStr) {
++  switch (errorCode) {
++  case ERROR_FILE_NOT_FOUND:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: File not found", prefix);
++    break;
++  case ERROR_INVALID_HANDLE:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Invalid handle", prefix);
++    break;
++  case ERROR_ACCESS_DENIED:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Access denied", prefix);
++    break;
++  case ERROR_OPERATION_ABORTED:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Operation aborted", prefix);
++    break;
++  case ERROR_INVALID_PARAMETER:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: The parameter is incorrect %d", prefix, errorCode);
++    break;
++  default:
++    _snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Unknown error code %d", prefix, errorCode);
++    break;
++  }
++}
++
+ void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
+   switch (errorCode) {
+   case ERROR_FILE_NOT_FOUND:
+@@ -608,9 +632,9 @@ void CloseBaton::Execute() {
+   }
+ }
+ 
+-char *copySubstring(char *someString, int n) {
+-  char *new_ = reinterpret_cast<char*>(malloc(sizeof(char)*n + 1));
+-  strncpy_s(new_, n + 1, someString, n);
++wchar_t *copySubstring(wchar_t *someString, int n) {
++  wchar_t *new_ = reinterpret_cast<wchar_t*>(malloc(sizeof(wchar_t)*n + 1));
++  wcsncpy_s(new_, n + 1, someString, n);
+   new_[n] = '\0';
+   return new_;
+ }
+@@ -625,7 +649,7 @@ Napi::Value List(const Napi::CallbackInfo& info) {
+ 
+   Napi::Function callback = info[0].As<Napi::Function>();
+   ListBaton* baton = new ListBaton(callback);
+-  snprintf(baton->errorString, sizeof(baton->errorString), "");
++  _snwprintf(baton->errorString, sizeof(baton->errorString), L"");
+ 
+   baton->Queue();
+   return env.Undefined();
+@@ -633,20 +657,20 @@ Napi::Value List(const Napi::CallbackInfo& info) {
+ 
+ // It's possible that the s/n is a construct and not the s/n of the parent USB
+ // composite device. This performs some convoluted registry lookups to fetch the USB s/n.
+-void getSerialNumber(const char *vid,
+-                     const char *pid,
++void getSerialNumber(const wchar_t *vid,
++                     const wchar_t *pid,
+                      const HDEVINFO hDevInfo,
+                      SP_DEVINFO_DATA deviceInfoData,
+                      const unsigned int maxSerialNumberLength,
+-                     char* serialNumber) {
+-  _snprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, "");
++                     wchar_t* serialNumber) {
++  _snwprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, L"");
+   if (vid == NULL || pid == NULL) {
+     return;
+   }
+ 
+   DWORD dwSize;
+   WCHAR szWUuidBuffer[MAX_BUFFER_SIZE];
+-  WCHAR containerUuid[MAX_BUFFER_SIZE];
++  WCHAR wantedUuid[MAX_BUFFER_SIZE];
+ 
+ 
+   // Fetch the "Container ID" for this device node. In USB context, this "Container
+@@ -683,7 +707,7 @@ void getSerialNumber(const char *vid,
+ 
+     // Given the UUID bytes, build up a (widechar) string from it. There's some mangling
+     // going on.
+-    StringFromGUID2((REFGUID)szWUuidBuffer, containerUuid, ARRAY_SIZE(containerUuid));
++    StringFromGUID2((REFGUID)szWUuidBuffer, wantedUuid, ARRAY_SIZE(wantedUuid));
+   } else {
+     // Container UUID could not be fetched, return empty serial number.
+     return;
+@@ -693,21 +717,15 @@ void getSerialNumber(const char *vid,
+   // This means they're non-removable, and are not handled (yet).
+   // Maybe they should inherit the s/n from somewhere else.
+ 
+-  // Sanitize input - for whatever reason, StringFromGUID2() returns a WCHAR* but
+-  // the comparisons later need a plain old char*, in lowercase ASCII.
+-  char wantedUuid[MAX_BUFFER_SIZE];
+-  _snprintf_s(wantedUuid, MAX_BUFFER_SIZE, _TRUNCATE, "%ws", containerUuid);
+-  strlwr(wantedUuid);
+-
+   // Iterate through all the USB devices with the given VendorID/ProductID
+ 
+   HKEY vendorProductHKey;
+   DWORD retCode;
+-  char hkeyPath[MAX_BUFFER_SIZE];
++  wchar_t hkeyPath[MAX_BUFFER_SIZE];
+ 
+-  _snprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE, "SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s", vid, pid);
++  _snwprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE, L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s", vid, pid);
+ 
+-  retCode = RegOpenKeyEx(
++  retCode = RegOpenKeyExW(
+     HKEY_LOCAL_MACHINE,
+     hkeyPath,
+     0,
+@@ -739,9 +757,9 @@ void getSerialNumber(const char *vid,
+           // Each of the subkeys here is the serial number of a USB device with the
+           // given VendorId/ProductId. Now fetch the string for the S/N.
+           DWORD serialNumberLength = maxSerialNumberLength;
+-          retCode = RegEnumKeyEx(vendorProductHKey,
++          retCode = RegEnumKeyExW(vendorProductHKey,
+                                   i,
+-                                  serialNumber,
++                                  reinterpret_cast<LPWSTR>(serialNumber),
+                                   &serialNumberLength,
+                                   NULL,
+                                   NULL,
+@@ -751,21 +769,21 @@ void getSerialNumber(const char *vid,
+           if (retCode == ERROR_SUCCESS) {
+             // Lookup info for VID_(vendorId)&PID_(productId)\(serialnumber)
+ 
+-            _snprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE,
+-                        "SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s\\%s",
++            _snwprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE,
++                        L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%ls&PID_%ls\\%ls",
+                         vid, pid, serialNumber);
+ 
+             HKEY deviceHKey;
+ 
+-            if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, hkeyPath, 0, KEY_READ, &deviceHKey) == ERROR_SUCCESS) {
+-                char readUuid[MAX_BUFFER_SIZE];
++            if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, hkeyPath, 0, KEY_READ, &deviceHKey) == ERROR_SUCCESS) {
++                wchar_t readUuid[MAX_BUFFER_SIZE];
+                 DWORD readSize = sizeof(readUuid);
+ 
+                 // Query VID_(vendorId)&PID_(productId)\(serialnumber)\ContainerID
+-                retCode = RegQueryValueEx(deviceHKey, "ContainerID", NULL, NULL, (LPBYTE)&readUuid, &readSize);
++                retCode = RegQueryValueExW(deviceHKey, L"ContainerID", NULL, NULL, (LPBYTE)&readUuid, &readSize);
+                 if (retCode == ERROR_SUCCESS) {
+                     readUuid[readSize] = '\0';
+-                    if (strcmp(wantedUuid, readUuid) == 0) {
++                    if (wcscmp(wantedUuid, readUuid) == 0) {
+                         // The ContainerID UUIDs match, return now that serialNumber has
+                         // the right value.
+                         RegCloseKey(deviceHKey);
+@@ -783,7 +801,7 @@ void getSerialNumber(const char *vid,
+     RegCloseKey(vendorProductHKey);
+   }
+ 
+-  _snprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, "");
++  _snwprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, L"");
+   return;
+ }
+ 
+@@ -795,15 +813,15 @@ void ListBaton::Execute() {
+ 
+   int memberIndex = 0;
+   DWORD dwSize, dwPropertyRegDataType;
+-  char szBuffer[MAX_BUFFER_SIZE];
+-  char *pnpId;
+-  char *vendorId;
+-  char *productId;
+-  char *name;
+-  char *manufacturer;
+-  char *locationId;
+-  char *friendlyName;
+-  char serialNumber[MAX_REGISTRY_KEY_SIZE];
++  wchar_t szBuffer[MAX_BUFFER_SIZE];
++  wchar_t *pnpId;
++  wchar_t *vendorId;
++  wchar_t *productId;
++  wchar_t *name;
++  wchar_t *manufacturer;
++  wchar_t *locationId;
++  wchar_t *friendlyName;
++  wchar_t serialNumber[MAX_REGISTRY_KEY_SIZE];
+   bool isCom;
+   while (true) {
+     isCom = false;
+@@ -814,7 +832,6 @@ void ListBaton::Execute() {
+     manufacturer = NULL;
+     locationId = NULL;
+     friendlyName = NULL;
+-    isCom = false;
+ 
+     ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
+     deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+@@ -826,16 +843,16 @@ void ListBaton::Execute() {
+     }
+ 
+     dwSize = sizeof(szBuffer);
+-    SetupDiGetDeviceInstanceId(hDevInfo, &deviceInfoData, szBuffer, dwSize, &dwSize);
++    SetupDiGetDeviceInstanceIdW(hDevInfo, &deviceInfoData, reinterpret_cast<PWSTR>(szBuffer), dwSize, &dwSize);
+     szBuffer[dwSize] = '\0';
+-    pnpId = strdup(szBuffer);
++    pnpId = wcsdup(szBuffer);
+ 
+-    vendorId = strstr(szBuffer, "VID_");
++    vendorId = wcsstr(szBuffer, L"VID_");
+     if (vendorId) {
+       vendorId += 4;
+       vendorId = copySubstring(vendorId, 4);
+     }
+-    productId = strstr(szBuffer, "PID_");
++    productId = wcsstr(szBuffer, L"PID_");
+     if (productId) {
+       productId += 4;
+       productId = copySubstring(productId, 4);
+@@ -843,32 +860,29 @@ void ListBaton::Execute() {
+ 
+     getSerialNumber(vendorId, productId, hDevInfo, deviceInfoData, MAX_REGISTRY_KEY_SIZE, serialNumber);
+ 
+-    if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData,
++    if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
+                                          SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType,
+-                                         reinterpret_cast<BYTE*>(szBuffer),
+-                                         sizeof(szBuffer), &dwSize)) {
+-      locationId = strdup(szBuffer);
++                                         reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
++      locationId = wcsdup(szBuffer);
+     }
+-    if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData,
++    if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
+                                          SPDRP_FRIENDLYNAME, &dwPropertyRegDataType,
+-                                         reinterpret_cast<BYTE*>(szBuffer),
+-                                         sizeof(szBuffer), &dwSize)) {
+-      friendlyName = strdup(szBuffer);
++                                         reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
++      friendlyName = wcsdup(szBuffer);
+     }
+-    if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData,
++    if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
+                                          SPDRP_MFG, &dwPropertyRegDataType,
+-                                         reinterpret_cast<BYTE*>(szBuffer),
+-                                         sizeof(szBuffer), &dwSize)) {
+-      manufacturer = strdup(szBuffer);
++                                         reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
++      manufacturer = wcsdup(szBuffer);
+     }
+ 
+     HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
+     if (hkey != INVALID_HANDLE_VALUE) {
+       dwSize = sizeof(szBuffer);
+-      if (RegQueryValueEx(hkey, "PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) {
++      if (RegQueryValueExW(hkey, L"PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) {
++        name = wcsdup(szBuffer);
+         szBuffer[dwSize] = '\0';
+-        name = strdup(szBuffer);
+-        isCom = strstr(szBuffer, "COM") != NULL;
++        isCom = wcsstr(szBuffer, L"COM") != NULL;
+       }
+     }
+     if (isCom) {
+@@ -916,6 +930,16 @@ void setIfNotEmpty(Napi::Object item, std::string key, const char *value) {
+   }
+ }
+ 
++void setIfNotEmpty(Napi::Object item, std::string key, const wchar_t *value) {
++  Napi::Env env = item.Env();
++  Napi::String v8key = Napi::String::New(env, key);
++  if (wcslen(value) > 0) {
++    (item).Set(v8key, Napi::String::New(env, (const char16_t*) value));
++  } else {
++    (item).Set(v8key, env.Undefined());
++  }
++}
++
+ void FlushBaton::Execute() {
+   DWORD purge_all = PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR;
+   if (!PurgeComm(int2handle(fd), purge_all)) {
+diff --git a/node_modules/@serialport/bindings-cpp/src/serialport_win.h b/node_modules/@serialport/bindings-cpp/src/serialport_win.h
+index f3e3c32..739b5dd 100644
+--- a/node_modules/@serialport/bindings-cpp/src/serialport_win.h
++++ b/node_modules/@serialport/bindings-cpp/src/serialport_win.h
+@@ -47,23 +47,24 @@ Napi::Value Read(const Napi::CallbackInfo& info);
+ 
+ Napi::Value List(const Napi::CallbackInfo& info);
+ void setIfNotEmpty(Napi::Object item, std::string key, const char *value);
++void setIfNotEmpty(Napi::Object item, std::string key, const wchar_t *value);
+ 
+ struct ListResultItem {
+-  std::string path;
+-  std::string manufacturer;
+-  std::string serialNumber;
+-  std::string pnpId;
+-  std::string locationId;
+-  std::string friendlyName;
+-  std::string vendorId;
+-  std::string productId;
++  std::wstring path;
++  std::wstring manufacturer;
++  std::wstring serialNumber;
++  std::wstring pnpId;
++  std::wstring locationId;
++  std::wstring friendlyName;
++  std::wstring vendorId;
++  std::wstring productId;
+ };
+ 
+ struct ListBaton : public Napi::AsyncWorker {
+   ListBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:ListBaton"),
+   errorString() {}
+   std::list<ListResultItem*> results;
+-  char errorString[ERROR_STRING_SIZE];
++  wchar_t errorString[ERROR_STRING_SIZE];
+   void Execute() override;
+ 
+   void OnOK() override {