Platform: Windows: Avoid windows.h

This way Windows.h doesn't pollute everything with random defines
v0.3.0-dev
Paul Hollinsky 2022-02-28 18:25:24 -05:00
parent caf5cca42f
commit 453d3366af
8 changed files with 90 additions and 70 deletions

View File

@ -1,19 +1,7 @@
#ifndef __DYNAMICLIB_WINDOWS_H_ #ifndef __DYNAMICLIB_WINDOWS_H_
#define __DYNAMICLIB_WINDOWS_H_ #define __DYNAMICLIB_WINDOWS_H_
#define NOMINMAX #include "icsneo/platform/windows/windows.h"
#ifndef WIN32_LEAN_AND_MEAN
#define LAM_DEFINED
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#ifdef LAM_DEFINED
#undef LAM_DEFINED
#undef WIN32_LEAN_AND_MEAN
#endif
#undef NOMINMAX
#undef near
#undef far
#ifdef ICSNEOC_MAKEDLL #ifdef ICSNEOC_MAKEDLL
#define DLLExport __declspec(dllexport) #define DLLExport __declspec(dllexport)

View File

@ -3,8 +3,7 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <Windows.h> #include "icsneo/platform/windows/windows.h"
#include <winsock2.h>
#include <pcap.h> #include <pcap.h>
#include <memory> #include <memory>

View File

@ -3,7 +3,6 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <Windows.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -20,17 +19,6 @@ public:
// Get DWORD value // Get DWORD value
static bool Get(std::wstring path, std::wstring key, uint32_t& 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); 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;
};
}; };
} }

View File

@ -8,7 +8,6 @@
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <Windows.h>
#include "icsneo/device/neodevice.h" #include "icsneo/device/neodevice.h"
#include "icsneo/communication/driver.h" #include "icsneo/communication/driver.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
@ -22,25 +21,21 @@ public:
static bool IsHandleValid(neodevice_handle_t handle); static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success); typedef void(*fn_boolCallback)(bool success);
VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) { VCP(const device_eventhandler_t& err, neodevice_t& forDevice);
overlappedRead.hEvent = INVALID_HANDLE_VALUE;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
overlappedWait.hEvent = INVALID_HANDLE_VALUE;
}
~VCP() { close(); } ~VCP() { close(); }
bool open() { return open(false); } bool open() { return open(false); }
void openAsync(fn_boolCallback callback); void openAsync(fn_boolCallback callback);
bool close(); bool close();
bool isOpen() { return handle != INVALID_HANDLE_VALUE; } bool isOpen();
private: private:
bool open(bool fromAsync); bool open(bool fromAsync);
bool opening = false; bool opening = false;
neodevice_t& device; neodevice_t& device;
HANDLE handle = INVALID_HANDLE_VALUE;
OVERLAPPED overlappedRead = {}; struct Detail;
OVERLAPPED overlappedWrite = {}; std::shared_ptr<Detail> detail;
OVERLAPPED overlappedWait = {};
std::vector<std::shared_ptr<std::thread>> threads; std::vector<std::shared_ptr<std::thread>> threads;
void readTask(); void readTask();
void writeTask(); void writeTask();

View File

@ -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 <Windows.h>
#ifdef LAM_DEFINED
#undef LAM_DEFINED
#undef WIN32_LEAN_AND_MEAN
#endif
#undef NOMINMAX

View File

@ -1,3 +1,6 @@
#include <windows.h>
#include <winsock2.h>
#include "icsneo/platform/windows/pcap.h" #include "icsneo/platform/windows/pcap.h"
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h" #include "icsneo/communication/communication.h"

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/windows/registry.h" #include "icsneo/platform/windows/registry.h"
#include "icsneo/platform/windows/windows.h"
#include <codecvt> #include <codecvt>
#include <vector> #include <vector>
#include <locale> #include <locale>
@ -7,7 +8,17 @@ using namespace icsneo;
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> 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; DWORD dwDisposition;
if(readwrite) if(readwrite)
RegCreateKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, nullptr, 0, KEY_QUERY_VALUE | KEY_WRITE, nullptr, &key, &dwDisposition); 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); RegOpenKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key);
} }
Registry::Key::~Key() { Key::~Key() {
if(IsOpen()) if(IsOpen())
RegCloseKey(key); RegCloseKey(key);
} }

View File

