diff --git a/include/icsneo/platform/windows/dynamiclib.h b/include/icsneo/platform/windows/dynamiclib.h index 31201bb..72c8a26 100644 --- a/include/icsneo/platform/windows/dynamiclib.h +++ b/include/icsneo/platform/windows/dynamiclib.h @@ -1,19 +1,7 @@ #ifndef __DYNAMICLIB_WINDOWS_H_ #define __DYNAMICLIB_WINDOWS_H_ -#define NOMINMAX -#ifndef WIN32_LEAN_AND_MEAN -#define LAM_DEFINED -#define WIN32_LEAN_AND_MEAN -#endif -#include -#ifdef LAM_DEFINED -#undef LAM_DEFINED -#undef WIN32_LEAN_AND_MEAN -#endif -#undef NOMINMAX -#undef near -#undef far +#include "icsneo/platform/windows/windows.h" #ifdef ICSNEOC_MAKEDLL #define DLLExport __declspec(dllexport) diff --git a/include/icsneo/platform/windows/internal/pcapdll.h b/include/icsneo/platform/windows/internal/pcapdll.h index b9248de..14db906 100644 --- a/include/icsneo/platform/windows/internal/pcapdll.h +++ b/include/icsneo/platform/windows/internal/pcapdll.h @@ -3,8 +3,7 @@ #ifdef __cplusplus -#include -#include +#include "icsneo/platform/windows/windows.h" #include #include diff --git a/include/icsneo/platform/windows/registry.h b/include/icsneo/platform/windows/registry.h index 3c468bd..38ffab0 100644 --- a/include/icsneo/platform/windows/registry.h +++ b/include/icsneo/platform/windows/registry.h @@ -3,7 +3,6 @@ #ifdef __cplusplus -#include #include #include @@ -20,17 +19,6 @@ public: // Get DWORD value static bool Get(std::wstring path, std::wstring key, uint32_t& value); static bool Get(std::string path, std::string key, uint32_t& value); - -private: - class Key { - public: - Key(std::wstring path, bool readwrite = false); - ~Key(); - HKEY GetKey() { return key; } - bool IsOpen() { return key != nullptr; } - private: - HKEY key; - }; }; } diff --git a/include/icsneo/platform/windows/vcp.h b/include/icsneo/platform/windows/vcp.h index aa4e7fc..3506ad8 100644 --- a/include/icsneo/platform/windows/vcp.h +++ b/include/icsneo/platform/windows/vcp.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "icsneo/device/neodevice.h" #include "icsneo/communication/driver.h" #include "icsneo/api/eventmanager.h" @@ -22,25 +21,21 @@ public: static bool IsHandleValid(neodevice_handle_t handle); typedef void(*fn_boolCallback)(bool success); - VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) { - overlappedRead.hEvent = INVALID_HANDLE_VALUE; - overlappedWrite.hEvent = INVALID_HANDLE_VALUE; - overlappedWait.hEvent = INVALID_HANDLE_VALUE; - } + VCP(const device_eventhandler_t& err, neodevice_t& forDevice); ~VCP() { close(); } bool open() { return open(false); } void openAsync(fn_boolCallback callback); bool close(); - bool isOpen() { return handle != INVALID_HANDLE_VALUE; } + bool isOpen(); private: bool open(bool fromAsync); bool opening = false; neodevice_t& device; - HANDLE handle = INVALID_HANDLE_VALUE; - OVERLAPPED overlappedRead = {}; - OVERLAPPED overlappedWrite = {}; - OVERLAPPED overlappedWait = {}; + + struct Detail; + std::shared_ptr detail; + std::vector> threads; void readTask(); void writeTask(); diff --git a/include/icsneo/platform/windows/windows.h b/include/icsneo/platform/windows/windows.h new file mode 100644 index 0000000..d7c7033 --- /dev/null +++ b/include/icsneo/platform/windows/windows.h @@ -0,0 +1,13 @@ +// Include Windows.h with as few annoying defines as possible + +#define NOMINMAX +#ifndef WIN32_LEAN_AND_MEAN +#define LAM_DEFINED +#define WIN32_LEAN_AND_MEAN +#endif +#include +#ifdef LAM_DEFINED +#undef LAM_DEFINED +#undef WIN32_LEAN_AND_MEAN +#endif +#undef NOMINMAX \ No newline at end of file diff --git a/platform/windows/pcap.cpp b/platform/windows/pcap.cpp index f5de8b4..662e6ca 100644 --- a/platform/windows/pcap.cpp +++ b/platform/windows/pcap.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "icsneo/platform/windows/pcap.h" #include "icsneo/communication/network.h" #include "icsneo/communication/communication.h" diff --git a/platform/windows/registry.cpp b/platform/windows/registry.cpp index 2d87b2d..698d5b1 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/windows.h" #include #include #include @@ -7,7 +8,17 @@ using namespace icsneo; static std::wstring_convert> converter; -Registry::Key::Key(std::wstring path, bool readwrite) { +class Key { +public: + Key(std::wstring path, bool readwrite = false); + ~Key(); + HKEY GetKey() { return key; } + bool IsOpen() { return key != nullptr; } +private: + HKEY key; +}; + +Key::Key(std::wstring path, bool readwrite) { DWORD dwDisposition; if(readwrite) RegCreateKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, nullptr, 0, KEY_QUERY_VALUE | KEY_WRITE, nullptr, &key, &dwDisposition); @@ -15,7 +26,7 @@ Registry::Key::Key(std::wstring path, bool readwrite) { RegOpenKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key); } -Registry::Key::~Key() { +Key::~Key() { if(IsOpen()) RegCloseKey(key); } diff --git a/platform/windows/vcp.cpp b/platform/windows/vcp.cpp index e950c2a..080a6cb 100644 --- a/platform/windows/vcp.cpp +++ b/platform/windows/vcp.cpp @@ -1,6 +1,7 @@ #include "icsneo/platform/windows/ftdi.h" #include "icsneo/platform/ftdi.h" #include "icsneo/platform/registry.h" +#include #include #include #include @@ -18,6 +19,19 @@ static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\ static constexpr unsigned int RETRY_TIMES = 5; static constexpr unsigned int RETRY_DELAY = 50; +struct VCP::Detail +{ + Detail() { + overlappedRead.hEvent = INVALID_HANDLE_VALUE; + overlappedWrite.hEvent = INVALID_HANDLE_VALUE; + overlappedWait.hEvent = INVALID_HANDLE_VALUE; + } + HANDLE handle = INVALID_HANDLE_VALUE; + OVERLAPPED overlappedRead = {}; + OVERLAPPED overlappedWrite = {}; + OVERLAPPED overlappedWait = {}; +}; + std::vector VCP::FindByProduct(int product, std::vector driverNames) { std::vector found; @@ -172,6 +186,10 @@ std::vector VCP::FindByProduct(int product, std::vector(); +} + bool VCP::IsHandleValid(neodevice_handle_t handle) { if(handle < 1) return false; @@ -200,7 +218,8 @@ bool VCP::open(bool fromAsync) { // We're going to attempt to open 5 (RETRY_TIMES) times in a row for(int i = 0; !isOpen() && i < RETRY_TIMES; i++) { - handle = CreateFileW(comss.str().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); + detail->handle = CreateFileW(comss.str().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if(GetLastError() == ERROR_SUCCESS) break; // We have the file handle @@ -216,7 +235,7 @@ bool VCP::open(bool fromAsync) { // Set the timeouts COMMTIMEOUTS timeouts; - if(!GetCommTimeouts(handle, &timeouts)) { + if(!GetCommTimeouts(detail->handle, &timeouts)) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; @@ -229,7 +248,7 @@ bool VCP::open(bool fromAsync) { timeouts.WriteTotalTimeoutConstant = 10000; timeouts.WriteTotalTimeoutMultiplier = 0; - if(!SetCommTimeouts(handle, &timeouts)) { + if(!SetCommTimeouts(detail->handle, &timeouts)) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; @@ -237,7 +256,7 @@ bool VCP::open(bool fromAsync) { // Set the COM state DCB comstate; - if(!GetCommState(handle, &comstate)) { + if(!GetCommState(detail->handle, &comstate)) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; @@ -250,26 +269,26 @@ bool VCP::open(bool fromAsync) { comstate.fDtrControl = DTR_CONTROL_ENABLE; comstate.fRtsControl = RTS_CONTROL_ENABLE; - if(!SetCommState(handle, &comstate)) { + if(!SetCommState(detail->handle, &comstate)) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; } - PurgeComm(handle, PURGE_RXCLEAR); + PurgeComm(detail->handle, PURGE_RXCLEAR); // Set up events so that overlapped IO can work with them - overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr); - overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr); - overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr); - if (overlappedRead.hEvent == nullptr || overlappedWrite.hEvent == nullptr || overlappedWait.hEvent == nullptr) { + detail->overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr); + detail->overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr); + detail->overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr); + if (detail->overlappedRead.hEvent == nullptr || detail->overlappedWrite.hEvent == nullptr || detail->overlappedWait.hEvent == nullptr) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; } // Set up event so that we will satisfy overlappedWait when a character comes in - if(!SetCommMask(handle, EV_RXCHAR)) { + if(!SetCommMask(detail->handle, EV_RXCHAR)) { close(); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; @@ -303,28 +322,28 @@ bool VCP::close() { writeThread.join(); closing = false; - if(!CloseHandle(handle)) { + if(!CloseHandle(detail->handle)) { report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error); return false; } - handle = INVALID_HANDLE_VALUE; + detail->handle = INVALID_HANDLE_VALUE; bool ret = true; // If one of the events fails closing, we probably still want to try and close the others - if(overlappedRead.hEvent != INVALID_HANDLE_VALUE) { - if(!CloseHandle(overlappedRead.hEvent)) + if(detail->overlappedRead.hEvent != INVALID_HANDLE_VALUE) { + if(!CloseHandle(detail->overlappedRead.hEvent)) ret = false; - overlappedRead.hEvent = INVALID_HANDLE_VALUE; + detail->overlappedRead.hEvent = INVALID_HANDLE_VALUE; } - if(overlappedWrite.hEvent != INVALID_HANDLE_VALUE) { - if(!CloseHandle(overlappedWrite.hEvent)) + if(detail->overlappedWrite.hEvent != INVALID_HANDLE_VALUE) { + if(!CloseHandle(detail->overlappedWrite.hEvent)) ret = false; - overlappedWrite.hEvent = INVALID_HANDLE_VALUE; + detail->overlappedWrite.hEvent = INVALID_HANDLE_VALUE; } - if(overlappedWait.hEvent != INVALID_HANDLE_VALUE) { - if(!CloseHandle(overlappedWait.hEvent)) + if(detail->overlappedWait.hEvent != INVALID_HANDLE_VALUE) { + if(!CloseHandle(detail->overlappedWait.hEvent)) ret = false; - overlappedWait.hEvent = INVALID_HANDLE_VALUE; + detail->overlappedWait.hEvent = INVALID_HANDLE_VALUE; } uint8_t flush; @@ -340,6 +359,10 @@ bool VCP::close() { return ret; } +bool VCP::isOpen() { + return detail->handle != INVALID_HANDLE_VALUE; +} + void VCP::readTask() { constexpr size_t READ_BUFFER_SIZE = 10240; uint8_t readbuf[READ_BUFFER_SIZE]; @@ -351,11 +374,11 @@ void VCP::readTask() { case LAUNCH: { COMSTAT comStatus; unsigned long errorCodes; - ClearCommError(handle, &errorCodes, &comStatus); + ClearCommError(detail->handle, &errorCodes, &comStatus); bytesRead = 0; - if(ReadFile(handle, readbuf, READ_BUFFER_SIZE, nullptr, &overlappedRead)) { - if(GetOverlappedResult(handle, &overlappedRead, &bytesRead, FALSE)) { + if(ReadFile(detail->handle, readbuf, READ_BUFFER_SIZE, nullptr, &detail->overlappedRead)) { + if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) { if(bytesRead) readQueue.enqueue_bulk(readbuf, bytesRead); } @@ -377,9 +400,9 @@ void VCP::readTask() { } break; case WAIT: { - auto ret = WaitForSingleObject(overlappedRead.hEvent, 100); + auto ret = WaitForSingleObject(detail->overlappedRead.hEvent, 100); if(ret == WAIT_OBJECT_0) { - if(GetOverlappedResult(handle, &overlappedRead, &bytesRead, FALSE)) { + if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) { readQueue.enqueue_bulk(readbuf, bytesRead); state = LAUNCH; } else @@ -406,7 +429,7 @@ void VCP::writeTask() { continue; bytesWritten = 0; - if(WriteFile(handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &overlappedWrite)) + if(WriteFile(detail->handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &detail->overlappedWrite)) continue; auto winerr = GetLastError(); @@ -423,9 +446,9 @@ void VCP::writeTask() { } break; case WAIT: { - auto ret = WaitForSingleObject(overlappedWrite.hEvent, 50); + auto ret = WaitForSingleObject(detail->overlappedWrite.hEvent, 50); if(ret == WAIT_OBJECT_0) { - if(!GetOverlappedResult(handle, &overlappedWrite, &bytesWritten, FALSE)) + if(!GetOverlappedResult(detail->handle, &detail->overlappedWrite, &bytesWritten, FALSE)) report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); state = LAUNCH; }