metadata-helper.cpp
Go to the documentation of this file.
1 #include "metadata-helper.h"
2 
3 #ifdef WIN32
4 
5 #include <Windows.h>
6 #include <memory>
7 #include <vector>
8 #include <algorithm>
9 #include <iterator>
10 
11 #include <regex>
12 #include <iostream>
13 #include <sstream>
14 #include <functional>
15 #include <map>
16 #include <memory>
17 
18 #include <librealsense2/rs.hpp>
19 
20 #define MAX_KEY_LENGTH 255
21 #define MAX_VALUE_NAME 16383
22 
23 #ifdef _MSC_VER
24 #define strncasecmp _strnicmp
25 #define strcasecmp _stricmp
26 #endif
27 
28 #endif
29 
30 namespace rs2
31 {
32 #ifdef WIN32
33  struct device_id
34  {
35  std::string pid, mi, guid, sn;
36  };
37 
38  inline bool equal(const std::string& a, const std::string& b)
39  {
40  return strcasecmp(a.c_str(), b.c_str()) == 0;
41  }
42 
43  inline bool operator==(const device_id& a, const device_id& b)
44  {
45  return equal(a.pid, b.pid) &&
46  equal(a.guid, b.guid) &&
47  equal(a.mi, b.mi) &&
48  equal(a.sn, b.sn);
49  }
50 
51  class windows_metadata_helper : public metadata_helper
52  {
53  public:
54  static bool parse_device_id(const std::string& id, device_id* res)
55  {
56  static const std::regex regex("pid_([0-9a-f]+)&mi_([0-9]+)#[0-9a-f]&([0-9a-f]+)&[\\s\\S]*\\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\}", std::regex_constants::icase);
57 
58  std::match_results<std::string::const_iterator> match;
59 
60  if (std::regex_search(id, match, regex) && match.size() > 4)
61  {
62  res->pid = match[1];
63  res->mi = match[2];
64  res->sn = match[3];
65  res->guid = match[4];
66  return true;
67  }
68  return false;
69  }
70 
71  static void foreach_device_path(const std::vector<device_id>& devices,
72  std::function<void(const device_id&, /* matched device */
73  std::wstring /* registry key of Device Parameters for that device */)> action)
74  {
75  std::map<std::string, std::vector<device_id>> guid_to_devices;
76  for (auto&& d : devices)
77  {
78  guid_to_devices[d.guid].push_back(d);
79  }
80 
81  for (auto&& kvp : guid_to_devices)
82  {
83  auto guid = kvp.first;
84 
85  std::stringstream ss;
86  ss << "SYSTEM\\CurrentControlSet\\Control\\DeviceClasses\\{" << guid << "}";
87  auto s = ss.str();
88  std::wstring prefix(s.begin(), s.end());
89 
90  HKEY key;
91  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, prefix.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
92  {
93  // Don't forget to release in the end:
94  std::shared_ptr<void> raii(key, RegCloseKey);
95 
96  TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
97  DWORD cchClassName = MAX_PATH; // size of class string
98  DWORD cSubKeys = 0; // number of subkeys
99  DWORD cbMaxSubKey; // longest subkey size
100  DWORD cchMaxClass; // longest class string
101  DWORD cValues; // number of values for key
102  DWORD cchMaxValue; // longest value name
103  DWORD cbMaxValueData; // longest value data
104  DWORD cbSecurityDescriptor; // size of security descriptor
105  FILETIME ftLastWriteTime; // last write time
106 
107  DWORD retCode = RegQueryInfoKey(
108  key, // key handle
109  achClass, // buffer for class name
110  &cchClassName, // size of class string
111  NULL, // reserved
112  &cSubKeys, // number of subkeys
113  &cbMaxSubKey, // longest subkey size
114  &cchMaxClass, // longest class string
115  &cValues, // number of values for this key
116  &cchMaxValue, // longest value name
117  &cbMaxValueData, // longest value data
118  &cbSecurityDescriptor, // security descriptor
119  &ftLastWriteTime); // last write time
120 
121  for (auto i = 0ul; i < cSubKeys; i++)
122  {
123  TCHAR achKey[MAX_KEY_LENGTH];
124  DWORD cbName = MAX_KEY_LENGTH;
125  retCode = RegEnumKeyEx(key, i,
126  achKey,
127  &cbName,
128  NULL,
129  NULL,
130  NULL,
131  &ftLastWriteTime);
132  if (retCode == ERROR_SUCCESS)
133  {
134  std::wstring suffix = achKey;
135  device_id rdid;
136  auto a = std::string(suffix.begin(), suffix.end());
137  if (parse_device_id(a, &rdid))
138  {
139  for (auto&& did : kvp.second)
140  {
141  if (rdid == did)
142  {
143  std::wstringstream ss;
144  ss << prefix << "\\" << suffix << "\\#GLOBAL\\Device Parameters";
145  auto path = ss.str();
146  action(rdid, path);
147  }
148  }
149  }
150  }
151  }
152  }
153  }
154  }
155 
156  // Heuristic that determines how many media-pins UVC device is expected to have
157  static int number_of_mediapins(const std::string& pid, const std::string& mi)
158  {
159  if (mi == "00")
160  {
161  // L500 has 3 media-pins
162  if (equal(pid, "0b0d") || equal(pid, "0b3d") || equal(pid, "0b64") || equal(pid, "0b68")) return 3;
163  // D405 has 3 media-pins
164  else if (equal(pid, "0b5b")) return 3;
165  else return 2; // D400 has two
166  }
167  return 1; // RGB has one
168  }
169 
170  bool is_running_as_admin()
171  {
172  BOOL result = FALSE;
173  PSID admin_group = NULL;
174 
175  SID_IDENTIFIER_AUTHORITY ntauthority = SECURITY_NT_AUTHORITY;
176  if (!AllocateAndInitializeSid(
177  &ntauthority,
178  2,
179  SECURITY_BUILTIN_DOMAIN_RID,
180  DOMAIN_ALIAS_RID_ADMINS,
181  0, 0, 0, 0, 0, 0,
182  &admin_group))
183  {
184  rs2::log(RS2_LOG_SEVERITY_WARN, "Unable to query permissions - AllocateAndInitializeSid failed");
185  return false;
186  }
187  std::shared_ptr<void> raii(admin_group, FreeSid);
188 
189  if (!CheckTokenMembership(NULL, admin_group, &result))
190  {
191  rs2::log(RS2_LOG_SEVERITY_WARN, "Unable to query permissions - CheckTokenMembership failed");
192  return false;
193  }
194 
195  return result;
196  }
197 
198  bool elevate_to_admin()
199  {
200  if (!is_running_as_admin())
201  {
202  wchar_t szPath[MAX_PATH];
203  if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)))
204  {
205  SHELLEXECUTEINFO sei = { sizeof(sei) };
206 
207  sei.lpVerb = L"runas";
208  sei.fMask = SEE_MASK_NOCLOSEPROCESS;
209  sei.lpFile = szPath;
210  sei.hwnd = NULL;
211  sei.nShow = SW_NORMAL;
212  auto cmd_line = get_command_line_param();
213  std::wstring wcmd(cmd_line.begin(), cmd_line.end());
214  sei.lpParameters = wcmd.c_str();
215 
216  if (ShellExecuteEx(&sei) != ERROR_SUCCESS)
217  {
218  rs2::log(RS2_LOG_SEVERITY_WARN, "Unable to elevate to admin privilege to enable metadata!");
219  return false;
220  }
221  else
222  {
223  WaitForSingleObject(sei.hProcess, INFINITE);
224  DWORD exitCode = 0;
225  GetExitCodeProcess(sei.hProcess, &exitCode);
226  CloseHandle(sei.hProcess);
227  if (exitCode)
228  throw std::runtime_error("Failed to set metadata registry keys!");
229  return true;
230  }
231  }
232  else
233  {
234  rs2::log(RS2_LOG_SEVERITY_WARN, "Unable to fetch module name!");
235  return false;
236  }
237  }
238  else
239  {
240  return true;
241  }
242  }
243 
244  bool is_enabled(std::string id) const override
245  {
246  bool res = false;
247 
248  device_id did;
249  if (parse_device_id(id, &did))
250  foreach_device_path({ did }, [&res, did](const device_id&, std::wstring path) {
251 
252  HKEY key;
253  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
254  {
255  // Don't forget to release in the end:
256  std::shared_ptr<void> raii(key, RegCloseKey);
257 
258  bool found = true;
259  DWORD len = sizeof(DWORD);//size of data
260 
261  for (int i = 0; i < number_of_mediapins(did.pid, did.mi); i++)
262  {
263  std::wstringstream ss; ss << L"MetadataBufferSizeInKB" << i;
264  std::wstring metadatakey = ss.str();
265 
266  DWORD MetadataBufferSizeInKB = 0;
267  if (RegQueryValueEx(
268  key,
269  metadatakey.c_str(),
270  NULL,
271  NULL,
272  (LPBYTE)(&MetadataBufferSizeInKB),
273  &len) != ERROR_SUCCESS)
274  rs2::log(RS2_LOG_SEVERITY_DEBUG, "Unable to read metadata registry key!");
275 
276  found = found && MetadataBufferSizeInKB;
277  }
278 
279  if (found) res = true;
280  }
281  });
282 
283  return res;
284  }
285 
286  void enable_metadata() override
287  {
288  if (elevate_to_admin()) // Elevation to admin was succesful?
289  {
290  std::vector<device_id> dids;
291 
293  auto list = ctx.query_devices();
294  for (uint32_t i = 0; i < list.size(); i++)
295  {
296  try
297  {
298  rs2::device dev = list[i];
299 
301  {
303  if (can_support_metadata(product))
304  {
305  for (auto sen : dev.query_sensors())
306  {
307  if (sen.supports(RS2_CAMERA_INFO_PHYSICAL_PORT))
308  {
310  device_id did;
311  if (parse_device_id(port, &did)) dids.push_back(did);
312  }
313  }
314  }
315  }
316  }
317  catch (...) {}
318  }
319 
320  bool failure = false;
321  foreach_device_path(dids, [&failure](const device_id& did, std::wstring path) {
322  HKEY key;
323  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
324  {
325  // Don't forget to release in the end:
326  std::shared_ptr<void> raii(key, RegCloseKey);
327 
328  bool found = true;
329  DWORD len = sizeof(DWORD);//size of data
330 
331  for (int i = 0; i < number_of_mediapins(did.pid, did.mi); i++)
332  {
333  std::wstringstream ss; ss << L"MetadataBufferSizeInKB" << i;
334  std::wstring metadatakey = ss.str();
335 
336  DWORD MetadataBufferSizeInKB = 5;
337  if (RegSetValueEx(key, metadatakey.c_str(), 0, REG_DWORD,
338  (const BYTE*)&MetadataBufferSizeInKB, sizeof(DWORD)) != ERROR_SUCCESS)
339  {
340  rs2::log(RS2_LOG_SEVERITY_DEBUG, "Unable to write metadata registry key!");
341  failure = true;
342  }
343  }
344  }
345  });
346  if (failure) throw std::runtime_error("Unable to write to metadata registry key!");
347  }
348  }
349  };
350 #endif
351 
353  {
354 #ifdef WIN32
355  static windows_metadata_helper instance;
356 #else
357  static metadata_helper instance;
358 #endif
359  return instance;
360  }
361 }
GLboolean GLboolean GLboolean b
std::vector< sensor > query_sensors() const
Definition: rs_device.hpp:25
bool operator==(const plane &lhs, const plane &rhs)
Definition: rendering.h:134
GLdouble s
GLsizei const GLchar *const * path
Definition: glext.h:4276
device_list query_devices() const
Definition: rs_context.hpp:112
void log(rs2_log_severity severity, const char *message)
Definition: rs.hpp:149
Definition: cah-model.h:10
static metadata_helper & instance()
GLsizei const GLchar *const * string
d
Definition: rmse.py:171
GLboolean GLboolean GLboolean GLboolean a
GLenum GLsizei len
Definition: glext.h:3285
GLuint64 key
Definition: glext.h:8966
Definition: parser.hpp:154
unsigned char BYTE
Definition: lz4.c:145
unsigned int uint32_t
Definition: stdint.h:80
devices
Definition: test-fg.py:9
const char * get_info(rs2_camera_info info) const
Definition: rs_device.hpp:79
action
Definition: enums.py:62
bool supports(rs2_camera_info info) const
Definition: rs_device.hpp:66
#define NULL
Definition: tinycthread.c:47
int i
GLuint res
Definition: glext.h:8856
#define FALSE
Definition: tinycthread.c:53
GLuint64EXT * result
Definition: glext.h:10921


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:21