VirtualBox

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

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette