-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathDeviceInstance.hpp
More file actions
100 lines (83 loc) · 3.65 KB
/
Copy pathDeviceInstance.hpp
File metadata and controls
100 lines (83 loc) · 3.65 KB
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
#pragma once
#include <Cfgmgr32.h>
#pragma comment(lib, "Cfgmgr32.lib")
#include <variant>
#include <vector>
class DeviceInstance {
public:
DeviceInstance(const wchar_t* instanceId) {
// device instance prefix search order
// try fake batteries first with fallback to real batteries
static const wchar_t* InstancePathPrefix[] = {
L"%s", // full Device Instance Path provided
L"SWD\\DEVGEN\\%s", // fake DevGen SW battery (disappears on reboot)
L"ROOT\\DEVGEN\\%s", // fake DevGen "HW" battery (persists across reboots)
L"ACPI\\PNP0C0A\\%s", // ACPI compliant control method battery (CmBatt driver)
};
for (size_t i = 0; i < std::size(InstancePathPrefix); ++i) {
wchar_t deviceInstancePath[64] = {};
swprintf_s(deviceInstancePath, InstancePathPrefix[i], instanceId); // device instance ID
// try to open device
CONFIGRET res = CM_Locate_DevNodeW(&m_devInst, deviceInstancePath, CM_LOCATE_DEVNODE_NORMAL);
if (res == CR_SUCCESS)
return; // found a match
}
throw std::runtime_error("ERROR: CM_Locate_DevNodeW");
}
~DeviceInstance() {
}
std::wstring GetDriverDesc() const {
auto res = GetProperty(DEVPKEY_Device_DriverDesc);
return std::get<std::wstring>(res);
}
std::wstring GetDriverProvider() const {
auto res = GetProperty(DEVPKEY_Device_DriverProvider);
return std::get<std::wstring>(res);
}
std::wstring GetDriverVersion() const {
auto res = GetProperty(DEVPKEY_Device_DriverVersion);
return std::get<std::wstring>(res);
}
FILETIME GetDriverDate() const {
auto res = GetProperty(DEVPKEY_Device_DriverDate);
return std::get<FILETIME>(res);
}
/** Get the virtual file physical device object (PDO) path of a device driver instance. */
std::wstring GetPDOPath() const {
auto res = GetProperty(DEVPKEY_Device_PDOName);
// add prefix before PDO name (see https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file)
return L"\\\\?\\GLOBALROOT" + std::get<std::wstring>(res);
}
std::variant<std::wstring, FILETIME> GetProperty(const DEVPROPKEY& propertyKey) const {
DEVPROPTYPE propertyType = 0;
std::vector<BYTE> buffer(1024, 0);
ULONG buffer_size = (ULONG)buffer.size();
CONFIGRET res = CM_Get_DevNode_PropertyW(m_devInst, &propertyKey, &propertyType, buffer.data(), &buffer_size, 0);
if (res != CR_SUCCESS) {
wprintf(L"ERROR: CM_Get_DevNode_PropertyW (res=%u).\n", res);
return {};
}
buffer.resize(buffer_size);
if (propertyType == DEVPROP_TYPE_STRING) {
return reinterpret_cast<wchar_t*>(buffer.data());
} else if (propertyType == DEVPROP_TYPE_FILETIME) {
return *reinterpret_cast<FILETIME*>(buffer.data());
}
throw std::runtime_error("Unsupported CM_Get_DevNode_PropertyW type");
}
static std::wstring FileTimeToDateStr(FILETIME fileTime) {
SYSTEMTIME time = {};
BOOL ok = FileTimeToSystemTime(&fileTime, &time);
if (!ok) {
DWORD err = GetLastError();
wprintf(L"ERROR: FileTimeToSystemTime failure (err %u).\n", err);
return {};
}
std::wstring dateString(128, L'\0');
int char_count = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, NULL, &time, NULL, dateString.data(), (int)dateString.size());
dateString.resize(char_count - 1); // exclude zero-termination
return dateString;
}
private:
DEVINST m_devInst = 0;
};