diff --git a/app/patches/@serialport+bindings-cpp+10.7.0.patch b/app/patches/@serialport+bindings-cpp+10.7.0.patch new file mode 100644 index 00000000..1587417a --- /dev/null +++ b/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 + #include + #include ++#include + #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 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(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(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(); + 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(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(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(szBuffer), +- sizeof(szBuffer), &dwSize)) { +- locationId = strdup(szBuffer); ++ reinterpret_cast(szBuffer), sizeof(szBuffer), &dwSize)) { ++ locationId = wcsdup(szBuffer); + } +- if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, ++ if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, + SPDRP_FRIENDLYNAME, &dwPropertyRegDataType, +- reinterpret_cast(szBuffer), +- sizeof(szBuffer), &dwSize)) { +- friendlyName = strdup(szBuffer); ++ reinterpret_cast(szBuffer), sizeof(szBuffer), &dwSize)) { ++ friendlyName = wcsdup(szBuffer); + } +- if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, ++ if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, + SPDRP_MFG, &dwPropertyRegDataType, +- reinterpret_cast(szBuffer), +- sizeof(szBuffer), &dwSize)) { +- manufacturer = strdup(szBuffer); ++ reinterpret_cast(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 results; +- char errorString[ERROR_STRING_SIZE]; ++ wchar_t errorString[ERROR_STRING_SIZE]; + void Execute() override; + + void OnOK() override {