If I understood your questions correctly, the C++ code below should help.
Edit: added support for friendly name (which includes COM number).
On my system I get this result, which seems to match your screenshots:
installed serial devices:
Dev. Id: PCI\VEN_8086&DEV_9D3D&SUBSYS_506D17AA&REV_21\3&11583659&1&B3
friendly name: Intel(R) Active Management Technology - SOL (COM3)
Dev. Id: FTDIBUS\VID_0403+PID_6001+A916RGSAA\0000
friendly name: USB Serial Port (COM4)
device interfaces:
Interface: \\?\PCI#VEN_8086&DEV_9D3D&SUBSYS_506D17AA&REV_21#3&11583659&1&B3#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
Interface: \\?\FTDIBUS#VID_0403+PID_6001+A916RGSAA#0000#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include <initguid.h>
#include <windows.h>
#include <devpkey.h>
#include <cfgmgr32.h>
auto splitListAsString(const std::wstring_view& s)
{
std::vector<std::wstring> l;
for (size_t pos{ 0 }; s.at(pos) != 0;) {
auto newpos = s.find(L'\0', pos);
l.emplace_back(s.substr(pos, newpos - pos));
pos = newpos + 1;
}
return l;
}
int main()
{
wchar_t guid_str[] = L"{4D36E978-E325-11CE-BFC1-08002BE10318}";
auto propKey{ DEVPKEY_Device_FriendlyName };
ULONG len{};
auto res = CM_Get_Device_ID_List_Size(&len, guid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
if (res != CR_SUCCESS) {
std::cerr << "error num " << res << " occured\n";
return -1;
}
std::wstring devIds(len,'\0');
res = CM_Get_Device_ID_ListW(guid_str, devIds.data(), len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
std::wcout << L"installed serial devices:\n";
for (auto& e : splitListAsString(devIds)) {
std::wcout << L"Dev. Id: " << e << L'\n';
DEVINST devInst{};
res = CM_Locate_DevInstW(&devInst, e.data(), CM_LOCATE_DEVNODE_NORMAL);
if (res != CR_SUCCESS) {
std::cerr << "error locating device " << res << " occured\n";
continue;
}
DEVPROPTYPE devpropt{};
CM_Get_DevNode_PropertyW(devInst, &propKey, &devpropt, nullptr, &len, 0);
if (res!=CR_BUFFER_SMALL && res != CR_SUCCESS) {
std::cerr << "error " << res << "\n";
continue;
//return -1;
}
auto buffer = std::make_unique<BYTE[]>(len);
res = CM_Get_DevNode_PropertyW(devInst, &propKey, &devpropt, buffer.get(), &len, 0);
if (devpropt == DEVPROP_TYPE_STRING) {
const auto val = reinterpret_cast<wchar_t*>(buffer.get());
std::wcout << L"friendly name: " << val << L"\n\n";
}
}
auto guid_comport_interface{ GUID_DEVINTERFACE_COMPORT };
res = CM_Get_Device_Interface_List_SizeW(&len, &guid_comport_interface, nullptr, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (res != CR_SUCCESS) {
std::cerr << "error num " << res << " occured\n";
return -1;
}
std::wstring devInterfaces(len, '\0');
res = CM_Get_Device_Interface_ListW(&guid_comport_interface, nullptr, devInterfaces.data(), len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
std::wcout << L"\ndevice interfaces:\n";
for (const auto& e : splitListAsString(devInterfaces)) {
std::wcout << L"Interface: " << e << '\n';
}
}