CreateFile method reports COM1 COM4 COM5 COM98 COM99 QueryDosDevice method reports COM5 COM1 COM98 COM99 COM4 GetDefaultCommConfig method reports COM1 COM4 COM5 COM98 COM99 Device Manager (SetupAPI - GUID_DEVINTERFACE_COMPORT) reports COM1 <通訊連接埠> COM4 <USB Serial Port> Device Manager (SetupAPI - Ports Device information set) reports COM99 <Bluetooth Serial Port> COM4 <USB Serial Port> COM1 <通訊連接埠> COM98 <Bluetooth Serial Port> COM5 <USB-SERIAL CH340> EnumPorts method reports COM1 COM2 COM4 COM7 COM8 COM10 COM6 COM5 COM98 COM99 COM9 COM11 COM12 COM13 COM14 COM16 COM17 COM18 COM19 COM20 COM21 COM22 COM23 COM24 COM25 COM26 COM27 COM28 COM29 COM30 COM31 COM32 COM3 WMI method reports COM1 <通訊連接埠 (COM1)> ComDB method reports COM1 COM3 COM4 COM5 COM6 COM7 COM8 COM9 COM22 COM23 COM24 COM25 COM26 COM27 COM28 COM29 COM30 COM31 COM32 COM98 COM99 Registry method reports COM98 COM99 COM5 COM1 COM4
/* Enumerating com ports in Windows original by PJ Naughter, 1998 - 2013 http://www.naughter.com/enumser.html (Web: www.naughter.com, Email: pjna@naughter.com) reorganize by Gaiger Chen , Jul, 20150 NO COPYRIGHT, welcome to use for everyone. */ #include <windows.h> #include <stdio.h> #include <tchar.h> #include <setupapi.h> #include <locale.h> #define MAX_PORT_NUM (256) #define MAX_STR_LEN (256*sizeof(TCHAR)) /*assure portName be double ARRAY , not double point*/ BOOL EnumerateComPortByCreateFile(UINT *pNumber, TCHAR *pPortName, int strMaxLen) { UINT i, jj; INT ret; TCHAR *pTempPortName; *pNumber = 0; jj = 0; pTempPortName = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, strMaxLen*sizeof(pTempPortName)); ret = FALSE; for (i = 1; i<= 255; i++){ HANDLE hSerial; _stprintf_s(pTempPortName, strMaxLen, TEXT("\\\\.\\COM%u"), i); hSerial = CreateFile(pTempPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(INVALID_HANDLE_VALUE == hSerial) continue; _tcsncpy(pPortName + jj*strMaxLen, pTempPortName, _tcsnlen(pTempPortName, strMaxLen)); jj++; }/*for [i MAX_PORT_NUM] */ HeapFree(GetProcessHeap(), 0, pTempPortName); pTempPortName = NULL; *pNumber = jj; if(0 <jj) ret = TRUE; return ret; }/*EnumerateComPortByCreateFile*/ BOOL EnumerateComPortQueryDosDevice(UINT *pNumber, TCHAR *pPortName, int strMaxLen) { UINT i, jj; INT ret; OSVERSIONINFOEX osvi; ULONGLONG dwlConditionMask; DWORD dwChars; TCHAR *pDevices; UINT nChars; ret = FALSE; memset(&osvi, 0, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); osvi.dwPlatformId = VER_PLATFORM_WIN32_NT; dwlConditionMask = 0; VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL); if(FALSE == VerifyVersionInfo(&osvi, VER_PLATFORMID, dwlConditionMask)) { DWORD dwError = GetLastError(); _tprintf(TEXT("VerifyVersionInfo error, %d\n", dwError)); return -1; }/*if*/ pDevices = NULL; nChars = 4096; pDevices = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, nChars*sizeof(TCHAR)); while(0 < nChars) { dwChars = QueryDosDevice(NULL, pDevices, nChars); if(0 == dwChars) { DWORD dwError = GetLastError(); if(ERROR_INSUFFICIENT_BUFFER == dwError) { nChars *= 2; HeapFree(GetProcessHeap(), 0, pDevices); pDevices = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, nChars*sizeof(TCHAR)); continue; }/*if ERROR_INSUFFICIENT_BUFFER == dwError*/ _tprintf(TEXT("QueryDosDevice error, %d\n", dwError)); return -1; }/*if */ //printf("dwChars = %d\n", dwChars); i = 0; jj = 0; while (TEXT(‘\0‘) != pDevices[i] ) { TCHAR* pszCurrentDevice; size_t nLen; pszCurrentDevice = &(pDevices[i]); nLen = _tcslen(pszCurrentDevice); //_tprintf(TEXT("%s\n"), &pTargetPathStr[i]); if (3 < nLen) { if ((0 == _tcsnicmp(pszCurrentDevice, TEXT("COM"), 3)) && FALSE != isdigit(pszCurrentDevice[3]) ) { //Work out the port number _tcsncpy(pPortName + jj*strMaxLen, pszCurrentDevice, MAX_STR_LEN); jj++; } } i += (nLen + 1); } break; }/*while*/ if(NULL != pDevices) HeapFree(GetProcessHeap(), 0, pDevices); *pNumber = jj; if(0 < jj) ret = TRUE; return ret; }/*EnumerateComPortByQueryDosDevice*/ BOOL EnumerateComPortByGetDefaultCommConfig(UINT *pNumber, TCHAR *pPortName, int strMaxLen) { UINT i, jj; INT ret; TCHAR *pTempPortName; pTempPortName = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS| HEAP_ZERO_MEMORY, strMaxLen); *pNumber = 0; jj = 0; ret = FALSE; for (i = 1; i<=255; i++){ //Form the Raw device name COMMCONFIG cc; DWORD dwSize ; dwSize = sizeof(COMMCONFIG); _stprintf_s(pTempPortName, strMaxLen/2, TEXT("COM%u"), i); if (FALSE == GetDefaultCommConfig(pTempPortName, &cc, &dwSize)) continue; _tcsncpy(pPortName + jj*strMaxLen, pTempPortName, _tcsnlen(pTempPortName, strMaxLen)); jj++; }/*for [1 255] */ HeapFree(GetProcessHeap(), 0, pTempPortName); pTempPortName = NULL; *pNumber = jj; if(0 <jj) ret = TRUE; return ret; }/*EnumerateComPortByGetDefaultCommConfig*/ BOOL EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT(UINT *pNumber, TCHAR *pPortName, int strMaxLen, TCHAR *pFriendName) { UINT i, jj; INT ret; TCHAR *pTempPortName; HMODULE hLibrary; TCHAR szFullPath[_MAX_PATH]; GUID guid; HDEVINFO hDevInfoSet; typedef HKEY (__stdcall SetupDiOpenDevRegKeyFunType) (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM); //typedef BOOL (__stdcall SetupDiClassGuidsFromNameFunType) // (LPCTSTR, LPGUID, DWORD, PDWORD); typedef BOOL (__stdcall SetupDiDestroyDeviceInfoListFunType) (HDEVINFO); typedef BOOL (__stdcall SetupDiEnumDeviceInfoFunType) (HDEVINFO, DWORD, PSP_DEVINFO_DATA); typedef HDEVINFO (__stdcall SetupDiGetClassDevsFunType) (LPGUID, LPCTSTR, HWND, DWORD); typedef BOOL (__stdcall SetupDiGetDeviceRegistryPropertyFunType) (HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); SetupDiOpenDevRegKeyFunType* SetupDiOpenDevRegKeyFunPtr; SetupDiGetClassDevsFunType *SetupDiGetClassDevsFunPtr; SetupDiGetDeviceRegistryPropertyFunType *SetupDiGetDeviceRegistryPropertyFunPtr; SetupDiDestroyDeviceInfoListFunType *SetupDiDestroyDeviceInfoListFunPtr; SetupDiEnumDeviceInfoFunType *SetupDiEnumDeviceInfoFunPtr; BOOL bMoreItems; SP_DEVINFO_DATA devInfo; ret = FALSE; jj = 0; szFullPath[0] = _T(‘\0‘); //Get the Windows System32 directory if(0 == GetSystemDirectory(szFullPath, _countof(szFullPath))) { _tprintf(TEXT("CEnumerateSerial::UsingSetupAPI1 failed, Error:%u\n"), GetLastError()); return FALSE; }/*if*/ //Setup the full path and delegate to LoadLibrary #pragma warning(suppress: 6102) //There is a bug with the SAL annotation of GetSystemDirectory in the Windows 8.1 SDK _tcscat_s(szFullPath, _countof(szFullPath), _T("\\")); _tcscat_s(szFullPath, _countof(szFullPath), TEXT("SETUPAPI.DLL")); hLibrary = LoadLibrary(szFullPath); SetupDiOpenDevRegKeyFunPtr = (SetupDiOpenDevRegKeyFunType*)GetProcAddress(hLibrary, "SetupDiOpenDevRegKey"); #if defined _UNICODE SetupDiGetClassDevsFunPtr = (SetupDiGetClassDevsFunType*)GetProcAddress(hLibrary, "SetupDiGetClassDevsW"); SetupDiGetDeviceRegistryPropertyFunPtr = (SetupDiGetDeviceRegistryPropertyFunType*) GetProcAddress(hLibrary, "SetupDiGetDeviceRegistryPropertyW"); #else SetupDiGetClassDevsFunPtr = (SetupDiGetClassDevsFunType*)GetProcAddress(hLibrary, "SetupDiGetClassDevsA"); SetupDiGetDeviceRegistryPropertyFunPtr = (SetupDiGetDeviceRegistryPropertyFunType*) GetProcAddress(hLibrary, "SetupDiGetDeviceRegistryPropertyA"); #endif SetupDiDestroyDeviceInfoListFunPtr = (SetupDiDestroyDeviceInfoListFunType*) GetProcAddress(hLibrary, "SetupDiDestroyDeviceInfoList"); SetupDiEnumDeviceInfoFunPtr = (SetupDiEnumDeviceInfoFunType*) GetProcAddress(hLibrary, "SetupDiEnumDeviceInfo"); guid = GUID_DEVINTERFACE_COMPORT; hDevInfoSet = SetupDiGetClassDevsFunPtr(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (INVALID_HANDLE_VALUE == hDevInfoSet) { //Set the error to report _tprintf(TEXT("error lpfnSETUPDIGETCLASSDEVS, %d"), GetLastError()); return FALSE; }/*if */ //bMoreItems = TRUE; devInfo.cbSize = sizeof(SP_DEVINFO_DATA); i = 0; jj = 0; do { HKEY hDeviceKey; BOOL isFound; isFound = FALSE; bMoreItems = SetupDiEnumDeviceInfoFunPtr(hDevInfoSet, i, &devInfo); if(FALSE == bMoreItems) break; i++; hDeviceKey = SetupDiOpenDevRegKeyFunPtr(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (INVALID_HANDLE_VALUE != hDeviceKey) { int nPort; size_t nLen; LPTSTR pszPortName; nPort = 0; pszPortName = NULL; { //First query for the size of the registry value DWORD dwType; DWORD dwDataSize; LONG err; DWORD dwAllocatedSize; DWORD dwReturnedSize; dwType = 0; dwDataSize = 0; err = RegQueryValueEx(hDeviceKey, TEXT("PortName"), NULL, &dwType, NULL, &dwDataSize); if (ERROR_SUCCESS != err) continue; //Ensure the value is a string if (dwType != REG_SZ) continue; //Allocate enough bytes for the return value dwAllocatedSize = dwDataSize + sizeof(TCHAR); /* +sizeof(TCHAR) is to allow us to NULL terminate the data if it is not null terminated in the registry */ pszPortName = (LPTSTR)LocalAlloc(LMEM_FIXED, dwAllocatedSize); if (pszPortName == NULL) continue; //Recall RegQueryValueEx to return the data pszPortName[0] = _T(‘\0‘); dwReturnedSize = dwAllocatedSize; err = RegQueryValueEx(hDeviceKey, TEXT("PortName"), NULL, &dwType, (LPBYTE)pszPortName, &dwReturnedSize); if (ERROR_SUCCESS != err) { LocalFree(pszPortName); pszPortName = NULL; continue; } //Handle the case where the data just returned is the same size as the allocated size. This could occur where the data //has been updated in the registry with a non null terminator between the two calls to ReqQueryValueEx above. Rather than //return a potentially non-null terminated block of data, just fail the method call if (dwReturnedSize >= dwAllocatedSize) continue; //NULL terminate the data if it was not returned NULL terminated because it is not stored null terminated in the registry if (pszPortName[dwReturnedSize/sizeof(TCHAR) - 1] != _T(‘\0‘)) pszPortName[dwReturnedSize/sizeof(TCHAR)] = _T(‘\0‘); }/*local varable*/ //If it looks like "COMX" then //add it to the array which will be returned nLen = _tcslen(pszPortName); if (3 < nLen) { if (0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)) { if(FALSE == isdigit(pszPortName[3]) ) continue; //Work out the port number _tcsncpy(pPortName + jj*strMaxLen, pszPortName, _tcsnlen(pszPortName, strMaxLen)); //_stprintf_s(&portName[jj][0], strMaxLen, TEXT("%s"), pszPortName); } else { continue; }/*if 0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)*/ }/*if 3 < nLen*/ LocalFree(pszPortName); isFound = TRUE; //Close the key now that we are finished with it RegCloseKey(hDeviceKey); }/*INVALID_HANDLE_VALUE != hDeviceKey*/ if(FALSE == isFound) continue; //If the port was a serial port, then also try to get its friendly name { TCHAR szFriendlyName[1024]; DWORD dwSize; DWORD dwType; szFriendlyName[0] = _T(‘\0‘); dwSize = sizeof(szFriendlyName); dwType = 0; if( (TRUE == SetupDiGetDeviceRegistryPropertyFunPtr(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, (PBYTE)(szFriendlyName), dwSize, &dwSize) ) && (REG_SZ == dwType) ) { _tcsncpy(pFriendName + jj*strMaxLen, &szFriendlyName[0], _tcsnlen(&szFriendlyName[0], strMaxLen)); } else { _stprintf_s(pFriendName + jj*strMaxLen, strMaxLen, TEXT("")); }/*if SetupDiGetDeviceRegistryPropertyFunPtr */ }/*local variable */ jj++; }while(1); *pNumber = jj; if(0 <jj) ret = TRUE; return ret; }/*EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT*/ BOOL EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort(UINT *pNumber, TCHAR *pPortName, int strMaxLen, TCHAR *pFriendName) { UINT i, jj; INT ret; TCHAR *pTempPortName; HMODULE hLibrary; TCHAR szFullPath[_MAX_PATH]; GUID *pGuid; DWORD dwGuids; HDEVINFO hDevInfoSet; typedef HKEY (__stdcall SetupDiOpenDevRegKeyFunType) (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM); typedef BOOL (__stdcall SetupDiClassGuidsFromNameFunType) (LPCTSTR, LPGUID, DWORD, PDWORD); typedef BOOL (__stdcall SetupDiDestroyDeviceInfoListFunType) (HDEVINFO); typedef BOOL (__stdcall SetupDiEnumDeviceInfoFunType) (HDEVINFO, DWORD, PSP_DEVINFO_DATA); typedef HDEVINFO (__stdcall SetupDiGetClassDevsFunType) (LPGUID, LPCTSTR, HWND, DWORD); typedef BOOL (__stdcall SetupDiGetDeviceRegistryPropertyFunType) (HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); SetupDiOpenDevRegKeyFunType* SetupDiOpenDevRegKeyFunPtr; SetupDiClassGuidsFromNameFunType *SetupDiClassGuidsFromNameFunPtr; SetupDiGetClassDevsFunType *SetupDiGetClassDevsFunPtr; SetupDiGetDeviceRegistryPropertyFunType *SetupDiGetDeviceRegistryPropertyFunPtr; SetupDiDestroyDeviceInfoListFunType *SetupDiDestroyDeviceInfoListFunPtr; SetupDiEnumDeviceInfoFunType *SetupDiEnumDeviceInfoFunPtr; BOOL bMoreItems; SP_DEVINFO_DATA devInfo; ret = FALSE; jj = 0; szFullPath[0] = _T(‘\0‘); //Get the Windows System32 directory if(0 == GetSystemDirectory(szFullPath, _countof(szFullPath))) { _tprintf(TEXT("CEnumerateSerial::UsingSetupAPI1 failed, Error:%u\n"), GetLastError()); return FALSE; }/*if*/ //Setup the full path and delegate to LoadLibrary #pragma warning(suppress: 6102) //There is a bug with the SAL annotation of GetSystemDirectory in the Windows 8.1 SDK _tcscat_s(szFullPath, _countof(szFullPath), _T("\\")); _tcscat_s(szFullPath, _countof(szFullPath), TEXT("SETUPAPI.DLL")); hLibrary = LoadLibrary(szFullPath); SetupDiOpenDevRegKeyFunPtr = (SetupDiOpenDevRegKeyFunType*)GetProcAddress(hLibrary, "SetupDiOpenDevRegKey"); #if defined _UNICODE SetupDiClassGuidsFromNameFunPtr = (SetupDiClassGuidsFromNameFunType*) GetProcAddress(hLibrary, "SetupDiGetDeviceRegistryPropertyW"); SetupDiGetClassDevsFunPtr = (SetupDiGetClassDevsFunType*)GetProcAddress(hLibrary, "SetupDiGetClassDevsW"); SetupDiGetDeviceRegistryPropertyFunPtr = (SetupDiGetDeviceRegistryPropertyFunType*)GetProcAddress(hLibrary, "SetupDiGetDeviceRegistryPropertyW"); #else SetupDiClassGuidsFromNameFunPtr = (SetupDiClassGuidsFromNameFunType*) GetProcAddress(hLibrary, "SetupDiClassGuidsFromNameA"); SetupDiGetClassDevsFunPtr = (SetupDiGetClassDevsFunType*) GetProcAddress(hLibrary, "SetupDiGetClassDevsA"); SetupDiGetDeviceRegistryPropertyFunPtr = (SetupDiGetDeviceRegistryPropertyFunType*) GetProcAddress(hLibrary, "SetupDiGetDeviceRegistryPropertyA"); #endif SetupDiDestroyDeviceInfoListFunPtr = (SetupDiDestroyDeviceInfoListFunType*) GetProcAddress(hLibrary, "SetupDiDestroyDeviceInfoList"); SetupDiEnumDeviceInfoFunPtr = (SetupDiEnumDeviceInfoFunType*) GetProcAddress(hLibrary, "SetupDiEnumDeviceInfo"); //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName dwGuids = 0; SetupDiClassGuidsFromNameFunPtr(TEXT("Ports"), NULL, 0, &dwGuids); if(0 == dwGuids) return FALSE; //Allocate the needed memory pGuid = (GUID*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, dwGuids * sizeof(GUID)); if(NULL == pGuid) return FALSE; //Call the function again if (FALSE == SetupDiClassGuidsFromNameFunPtr(TEXT("Ports"), pGuid, dwGuids, &dwGuids)) { return FALSE; }/*if*/ hDevInfoSet = SetupDiGetClassDevsFunPtr(pGuid, NULL, NULL, DIGCF_PRESENT /*| DIGCF_DEVICEINTERFACE*/); if (INVALID_HANDLE_VALUE == hDevInfoSet) { //Set the error to report _tprintf(TEXT("error SetupDiGetClassDevsFunPtr, %d"), GetLastError()); return FALSE; }/*if */ //bMoreItems = TRUE; devInfo.cbSize = sizeof(SP_DEVINFO_DATA); i = 0; jj = 0; do { HKEY hDeviceKey; BOOL isFound; isFound = FALSE; bMoreItems = SetupDiEnumDeviceInfoFunPtr(hDevInfoSet, i, &devInfo); if(FALSE == bMoreItems) break; i++; hDeviceKey = SetupDiOpenDevRegKeyFunPtr(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (INVALID_HANDLE_VALUE != hDeviceKey) { int nPort; size_t nLen; LPTSTR pszPortName; nPort = 0; pszPortName = NULL; { //First query for the size of the registry value DWORD dwType; DWORD dwDataSize; LONG err; DWORD dwAllocatedSize; DWORD dwReturnedSize; dwType = 0; dwDataSize = 0; err = RegQueryValueEx(hDeviceKey, TEXT("PortName"), NULL, &dwType, NULL, &dwDataSize); if (ERROR_SUCCESS != err) continue; //Ensure the value is a string if (dwType != REG_SZ) continue; //Allocate enough bytes for the return value dwAllocatedSize = dwDataSize + sizeof(TCHAR); /* +sizeof(TCHAR) is to allow us to NULL terminate the data if it is not null terminated in the registry */ pszPortName = (LPTSTR)LocalAlloc(LMEM_FIXED, dwAllocatedSize); if (pszPortName == NULL) continue; //Recall RegQueryValueEx to return the data pszPortName[0] = TEXT(‘\0‘); dwReturnedSize = dwAllocatedSize; err = RegQueryValueEx(hDeviceKey, TEXT("PortName"), NULL, &dwType, (LPBYTE)pszPortName, &dwReturnedSize); if (ERROR_SUCCESS != err) { LocalFree(pszPortName); pszPortName = NULL; continue; } //Handle the case where the data just returned is the same size as the allocated size. This could occur where the data //has been updated in the registry with a non null terminator between the two calls to ReqQueryValueEx above. Rather than //return a potentially non-null terminated block of data, just fail the method call if (dwReturnedSize >= dwAllocatedSize) continue; //NULL terminate the data if it was not returned NULL terminated because it is not stored null terminated in the registry if (pszPortName[dwReturnedSize/sizeof(TCHAR) - 1] != _T(‘\0‘)) pszPortName[dwReturnedSize/sizeof(TCHAR)] = _T(‘\0‘); }/*local varable*/ //If it looks like "COMX" then //add it to the array which will be returned nLen = _tcslen(pszPortName); if (3 < nLen) { if (0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)) { if(FALSE == isdigit(pszPortName[3]) ) continue; //Work out the port number _tcsncpy(pPortName + jj*strMaxLen, pszPortName, _tcsnlen(pszPortName, strMaxLen)); //_stprintf_s(&portName[jj][0], strMaxLen, TEXT("%s"), pszPortName); } else { continue; }/*if 0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)*/ }/*if 3 < nLen*/ LocalFree(pszPortName); isFound = TRUE; //Close the key now that we are finished with it RegCloseKey(hDeviceKey); }/*INVALID_HANDLE_VALUE != hDeviceKey*/ if(FALSE == isFound) continue; //If the port was a serial port, then also try to get its friendly name { TCHAR szFriendlyName[1024]; DWORD dwSize; DWORD dwType; szFriendlyName[0] = _T(‘\0‘); dwSize = sizeof(szFriendlyName); dwType = 0; if( (TRUE == SetupDiGetDeviceRegistryPropertyFunPtr(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, (PBYTE)(szFriendlyName), dwSize, &dwSize) ) && (REG_SZ == dwType) ) { _tcsncpy(pFriendName + jj*strMaxLen, &szFriendlyName[0], _tcsnlen(&szFriendlyName[0], strMaxLen)); } else { _stprintf_s(pFriendName + jj*strMaxLen, strMaxLen, TEXT("")); }/*if SetupDiGetDeviceRegistryPropertyFunPtr */ }/*local variable */ jj++; }while(1); HeapFree(GetProcessHeap(), 0, pGuid); *pNumber = jj; if(0 <jj) ret = TRUE; return ret; }/*EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort*/ BOOL EnumerateComPortRegistry(UINT *pNumber, TCHAR *pPortName, int strMaxLen) { //What will be the return value from this function (assume the worst) UINT jj; BOOL ret; HKEY hSERIALCOMM; ret = FALSE; if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) ) { //Get the max value name and max value lengths DWORD dwMaxValueNameLen; DWORD dwMaxValueLen; DWORD dwQueryInfo; dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL); if(ERROR_SUCCESS == dwQueryInfo) { DWORD dwMaxValueNameSizeInChars, dwMaxValueNameSizeInBytes, dwMaxValueDataSizeInChars, dwMaxValueDataSizeInBytes; DWORD *pValueName; DWORD *pValueData; dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1; //Include space for the NULL terminator dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars * sizeof(TCHAR); dwMaxValueDataSizeInChars = dwMaxValueLen/sizeof(TCHAR) + 1; //Include space for the NULL terminator dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars * sizeof(TCHAR); //Allocate some space for the value name and value data pValueName = (GUID*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS| HEAP_ZERO_MEMORY, dwMaxValueNameSizeInBytes); pValueData = (GUID*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS| HEAP_ZERO_MEMORY, dwMaxValueDataSizeInBytes); if(NULL != pValueName && NULL != pValueData) { //Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM DWORD i; DWORD dwType; DWORD dwValueNameSize; DWORD dwDataSize; LONG nEnum; dwValueNameSize = dwMaxValueNameSizeInChars; dwDataSize = dwMaxValueDataSizeInBytes; i = 0; nEnum = RegEnumValue(hSERIALCOMM, i, pValueName, &dwValueNameSize, NULL, &dwType, pValueData, &dwDataSize); jj = 0; while (ERROR_SUCCESS == nEnum) { //If the value is of the correct type, then add it to the array if (REG_SZ == dwType) { _stprintf_s(pPortName + jj*strMaxLen, strMaxLen, TEXT("%s"), pValueData); jj++; }/*if */ //Prepare for the next time around dwValueNameSize = dwMaxValueNameSizeInChars; dwDataSize = dwMaxValueDataSizeInBytes; ZeroMemory(pValueName, dwMaxValueNameSizeInBytes); ZeroMemory(pValueData, dwMaxValueDataSizeInBytes); i++; nEnum = RegEnumValue(hSERIALCOMM, i, pValueName, &dwValueNameSize, NULL, &dwType, pValueData, &dwDataSize); }/*while*/ } else { return FALSE; }/*if NULL != pValueName && NULL != pValueData*/ HeapFree(GetProcessHeap(), 0, pValueName); HeapFree(GetProcessHeap(), 0, pValueData); }/*ERROR_SUCCESS == dwQueryInfo*/ //Close the registry key now that we are finished with it RegCloseKey(hSERIALCOMM); if (dwQueryInfo != ERROR_SUCCESS) return FALSE; }/*ERROR_SUCCESS == RegOpenKeyEx*/ *pNumber = jj; if(0 <jj) ret = TRUE; return ret; }/*EnumerateComPortRegistry*/ #define TIMER_BEGIN(TIMER_LABEL) \ { unsigned int tBegin##TIMER_LABEL, tEnd##TIMER_LABEL; \ tBegin##TIMER_LABEL = GetTime(); #define TIMER_END(TIMER_LABEL) \ tEnd##TIMER_LABEL = GetTime();\ fprintf(stderr, "%s cost time = %d ms\n", \ #TIMER_LABEL, tEnd##TIMER_LABEL - tBegin##TIMER_LABEL); \ } unsigned int GetTime(void) { /*winmm.lib*/ return ( unsigned int)timeGetTime(); }/*GetTime*/ int main(int argc, TCHAR argv[]) { TCHAR portName[MAX_PORT_NUM][MAX_STR_LEN]; TCHAR friendlyName[MAX_PORT_NUM][MAX_STR_LEN]; UINT i; UINT n; char* nativeLocale; nativeLocale = _strdup( setlocale(LC_CTYPE,NULL) ); for(i = 0; i< MAX_PORT_NUM; i++) ZeroMemory(&portName[i][0], MAX_STR_LEN); _tprintf(TEXT("\nCreateFile method : \n")); TIMER_BEGIN(EnumerateComPortByCreateFile); EnumerateComPortByCreateFile(&n, &portName[0][0], MAX_STR_LEN); TIMER_END(EnumerateComPortByCreateFile); _tprintf(TEXT("sought %d:\n"), n); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s\n"), &portName[i][0]); for(i = 0; i< MAX_PORT_NUM; i++) ZeroMemory(&portName[0][0], MAX_STR_LEN); _tprintf(TEXT("\nQueryDosDevice method : ")); TIMER_BEGIN(EnumerateComPortQueryDosDevice); EnumerateComPortQueryDosDevice(&n, &portName[0][0], MAX_STR_LEN); TIMER_END(EnumerateComPortQueryDosDevice); _tprintf(TEXT("sought %d:\n"), n); for(i = 0; i< n; i++) _tprintf("\t%s\n", &portName[i][0]); for(i = 0; i< MAX_PORT_NUM; i++) ZeroMemory(&portName[i][0], MAX_STR_LEN); _tprintf(TEXT("\nGetDefaultCommConfig method : \n")); TIMER_BEGIN(EnumerateComPortByGetDefaultCommConfig); EnumerateComPortByGetDefaultCommConfig(&n, &portName[0][0], MAX_STR_LEN); TIMER_END(EnumerateComPortByGetDefaultCommConfig); _tprintf(TEXT("sought %d:\n"), n); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s\n"), &portName[i][0]); for(i = 0; i< MAX_PORT_NUM; i++){ ZeroMemory(&portName[i][0], MAX_STR_LEN); ZeroMemory(&friendlyName[i][0], MAX_STR_LEN); }/*for i[i MAX_PORT_NUM]*/ _tprintf(TEXT("\nSetupAPI GUID_DEVINTERFACE_COMPORT method : \n")); TIMER_BEGIN(EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT); EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT(&n, &portName[0][0], MAX_STR_LEN, &friendlyName[0][0]); TIMER_END(EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT); _tprintf(TEXT("sought %d:\n"), n); setlocale(LC_CTYPE, "" ); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s <%s> \n"), &portName[i][0], &friendlyName[i][0]); setlocale(LC_CTYPE, nativeLocale); for(i = 0; i< MAX_PORT_NUM; i++){ ZeroMemory(&portName[i][0], MAX_STR_LEN); ZeroMemory(&friendlyName[i][0], MAX_STR_LEN); }/*for i[i MAX_PORT_NUM]*/ _tprintf(TEXT("\nSetupAPI SetupDiClassGuidsFromNamePort method : \n")); TIMER_BEGIN(EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort); EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort(&n, &portName[0][0], MAX_STR_LEN, &friendlyName[0][0]); TIMER_END(EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort); _tprintf(TEXT("sought %d:\n"), n); setlocale(LC_CTYPE, "" ); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s <%s> \n"), &portName[i][0], &friendlyName[i][0]); setlocale(LC_CTYPE, nativeLocale); for(i = 0; i< MAX_PORT_NUM; i++) ZeroMemory(&portName[i][0], MAX_STR_LEN); _tprintf(TEXT("\nRegistry method : \n")); TIMER_BEGIN(EnumerateComPortRegistry); EnumerateComPortRegistry(&n, &portName[0][0], MAX_STR_LEN); TIMER_END(EnumerateComPortRegistry); _tprintf(TEXT("sought %d:\n"), n); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s\n"), &portName[i][0]); return 0; }/*main*/
CreateFile method : EnumerateComPortByCreateFile cost time = 35 ms sought 5: \\.\COM1 \\.\COM4 \\.\COM5 \\.\COM98 \\.\COM99 QueryDosDevice method : EnumerateComPortQueryDosDevice cost time = 7 ms sought 5: COM5 COM1 COM98 COM99 COM4 GetDefaultCommConfig method : EnumerateComPortByGetDefaultCommConfig cost time = 772 ms sought 5: COM1 COM4 COM5 COM98 COM99 SetupAPI GUID_DEVINTERFACE_COMPORT method : EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT cost time = 12 ms sought 2: COM1 <通訊連接埠> COM4 <USB Serial Port> SetupAPI SetupDiClassGuidsFromNamePort method : EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort cost time = 10 ms sought 5: COM99 <Bluetooth Serial Port> COM4 <USB Serial Port> COM1 <通訊連接埠> COM98 <Bluetooth Serial Port> COM5 <USB-SERIAL CH340> Registry method : EnumerateComPortRegistry cost time = 0 ms sought 5: COM98 COM99 COM5 COM1 COM4
BOOL EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort(UINT *pNumber, TCHAR *pPortName, int strMaxLen, TCHAR *pFriendName)
版权声明:本文为博主原创文章,未经博主允许不得转载。
Methods Collection of Enumerating Com Port in Windows, by C
原文地址:http://blog.csdn.net/u013606170/article/details/46903713