@ -1,6 +1,7 @@
#include "icsneo/platform/windows/ftdi.h" #include "icsneo/platform/windows/ftdi.h"
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#include "icsneo/platform/registry.h" #include "icsneo/platform/registry.h"
#include <windows.h>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -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_TIMES = 5;
static constexpr unsigned int RETRY_DELAY = 50; 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<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstring> driverNames) { std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstring> driverNames) {
std::vector<neodevice_t> found; std::vector<neodevice_t> found;
@ -172,6 +186,10 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
return found; return found;
} }
VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {
detail = std::make_shared<Detail>();
}
bool VCP::IsHandleValid(neodevice_handle_t handle) { bool VCP::IsHandleValid(neodevice_handle_t handle) {
if(handle < 1) if(handle < 1)
return false; 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 // We're going to attempt to open 5 (RETRY_TIMES) times in a row
for(int i = 0; !isOpen() && i < RETRY_TIMES; i++) { 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) if(GetLastError() == ERROR_SUCCESS)
break; // We have the file handle break; // We have the file handle
@ -216,7 +235,7 @@ bool VCP::open(bool fromAsync) {
// Set the timeouts // Set the timeouts
COMMTIMEOUTS timeouts; COMMTIMEOUTS timeouts;
if(!GetCommTimeouts(handle, &timeouts)) { if(!GetCommTimeouts(detail->handle, &timeouts)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
@ -229,7 +248,7 @@ bool VCP::open(bool fromAsync) {
timeouts.WriteTotalTimeoutConstant = 10000; timeouts.WriteTotalTimeoutConstant = 10000;
timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutMultiplier = 0;
if(!SetCommTimeouts(handle, &timeouts)) { if(!SetCommTimeouts(detail->handle, &timeouts)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
@ -237,7 +256,7 @@ bool VCP::open(bool fromAsync) {
// Set the COM state // Set the COM state
DCB comstate; DCB comstate;
if(!GetCommState(handle, &comstate)) { if(!GetCommState(detail->handle, &comstate)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
@ -250,26 +269,26 @@ bool VCP::open(bool fromAsync) {
comstate.fDtrControl = DTR_CONTROL_ENABLE; comstate.fDtrControl = DTR_CONTROL_ENABLE;
comstate.fRtsControl = RTS_CONTROL_ENABLE; comstate.fRtsControl = RTS_CONTROL_ENABLE;
if(!SetCommState(handle, &comstate)) { if(!SetCommState(detail->handle, &comstate)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
PurgeComm(handle, PURGE_RXCLEAR); PurgeComm(detail->handle, PURGE_RXCLEAR);
// Set up events so that overlapped IO can work with them // Set up events so that overlapped IO can work with them
overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr); detail->overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr);
overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr); detail->overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr);
overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr); detail->overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr);
if (overlappedRead.hEvent == nullptr || overlappedWrite.hEvent == nullptr || overlappedWait.hEvent == nullptr) { if (detail->overlappedRead.hEvent == nullptr || detail->overlappedWrite.hEvent == nullptr || detail->overlappedWait.hEvent == nullptr) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// Set up event so that we will satisfy overlappedWait when a character comes in // 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(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
@ -303,28 +322,28 @@ bool VCP::close() {
writeThread.join(); writeThread.join();
closing = false; closing = false;
if(!CloseHandle(handle)) { if(!CloseHandle(detail->handle)) {
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
return false; 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 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(detail->overlappedRead.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(overlappedRead.hEvent)) if(!CloseHandle(detail->overlappedRead.hEvent))
ret = false; ret = false;
overlappedRead.hEvent = INVALID_HANDLE_VALUE; detail->overlappedRead.hEvent = INVALID_HANDLE_VALUE;
} }
if(overlappedWrite.hEvent != INVALID_HANDLE_VALUE) { if(detail->overlappedWrite.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(overlappedWrite.hEvent)) if(!CloseHandle(detail->overlappedWrite.hEvent))
ret = false; ret = false;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE; detail->overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
} }
if(overlappedWait.hEvent != INVALID_HANDLE_VALUE) { if(detail->overlappedWait.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(overlappedWait.hEvent)) if(!CloseHandle(detail->overlappedWait.hEvent))
ret = false; ret = false;
overlappedWait.hEvent = INVALID_HANDLE_VALUE; detail->overlappedWait.hEvent = INVALID_HANDLE_VALUE;
} }
uint8_t flush; uint8_t flush;
@ -340,6 +359,10 @@ bool VCP::close() {
return ret; return ret;
} }
bool VCP::isOpen() {
return detail->handle != INVALID_HANDLE_VALUE;
}
void VCP::readTask() { void VCP::readTask() {
constexpr size_t READ_BUFFER_SIZE = 10240; constexpr size_t READ_BUFFER_SIZE = 10240;
uint8_t readbuf[READ_BUFFER_SIZE]; uint8_t readbuf[READ_BUFFER_SIZE];
@ -351,11 +374,11 @@ void VCP::readTask() {
case LAUNCH: { case LAUNCH: {
COMSTAT comStatus; COMSTAT comStatus;
unsigned long errorCodes; unsigned long errorCodes;
ClearCommError(handle, &errorCodes, &comStatus); ClearCommError(detail->handle, &errorCodes, &comStatus);
bytesRead = 0; bytesRead = 0;
if(ReadFile(handle, readbuf, READ_BUFFER_SIZE, nullptr, &overlappedRead)) { if(ReadFile(detail->handle, readbuf, READ_BUFFER_SIZE, nullptr, &detail->overlappedRead)) {
if(GetOverlappedResult(handle, &overlappedRead, &bytesRead, FALSE)) { if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) {
if(bytesRead) if(bytesRead)
readQueue.enqueue_bulk(readbuf, bytesRead); readQueue.enqueue_bulk(readbuf, bytesRead);
} }
@ -377,9 +400,9 @@ void VCP::readTask() {
} }
break; break;
case WAIT: { case WAIT: {
auto ret = WaitForSingleObject(overlappedRead.hEvent, 100); auto ret = WaitForSingleObject(detail->overlappedRead.hEvent, 100);
if(ret == WAIT_OBJECT_0) { if(ret == WAIT_OBJECT_0) {
if(GetOverlappedResult(handle, &overlappedRead, &bytesRead, FALSE)) { if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) {
readQueue.enqueue_bulk(readbuf, bytesRead); readQueue.enqueue_bulk(readbuf, bytesRead);
state = LAUNCH; state = LAUNCH;
} else } else
@ -406,7 +429,7 @@ void VCP::writeTask() {
continue; continue;
bytesWritten = 0; 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; continue;
auto winerr = GetLastError(); auto winerr = GetLastError();
@ -423,9 +446,9 @@ void VCP::writeTask() {
} }
break; break;
case WAIT: { case WAIT: {
auto ret = WaitForSingleObject(overlappedWrite.hEvent, 50); auto ret = WaitForSingleObject(detail->overlappedWrite.hEvent, 50);
if(ret == WAIT_OBJECT_0) { 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); report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
state = LAUNCH; state = LAUNCH;
} }