Use minimal amount of memory needed to enumerate in Windows

This commit is contained in:
Will Hedgecock 2022-02-17 15:17:34 -06:00
parent ea3c593776
commit 05aae9078a
7 changed files with 176 additions and 86 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Feb 16, 2022
* Last Updated on: Feb 17, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -108,7 +108,6 @@ static void enumeratePorts(void)
serialPorts.ports[i]->enumerated = (serialPorts.ports[i]->handle != INVALID_HANDLE_VALUE);
// Enumerate all serial ports present on the current system
wchar_t comPort[128];
const struct { GUID guid; DWORD flags; } setupClasses[] = {
{ .guid = GUID_DEVCLASS_PORTS, .flags = DIGCF_PRESENT },
{ .guid = GUID_DEVCLASS_MODEM, .flags = DIGCF_PRESENT },
@ -129,57 +128,81 @@ static void enumeratePorts(void)
while (SetupDiEnumDeviceInfo(devList, devInterfaceIndex++, &devInfoData))
{
// Fetch the corresponding COM port for this device
wchar_t *comPortString = NULL;
DWORD comPortLength = sizeof(comPort) / sizeof(wchar_t);
DWORD comPortLength = 0;
wchar_t *comPort = NULL, *comPortString = NULL;
char friendlyNameMemory = 0, portDescriptionMemory = 0;
HKEY key = SetupDiOpenDevRegKey(devList, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
if ((key != INVALID_HANDLE_VALUE) && (RegQueryValueExW(key, L"PortName", NULL, NULL, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS))
comPortString = (comPort[0] == L'\\') ? (wcsrchr(comPort, L'\\') + 1) : comPort;
if (key != INVALID_HANDLE_VALUE)
{
if ((RegQueryValueExW(key, L"PortName", NULL, NULL, NULL, &comPortLength) == ERROR_SUCCESS) && (comPortLength < 32))
{
comPortLength += sizeof(wchar_t);
comPort = (wchar_t*)malloc(comPortLength);
if (comPort && (RegGetValueW(key, NULL, L"PortName", RRF_RT_REG_SZ, NULL, (LPBYTE)comPort, &comPortLength) == ERROR_SUCCESS))
comPortString = (comPort[0] == L'\\') ? (wcsrchr(comPort, L'\\') + 1) : comPort;
}
RegCloseKey(key);
}
if (!comPortString || wcsstr(comPortString, L"LPT"))
{
if (comPort)
free(comPort);
continue;
}
// Fetch the friendly name for this device
DWORD friendlyNameLength = 0;
wchar_t *friendlyNameString = NULL;
SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_FriendlyName, &devInfoPropType, NULL, 0, &friendlyNameLength, 0);
if (!friendlyNameLength)
if ((!SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_FriendlyName, &devInfoPropType, NULL, 0, &friendlyNameLength, 0) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) || !friendlyNameLength)
SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_FRIENDLYNAME, NULL, NULL, 0, &friendlyNameLength);
if (friendlyNameLength)
if (friendlyNameLength && (friendlyNameLength < 256))
{
friendlyNameLength += sizeof(wchar_t);
friendlyNameString = (wchar_t*)malloc(friendlyNameLength);
if (!SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_FriendlyName, &devInfoPropType, (BYTE*)friendlyNameString, friendlyNameLength, NULL, 0) &&
!SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_FRIENDLYNAME, NULL, (BYTE*)friendlyNameString, friendlyNameLength, NULL))
if (!friendlyNameString || (SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_FriendlyName, &devInfoPropType, (BYTE*)friendlyNameString, friendlyNameLength, NULL, 0) &&
!SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_FRIENDLYNAME, NULL, (BYTE*)friendlyNameString, friendlyNameLength, NULL)))
{
if (friendlyNameString)
free(friendlyNameString);
friendlyNameString = comPortString;
friendlyNameLength = comPortLength;
friendlyNameString = (wchar_t*)realloc(friendlyNameString, comPortLength);
wcscpy_s(friendlyNameString, comPortLength / sizeof(wchar_t), comPortString);
}
else
{
friendlyNameMemory = 1;
friendlyNameString[(friendlyNameLength / sizeof(wchar_t)) - 1] = 0;
}
}
else
{
friendlyNameString = comPortString;
friendlyNameLength = comPortLength;
friendlyNameString = (wchar_t*)malloc(comPortLength);
wcscpy_s(friendlyNameString, comPortLength / sizeof(wchar_t), comPortString);
}
// Fetch the bus-reported device description
DWORD portDescriptionLength = 0;
wchar_t *portDescriptionString = NULL;
SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, NULL, 0, &portDescriptionLength, 0);
if (portDescriptionLength)
if ((SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, NULL, 0, &portDescriptionLength, 0) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) && portDescriptionLength && (portDescriptionLength < 256))
{
portDescriptionLength += sizeof(wchar_t);
portDescriptionString = (wchar_t*)malloc(portDescriptionLength);
if (!SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, (BYTE*)portDescriptionString, portDescriptionLength, NULL, 0))
if (!portDescriptionString || !SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, (BYTE*)portDescriptionString, portDescriptionLength, NULL, 0))
{
portDescriptionString = (wchar_t*)realloc(portDescriptionString, friendlyNameLength);
wcscpy_s(portDescriptionString, friendlyNameLength / sizeof(wchar_t), friendlyNameString);
if (portDescriptionString)
free(portDescriptionString);
portDescriptionString = friendlyNameString;
portDescriptionLength = friendlyNameLength;
}
else
{
portDescriptionMemory = 1;
portDescriptionString[(portDescriptionLength / sizeof(wchar_t)) - 1] = 0;
}
}
else
{
portDescriptionString = (wchar_t*)malloc(friendlyNameLength);
wcscpy_s(portDescriptionString, friendlyNameLength / sizeof(wchar_t), friendlyNameString);
portDescriptionString = friendlyNameString;
portDescriptionLength = friendlyNameLength;
}
// Fetch the physical location for this device
@ -191,15 +214,16 @@ static void enumeratePorts(void)
if (!SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_Address, &devInfoPropType, (BYTE*)&portNumber, sizeof(portNumber), NULL, 0) &&
!SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_ADDRESS, NULL, (BYTE*)&portNumber, sizeof(portNumber), NULL))
portNumber = -1;
SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_LocationInfo, &devInfoPropType, NULL, 0, &locationLength, 0);
if (!locationLength)
if ((!SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_LocationInfo, &devInfoPropType, NULL, 0, &locationLength, 0) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) || !locationLength)
SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_LOCATION_INFORMATION, NULL, NULL, 0, &locationLength);
if (locationLength)
if (locationLength && (locationLength < 256))
{
locationLength += sizeof(wchar_t);
locationString = (wchar_t*)malloc(locationLength);
if (SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_LocationInfo, &devInfoPropType, (BYTE*)locationString, locationLength, NULL, 0) ||
SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_LOCATION_INFORMATION, NULL, (BYTE*)locationString, locationLength, NULL))
if (locationString && (SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_LocationInfo, &devInfoPropType, (BYTE*)locationString, locationLength, NULL, 0) ||
SetupDiGetDeviceRegistryPropertyW(devList, &devInfoData, SPDRP_LOCATION_INFORMATION, NULL, (BYTE*)locationString, locationLength, NULL)))
{
locationString[(locationLength / sizeof(wchar_t)) - 1] = 0;
if (wcsstr(locationString, L"Hub"))
hubNumber = _wtoi(wcschr(wcsstr(locationString, L"Hub"), L'#') + 1);
if ((portNumber == -1) && wcsstr(locationString, L"Port"))
@ -214,7 +238,8 @@ static void enumeratePorts(void)
portNumber = _wtoi(portString);
}
}
free(locationString);
if (locationString)
free(locationString);
}
if (busNumber == -1)
busNumber = 0;
@ -222,8 +247,18 @@ static void enumeratePorts(void)
hubNumber = 0;
if (portNumber == -1)
portNumber = 0;
locationString = (wchar_t*)malloc(32*sizeof(wchar_t));
_snwprintf_s(locationString, 32, 32, L"%d-%d.%d", busNumber, hubNumber, portNumber);
locationString = (wchar_t*)malloc(16*sizeof(wchar_t));
if (locationString)
_snwprintf_s(locationString, 16, 16, L"%d-%d.%d", busNumber, hubNumber, portNumber);
else
{
free(comPort);
if (friendlyNameMemory)
free(friendlyNameString);
if (portDescriptionMemory)
free(portDescriptionString);
continue;
}
// Check if port is already enumerated
serialPort *port = fetchPort(&serialPorts, comPortString);
@ -231,23 +266,32 @@ static void enumeratePorts(void)
{
// See if device has changed locations
port->enumerated = 1;
int oldLength = wcslen(port->portLocation);
int newLength = wcslen(locationString);
int oldLength = 1 + wcslen(port->portLocation);
int newLength = 1 + wcslen(locationString);
if (oldLength != newLength)
{
port->portLocation = (wchar_t*)realloc(port->portLocation, (1 + newLength) * sizeof(wchar_t));
wcscpy_s(port->portLocation, 32, locationString);
wchar_t *newMemory = (wchar_t*)realloc(port->portLocation, newLength * sizeof(wchar_t));
if (newMemory)
{
port->portLocation = newMemory;
wcscpy_s(port->portLocation, newLength, locationString);
}
else
wcscpy_s(port->portLocation, oldLength, locationString);
}
else if (wcscmp(port->portLocation, locationString))
wcscpy_s(port->portLocation, 32, locationString);
wcscpy_s(port->portLocation, newLength, locationString);
}
else
pushBack(&serialPorts, comPortString, friendlyNameString, portDescriptionString, locationString);
// Clean up memory and reset device info structure
free(comPort);
free(locationString);
free(portDescriptionString);
free(friendlyNameString);
if (friendlyNameMemory)
free(friendlyNameString);
if (portDescriptionMemory)
free(portDescriptionString);
devInfoData.cbSize = sizeof(devInfoData);
}
SetupDiDestroyDeviceInfoList(devList);
@ -266,12 +310,12 @@ static void enumeratePorts(void)
if ((FT_CreateDeviceInfoList(&numDevs) == FT_OK) && (numDevs > 0))
{
FT_DEVICE_LIST_INFO_NODE *devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs);
if (FT_GetDeviceInfoList(devInfo, &numDevs) == FT_OK)
if (devInfo && (FT_GetDeviceInfoList(devInfo, &numDevs) == FT_OK))
{
for (int i = 0; i < numDevs; ++i)
{
// Determine if the port is currently enumerated and already open
char isOpen = ((devInfo[i].Flags & FT_FLAGS_OPENED) || !strlen(devInfo[i].SerialNumber)) ? 1 : 0;
char isOpen = ((devInfo[i].Flags & FT_FLAGS_OPENED) || (devInfo[i].SerialNumber[0] == 0)) ? 1 : 0;
if (!isOpen)
for (int j = 0; j < serialPorts.length; ++j)
if ((memcmp(serialPorts.ports[j]->serialNumber, devInfo[i].SerialNumber, sizeof(serialPorts.ports[j]->serialNumber)) == 0) && (serialPorts.ports[j]->handle != INVALID_HANDLE_VALUE))
@ -282,7 +326,11 @@ static void enumeratePorts(void)
}
// Update the port description if not already open
if (!isOpen && getPortPathFromSerial(comPort, devInfo[i].SerialNumber))
const int comPortLength = 16;
wchar_t *comPort = (wchar_t*)malloc(comPortLength);
devInfo[i].Description[sizeof(devInfo[i].Description)-1] = 0;
devInfo[i].SerialNumber[sizeof(devInfo[i].SerialNumber)-1] = 0;
if (!isOpen && comPort && getPortPathFromSerial(comPort, comPortLength, devInfo[i].SerialNumber))
{
// Check if actually connected and present in the port list
for (int j = 0; j < serialPorts.length; ++j)
@ -301,9 +349,12 @@ static void enumeratePorts(void)
break;
}
}
if (comPort)
free(comPort);
}
}
free(devInfo);
if (devInfo)
free(devInfo);
}
}
FreeLibrary(ftdiLibInstance);

