-
Notifications
You must be signed in to change notification settings - Fork 1
/
Settings.cpp
148 lines (130 loc) · 6.78 KB
/
Settings.cpp
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
144
145
146
147
148
#include "Settings.h"
#include "XFS/Logger.h"
#include <string>
#include <vector>
// XFS API для функций доступа к реестру.
#include <xfsconf.h>
/// Класс для автоматического закрытия открытых ключей реестра, когда они более не нужны.
class RegKey {
HKEY hKey;
public:
inline RegKey(HKEY root, const char* name) {
HRESULT r = WFMOpenKey(root, (LPSTR)name, &hKey);
XFS::Logger() << "RegKey::RegKey(root=" << root << ", name=" << name << ", hKey=&" << hKey << ") = " << r;
}
inline ~RegKey() {
HRESULT r = WFMCloseKey(hKey);
XFS::Logger() << "WFMCloseKey(hKey=" << hKey << ") = " << r;
}
inline RegKey child(const char* name) const {
return RegKey(hKey, name);
}
/** Получает значение из ключа реестра с указанным именем.
@param name
Имя значения в ключе реестра, которое требуется получить. Значение по умолчанию (`NULL`)
означает, что необходимо получить значение ключа по умолчанию.
@return
Строка со значением ключа. Если значения не существует, возвращает пустую строку.
*/
inline std::string value(const char* name = NULL) const {
// Узнаем размер значения ключа.
DWORD dwSize = 0;
HRESULT r = WFMQueryValue(hKey, (LPSTR)name, NULL, &dwSize);
{XFS::Logger() << "RegKey::value[size](name=" << name << ", size=&" << dwSize << ") = " << r;}
// Используем вектор, т.к. он гарантирует непрерывность памяти под данные,
// чего нельзя сказать в случае со string.
// dwSize содержит длину строки без завершающего NULL, но он записывается в выходное значение.
std::vector<char> value(dwSize+1);
if (dwSize > 0) {
dwSize = value.capacity();
r = WFMQueryValue(hKey, (LPSTR)name, &value[0], &dwSize);
{XFS::Logger() << "RegKey::value[value](name=" << name << ", value=&" << &value[0] << ", size=&" << dwSize << ") = " << r;}
}
std::string result = std::string(value.begin(), value.end()-1);
XFS::Logger() << "RegKey::value(name=" << name << ") = " << result;
return result;
}
inline DWORD dwValue(const char* name) const {
// Узнаем размер значения ключа.
DWORD result = 0;
DWORD dwSize = sizeof(DWORD);
HRESULT r = WFMQueryValue(hKey, (LPSTR)name, (LPSTR)&result, &dwSize);
XFS::Logger() << "RegKey::value(name=" << name << ") = " << result;
return result;
}
/// Отладочная функция для вывода в трассу всех дочерных ключей.
void keys() const {
{XFS::Logger() << "keys";}
std::vector<char> keyName(256);
for (DWORD i = 0; ; ++i) {
DWORD size = keyName.capacity();
HRESULT r = WFMEnumKey(hKey, i, &keyName[0], &size, NULL);
if (r == WFS_ERR_CFG_NO_MORE_ITEMS) {
break;
}
keyName[size] = '\0';
XFS::Logger() << &keyName[0];
}
}
/// Отладочная функция для вывода в трассу всех дочерных значений ключа.
/// Значение ключа -- это пара (имя=значение).
void values() const {
{XFS::Logger() << "values";}
// К сожалению, узнать конкретные длины заранее невозможно.
std::vector<char> name(256);
std::vector<char> value(256);
for (DWORD i = 0; ; ++i) {
DWORD szName = name.capacity();
DWORD szValue = value.capacity();
HRESULT r = WFMEnumValue(hKey, i, &name[0], &szName, &value[0], &szValue);
if (r == WFS_ERR_CFG_NO_MORE_ITEMS) {
break;
}
name[szName] = '\0';
value[szValue] = '\0';
XFS::Logger()
<< i << ": " << '('<<szName<<','<<szValue<<')' << std::string(name.begin(), name.begin()+szName) << "="
<< std::string(value.begin(), value.begin()+szValue);
}
}
};
Settings::Settings(const char* serviceName, int traceLevel)
: traceLevel(traceLevel)
, exclusive(false)
{
// У Калигнайта под данным корнем не появляется провайдера, если он в
// HKEY_LOCAL_MACHINE\SOFTWARE\XFS\SERVICE_PROVIDERS\
// HKEY root = WFS_CFG_HKEY_XFS_ROOT;
HKEY root = WFS_CFG_USER_DEFAULT_XFS_ROOT;// HKEY_USERS\.DEFAULT\XFS
providerName = RegKey(root, "LOGICAL_SERVICES").child(serviceName).value("Provider");
reread();
}
void Settings::reread() {
HKEY root = WFS_CFG_USER_DEFAULT_XFS_ROOT;// HKEY_USERS\.DEFAULT\XFS
RegKey pcscSettings = RegKey(root, "SERVICE_PROVIDERS").child(providerName.c_str());
readerName = pcscSettings.value("ReaderName");
traceLevel = pcscSettings.dwValue("TraceLevel");
exclusive = pcscSettings.dwValue("Exclusive") != 0;
// Настройки обходов различных проблем
RegKey workaroundSettings = pcscSettings.child("Workarounds");
workarounds.correctChipIO = workaroundSettings.dwValue("CorrectChipIO") != 0;
workarounds.canEject = workaroundSettings.dwValue("CanEject") != 0;
RegKey track2Settings = workaroundSettings.child("Track2");
workarounds.track2.report = track2Settings.dwValue("Report") != 0;
workarounds.track2.value = track2Settings.value();
XFS::Logger() << "Settings::reread: Readed new settings: " << toJSONString();
}
std::string Settings::toJSONString() const {
std::stringstream ss;
ss << "{\n";
ss << "\tProviderName: " << providerName << ",\n";
ss << "\tReaderName: " << readerName << ",\n";
ss << "\tTraceLevel: " << traceLevel << ",\n";
ss << "\tExclusive: " << std::boolalpha << exclusive << ",\n";
ss << "\tWorkarounds.CorrectChipIO: " << std::boolalpha << workarounds.correctChipIO << ",\n";
ss << "\tWorkarounds.CanEject: " << std::boolalpha << workarounds.canEject << ",\n";
ss << "\tWorkarounds.Track2.Report: " << std::boolalpha << workarounds.track2.report << ",\n";
ss << "\tWorkarounds.Track2.Value: " << workarounds.track2.value << ",\n";
ss << '}';
return ss.str();
}