list_ports_win.cc
Go to the documentation of this file.
00001 #if defined(_WIN32)
00002 
00003 /*
00004  * Copyright (c) 2014 Craig Lilley <cralilley@gmail.com>
00005  * This software is made available under the terms of the MIT licence.
00006  * A copy of the licence can be obtained from:
00007  * http://opensource.org/licenses/MIT
00008  */
00009 
00010 #include "serial/serial.h"
00011 #include <tchar.h>
00012 #include <windows.h>
00013 #include <setupapi.h>
00014 #include <initguid.h>
00015 #include <devguid.h>
00016 #include <cstring>
00017 
00018 using serial::PortInfo;
00019 using std::vector;
00020 using std::string;
00021 
00022 static const DWORD port_name_max_length = 256;
00023 static const DWORD friendly_name_max_length = 256;
00024 static const DWORD hardware_id_max_length = 256;
00025 
00026 // Convert a wide Unicode string to an UTF8 string
00027 std::string utf8_encode(const std::wstring &wstr)
00028 {
00029         int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
00030         std::string strTo( size_needed, 0 );
00031         WideCharToMultiByte                  (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
00032         return strTo;
00033 }
00034 
00035 vector<PortInfo>
00036 serial::list_ports()
00037 {
00038         vector<PortInfo> devices_found;
00039 
00040         HDEVINFO device_info_set = SetupDiGetClassDevs(
00041                 (const GUID *) &GUID_DEVCLASS_PORTS,
00042                 NULL,
00043                 NULL,
00044                 DIGCF_PRESENT);
00045 
00046         unsigned int device_info_set_index = 0;
00047         SP_DEVINFO_DATA device_info_data;
00048 
00049         device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
00050 
00051         while(SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data))
00052         {
00053                 device_info_set_index++;
00054 
00055                 // Get port name
00056 
00057                 HKEY hkey = SetupDiOpenDevRegKey(
00058                         device_info_set,
00059                         &device_info_data,
00060                         DICS_FLAG_GLOBAL,
00061                         0,
00062                         DIREG_DEV,
00063                         KEY_READ);
00064 
00065                 TCHAR port_name[port_name_max_length];
00066                 DWORD port_name_length = port_name_max_length;
00067 
00068                 LONG return_code = RegQueryValueEx(
00069                                         hkey,
00070                                         _T("PortName"),
00071                                         NULL,
00072                                         NULL,
00073                                         (LPBYTE)port_name,
00074                                         &port_name_length);
00075 
00076                 RegCloseKey(hkey);
00077 
00078                 if(return_code != EXIT_SUCCESS)
00079                         continue;
00080 
00081                 if(port_name_length > 0 && port_name_length <= port_name_max_length)
00082                         port_name[port_name_length-1] = '\0';
00083                 else
00084                         port_name[0] = '\0';
00085 
00086                 // Ignore parallel ports
00087 
00088                 if(_tcsstr(port_name, _T("LPT")) != NULL)
00089                         continue;
00090 
00091                 // Get port friendly name
00092 
00093                 TCHAR friendly_name[friendly_name_max_length];
00094                 DWORD friendly_name_actual_length = 0;
00095 
00096                 BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty(
00097                                         device_info_set,
00098                                         &device_info_data,
00099                                         SPDRP_FRIENDLYNAME,
00100                                         NULL,
00101                                         (PBYTE)friendly_name,
00102                                         friendly_name_max_length,
00103                                         &friendly_name_actual_length);
00104 
00105                 if(got_friendly_name == TRUE && friendly_name_actual_length > 0)
00106                         friendly_name[friendly_name_actual_length-1] = '\0';
00107                 else
00108                         friendly_name[0] = '\0';
00109 
00110                 // Get hardware ID
00111 
00112                 TCHAR hardware_id[hardware_id_max_length];
00113                 DWORD hardware_id_actual_length = 0;
00114 
00115                 BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty(
00116                                         device_info_set,
00117                                         &device_info_data,
00118                                         SPDRP_HARDWAREID,
00119                                         NULL,
00120                                         (PBYTE)hardware_id,
00121                                         hardware_id_max_length,
00122                                         &hardware_id_actual_length);
00123 
00124                 if(got_hardware_id == TRUE && hardware_id_actual_length > 0)
00125                         hardware_id[hardware_id_actual_length-1] = '\0';
00126                 else
00127                         hardware_id[0] = '\0';
00128 
00129                 #ifdef UNICODE
00130                         std::string portName = utf8_encode(port_name);
00131                         std::string friendlyName = utf8_encode(friendly_name);
00132                         std::string hardwareId = utf8_encode(hardware_id);
00133                 #else
00134                         std::string portName = port_name;
00135                         std::string friendlyName = friendly_name;
00136                         std::string hardwareId = hardware_id;
00137                 #endif
00138 
00139                 PortInfo port_entry;
00140                 port_entry.port = portName;
00141                 port_entry.description = friendlyName;
00142                 port_entry.hardware_id = hardwareId;
00143 
00144                 devices_found.push_back(port_entry);
00145         }
00146 
00147         SetupDiDestroyDeviceInfoList(device_info_set);
00148 
00149         return devices_found;
00150 }
00151 
00152 #endif // #if defined(_WIN32)


serial
Author(s): William Woodall , John Harrison
autogenerated on Thu Mar 28 2019 03:29:52