--- /dev/null
+/* 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;
+}