Posted to tcl by patthoyts at Thu Mar 01 12:55:28 GMT 2007view pretty
/* lscomport.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net> * * List all COM ports (esp. including USB devices) * */ #define STRICT #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <tchar.h> #include <setupapi.h> #include <stdio.h> #ifdef _MSC_VER #pragma comment(lib, "advapi32") #pragma comment(lib, "setupapi") #pragma comment(lib, "user32") #endif typedef struct tagSERIALPORTINFO { int nPortNumber; LPTSTR pszPortName; LPTSTR pszFriendlyName; struct tagSERIALPORTINFO* next; } SERIALPORTINFO, *LPSERIALPORTINFO; BOOL GetSerialPortInfo(LPSERIALPORTINFO *ppInfo); /* ---------------------------------------------------------------------- */ int _tmain(int argc, TCHAR *argv[]) { LPSERIALPORTINFO pPortInfo = 0; GetSerialPortInfo(&pPortInfo); while (pPortInfo) { LPSERIALPORTINFO p = pPortInfo; pPortInfo = pPortInfo->next; _tprintf(_T("Port %d '%s'\n"), p->nPortNumber, p->pszFriendlyName); HeapFree(GetProcessHeap(), 0, p->pszPortName); HeapFree(GetProcessHeap(), 0, p->pszFriendlyName); HeapFree(GetProcessHeap(), 0, p); } return 0; } /* ---------------------------------------------------------------------- */ static HANDLE SetupEnumeratePorts() { HDEVINFO hDevices = INVALID_HANDLE_VALUE; DWORD dwGuids = 0; BOOL br = SetupDiClassGuidsFromName(_T("Ports"), 0, 0, &dwGuids); if (dwGuids) { LPGUID pguids = (LPGUID)HeapAlloc(GetProcessHeap(), 0, sizeof(GUID) * dwGuids); if (pguids) { br = SetupDiClassGuidsFromName(_T("Ports"), pguids, dwGuids, &dwGuids); if (br) { hDevices = SetupDiGetClassDevs(pguids, NULL, NULL, DIGCF_PRESENT); } HeapFree(GetProcessHeap(), 0, pguids); } } return hDevices; } static BOOL EndEnumeratePorts(HANDLE hDevices) { if (SetupDiDestroyDeviceInfoList(hDevices)) { return TRUE; } return FALSE; } BOOL GetSerialPortInfo(LPSERIALPORTINFO *ppInfo) { HANDLE hDevices = SetupEnumeratePorts(); BOOL br = TRUE; LPSERIALPORTINFO pHead = 0, pTail = 0; DWORD nDevice = 0; for (nDevice = 0; br ; nDevice++) { DWORD cbData = 0; SP_DEVINFO_DATA deviceData; deviceData.cbSize = sizeof(SP_DEVINFO_DATA); br = SetupDiEnumDeviceInfo(hDevices, nDevice, &deviceData); if (br) { TCHAR sz[16] = {0}; HKEY hkey = SetupDiOpenDevRegKey(hDevices, &deviceData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (hkey) { DWORD cbSize = 16 * sizeof(TCHAR); RegQueryValueEx(hkey, _T("PortName"), NULL, NULL, (LPBYTE)sz, &cbSize); RegCloseKey(hkey); } CharUpper(sz); if (sz[0] == _T('C') && sz[1] == _T('O') && sz[2] == _T('M')) { LPSERIALPORTINFO pInfo = (LPSERIALPORTINFO)HeapAlloc(GetProcessHeap(), 0, sizeof(SERIALPORTINFO)); pInfo->next = 0; pInfo->pszPortName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR) * (lstrlen(sz) + 1)); lstrcpy(pInfo->pszPortName, sz); pInfo->nPortNumber = _ttoi(&sz[3]); SetupDiGetDeviceRegistryProperty(hDevices, &deviceData, SPDRP_FRIENDLYNAME, NULL, NULL, 0, &cbData); if (cbData) { pInfo->pszFriendlyName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(TCHAR)); br = SetupDiGetDeviceRegistryProperty(hDevices, &deviceData, SPDRP_FRIENDLYNAME, NULL, (LPBYTE)pInfo->pszFriendlyName, cbData, NULL); pInfo->pszFriendlyName[cbData] = 0; } if (pTail == 0) { pHead = pTail = pInfo; } else { pTail->next = pInfo; pTail = pInfo; } } } } EndEnumeratePorts(hDevices); *ppInfo = pHead; return br; }