diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-01-30 19:52:48 +0400 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-07 11:31:39 +0100 |
commit | 78b8866c4d3e846f3dd142bc4bac38385298dc40 (patch) | |
tree | cc2aec9b5c755317a85b3d601763f0ee669f711a | |
parent | 3660b4d0ca3dae1c69a3f4e817561844a37d334e (diff) |
Add enumeration through the SERIALCOMM registry entry
When using some software that provide an virtual serial
ports functionality is impossible to use the Win32 SetupAPI
feature to enumerate these serial ports.
For example, such software is "Virtual Serial Ports Emulator"
from Eterlogic: http://www.eterlogic.com/Products.VSPE.html
The only possible simple way to detect these serial ports
it to read the registry key HARDWARE\\DEVICEMAP\\SERIALCOMM:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff546502%28v=vs.85%29.aspx
In this case it is possible to get only a name of the serial
port without any additional information.
This method is simply addition to the main SetupAPI functionality.
Task-number: QTBUG-36526
Change-Id: Ib505aee66b74b6a8ebe16cf88c3060c8267397a0
Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r-- | src/serialport/qserialportinfo_win.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 54ea7869..9fceb316 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -75,6 +75,35 @@ static inline const QList<GuidFlagsPair>& guidFlagsPairs() return guidFlagsPairList; } +static QStringList portNamesFromHardwareDeviceMap() +{ + HKEY hKey = 0; + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + return QStringList(); + + QStringList result; + DWORD index = 0; + static const DWORD maximumValueNameInChars = 16383; + QByteArray outputValueName(maximumValueNameInChars * sizeof(wchar_t), 0); + QByteArray outputBuffer; + DWORD requiredDataBytes = 0; + forever { + DWORD requiredValueNameChars = maximumValueNameInChars; + const LONG ret = ::RegEnumValue(hKey, index, reinterpret_cast<wchar_t *>(outputValueName.data()), &requiredValueNameChars, + NULL, NULL, reinterpret_cast<unsigned char *>(outputBuffer.data()), &requiredDataBytes); + if (ret == ERROR_MORE_DATA) { + outputBuffer.resize(requiredDataBytes); + } else if (ret == ERROR_SUCCESS) { + result.append(QString::fromWCharArray(reinterpret_cast<const wchar_t *>(outputBuffer.constData()))); + ++index; + } else { + break; + } + } + ::RegCloseKey(hKey); + return result; +} + static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData, DWORD property) @@ -256,6 +285,17 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() } ::SetupDiDestroyDeviceInfoList(deviceInfoSet); } + + foreach (const QString &portName, portNamesFromHardwareDeviceMap()) { + if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(), + SerialPortNameEqualFunctor(portName)) == serialPortInfoList.end()) { + QSerialPortInfo serialPortInfo; + serialPortInfo.d_ptr->portName = portName; + serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(portName); + serialPortInfoList.append(serialPortInfo); + } + } + return serialPortInfoList; } |