VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBugReport/VBoxBugReportWin.cpp@ 74942

Last change on this file since 74942 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.5 KB
Line 
1/* $Id: VBoxBugReportWin.cpp 69500 2017-10-28 15:14:05Z vboxsync $ */
2/** @file
3 * VBoxBugReportWin - VirtualBox command-line diagnostics tool, Windows-specific part.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/com/com.h>
19#include <VBox/com/string.h>
20
21#include <iprt/cpp/exception.h>
22
23#include "VBoxBugReport.h"
24
25#include <netcfgx.h>
26#include <iprt/win/setupapi.h>
27#include <initguid.h>
28#include <devguid.h>
29#include <usbiodef.h>
30#include <usbioctl.h>
31#include <psapi.h>
32
33#define ReleaseAndReset(obj) \
34 if (obj) \
35 obj->Release(); \
36 obj = NULL;
37
38
39class BugReportNetworkAdaptersWin : public BugReportStream
40{
41public:
42 BugReportNetworkAdaptersWin() : BugReportStream("NetworkAdapters") {};
43 virtual ~BugReportNetworkAdaptersWin() {};
44 virtual PRTSTREAM getStream(void) { collect(); return BugReportStream::getStream(); };
45private:
46 struct CharacteristicsName
47 {
48 DWORD dwChar;
49 const char *szName;
50 };
51 void printCharteristics(DWORD dwChars);
52 void collect();
53 void collectNetCfgComponentInfo(int ident, bool fEnabled, INetCfgComponent *pComponent);
54};
55
56
57
58void BugReportNetworkAdaptersWin::printCharteristics(DWORD dwChars)
59{
60 static CharacteristicsName cMap[] =
61 {
62 { NCF_VIRTUAL, "virtual" },
63 { NCF_SOFTWARE_ENUMERATED, "software_enumerated" },
64 { NCF_PHYSICAL, "physical" },
65 { NCF_HIDDEN, "hidden" },
66 { NCF_NO_SERVICE, "no_service" },
67 { NCF_NOT_USER_REMOVABLE, "not_user_removable" },
68 { NCF_MULTIPORT_INSTANCED_ADAPTER, "multiport_instanced_adapter" },
69 { NCF_HAS_UI, "has_ui" },
70 { NCF_SINGLE_INSTANCE, "single_instance" },
71 { NCF_FILTER, "filter" },
72 { NCF_DONTEXPOSELOWER, "dontexposelower" },
73 { NCF_HIDE_BINDING, "hide_binding" },
74 { NCF_NDIS_PROTOCOL, "ndis_protocol" },
75 { NCF_FIXED_BINDING, "fixed_binding" },
76 { NCF_LW_FILTER, "lw_filter" }
77 };
78 bool fPrintDelim = false;
79
80 for (int i = 0; i < RT_ELEMENTS(cMap); ++i)
81 {
82 if (dwChars & cMap[i].dwChar)
83 {
84 if (fPrintDelim)
85 {
86 putStr(", ");
87 fPrintDelim = false;
88 }
89 putStr(cMap[i].szName);
90 fPrintDelim = true;
91 }
92 }
93}
94
95void BugReportNetworkAdaptersWin::collectNetCfgComponentInfo(int ident, bool fEnabled, INetCfgComponent *pComponent)
96{
97 LPWSTR pwszName = NULL;
98 HRESULT hr = pComponent->GetDisplayName(&pwszName);
99 if (FAILED(hr))
100 throw RTCError(com::Utf8StrFmt("Failed to get component display name, hr=0x%x.\n", hr));
101 printf("%s%c %ls [", RTCString(ident, ' ').c_str(), fEnabled ? '+' : '-', pwszName);
102 if (pwszName)
103 CoTaskMemFree(pwszName);
104
105 DWORD dwChars = 0;
106 hr = pComponent->GetCharacteristics(&dwChars);
107 if (FAILED(hr))
108 throw RTCError(com::Utf8StrFmt("Failed to get component characteristics, hr=0x%x.\n", hr));
109 printCharteristics(dwChars);
110 putStr("]\n");
111}
112
113void BugReportNetworkAdaptersWin::collect(void)
114{
115 INetCfg *pNetCfg = NULL;
116 IEnumNetCfgComponent *pEnumAdapters = NULL;
117 INetCfgComponent *pNetCfgAdapter = NULL;
118 INetCfgComponentBindings *pAdapterBindings = NULL;
119 IEnumNetCfgBindingPath *pEnumBp = NULL;
120 INetCfgBindingPath *pBp = NULL;
121 IEnumNetCfgBindingInterface *pEnumBi = NULL;
122 INetCfgBindingInterface *pBi = NULL;
123 INetCfgComponent *pUpperComponent = NULL;
124
125 try
126 {
127 HRESULT hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNetCfg);
128 if (FAILED(hr))
129 throw RTCError(com::Utf8StrFmt("Failed to create instance of INetCfg, hr=0x%x.\n", hr));
130 hr = pNetCfg->Initialize(NULL);
131 if (FAILED(hr))
132 throw RTCError(com::Utf8StrFmt("Failed to initialize instance of INetCfg, hr=0x%x.\n", hr));
133
134 hr = pNetCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumAdapters);
135 if (FAILED(hr))
136 throw RTCError(com::Utf8StrFmt("Failed enumerate network adapters, hr=0x%x.\n", hr));
137
138 hr = pEnumAdapters->Reset();
139 Assert(SUCCEEDED(hr));
140 do
141 {
142 hr = pEnumAdapters->Next(1, &pNetCfgAdapter, NULL);
143 if (hr == S_FALSE)
144 break;
145 if (hr != S_OK)
146 throw RTCError(com::Utf8StrFmt("Failed to get next network adapter, hr=0x%x.\n", hr));
147 hr = pNetCfgAdapter->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pAdapterBindings);
148 if (FAILED(hr))
149 throw RTCError(com::Utf8StrFmt("Failed to query INetCfgComponentBindings, hr=0x%x.\n", hr));
150 hr = pAdapterBindings->EnumBindingPaths(EBP_ABOVE, &pEnumBp);
151 if (FAILED(hr))
152 throw RTCError(com::Utf8StrFmt("Failed to enumerate binding paths, hr=0x%x.\n", hr));
153 hr = pEnumBp->Reset();
154 if (FAILED(hr))
155 throw RTCError(com::Utf8StrFmt("Failed to reset enumeration of binding paths (0x%x)\n", hr));
156 do
157 {
158 hr = pEnumBp->Next(1, &pBp, NULL);
159 if (hr == S_FALSE)
160 break;
161 if (hr != S_OK)
162 throw RTCError(com::Utf8StrFmt("Failed to get next network adapter, hr=0x%x.\n", hr));
163 bool fBpEnabled;
164 hr = pBp->IsEnabled();
165 if (hr == S_FALSE)
166 fBpEnabled = false;
167 else if (hr != S_OK)
168 throw RTCError(com::Utf8StrFmt("Failed to check if bind path is enabled, hr=0x%x.\n", hr));
169 else
170 fBpEnabled = true;
171 hr = pBp->EnumBindingInterfaces(&pEnumBi);
172 if (FAILED(hr))
173 throw RTCError(com::Utf8StrFmt("Failed to enumerate binding interfaces (0x%x)\n", hr));
174 hr = pEnumBi->Reset();
175 if (FAILED(hr))
176 throw RTCError(com::Utf8StrFmt("Failed to reset enumeration of binding interfaces (0x%x)\n", hr));
177 int ident;
178 for (ident = 0;; ++ident)
179 {
180 hr = pEnumBi->Next(1, &pBi, NULL);
181 if (hr == S_FALSE)
182 break;
183 if (hr != S_OK)
184 throw RTCError(com::Utf8StrFmt("Failed to get next binding interface, hr=0x%x.\n", hr));
185 hr = pBi->GetUpperComponent(&pUpperComponent);
186 if (FAILED(hr))
187 throw RTCError(com::Utf8StrFmt("Failed to get upper component, hr=0x%x.\n", hr));
188 collectNetCfgComponentInfo(ident, fBpEnabled, pUpperComponent);
189 ReleaseAndReset(pUpperComponent);
190 ReleaseAndReset(pBi);
191 }
192 collectNetCfgComponentInfo(ident, fBpEnabled, pNetCfgAdapter);
193 ReleaseAndReset(pEnumBi);
194 ReleaseAndReset(pBp);
195 } while (true);
196
197 ReleaseAndReset(pEnumBp);
198 ReleaseAndReset(pAdapterBindings);
199 ReleaseAndReset(pNetCfgAdapter);
200 } while (true);
201 ReleaseAndReset(pEnumAdapters);
202 ReleaseAndReset(pNetCfg);
203 }
204
205 catch (RTCError &e)
206 {
207 ReleaseAndReset(pUpperComponent);
208 ReleaseAndReset(pBi);
209 ReleaseAndReset(pEnumBi);
210 ReleaseAndReset(pBp);
211 ReleaseAndReset(pEnumBp);
212 ReleaseAndReset(pAdapterBindings);
213 ReleaseAndReset(pNetCfgAdapter);
214 ReleaseAndReset(pEnumAdapters);
215 ReleaseAndReset(pNetCfg);
216 RTPrintf("ERROR in osCollect: %s\n", e.what());
217 throw;
218 }
219
220}
221
222
223class ErrorHandler
224{
225public:
226 ErrorHandler(const char *pszFunction, int iLine)
227 : m_function(pszFunction), m_line(iLine)
228 { }
229
230 void handleWinError(DWORD uError, const char *pszMsgFmt, ...)
231 {
232 if (uError != ERROR_SUCCESS)
233 {
234 va_list va;
235 va_start(va, pszMsgFmt);
236 RTCString msgArgs(pszMsgFmt, va);
237 va_end(va);
238
239 LPSTR pBuf = NULL;
240 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
241 NULL, uError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&pBuf, 0, NULL);
242 RTCStringFmt msg("%s at %s(%d): err=%u %s", msgArgs.c_str(), m_function, m_line, uError, pBuf);
243 LocalFree(pBuf);
244 throw RTCError(msg.c_str());
245 }
246 }
247
248private:
249 const char *m_function;
250 int m_line;
251};
252#define handleWinError ErrorHandler(__FUNCTION__, __LINE__).handleWinError
253
254
255class BugReportUsbTreeWin : public BugReportStream
256{
257public:
258 BugReportUsbTreeWin();
259 virtual ~BugReportUsbTreeWin();
260 virtual PRTSTREAM getStream(void) { enumerate(); return BugReportStream::getStream(); }
261private:
262 class AutoHandle {
263 public:
264 AutoHandle(HANDLE h) { m_h = h; }
265 ~AutoHandle() { close(); }
266 bool isValid() { return m_h != INVALID_HANDLE_VALUE; }
267 operator HANDLE() { return m_h; }
268 void close(void) { if (isValid()) { CloseHandle(m_h); m_h = INVALID_HANDLE_VALUE; } }
269 private:
270 HANDLE m_h;
271 };
272 void enumerate();
273
274 void enumerateController(PSP_DEVINFO_DATA pInfoData, PSP_DEVICE_INTERFACE_DATA pInterfaceData);
275 void enumerateHub(RTCString strFullName, RTCString strPrefix);
276 void enumeratePorts(HANDLE hHub, unsigned cPorts, RTCString strPrefix);
277 PBYTE getDeviceRegistryProperty(HDEVINFO hDev, PSP_DEVINFO_DATA pInfoData, DWORD uProperty,
278 DWORD uExpectedType, PDWORD puSize);
279 RTCString getDeviceRegistryPropertyString(HDEVINFO hDev, PSP_DEVINFO_DATA pInfoData, DWORD uProperty);
280
281 RTCString getDeviceDescByDriverName(RTCString strDrvName);
282 RTCString getDriverKeyName(HANDLE hHub, int iPort);
283 RTCString getExternalHubName(HANDLE hHub, int iPort);
284
285 HDEVINFO m_hDevInfo;
286 PSP_DEVICE_INTERFACE_DETAIL_DATA m_pDetailData;
287 HANDLE m_hHostCtrlDev;
288};
289
290BugReportUsbTreeWin::BugReportUsbTreeWin() : BugReportStream("HostUsbTree")
291{
292 m_hDevInfo = INVALID_HANDLE_VALUE;
293 m_pDetailData = NULL;
294 m_hHostCtrlDev = INVALID_HANDLE_VALUE;
295}
296
297BugReportUsbTreeWin::~BugReportUsbTreeWin()
298{
299 if (m_hHostCtrlDev != INVALID_HANDLE_VALUE)
300 CloseHandle(m_hHostCtrlDev);
301 if (m_pDetailData)
302 RTMemFree(m_pDetailData);
303 if (m_hDevInfo != INVALID_HANDLE_VALUE)
304 SetupDiDestroyDeviceInfoList(m_hDevInfo);
305}
306
307
308PBYTE BugReportUsbTreeWin::getDeviceRegistryProperty(HDEVINFO hDev,
309 PSP_DEVINFO_DATA pInfoData,
310 DWORD uProperty,
311 DWORD uExpectedType,
312 PDWORD puSize)
313{
314 DWORD uActualType, cbNeeded = 0;
315 if (!SetupDiGetDeviceRegistryProperty(hDev, pInfoData, uProperty, &uActualType,
316 NULL, 0, &cbNeeded)
317 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
318 {
319 if (GetLastError() == ERROR_INVALID_DATA)
320 return NULL;
321 handleWinError(GetLastError(), "SetupDiGetDeviceRegistryProperty(0x%x) failed", uProperty);
322 }
323 if (uExpectedType != REG_NONE && uActualType != uExpectedType)
324 throw RTCError(RTCStringFmt("SetupDiGetDeviceRegistryProperty(0x%x) returned type %d instead of %d",
325 uActualType, uExpectedType).c_str());
326 PBYTE pBuffer = (PBYTE)RTMemAlloc(cbNeeded);
327 if (!pBuffer)
328 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbNeeded).c_str());
329 if (!SetupDiGetDeviceRegistryProperty(hDev, pInfoData, uProperty, NULL,
330 pBuffer, cbNeeded, &cbNeeded))
331 {
332 DWORD dwErr = GetLastError();
333 RTMemFree(pBuffer);
334 pBuffer = NULL;
335 handleWinError(dwErr, "SetupDiGetDeviceRegistryProperty(0x%x) failed", uProperty);
336 }
337 if (puSize)
338 *puSize = cbNeeded;
339
340 return pBuffer;
341}
342
343RTCString BugReportUsbTreeWin::getDeviceRegistryPropertyString(HDEVINFO hDev, PSP_DEVINFO_DATA pInfoData, DWORD uProperty)
344{
345 PWSTR pUnicodeString = (PWSTR)getDeviceRegistryProperty(hDev, pInfoData, uProperty, REG_SZ, NULL);
346
347 if (!pUnicodeString)
348 return RTCString();
349
350 RTCStringFmt utf8string("%ls", pUnicodeString);
351 RTMemFree(pUnicodeString);
352 return utf8string;
353}
354
355
356RTCString BugReportUsbTreeWin::getDeviceDescByDriverName(RTCString strDrvName)
357{
358 DWORD dwErr;
359 SP_DEVINFO_DATA devInfoData;
360 HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
361
362 if (hDevInfo == INVALID_HANDLE_VALUE)
363 handleWinError(GetLastError(), "SetupDiGetClassDevs failed");
364
365 bool fFound = false;
366 devInfoData.cbSize = sizeof(devInfoData);
367 for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); ++i)
368 {
369 if (getDeviceRegistryPropertyString(hDevInfo, &devInfoData, SPDRP_DRIVER).equals(strDrvName))
370 {
371 fFound = true;
372 break;
373 }
374 }
375 if (!fFound)
376 {
377 dwErr = GetLastError();
378 SetupDiDestroyDeviceInfoList(hDevInfo);
379 handleWinError(dwErr, "SetupDiEnumDeviceInfo failed");
380 }
381
382 RTCString strDesc = getDeviceRegistryPropertyString(hDevInfo, &devInfoData, SPDRP_DEVICEDESC);
383 SetupDiDestroyDeviceInfoList(hDevInfo);
384 return strDesc;
385}
386
387
388RTCString BugReportUsbTreeWin::getDriverKeyName(HANDLE hHub, int iPort)
389{
390 USB_NODE_CONNECTION_DRIVERKEY_NAME name;
391 ULONG cbNeeded = 0;
392
393 name.ConnectionIndex = iPort;
394 if (!DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
395 &name, sizeof(name), &name, sizeof(name), &cbNeeded, NULL))
396 handleWinError(GetLastError(), "DeviceIoControl(IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME) failed");
397 cbNeeded = name.ActualLength;
398 PUSB_NODE_CONNECTION_DRIVERKEY_NAME pName = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)RTMemAlloc(cbNeeded);
399 if (!pName)
400 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbNeeded).c_str());
401 pName->ConnectionIndex = iPort;
402 if (!DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
403 pName, cbNeeded, pName, cbNeeded, &cbNeeded, NULL))
404 {
405 DWORD dwErr = GetLastError();
406 RTMemFree(pName);
407 handleWinError(dwErr, "DeviceIoControl(IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME) failed");
408 }
409 RTCStringFmt strName("%ls", pName->DriverKeyName);
410 RTMemFree(pName);
411 return strName;
412}
413
414
415RTCString BugReportUsbTreeWin::getExternalHubName(HANDLE hHub, int iPort)
416{
417 USB_NODE_CONNECTION_NAME name;
418 ULONG cbNeeded = 0;
419
420 name.ConnectionIndex = iPort;
421 if (!DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
422 &name, sizeof(name), &name, sizeof(name), &cbNeeded, NULL))
423 handleWinError(GetLastError(), "DeviceIoControl(IOCTL_USB_GET_NODE_CONNECTION_NAME) failed");
424 cbNeeded = name.ActualLength;
425 PUSB_NODE_CONNECTION_NAME pName = (PUSB_NODE_CONNECTION_NAME)RTMemAlloc(cbNeeded);
426 if (!pName)
427 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbNeeded).c_str());
428 pName->ConnectionIndex = iPort;
429 if (!DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
430 pName, cbNeeded, pName, cbNeeded, &cbNeeded, NULL))
431 {
432 DWORD dwErr = GetLastError();
433 RTMemFree(pName);
434 handleWinError(dwErr, "DeviceIoControl(IOCTL_USB_GET_NODE_CONNECTION_NAME) failed");
435 }
436 RTCStringFmt strName("%ls", pName->NodeName);
437 RTMemFree(pName);
438 return strName;
439}
440
441
442void BugReportUsbTreeWin::enumeratePorts(HANDLE hHub, unsigned cPorts, RTCString strPrefix)
443{
444 DWORD cbInfo = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + 30 * sizeof(USB_PIPE_INFO);
445 PUSB_NODE_CONNECTION_INFORMATION_EX pInfo = (PUSB_NODE_CONNECTION_INFORMATION_EX)RTMemAlloc(cbInfo);
446 if (!pInfo)
447 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbInfo).c_str());
448 for (unsigned i = 1; i <= cPorts; ++i)
449 {
450 pInfo->ConnectionIndex = i;
451 if (!DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
452 pInfo, cbInfo, pInfo, cbInfo, &cbInfo, NULL))
453 {
454 DWORD dwErr = GetLastError();
455 RTMemFree(pInfo);
456 handleWinError(dwErr, "DeviceIoControl(IOCTL_USB_GET_NODE_CONNECTION_INFORMATION) failed");
457 }
458 if (pInfo->ConnectionStatus == NoDeviceConnected)
459 printf("%s[Port %d]\n", strPrefix.c_str(), i);
460 else
461 {
462 RTCString strName = getDeviceDescByDriverName(getDriverKeyName(hHub, i));
463 printf("%s[Port %d] %s\n", strPrefix.c_str(), i, strName.c_str());
464 if (pInfo->DeviceIsHub)
465 enumerateHub(getExternalHubName(hHub, i), strPrefix + " ");
466 }
467 }
468 RTMemFree(pInfo);
469}
470
471void BugReportUsbTreeWin::enumerateHub(RTCString strFullName, RTCString strPrefix)
472{
473 AutoHandle hHubDev(CreateFileA(RTCString("\\\\.\\").append(strFullName).c_str(),
474 GENERIC_WRITE, FILE_SHARE_WRITE,
475 NULL, OPEN_EXISTING, 0, NULL));
476 if (!hHubDev.isValid())
477 handleWinError(GetLastError(), "CreateFile(%s) failed", strFullName.c_str());
478 ULONG cb;
479 USB_NODE_INFORMATION hubInfo;
480 if (!DeviceIoControl(hHubDev,
481 IOCTL_USB_GET_NODE_INFORMATION,
482 &hubInfo,
483 sizeof(USB_NODE_INFORMATION),
484 &hubInfo,
485 sizeof(USB_NODE_INFORMATION),
486 &cb,
487 NULL))
488 handleWinError(GetLastError(), "DeviceIoControl(IOCTL_USB_GET_NODE_INFORMATION) failed");
489 enumeratePorts(hHubDev, hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts, strPrefix);
490}
491
492void BugReportUsbTreeWin::enumerateController(PSP_DEVINFO_DATA pInfoData, PSP_DEVICE_INTERFACE_DATA pInterfaceData)
493{
494 RT_NOREF(pInterfaceData);
495 RTCString strCtrlDesc = getDeviceRegistryPropertyString(m_hDevInfo, pInfoData, SPDRP_DEVICEDESC);
496 printf("%s\n", strCtrlDesc.c_str());
497
498 ULONG cbNeeded;
499 USB_ROOT_HUB_NAME rootHub;
500 /* Find out the name length first */
501 if (!DeviceIoControl(m_hHostCtrlDev, IOCTL_USB_GET_ROOT_HUB_NAME, NULL, 0,
502 &rootHub, sizeof(rootHub),
503 &cbNeeded, NULL))
504 handleWinError(GetLastError(), "DeviceIoControl(IOCTL_USB_GET_ROOT_HUB_NAME) failed");
505 cbNeeded = rootHub.ActualLength;
506 PUSB_ROOT_HUB_NAME pUnicodeName = (PUSB_ROOT_HUB_NAME)RTMemAlloc(cbNeeded);
507 if (!pUnicodeName)
508 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbNeeded).c_str());
509
510 if (!DeviceIoControl(m_hHostCtrlDev, IOCTL_USB_GET_ROOT_HUB_NAME, NULL, 0,
511 pUnicodeName, cbNeeded,
512 &cbNeeded, NULL))
513 {
514 DWORD dwErr = GetLastError();
515 RTMemFree(pUnicodeName);
516 handleWinError(dwErr, "DeviceIoControl(IOCTL_USB_GET_ROOT_HUB_NAME) failed");
517 }
518
519 RTCStringFmt strRootHubName("%ls", pUnicodeName->RootHubName);
520 RTMemFree(pUnicodeName);
521 printf(" Root Hub\n");
522 enumerateHub(strRootHubName, " ");
523}
524
525void BugReportUsbTreeWin::enumerate()
526{
527 m_hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, NULL,
528 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
529 if (m_hDevInfo == INVALID_HANDLE_VALUE)
530 handleWinError(GetLastError(), "SetupDiGetClassDevs(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) failed");
531
532 SP_DEVINFO_DATA deviceInfoData;
533 deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
534 for (int i = 0; SetupDiEnumDeviceInfo(m_hDevInfo, i, &deviceInfoData); ++i)
535 {
536 if (m_hHostCtrlDev != INVALID_HANDLE_VALUE)
537 CloseHandle(m_hHostCtrlDev);
538 if (m_pDetailData)
539 RTMemFree(m_pDetailData);
540
541 SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
542 deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
543 if (!SetupDiEnumDeviceInterfaces(m_hDevInfo, 0, (LPGUID)&GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
544 i, &deviceInterfaceData))
545 handleWinError(GetLastError(), "SetupDiEnumDeviceInterfaces(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) failed");
546
547 ULONG cbNeeded = 0;
548 if (!SetupDiGetDeviceInterfaceDetail(m_hDevInfo, &deviceInterfaceData, NULL, 0, &cbNeeded, NULL)
549 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
550 handleWinError(GetLastError(), "SetupDiGetDeviceInterfaceDetail failed");
551
552 m_pDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)RTMemAlloc(cbNeeded);
553 if (!m_pDetailData)
554 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", cbNeeded).c_str());
555
556 m_pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
557 if (!SetupDiGetDeviceInterfaceDetail(m_hDevInfo, &deviceInterfaceData, m_pDetailData, cbNeeded, &cbNeeded, NULL))
558 handleWinError(GetLastError(), "SetupDiGetDeviceInterfaceDetail failed");
559
560 m_hHostCtrlDev = CreateFile(m_pDetailData->DevicePath, GENERIC_WRITE, FILE_SHARE_WRITE,
561 NULL, OPEN_EXISTING, 0, NULL);
562 if (m_hHostCtrlDev == INVALID_HANDLE_VALUE)
563 handleWinError(GetLastError(), "CreateFile(%ls) failed", m_pDetailData);
564
565 enumerateController(&deviceInfoData, &deviceInterfaceData);
566 }
567}
568
569class BugReportDriversWin : public BugReportStream
570{
571public:
572 BugReportDriversWin();
573 virtual ~BugReportDriversWin();
574 virtual PRTSTREAM getStream(void) { enumerateDrivers(); return BugReportStream::getStream(); }
575private:
576 void enumerateDrivers(void);
577
578 WCHAR *m_pwszSystemRoot;
579 UINT m_cSystemRoot;
580 LPVOID *m_pDrivers;
581 DWORD m_cDrivers;
582 LPVOID m_pVerInfo;
583 DWORD m_cbVerInfo;
584};
585
586BugReportDriversWin::BugReportDriversWin() : BugReportStream("DriverVersions")
587{
588 m_cSystemRoot = MAX_PATH;
589 m_pwszSystemRoot = new WCHAR[MAX_PATH];
590 m_cDrivers = 1024;
591 m_pDrivers = new LPVOID[m_cDrivers];
592 m_pVerInfo = NULL;
593 m_cbVerInfo = 0;
594}
595
596BugReportDriversWin::~BugReportDriversWin()
597{
598 if (m_pVerInfo)
599 RTMemTmpFree(m_pVerInfo);
600 delete[] m_pDrivers;
601 delete[] m_pwszSystemRoot;
602}
603
604void BugReportDriversWin::enumerateDrivers()
605{
606 UINT cNeeded = GetWindowsDirectory(m_pwszSystemRoot, m_cSystemRoot);
607 if (cNeeded > m_cSystemRoot)
608 {
609 /* Re-allocate and try again */
610 m_cSystemRoot = cNeeded;
611 delete[] m_pwszSystemRoot;
612 m_pwszSystemRoot = new WCHAR[m_cSystemRoot];
613 cNeeded = GetWindowsDirectory(m_pwszSystemRoot, m_cSystemRoot);
614 }
615 if (cNeeded == 0)
616 handleWinError(GetLastError(), "GetWindowsDirectory failed");
617
618 DWORD cbNeeded = 0;
619 if ( !EnumDeviceDrivers(m_pDrivers, m_cDrivers * sizeof(m_pDrivers[0]), &cbNeeded)
620 || cbNeeded > m_cDrivers * sizeof(m_pDrivers[0]))
621 {
622 /* Re-allocate and try again */
623 m_cDrivers = cbNeeded / sizeof(m_pDrivers[0]);
624 delete[] m_pDrivers;
625 m_pDrivers = new LPVOID[m_cDrivers];
626 if (!EnumDeviceDrivers(m_pDrivers, cbNeeded, &cbNeeded))
627 handleWinError(GetLastError(), "EnumDeviceDrivers failed (%p, %u)", m_pDrivers, cbNeeded);
628 }
629
630 WCHAR wszDriver[1024];
631 for (unsigned i = 0; i < m_cDrivers; i++)
632 {
633 if (GetDeviceDriverBaseName(m_pDrivers[i], wszDriver, RT_ELEMENTS(wszDriver)))
634 {
635 if (_wcsnicmp(L"vbox", wszDriver, 4))
636 continue;
637 }
638 else
639 continue;
640 if (GetDeviceDriverFileName(m_pDrivers[i], wszDriver, RT_ELEMENTS(wszDriver)))
641 {
642 WCHAR wszTmpDrv[1024];
643 WCHAR *pwszDrv = wszDriver;
644 if (!wcsncmp(L"\\SystemRoot", wszDriver, 11))
645 {
646 wcsncpy_s(wszTmpDrv, m_pwszSystemRoot, m_cSystemRoot);
647 wcsncat_s(wszTmpDrv, wszDriver + 11, RT_ELEMENTS(wszTmpDrv) - m_cSystemRoot);
648 pwszDrv = wszTmpDrv;
649 }
650 else if (!wcsncmp(L"\\??\\", wszDriver, 4))
651 pwszDrv = wszDriver + 4;
652
653
654 /* Allocate a buffer for version info. Reuse if large enough. */
655 DWORD cbNewVerInfo = GetFileVersionInfoSize(pwszDrv, NULL);
656 if (cbNewVerInfo > m_cbVerInfo)
657 {
658 if (m_pVerInfo)
659 RTMemTmpFree(m_pVerInfo);
660 m_cbVerInfo = cbNewVerInfo;
661 m_pVerInfo = RTMemTmpAlloc(m_cbVerInfo);
662 if (!m_pVerInfo)
663 throw RTCError(RTCStringFmt("Failed to allocate %u bytes", m_cbVerInfo).c_str());
664 }
665
666 if (GetFileVersionInfo(pwszDrv, NULL, m_cbVerInfo, m_pVerInfo))
667 {
668 UINT cbSize = 0;
669 LPBYTE lpBuffer = NULL;
670 if (VerQueryValue(m_pVerInfo, L"\\", (VOID FAR* FAR*)&lpBuffer, &cbSize))
671 {
672 if (cbSize)
673 {
674 VS_FIXEDFILEINFO *pFileInfo = (VS_FIXEDFILEINFO *)lpBuffer;
675 if (pFileInfo->dwSignature == 0xfeef04bd)
676 {
677 printf("%ls (Version: %d.%d.%d.%d)\n", pwszDrv,
678 (pFileInfo->dwFileVersionMS >> 16) & 0xffff,
679 (pFileInfo->dwFileVersionMS >> 0) & 0xffff,
680 (pFileInfo->dwFileVersionLS >> 16) & 0xffff,
681 (pFileInfo->dwFileVersionLS >> 0) & 0xffff);
682 }
683 else
684 printf("%ls - invalid signature\n", pwszDrv);
685 }
686 else
687 printf("%ls - version info size is 0\n", pwszDrv);
688 }
689 else
690 printf("%ls - failed to query version info size\n", pwszDrv);
691 }
692 else
693 printf("%ls - failed to get version info with 0x%x\n", pwszDrv, GetLastError());
694 }
695 else
696 printf("%ls - GetDeviceDriverFileName failed with 0x%x\n", wszDriver, GetLastError());
697 }
698}
699
700
701class BugReportFilterRegistryWin : public BugReportFilter
702{
703public:
704 BugReportFilterRegistryWin() {};
705 virtual ~BugReportFilterRegistryWin() {};
706 virtual void *apply(void *pvSource, size_t *pcbInOut);
707};
708
709void *BugReportFilterRegistryWin::apply(void *pvSource, size_t *pcbInOut)
710{
711 /*
712 * The following implementation is not optimal by any means. It serves to
713 * illustrate and test the case when filter's output is longer than its
714 * input.
715 */
716 RT_NOREF(pcbInOut);
717 /* Registry export files are encoded in UTF-16 (little endian on Intel x86). */
718 void *pvDest = pvSource;
719 uint16_t *pwsSource = (uint16_t *)pvSource;
720 if (*pwsSource++ == 0xFEFF && *pcbInOut > 48)
721 {
722 if (!memcmp(pwsSource, L"Windows Registry Editor", 46))
723 {
724 *pcbInOut += 2;
725 pvDest = allocateBuffer(*pcbInOut);
726 uint16_t *pwsDest = (uint16_t *)pvDest;
727 *pwsDest++ = 0xFEFF;
728 *pwsDest++ = '#';
729 /* Leave space for 0xFEFF and '#' */
730 memcpy(pwsDest, pwsSource, *pcbInOut - 4);
731 }
732 }
733 return pvDest;
734}
735
736
737void createBugReportOsSpecific(BugReport* report, const char *pszHome)
738{
739 RT_NOREF(pszHome);
740 WCHAR szWinDir[MAX_PATH];
741
742 int cbNeeded = GetWindowsDirectory(szWinDir, RT_ELEMENTS(szWinDir));
743 if (cbNeeded == 0)
744 throw RTCError(RTCStringFmt("Failed to get Windows directory (err=%d)\n", GetLastError()));
745 if (cbNeeded > MAX_PATH)
746 throw RTCError(RTCStringFmt("Failed to get Windows directory (needed %d-byte buffer)\n", cbNeeded));
747 RTCStringFmt WinInfDir("%ls/inf", szWinDir);
748 report->addItem(new BugReportFile(PathJoin(WinInfDir.c_str(), "setupapi.app.log"), "setupapi.app.log"));
749 report->addItem(new BugReportFile(PathJoin(WinInfDir.c_str(), "setupapi.dev.log"), "setupapi.dev.log"));
750 report->addItem(new BugReportNetworkAdaptersWin);
751 RTCStringFmt WinSysDir("%ls/System32", szWinDir);
752 report->addItem(new BugReportCommand("IpConfig", PathJoin(WinSysDir.c_str(), "ipconfig.exe"), "/all", NULL));
753 report->addItem(new BugReportCommand("RouteTable", PathJoin(WinSysDir.c_str(), "netstat.exe"), "-rn", NULL));
754 report->addItem(new BugReportCommand("SystemEvents", PathJoin(WinSysDir.c_str(), "wevtutil.exe"),
755 "qe", "System",
756 "/q:*[System[Provider[@Name='VBoxUSBMon' or @Name='VBoxNetLwf']]]", NULL));
757 report->addItem(new BugReportCommand("UpdateHistory", PathJoin(WinSysDir.c_str(), "wbem/wmic.exe"),
758 "qfe", "list", "brief", NULL));
759 report->addItem(new BugReportCommand("DriverServices", PathJoin(WinSysDir.c_str(), "sc.exe"),
760 "query", "type=", "driver", "state=", "all", NULL));
761 report->addItem(new BugReportCommand("DriverStore", PathJoin(WinSysDir.c_str(), "pnputil.exe"), "-e", NULL));
762 report->addItem(new BugReportCommandTemp("RegDevKeys", PathJoin(WinSysDir.c_str(), "reg.exe"), "export",
763 "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\Root\\NET", NULL),
764 new BugReportFilterRegistryWin());
765 report->addItem(new BugReportCommandTemp("RegDrvKeys", PathJoin(WinSysDir.c_str(), "reg.exe"), "export",
766 "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", NULL),
767 new BugReportFilterRegistryWin());
768 report->addItem(new BugReportCommandTemp("RegNetwork", PathJoin(WinSysDir.c_str(), "reg.exe"), "export",
769 "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Network", NULL),
770 new BugReportFilterRegistryWin());
771 report->addItem(new BugReportCommandTemp("RegNetFltNobj", PathJoin(WinSysDir.c_str(), "reg.exe"), "export",
772 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}", NULL),
773 new BugReportFilterRegistryWin());
774 report->addItem(new BugReportUsbTreeWin);
775 report->addItem(new BugReportDriversWin);
776}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use