BOOL CEnumerateSerial::UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames) #endif { //Make sure we clear out any elements which may already be in the array(s) #if defined CENUMERATESERIAL_USE_STL ports.clear(); friendlyNames.clear(); #else ports.RemoveAll(); friendlyNames.RemoveAll(); #endif //Get the function pointers to "SetupDiGetClassDevs", "SetupDiGetClassDevs", "SetupDiEnumDeviceInfo", "SetupDiOpenDevRegKey" //and "SetupDiDestroyDeviceInfoList" in setupapi.dll CAutoHModule setupAPI(LoadLibraryFromSystem32(_T("SETUPAPI.DLL"))); if (setupAPI == NULL) return FALSE; SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(setupAPI, "SetupDiOpenDevRegKey")); #if defined _UNICODE SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameW")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsW")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyW")); #else SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameA")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsA")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyA")); #endif SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(setupAPI, "SetupDiDestroyDeviceInfoList")); SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(setupAPI, "SetupDiEnumDeviceInfo")); if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) || (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL)) { //Set the error to report setupAPI.m_dwError = ERROR_CALL_NOT_IMPLEMENTED; return FALSE; } //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName DWORD dwGuids = 0; lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids); if (dwGuids == 0) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Allocate the needed memory ATL::CHeapPtr<GUID> pGuids; if (!pGuids.Allocate(dwGuids)) { //Set the error to report setupAPI.m_dwError = ERROR_OUTOFMEMORY; return FALSE; } //Call the function again if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids)) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Now create a "device information set" which is required to enumerate all the ports HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT); if (hDevInfoSet == INVALID_HANDLE_VALUE) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Finally do the enumeration BOOL bMoreItems = TRUE; int nIndex = 0; SP_DEVINFO_DATA devInfo; while (bMoreItems) { //Enumerate the current device devInfo.cbSize = sizeof(SP_DEVINFO_DATA); bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo); if (bMoreItems) { //Did we find a serial port for this device BOOL bAdded = FALSE; //Get the registry key which stores the ports settings HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (hDeviceKey) { int nPort = 0; if (QueryRegistryPortName(hDeviceKey, nPort)) { #if defined CENUMERATESERIAL_USE_STL ports.push_back(nPort); #else ports.Add(nPort); #endif bAdded = TRUE; } //Close the key now that we are finished with it RegCloseKey(hDeviceKey); } //If the port was a serial port, then also try to get its friendly name if (bAdded) { TCHAR szFriendlyName[1024]; szFriendlyName[0] = _T('\0'); DWORD dwSize = sizeof(szFriendlyName); DWORD dwType = 0; if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ)) { #if defined CENUMERATESERIAL_USE_STL friendlyNames.push_back(szFriendlyName); #else friendlyNames.Add(szFriendlyName); #endif } else { #if defined CENUMERATESERIAL_USE_STL friendlyNames.push_back(_T("")); #else friendlyNames.Add(_T("")); #endif } } } ++nIndex; } //Free up the "device information set" now that we are finished with it lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet); //Return the success indicator return TRUE; }
BOOL ComPortDiscovery::QueryUsingSetupAPI(const GUID& guid, WORD dwFlags, CPortsArray& ports, CNamesArray& friendlyNames) { //Set our output parameters to sane defaults ports.clear(); friendlyNames.clear(); //Create a "device information set" for the specified GUID HDEVINFO hDevInfoSet = SetupDiGetClassDevs(&guid, NULL, NULL, dwFlags); if (hDevInfoSet == INVALID_HANDLE_VALUE) return FALSE; //Finally do the enumeration BOOL bMoreItems = TRUE; int nIndex = 0; SP_DEVINFO_DATA devInfo; while (bMoreItems) { //Enumerate the current device devInfo.cbSize = sizeof(SP_DEVINFO_DATA); bMoreItems = SetupDiEnumDeviceInfo(hDevInfoSet, nIndex, &devInfo); if (bMoreItems) { //Did we find a serial port for this device BOOL bAdded = FALSE; //Get the registry key which stores the ports settings ATL::CRegKey deviceKey; deviceKey.Attach(SetupDiOpenDevRegKey(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE)); if (deviceKey != INVALID_HANDLE_VALUE) { int nPort = 0; if (QueryRegistryPortName(deviceKey, nPort)) { ports.push_back(nPort); bAdded = TRUE; } } //If the port was a serial port, then also try to get its friendly name if (bAdded) { ATL::CHeapPtr<BYTE> byFriendlyName; if (QueryDeviceDescription(hDevInfoSet, devInfo, byFriendlyName)) { friendlyNames.push_back(reinterpret_cast<LPCTSTR>(byFriendlyName.m_pData)); } else { friendlyNames.push_back(_T("")); } } } ++nIndex; } //Free up the "device information set" now that we are finished with it SetupDiDestroyDeviceInfoList(hDevInfoSet); //Return the success indicator return TRUE; }