Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I decided to punt on this and to do away with the dependency on the SetupDi() functions. Instead, I have written code that traverses the subkeys in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum to find any drivers that support the serial port GUID. I have the feeling that this is what the device manager does. In case anyone is interested, my code fragment can be seen below:</p> <pre><code>typedef std::string StrAsc; typedef std::pair&lt;StrAsc, StrAsc&gt; port_name_type; typedef std::list&lt;port_name_type&gt; friendly_names_type; void SerialPortBase::list_ports_friendly(friendly_names_type &amp;port_names) { // we will first get the list of names. This will ensure that, at the very least, we get // the same list of names as we would have otherwise obtained. port_names_type simple_list; list_ports(simple_list); port_names.clear(); for(port_names_type::iterator pi = simple_list.begin(); pi != simple_list.end(); ++pi) port_names.push_back(friendly_name_type(*pi, *pi)); // we will now need to enumerate the subkeys of the Enum registry key. We will need to // consider many levels of the registry key structure in doing this so we will use a list // of key handles as a stack. HKEY enum_key ; char const enum_key_name[] = "SYSTEM\\CurrentControlSet\\Enum"; StrAsc const com_port_guid("{4d36e978-e325-11ce-bfc1-08002be10318}"); char const class_guid_name[] = "ClassGUID"; char const friendly_name_name[] = "FriendlyName"; char const device_parameters_name[] = "Device Parameters"; char const port_name_name[] = "PortName"; long rcd = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, enum_key_name, 0, KEY_READ, &amp;enum_key); char value_buff[MAX_PATH]; StrAsc port_name, friendly_name; if(!port_names.empty() &amp;&amp; rcd == ERROR_SUCCESS) { std::list&lt;HKEY&gt; key_stack; key_stack.push_back(enum_key); while(!key_stack.empty()) { // we need to determine whether this key has a "ClassGUID" value HKEY current = key_stack.front(); uint4 value_buff_len = sizeof(value_buff); key_stack.pop_front(); rcd = ::RegQueryValueEx( current, class_guid_name, 0, 0, reinterpret_cast&lt;byte *&gt;(value_buff), &amp;value_buff_len); if(rcd == ERROR_SUCCESS) { // we will only consider devices that match the com port GUID if(com_port_guid == value_buff) { // this key appears to identify a com port. We will need to get the friendly name // and try to get the 'PortName' from the 'Device Parameters' subkey. Once we // have those things, we can update the friendly name in our original list value_buff_len = sizeof(value_buff); rcd = ::RegQueryValueEx( current, friendly_name_name, 0, 0, reinterpret_cast&lt;byte *&gt;(value_buff), &amp;value_buff_len); if(rcd == ERROR_SUCCESS) { HKEY device_parameters_key; rcd = ::RegOpenKeyEx( current, device_parameters_name, 0, KEY_READ, &amp;device_parameters_key); if(rcd == ERROR_SUCCESS) { friendly_name = value_buff; value_buff_len = sizeof(value_buff); rcd = ::RegQueryValueEx( device_parameters_key, port_name_name, 0, 0, reinterpret_cast&lt;byte *&gt;(value_buff), &amp;value_buff_len); if(rcd == ERROR_SUCCESS) { friendly_names_type::iterator fi; port_name = value_buff; fi = std::find_if( port_names.begin(), port_names.end(), port_has_name(port_name)); if(fi != port_names.end()) fi-&gt;second = friendly_name; } ::RegCloseKey(device_parameters_key); } } } } else { // since this key did not have what we expected, we will need to check its // children uint4 index = 0; rcd = ERROR_SUCCESS; while(rcd == ERROR_SUCCESS) { value_buff_len = sizeof(value_buff); rcd = ::RegEnumKeyEx( current, index, value_buff, &amp;value_buff_len, 0, 0, 0, 0); if(rcd == ERROR_SUCCESS) { HKEY child; rcd = ::RegOpenKeyEx(current, value_buff, 0, KEY_READ, &amp;child); if(rcd == ERROR_SUCCESS) key_stack.push_back(child); } ++index; } } ::RegCloseKey(current); } } } // list_ports_friendly </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload