-
Notifications
You must be signed in to change notification settings - Fork 1
/
enumcom.c
143 lines (126 loc) · 4.52 KB
/
enumcom.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*************************************************************************
* Derived from code by Zach Gorman with the following license:
*
* Serial port enumeration routines
*
* The EnumSerialPort function will populate an array of SSerInfo structs,
* each of which contains information about one serial port present in
* the system. Note that this code must be linked with setupapi.lib,
* which is included with the Win32 SDK.
*
* by Zach Gorman <[email protected]>
*
* Copyright (c) 2002 Archetype Auction Software, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is
* met: Redistributions of source code must retain the above copyright
* notice, this condition and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ARCHETYPE AUCTION SOFTWARE OR ITS
* AFFILIATES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
#define INITGUID
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <initguid.h>
#include <objbase.h>
#include <setupapi.h>
#ifndef GUID_DEVINTERFACE_COMPORT
DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
#endif
#ifdef MAIN
int CheckPort(const char* port, void* data)
{
printf("Found %s\n", port);
return 0;
}
int main(void)
{
printf("serial_file returned %d\n", serial_find(NULL, CheckPort, NULL));
return 0;
}
#endif
int serial_find(const char* prefix, int (*check)(const char* port, void* data), void* data)
{
GUID *guidDev = (GUID *) &GUID_DEVINTERFACE_COMPORT;
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
SP_DEVICE_INTERFACE_DATA ifcData;
DWORD dwDetDataSize;
int rc = -1;
BOOL bOk;
DWORD i;
hDevInfo = SetupDiGetClassDevs( guidDev,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
);
if(hDevInfo == INVALID_HANDLE_VALUE) {
printf("error: SetupDiGetClassDevs failed. (err=%lx)\n", GetLastError());
goto done;
}
// Enumerate the serial ports
dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(dwDetDataSize);
ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
pDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for (i = 0, bOk = TRUE; bOk; ++i) {
// get the next device
bOk = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guidDev, i, &ifcData);
if (bOk) {
// get the device details
SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};
bOk = SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifcData, pDetData, dwDetDataSize, NULL, &devdata);
if (bOk) {
TCHAR fname[256], desc[256];
// get some additional info
BOOL bSuccess = SetupDiGetDeviceRegistryProperty(hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL, (PBYTE)fname, sizeof(fname), NULL)
&& SetupDiGetDeviceRegistryProperty(hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL, (PBYTE)desc, sizeof(desc), NULL);
if (bSuccess) {
char *comx, *p;
//printf("Device path: %s\n", pDetData->DevicePath);
//printf("Friendly name: %s\n", fname);
//printf("Description: %s\n", desc);
if ((comx = strchr(fname, '(')) != NULL)
++comx;
else
comx = fname;
if ((p = strchr(comx, ')')) != NULL)
*p = '\0';
if ((*check)(comx, data) == 0) {
rc = 0;
goto done;
}
}
}
else {
printf("error: SetupDiGetDeviceInterfaceDetail failed. (err=%lx)\n", GetLastError());
return 1;
}
}
else {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_ITEMS) {
printf("error: SetupDiEnumDeviceInterfaces failed. (err=%lx)\n", err);
goto done;
}
}
}
done:
if (pDetData != NULL)
free(pDetData);
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
return rc;
}