diff --git a/include/icsneo/platform/windows/registry.h b/include/icsneo/platform/windows/registry.h index 7964833..b9f7d18 100644 --- a/include/icsneo/platform/windows/registry.h +++ b/include/icsneo/platform/windows/registry.h @@ -3,11 +3,14 @@ #include #include +#include namespace icsneo { class Registry { public: + static bool EnumerateSubkeys(std::wstring path, std::vector& subkeys); + // Get string value static bool Get(std::wstring path, std::wstring key, std::wstring& value); static bool Get(std::string path, std::string key, std::string& value); diff --git a/platform/windows/registry.cpp b/platform/windows/registry.cpp index a569f30..33e8274 100644 --- a/platform/windows/registry.cpp +++ b/platform/windows/registry.cpp @@ -19,6 +19,46 @@ Registry::Key::~Key() { RegCloseKey(key); } +bool Registry::EnumerateSubkeys(std::wstring path, std::vector& subkeys) { + Key regKey(path); + if(!regKey.IsOpen()) + return false; + + char className[MAX_PATH]; + memset(className, 0, sizeof(className)); + DWORD classNameLen = MAX_PATH; + DWORD subKeyCount = 0; + DWORD maxSubKeyLen, maxClassStringLen, valueCount, maxValueNameLen, maxValueDataLen, securityDescriptorLen; + FILETIME lastWriteTime; + auto ret = RegQueryInfoKey( + regKey.GetKey(), + className, + &classNameLen, + nullptr, + &subKeyCount, + &maxSubKeyLen, + &maxClassStringLen, + &valueCount, + &maxValueNameLen, + &maxValueDataLen, + &securityDescriptorLen, + &lastWriteTime); + + if(ret != ERROR_SUCCESS) + return false; + + subkeys.clear(); + for(DWORD i = 0; i < subKeyCount; i++) { + DWORD nameLen = MAX_PATH; + char name[MAX_PATH]; + memset(name, 0, sizeof(name)); + ret = RegEnumKeyEx(regKey.GetKey(), i, name, &nameLen, nullptr, nullptr, nullptr, &lastWriteTime); + if(ret == ERROR_SUCCESS) + subkeys.push_back(converter.from_bytes(name)); + } + return true; +} + bool Registry::Get(std::wstring path, std::wstring key, std::wstring& value) { Key regKey(path); if(!regKey.IsOpen()) diff --git a/platform/windows/vcp.cpp b/platform/windows/vcp.cpp index 58e52ce..16b5bed 100644 --- a/platform/windows/vcp.cpp +++ b/platform/windows/vcp.cpp @@ -71,17 +71,68 @@ std::vector VCP::FindByProduct(int product, std::vector subkeys; + if(!Registry::EnumerateSubkeys(uess.str(), subkeys)) + continue; // VID/PID combo was not present at all. + if(subkeys.empty()) + continue; // No devices for VID/PID. + std::wstring correctSerial; + for(auto& subkey : subkeys) { + std::wstringstream skss; + skss << uess.str() << L'\\' << subkey; + if(!Registry::Get(skss.str(), L"ContainerID", containerIDFromEnum)) + continue; + if(containerIDFromEntry != containerIDFromEnum) + continue; + correctSerial = subkey; + break; + } + if(correctSerial.empty()) + continue; // Didn't find the device within the subkeys of the enumeration + + sn = 0; + conversionError = false; + try { + sn = std::stoi(correctSerial); + } + catch(...) { + conversionError = true; + } + + if(!sn || conversionError) { + // This is a device with characters in the serial number + if(correctSerial.size() != 6) + continue; + serial = converter.to_bytes(correctSerial); + } + else { + std::wstringstream soss; + soss << sn; + serial = converter.to_bytes(soss.str()); + } + + if(serial.find_first_of('\\') != std::string::npos) + continue; + } strcpy_s(device.serial, sizeof(device.serial), serial.c_str()); // Serial number is saved, we want the COM port number now