devices.cpp
1#include <windows.h>
2#include <setupapi.h>
3#include <cfgmgr32.h> // For MAX_DEVICE_ID_LEN
4#include <devguid.h>
5#include <regstr.h> // For REGSTR_VAL_* strings if needed
6#include <iostream>
7#include <string>
8#include <iomanip>
9#include <vector>
10
11#pragma comment(lib, "setupapi.lib")
12
13// Helper to get a device property as string
14std::wstring GetDeviceProperty(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pDevInfoData, DWORD property) {
15 DWORD dataType, requiredSize = 0;
16 std::wstring result;
17
18 // Get required buffer size
19 SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDevInfoData, property, &dataType, nullptr, 0, &requiredSize);
20 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
21 return L"";
22 }
23
24 std::vector<BYTE> buffer(requiredSize);
25 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDevInfoData, property, &dataType,
26 buffer.data(), requiredSize, nullptr)) {
27 if (dataType == REG_SZ || dataType == REG_MULTI_SZ) {
28 result = reinterpret_cast<const wchar_t*>(buffer.data());
29 }
30 }
31 return result;
32}
33
34// Parse VID:PID from HardwareID (e.g. "USB\\VID_2341&PID_8036...")
35std::wstring ExtractVidPid(const std::wstring& hardwareId) {
36 size_t vidPos = hardwareId.find(L"VID_");
37 if (vidPos == std::wstring::npos) return L"N/A";
38
39 std::wstring vid = hardwareId.substr(vidPos + 4, 4);
40 size_t pidPos = hardwareId.find(L"PID_", vidPos);
41 if (pidPos == std::wstring::npos) return vid;
42
43 std::wstring pid = hardwareId.substr(pidPos + 4, 4);
44 return vid + L":" + pid;
45}
46
47void ListConnectedUsbDevices() {
48 std::wcout << L"=== Connected USB Devices (via SetupAPI) ===\n\n";
49
50 // Enumerate all present USB devices (using "USB" enumerator)
51 HDEVINFO hDevInfo = SetupDiGetClassDevsW(nullptr, L"USB", nullptr, DIGCF_PRESENT | DIGCF_ALLCLASSES);
52 if (hDevInfo == INVALID_HANDLE_VALUE) {
53 std::wcerr << L"SetupDiGetClassDevs failed: " << GetLastError() << L"\n";
54 return;
55 }
56
57 SP_DEVINFO_DATA devInfoData{};
58 devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
59
60 for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData); ++index) {
61 // Get friendly description
62 std::wstring desc = GetDeviceProperty(hDevInfo, &devInfoData, SPDRP_DEVICEDESC);
63 if (desc.empty()) desc = L"(No description)";
64
65 // Get hardware IDs (multi-sz, but we take first one usually)
66 std::wstring hwId = GetDeviceProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID);
67 std::wstring vidPid = ExtractVidPid(hwId);
68
69 // Get device instance ID (full path like USB\VID_... )
70 wchar_t instanceId[MAX_DEVICE_ID_LEN] = {};
71 if (CM_Get_Device_IDW(devInfoData.DevInst, instanceId, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS) {
72 wcscpy_s(instanceId, L"(Failed to get instance ID)");
73 }
74
75 // Get status (from SP_DEVINFO_DATA, but simplified)
76
77 ULONG devNodeStatus = 0;
78 ULONG problem = 0;
79 std::wstring status = L"Present";
80
81 if (CM_Get_DevNode_Status(&devNodeStatus, &problem, devInfoData.DevInst, 0) == CR_SUCCESS) {
82 if (devNodeStatus & DN_HAS_PROBLEM) {
83 status = L"Problem (code " + std::to_wstring(problem) + L")";
84 }
85 else {
86 status = (devNodeStatus & DN_STARTED) ? L"Running" : L"Stopped/OK";
87 }
88 }
89
90 std::wcout << L" Status: " << status << L"\n";
91
92 std::wcout << L"Device #" << (index + 1) << L":\n";
93 std::wcout << L" Description: " << desc << L"\n";
94 std::wcout << L" VID:PID: " << vidPid << L"\n";
95 std::wcout << L" Instance ID: " << instanceId << L"\n";
96 std::wcout << L" Status: " << status << L"\n";
97 std::wcout << L" Hardware ID: " << (hwId.empty() ? L"N/A" : hwId) << L"\n";
98 std::wcout << L"------------------------------------------------------------\n";
99 }
100
101 if (GetLastError() != ERROR_NO_MORE_ITEMS) {
102 std::wcerr << L"Enumeration error: " << GetLastError() << L"\n";
103 }
104
105 SetupDiDestroyDeviceInfoList(hDevInfo);
106 std::wcout << L"\nDone.\n";
107}
108
109int main() {
110 SetConsoleOutputCP(CP_UTF8); // For better Unicode support
111 ListConnectedUsbDevices();
112 std::wcout << L"\nPress Enter to exit...\n";
113 std::cin.get();
114 return 0;
115}