diff --git a/CMakeLists.txt b/CMakeLists.txt index 7732b07..c98ed30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ endif() if(WIN32) set(PLATFORM_SRC + platform/windows/strings.cpp platform/windows/registry.cpp ) @@ -527,6 +528,7 @@ if(LIBICSNEO_BUILD_UNIT_TESTS) test/unit/livedataencoderdecodertest.cpp test/unit/ringbuffertest.cpp test/unit/apperrordecodertest.cpp + test/unit/windowsstrings.cpp ) target_link_libraries(libicsneo-unit-tests gtest gtest_main) diff --git a/include/icsneo/platform/windows/strings.h b/include/icsneo/platform/windows/strings.h new file mode 100644 index 0000000..2e9107c --- /dev/null +++ b/include/icsneo/platform/windows/strings.h @@ -0,0 +1,22 @@ +#ifndef __WINDOWS_STRINGS_H__ +#define __WINDOWS_STRINGS_H__ + +#ifdef __cplusplus + + +#include + +namespace icsneo { + +// Helper function to convert UTF-16 to UTF-8 strings (wide to standard) +std::string convertWideString(const std::wstring& value); + +// Helper function to convert UTF-8 to UTF-16 strings (standard to wide) +std::wstring convertStringToWide(const std::string& value); + +}; + + +#endif // __cplusplus + +#endif // __WINDOWS_STRINGS_H__ diff --git a/platform/windows/pcap.cpp b/platform/windows/pcap.cpp index 198af09..d2c3d00 100644 --- a/platform/windows/pcap.cpp +++ b/platform/windows/pcap.cpp @@ -2,6 +2,7 @@ #include #include "icsneo/platform/windows/pcap.h" +#include "icsneo/platform/windows/strings.h" #include "icsneo/communication/network.h" #include "icsneo/communication/communication.h" #include "icsneo/communication/ethernetpacketizer.h" @@ -11,14 +12,12 @@ #include #include #pragma comment(lib, "IPHLPAPI.lib") -#include #include #include #include using namespace icsneo; -static std::wstring_convert> converter; std::vector PCAP::knownInterfaces; @@ -80,8 +79,8 @@ void PCAP::Find(std::vector& found) { memcpy(iface.macAddress, aa->PhysicalAddress, sizeof(iface.macAddress)); iface.nameFromWin32API = aa->AdapterName; - iface.descriptionFromWin32API = converter.to_bytes(aa->Description); - iface.friendlyNameFromWin32API = converter.to_bytes(aa->FriendlyName); + iface.descriptionFromWin32API = convertWideString(aa->Description); + iface.friendlyNameFromWin32API = convertWideString(aa->FriendlyName); if(iface.descriptionFromWin32API.find("LAN9512/LAN9514") != std::string::npos) { // This is an Ethernet EVB device iface.fullName = "Intrepid Ethernet EVB ( " + iface.friendlyNameFromWin32API + " : " + iface.descriptionFromWin32API + " )"; @@ -187,7 +186,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) { return (netifIndex < knownInterfaces.size()); } -PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice), pcap(PCAPDLL::getInstance()), ethPacketizer(err) { +PCAP::PCAP(const device_eventhandler_t& eventHandler, neodevice_t& forDevice) : Driver(eventHandler), pcap(PCAPDLL::getInstance()), device(forDevice), ethPacketizer(eventHandler) { if(IsHandleValid(device.handle)) { iface = knownInterfaces[(device.handle >> 24) & 0xFF]; iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case. diff --git a/platform/windows/registry.cpp b/platform/windows/registry.cpp index 0656714..97e12ea 100644 --- a/platform/windows/registry.cpp +++ b/platform/windows/registry.cpp @@ -1,4 +1,5 @@ #include "icsneo/platform/windows/registry.h" +#include "icsneo/platform/windows/strings.h" #include "icsneo/platform/windows.h" #include #include @@ -6,8 +7,6 @@ using namespace icsneo; -static std::wstring_convert> converter; - class Key { public: Key(std::wstring path, bool readwrite = false); @@ -95,8 +94,8 @@ bool Registry::Get(std::wstring path, std::wstring key, std::wstring& value) { bool Registry::Get(std::string path, std::string key, std::string& value) { std::wstring wvalue; - bool ret = Get(converter.from_bytes(path), converter.from_bytes(key), wvalue); - value = converter.to_bytes(wvalue); + bool ret = Get(convertStringToWide(path), convertStringToWide(key), wvalue); + value = convertWideString(wvalue); return ret; } @@ -116,5 +115,5 @@ bool Registry::Get(std::wstring path, std::wstring key, uint32_t& value) { } bool Registry::Get(std::string path, std::string key, uint32_t& value) { - return Get(converter.from_bytes(path), converter.from_bytes(key), value); + return Get(convertStringToWide(path), convertStringToWide(key), value); } diff --git a/platform/windows/strings.cpp b/platform/windows/strings.cpp new file mode 100644 index 0000000..84eb276 --- /dev/null +++ b/platform/windows/strings.cpp @@ -0,0 +1,26 @@ +#include +#include + +#include + +// Helper function to convert UTF-16 to UTF-8 strings (wide to standard) +std::string icsneo::convertWideString(const std::wstring& value) { + // Get the width of the string (character count) + int width = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)value.c_str(), -1, 0, 0, NULL, NULL); + // Create the new string + std::string new_string(width+1, '\0'); + // fill the new string with the converted characters + WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)value.c_str(), -1, new_string.data(), width, NULL, NULL); + return new_string; +}; + +// Helper function to convert UTF-8 to UTF-16 strings (standard to wide) +std::wstring icsneo::convertStringToWide(const std::string& value) { + // Get the width of the string (character count) + int width = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, NULL, 0); + // Create the new string + std::wstring new_string(width+1, '\0'); + // fill the new string with the converted characters + MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, (LPWSTR)new_string.data(), width); + return new_string; +} \ No newline at end of file diff --git a/platform/windows/vcp.cpp b/platform/windows/vcp.cpp index c9cff53..43e6922 100644 --- a/platform/windows/vcp.cpp +++ b/platform/windows/vcp.cpp @@ -1,4 +1,5 @@ #include "icsneo/platform/windows/ftdi.h" +#include "icsneo/platform/windows/strings.h" #include "icsneo/platform/ftdi.h" #include "icsneo/platform/registry.h" #include "icsneo/device/founddevice.h" @@ -15,7 +16,6 @@ using namespace icsneo; -static std::wstring_convert> converter; static const std::wstring DRIVER_SERVICES_REG_KEY = L"SYSTEM\\CurrentControlSet\\services\\"; static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\"; static constexpr unsigned int RETRY_TIMES = 5; @@ -95,7 +95,7 @@ void VCP::Find(std::vector& found, std::vector driver if(!device.productId) continue; - std::string serial = converter.to_bytes(oss.str()); + std::string serial = convertWideString(oss.str()); // The serial number should not have a path slash in it. If it does, that means we don't have the real serial. if(serial.find_first_of('\\') != std::string::npos) { // The serial number was not in the first serenum key where we expected it. @@ -142,12 +142,12 @@ void VCP::Find(std::vector& found, std::vector driver // This is a device with characters in the serial number if(correctSerial.size() != 6) continue; - serial = converter.to_bytes(correctSerial); + serial = convertWideString(correctSerial); } else { std::wstringstream soss; soss << sn; - serial = converter.to_bytes(soss.str()); + serial = convertWideString(soss.str()); } if(serial.find_first_of('\\') != std::string::npos) diff --git a/test/unit/windowsstrings.cpp b/test/unit/windowsstrings.cpp new file mode 100644 index 0000000..86e3c74 --- /dev/null +++ b/test/unit/windowsstrings.cpp @@ -0,0 +1,23 @@ +#include + +#include + +#include + +TEST(WindowsUtilTest, testConvertWideString) { +#ifdef WIN32 + std::wstring wideString(L"Hello World!"); + auto normalString = icsneo::convertWideString(wideString); + + ASSERT_STREQ(normalString.c_str(), "Hello World!"); +#endif +} + +TEST(WindowsUtilTest, testConvertStringToWide) { +#ifdef WIN32 + std::string normalString("Hello World!"); + auto wideString = icsneo::convertStringToWide(normalString); + + ASSERT_STREQ(wideString.c_str(), L"Hello World!"); +#endif +} \ No newline at end of file