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
|
#include "stdafx.h"
#include "version.h"
#include "device.h"
#include <setupapi.h>
#include <initguid.h>
#include <devpkey.h>
#include <libcommon/string.h>
#include <libcommon/memory.h>
#include <stdexcept>
DRIVER_UPGRADE_STATUS
EvaluateDriverUpgrade
(
const std::wstring &existingVersion,
const std::wstring &proposedVersion
)
{
//
// "x.y.z.a"
//
using namespace common::string;
auto et = Tokenize(existingVersion, L".");
auto pt = Tokenize(proposedVersion, L".");
auto items = min(et.size(), pt.size());
for (auto index = 0; index < items; ++index)
{
auto ev = wcstoul(et[index].c_str(), nullptr, 10);
auto pv = wcstoul(pt[index].c_str(), nullptr, 10);
if (pv > ev)
{
return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE;
}
if (ev > pv)
{
return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE;
}
}
if (pt.size() > et.size())
{
return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE;
}
if (et.size() > pt.size())
{
return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE;
}
return DRIVER_UPGRADE_STATUS::WOULD_INSTALL_SAME_VERSION;
}
std::wstring
InfGetDriverVersion
(
const std::wstring &filePath
)
{
auto infHandle = SetupOpenInfFileW(filePath.c_str(), nullptr, INF_STYLE_WIN4, nullptr);
if (infHandle == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("SetupOpenInfFileW()");
}
common::memory::ScopeDestructor dtor;
dtor += [infHandle]()
{
SetupCloseInfFile(infHandle);
};
INFCONTEXT infContext { 0 };
auto status = SetupFindFirstLineW(infHandle, L"Version", L"DriverVer", &infContext);
if (status == FALSE)
{
throw std::runtime_error("SetupFindFirstLineW()");
}
DWORD requiredSize;
//
// This is a multi-value key.
// 0 = key, 1 = driver date
//
const DWORD VersionFieldIndex = 2;
status = SetupGetStringFieldW(&infContext, VersionFieldIndex, nullptr, 0, &requiredSize);
if (status == FALSE || requiredSize < 2)
{
throw std::runtime_error("SetupGetStringFieldW()");
}
std::vector<wchar_t> buffer(requiredSize);
status = SetupGetStringFieldW(&infContext, VersionFieldIndex,
&buffer[0], static_cast<DWORD>(buffer.size()), nullptr);
if (status == FALSE)
{
throw std::runtime_error("SetupGetStringFieldW()");
}
// Remove null terminator.
buffer.resize(requiredSize - 1);
return buffer.data();
}
std::wstring
GetDriverVersion
(
const EnumeratedDevice &device
)
{
return GetDeviceStringProperty(device.deviceInfoSet, device.deviceInfo, &DEVPKEY_Device_DriverVersion);
}
|