Processor Counter Monitor
windriver.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 // Copyright (c) 2009-2012, Intel Corporation
3 
4 #ifndef WINDRIVER_HEADER
5 #define WINDRIVER_HEADER
6 
7 // contact: Roman Dementiev
8 // WARNING: This driver code is only for testing purposes, not for production use
9 //
10 
11 #include <iostream>
12 #include <winreg.h>
13 #include <comdef.h>
14 #include "../cpucounters.h"
15 
16 namespace pcm {
17 
22 extern void restrictDriverAccess(LPCTSTR path);
23 
29 class Driver
30 {
31  SC_HANDLE hSCManager{};
32  SC_HANDLE hService{};
33  SERVICE_STATUS ss{};
34 
35 public:
36  static tstring msrLocalPath()
37  {
38  tstring driverPath;
39  DWORD driverPathLen = 1;
40  DWORD gcdReturn = 0;
41 
42  do {
43  if (0 != gcdReturn)
44  {
45  driverPathLen = gcdReturn;
46  }
47  driverPath.resize(driverPathLen);
48  gcdReturn = GetCurrentDirectory(driverPathLen, &driverPath[0]);
49  } while (0 != gcdReturn && driverPathLen < gcdReturn);
50 
51  removeNullTerminator(driverPath);
52 
53  return driverPath + TEXT("\\msr.sys");
54  }
55 
56  Driver() :
57  Driver(TEXT("c:\\windows\\system32\\msr.sys"))
58  {
59  }
60 
61  Driver(const tstring& driverPath) :
62  Driver(driverPath, TEXT("PCM MSR"), TEXT("PCM MSR Driver"))
63  {
64  }
65 
66  Driver(const tstring& driverPath, const tstring& driverName, const tstring& driverDescription) :
67  driverPath_(setConfigValue(TEXT("DriverPath"), driverPath)),
68  driverName_(setConfigValue(TEXT("DriverName"), driverName)),
69  driverDescription_(setConfigValue(TEXT("DriverDescription"), driverDescription))
70  {
71  }
72 
73  const tstring& driverPath() const
74  {
75  return driverPath_;
76  }
77 
78 
86  bool start()
87  {
88  hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
89  if (hSCManager)
90  {
91  hService = CreateService(hSCManager, &driverName_[0], &driverDescription_[0], SERVICE_START | DELETE | SERVICE_STOP,
92  SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, &driverPath_[0], NULL, NULL, NULL, NULL, NULL);
93 
94  if (!hService)
95  {
96  hService = OpenService(hSCManager, &driverName_[0], SERVICE_START | DELETE | SERVICE_STOP);
97  }
98 
99  if (hService)
100  {
101  if (0 != StartService(hService, 0, NULL))
102  {
103  tstring convDriverName(&driverName_[0]);
104  tstring driverPath = TEXT("\\\\.\\") + convDriverName;
105  restrictDriverAccess(driverPath.c_str());
106  return true;
107  }
108  DWORD err = GetLastError();
109  if (err == ERROR_SERVICE_ALREADY_RUNNING) return true;
110 
111  std::wcerr << "Starting MSR service failed with error " << err << " ";
112  const TCHAR * errorStr = _com_error(err).ErrorMessage();
113  if (errorStr)
114  std::wcerr << errorStr << "\n";
115 
116  ControlService(hService, SERVICE_CONTROL_STOP, &ss);
117 
118  // DeleteService(hService);
119 
120  CloseServiceHandle(hService);
121  }
122  else
123  {
124  std::wcerr << "Opening service manager failed with error " << GetLastError() << " ";
125  const TCHAR * errorStr = _com_error(GetLastError()).ErrorMessage();
126  if (errorStr)
127  std::wcerr << errorStr << "\n";
128  }
129 
130  CloseServiceHandle(hSCManager);
131  }
132  else
133  {
134  std::wcerr << "Opening service manager failed with error " << GetLastError() << " ";
135  const TCHAR * errorStr = _com_error(GetLastError()).ErrorMessage();
136  if (errorStr)
137  std::wcerr << errorStr << "\n";
138  }
139 
140  #ifndef NO_WINRING // In cases where loading the WinRing0 driver is not desirable as a fallback to MSR.sys, add -DNO_WINRING to compile command to remove ability to load driver (will also remove initWinRing0Lib function)
141  std::cerr << "Trying to load winring0.dll/winring0.sys driver...\n";
143  {
144  std::cerr << "Using winring0.dll/winring0.sys driver.\n\n";
145  return true;
146  }
147  else
148  {
149  std::cerr << "Failed to load winring0.dll/winring0.sys driver.\n\n";
150  }
151  #endif // NO_WINRING
152 
153  return false;
154  }
155 
157  void stop()
158  {
159  hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
160  if (hSCManager)
161  {
162  hService = OpenService(hSCManager, &driverName_[0], SERVICE_START | DELETE | SERVICE_STOP);
163  if (hService)
164  {
165  ControlService(hService, SERVICE_CONTROL_STOP, &ss);
166  CloseServiceHandle(hService);
167  }
168 
169  CloseServiceHandle(hSCManager);
170  }
171  else
172  {
173  std::wcerr << "Opening service manager failed with error " << GetLastError() << " ";
174  const TCHAR * errorStr = _com_error(GetLastError()).ErrorMessage();
175  if (errorStr)
176  std::wcerr << errorStr;
177  }
178  }
179 
184  void uninstall()
185  {
186  hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
187  if (hSCManager)
188  {
189  hService = OpenService(hSCManager, &driverName_[0], SERVICE_START | DELETE | SERVICE_STOP);
190  if (hService)
191  {
192  ControlService(hService, SERVICE_CONTROL_STOP, &ss);
193  DeleteService(hService);
194  CloseServiceHandle(hService);
195  }
196 
197  CloseServiceHandle(hSCManager);
198  }
199  else
200  {
201  std::wcerr << "Opening service manager failed with error " << GetLastError() << " ";
202  const TCHAR * errorStr = _com_error(GetLastError()).ErrorMessage();
203  if (errorStr)
204  std::wcerr << errorStr;
205  }
206  }
207 
208 private:
209 
210  static tstring setConfigValue(LPCTSTR key, const tstring& defaultValue)
211  {
212  tstring regRead;
213  DWORD regLen = 1 * sizeof(TCHAR);
214  DWORD regRes = ERROR_FILE_NOT_FOUND; // Safe error to start with in case key doesn't exist
215 
216  HKEY hKey;
217  if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\pcm"), NULL, KEY_READ, &hKey))
218  {
219  do {
220  regRead.resize(regLen / sizeof(TCHAR));
221  regRes = RegQueryValueEx(hKey, key, NULL, NULL, (LPBYTE)&regRead[0], &regLen);
222  } while (ERROR_MORE_DATA == regRes);
223 
224  RegCloseKey(hKey);
225  }
226 
227  removeNullTerminator(regRead);
228 
229  return ERROR_SUCCESS == regRes ? regRead : defaultValue;
230  }
231 
232  static void removeNullTerminator(tstring& s)
233  {
234  if (!s.empty() && s.back() == '\0')
235  {
236  s.pop_back();
237  }
238  }
239 
240  const tstring driverName_;
241  const tstring driverPath_;
242  const tstring driverDescription_;
243 };
244 
245 } // namespace pcm
246 
247 #endif
static bool initWinRing0Lib()
Loads and initializes Winring0 third party library for access to processor model specific and PCI con...
Manage custom Windows MSR (Model Specific Register) Driver The driver is required to access hardware ...
Definition: windriver.h:29
Definition: bw.cpp:12
void uninstall()
Uninstall the driver.
Definition: windriver.h:184
bool start()
Installs and loads the driver.
Definition: windriver.h:86
void stop()
Stop and unload the driver.
Definition: windriver.h:157