View File

@ -2,7 +2,7 @@
* WindowsHelperFunctions.c
*
* Created on: May 05, 2015
* Last Updated on: Feb 16, 2022
* Last Updated on: Feb 17, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -33,6 +33,7 @@
#include <shellapi.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "WindowsHelperFunctions.h"
// Common storage functionality
@ -65,6 +66,21 @@ serialPort* pushBack(serialPortVector* vector, const wchar_t* key, const wchar_t
port->portLocation = (wchar_t*)malloc((wcslen(location)+1)*sizeof(wchar_t));
port->friendlyName = (wchar_t*)malloc((wcslen(friendlyName)+1)*sizeof(wchar_t));
port->portDescription = (wchar_t*)malloc((wcslen(description)+1)*sizeof(wchar_t));
if (!port->portPath || !port->portLocation || !port->friendlyName || !port->portDescription)
{
// Clean up memory associated with the port
vector->length--;
if (port->portPath)
free(port->portPath);
if (port->portLocation)
free(port->portLocation);
if (port->friendlyName)
free(port->friendlyName);
if (port->portDescription)
free(port->portDescription);
free(port);
return NULL;
}
// Store port strings
if (containsSlashes)
@ -120,32 +136,43 @@ void removePort(serialPortVector* vector, serialPort* port)
void reduceLatencyToMinimum(const wchar_t* portName, unsigned char requestElevatedPermissions)
{
// Search for this port in all FTDI enumerated ports
HKEY key, paramKey = 0;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS", 0, KEY_READ, &key) == ERROR_SUCCESS)
HKEY key, paramKey;
DWORD maxSubkeySize, maxPortNameSize = 8;
if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS", 0, KEY_READ, &key) == ERROR_SUCCESS) &&
(RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, &maxSubkeySize, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS))
{
DWORD index = 0, subkeySize = 255, portNameSize = 16;
wchar_t *subkey = (wchar_t*)malloc(subkeySize*sizeof(wchar_t)), *regPortName = (wchar_t*)malloc(portNameSize*sizeof(wchar_t));
while (RegEnumKeyExW(key, index++, subkey, &subkeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
maxSubkeySize += 32;
DWORD index = 0, subkeySize = maxSubkeySize;
wchar_t *subkey = (wchar_t*)malloc(maxSubkeySize * sizeof(wchar_t)), *portPath = (wchar_t*)malloc(maxPortNameSize * sizeof(wchar_t));
while (subkey && portPath && (RegEnumKeyExW(key, index++, subkey, &subkeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS))
{
DWORD latency = 2, oldLatency = 2, oldLatencySize = sizeof(DWORD);
char *subkeyString = (char*)malloc(subkeySize + 2);
memset(subkeyString, 0, subkeySize + 2);
wcstombs(subkeyString, subkey, subkeySize + 1);
subkeySize = 255;
portNameSize = 16;
memset(regPortName, 0, portNameSize * sizeof(wchar_t));
wcscat_s(subkey, subkeySize, L"\\0000\\Device Parameters");
if (RegOpenKeyExW(key, subkey, 0, KEY_QUERY_VALUE, &paramKey) == ERROR_SUCCESS)
// Retrieve the current port latency value
size_t convertedSize;
char *subkeyString = NULL;
subkeySize = maxSubkeySize;
DWORD desiredLatency = 2, oldLatency = 2;
if ((wcstombs_s(&convertedSize, NULL, 0, subkey, 0) == 0) && (convertedSize < 255))
{
if ((RegQueryValueExW(paramKey, L"PortName", NULL, NULL, (LPBYTE)regPortName, &portNameSize) == ERROR_SUCCESS) && (wcscmp(portName, regPortName) == 0))
RegQueryValueExW(paramKey, L"LatencyTimer", NULL, NULL, (LPBYTE)&oldLatency, &oldLatencySize);
RegCloseKey(paramKey);
subkeyString = (char*)malloc(convertedSize);
if (subkeyString && (wcstombs_s(NULL, subkeyString, convertedSize, subkey, convertedSize - 1) == 0) &&
(wcscat_s(subkey, maxSubkeySize, L"\\0000\\Device Parameters") == 0))
{
if (RegOpenKeyExW(key, subkey, 0, KEY_QUERY_VALUE, &paramKey) == ERROR_SUCCESS)
{
DWORD oldLatencySize = sizeof(DWORD), portNameSize = maxPortNameSize * sizeof(wchar_t);
if ((RegGetValueW(paramKey, NULL, L"PortName", RRF_RT_REG_SZ, NULL, (LPBYTE)portPath, &portNameSize) == ERROR_SUCCESS) && (wcscmp(portName, portPath) == 0))
RegGetValueW(paramKey, NULL, L"LatencyTimer", RRF_RT_REG_DWORD, NULL, (LPBYTE)&oldLatency, &oldLatencySize);
RegCloseKey(paramKey);
}
}
}
if (oldLatency > latency)
// Update the port latency value if it is too high
if (oldLatency > desiredLatency)
{
if (RegOpenKeyExW(key, subkey, 0, KEY_SET_VALUE, &paramKey) == ERROR_SUCCESS)
{
RegSetValueExW(paramKey, L"LatencyTimer", 0, REG_DWORD, (LPBYTE)&latency, sizeof(latency));
RegSetValueExW(paramKey, L"LatencyTimer", 0, REG_DWORD, (LPBYTE)&desiredLatency, sizeof(desiredLatency));
RegCloseKey(paramKey);
}
else if (requestElevatedPermissions)
@ -192,46 +219,58 @@ void reduceLatencyToMinimum(const wchar_t* portName, unsigned char requestElevat
free(paramsString);
}
}
free(subkeyString);
// Clean up memory
if (subkeyString)
free(subkeyString);
}
RegCloseKey(key);
free(regPortName);
free(portPath);
free(subkey);
}
}
int getPortPathFromSerial(wchar_t* portPath, const char* serialNumber)
int getPortPathFromSerial(wchar_t* portPath, int portPathLength, const char* serialNumber)
{
// Search for this port in all FTDI enumerated ports
int found = 0;
HKEY key, paramKey = 0;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS", 0, KEY_READ, &key) == ERROR_SUCCESS)
HKEY key, paramKey;
DWORD maxSubkeySize;
if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS", 0, KEY_READ, &key) == ERROR_SUCCESS) &&
(RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, &maxSubkeySize, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS))
{
DWORD index = 0, subkeySize = 255, portNameSize = 16;
wchar_t *subkey = (wchar_t*)malloc(subkeySize * sizeof(wchar_t));
while (RegEnumKeyExW(key, index++, subkey, &subkeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
maxSubkeySize += 32;
DWORD index = 0, subkeySize = maxSubkeySize;
wchar_t *subkey = (wchar_t*)malloc(maxSubkeySize * sizeof(wchar_t));
while (subkey && (RegEnumKeyExW(key, index++, subkey, &subkeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS))
{
// Determine if this device matches the specified serial number
char *subkeyString = (char*)malloc(subkeySize + 2);
memset(subkeyString, 0, subkeySize + 2);
wcstombs(subkeyString, subkey, subkeySize + 1);
subkeySize = 255;
if (strstr(subkeyString, serialNumber))
// Convert this string from wchar* to char*
size_t convertedSize;
subkeySize = maxSubkeySize;
if ((wcstombs_s(&convertedSize, NULL, 0, subkey, 0) == 0) && (convertedSize < 255))
{
portNameSize = 16;
memset(portPath, 0, portNameSize * sizeof(wchar_t));
wcscat_s(subkey, subkeySize, L"\\0000\\Device Parameters");
if (RegOpenKeyExW(key, subkey, 0, KEY_QUERY_VALUE, &paramKey) == ERROR_SUCCESS)
char *subkeyString = (char*)malloc(convertedSize);
if (subkeyString && (wcstombs_s(NULL, subkeyString, convertedSize, subkey, convertedSize - 1) == 0))
{
if (RegQueryValueExW(paramKey, L"PortName", NULL, NULL, (LPBYTE)portPath, &portNameSize) == ERROR_SUCCESS)
found = 1;
RegCloseKey(paramKey);
// Determine if this device matches the specified serial number
if (serialNumber && strstr(subkeyString, serialNumber) && (wcscat_s(subkey, maxSubkeySize, L"\\0000\\Device Parameters") == 0))
{
DWORD portNameSize = portPathLength;
if ((RegOpenKeyExW(key, subkey, 0, KEY_QUERY_VALUE, &paramKey) == ERROR_SUCCESS) &&
(RegGetValueW(paramKey, NULL, L"PortName", RRF_RT_REG_SZ, NULL, (LPBYTE)portPath, &portNameSize) == ERROR_SUCCESS))
{
found = 1;
RegCloseKey(paramKey);
}
}
}
if (subkeyString)
free(subkeyString);
}
free(subkeyString);
}
RegCloseKey(key);
free(subkey);
if (subkey)
free(subkey);
}
return found;
}

View File

@ -2,7 +2,7 @@
* WindowsHelperFunctions.h
*
* Created on: May 05, 2015
* Last Updated on: Jan 28, 2022
* Last Updated on: Feb 17, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -52,6 +52,6 @@ void removePort(serialPortVector* vector, serialPort* port);
// Windows-specific functionality
void reduceLatencyToMinimum(const wchar_t* portName, unsigned char requestElevatedPermissions);
int getPortPathFromSerial(wchar_t* portPath, const char* serialNumber);
int getPortPathFromSerial(wchar_t* portPath, int portPathLength, const char* serialNumber);
#endif // #ifndef __WINDOWS_HELPER_FUNCTIONS_HEADER_H__