VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/win/cfg/VBoxDrvCfg.cpp@ 98186

Last change on this file since 98186 was 98103, checked in by vboxsync, 21 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: 39.7 KB
Line 
1/* $Id: VBoxDrvCfg.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxDrvCfg.cpp - Windows Driver Manipulation API implementation.
4 *
5 * @note This is EXTREMELY BADLY documented code. Please help improve by
6 * adding comments whenever you've got a chance!
7 */
8
9/*
10 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.virtualbox.org.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * The contents of this file may alternatively be used under the terms
29 * of the Common Development and Distribution License Version 1.0
30 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
31 * in the VirtualBox distribution, in which case the provisions of the
32 * CDDL are applicable instead of those of the GPL.
33 *
34 * You may elect to license modified versions of this file under the
35 * terms and conditions of either the GPL or the CDDL or both.
36 *
37 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
38 */
39
40
41/*********************************************************************************************************************************
42* Header Files *
43*********************************************************************************************************************************/
44#include <VBox/VBoxDrvCfg-win.h>
45
46#include <iprt/win/setupapi.h>
47#include <iprt/win/shlobj.h>
48#include <Newdev.h>
49
50#include <iprt/alloca.h>
51#include <iprt/mem.h>
52#include <iprt/path.h>
53#include <iprt/string.h>
54#include <iprt/utf16.h>
55
56
57/*********************************************************************************************************************************
58* Global Variables *
59*********************************************************************************************************************************/
60static PFNVBOXDRVCFGLOG g_pfnVBoxDrvCfgLog;
61static void *g_pvVBoxDrvCfgLog;
62
63static PFNVBOXDRVCFGPANIC g_pfnVBoxDrvCfgPanic;
64static void *g_pvVBoxDrvCfgPanic;
65
66
67VBOXDRVCFG_DECL(void) VBoxDrvCfgLoggerSet(PFNVBOXDRVCFGLOG pfnLog, void *pvLog)
68{
69 g_pfnVBoxDrvCfgLog = pfnLog;
70 g_pvVBoxDrvCfgLog = pvLog;
71}
72
73VBOXDRVCFG_DECL(void) VBoxDrvCfgPanicSet(PFNVBOXDRVCFGPANIC pfnPanic, void *pvPanic)
74{
75 g_pfnVBoxDrvCfgPanic = pfnPanic;
76 g_pvVBoxDrvCfgPanic = pvPanic;
77}
78
79static void vboxDrvCfgLogRel(const char *pszFormat, ...)
80{
81 PFNVBOXDRVCFGLOG pfnLog = g_pfnVBoxDrvCfgLog;
82 void *pvLog = g_pvVBoxDrvCfgLog;
83 if (pfnLog)
84 {
85 char szBuffer[4096];
86 va_list va;
87 va_start(va, pszFormat);
88 RTStrPrintfV(szBuffer, RT_ELEMENTS(szBuffer), pszFormat, va);
89 va_end(va);
90 pfnLog(VBOXDRVCFG_LOG_SEVERITY_REL, szBuffer, pvLog);
91 }
92}
93
94static void vboxDrvCfgLogRegular(const char *pszFormat, ...)
95{
96 PFNVBOXDRVCFGLOG pfnLog = g_pfnVBoxDrvCfgLog;
97 void *pvLog = g_pvVBoxDrvCfgLog;
98 if (pfnLog)
99 {
100 char szBuffer[4096];
101 va_list va;
102 va_start(va, pszFormat);
103 RTStrPrintfV(szBuffer, RT_ELEMENTS(szBuffer), pszFormat, va);
104 va_end(va);
105 pfnLog(VBOXDRVCFG_LOG_SEVERITY_REGULAR, szBuffer, pvLog);
106 }
107}
108
109static void vboxDrvCfgLogFlow(const char *pszFormat, ...)
110{
111 PFNVBOXDRVCFGLOG pfnLog = g_pfnVBoxDrvCfgLog;
112 void *pvLog = g_pvVBoxDrvCfgLog;
113 if (pfnLog)
114 {
115 char szBuffer[4096];
116 va_list va;
117 va_start(va, pszFormat);
118 RTStrPrintfV(szBuffer, RT_ELEMENTS(szBuffer), pszFormat, va);
119 va_end(va);
120 pfnLog(VBOXDRVCFG_LOG_SEVERITY_FLOW, szBuffer, pvLog);
121 }
122}
123
124static void vboxDrvCfgPanic(void)
125{
126 PFNVBOXDRVCFGPANIC pfnPanic = g_pfnVBoxDrvCfgPanic;
127 void *pvPanic = g_pvVBoxDrvCfgPanic;
128 if (pfnPanic)
129 pfnPanic(pvPanic);
130}
131
132/* we do not use IPRT Logging because the lib is used in host installer and needs to
133 * post its msgs to MSI logger */
134#define NonStandardLogCrap(_m) do { vboxDrvCfgLogRegular _m ; } while (0)
135#define NonStandardLogFlowCrap(_m) do { vboxDrvCfgLogFlow _m ; } while (0)
136#define NonStandardLogRelCrap(_m) do { vboxDrvCfgLogRel _m ; } while (0)
137#define NonStandardAssertFailed() vboxDrvCfgPanic()
138#define NonStandardAssert(_m) do { \
139 if (RT_UNLIKELY(!(_m))) { vboxDrvCfgPanic(); } \
140 } while (0)
141
142
143/**
144 * This is a simple string vector class.
145 *
146 * @note Is is _NOT_ a list as the name could lead you to believe, but a vector.
147 */
148class VBoxDrvCfgStringList
149{
150public:
151 VBoxDrvCfgStringList(size_t a_cElements);
152 ~VBoxDrvCfgStringList();
153
154 HRESULT add(LPWSTR pStr);
155
156 size_t size() { return m_cUsed; }
157
158 LPWSTR get(size_t i) { return i < m_cUsed ? m_paStrings[i] : NULL; }
159private:
160 HRESULT grow(size_t a_cNew);
161
162 /** Array of strings. */
163 LPWSTR *m_paStrings;
164 size_t m_cAllocated;
165 size_t m_cUsed;
166};
167
168VBoxDrvCfgStringList::VBoxDrvCfgStringList(size_t a_cElements)
169{
170 m_paStrings = (LPWSTR *)RTMemAllocZ(sizeof(m_paStrings[0]) * a_cElements);
171 m_cAllocated = a_cElements;
172 m_cUsed = 0;
173}
174
175VBoxDrvCfgStringList::~VBoxDrvCfgStringList()
176{
177 if (!m_cAllocated)
178 return;
179
180 for (size_t i = 0; i < m_cUsed; ++i)
181 RTMemFree(m_paStrings[i]);
182 RTMemFree(m_paStrings);
183 m_paStrings = NULL;
184 m_cAllocated = 0;
185 m_cUsed = 0;
186}
187
188HRESULT VBoxDrvCfgStringList::add(LPWSTR pStr)
189{
190 if (m_cUsed == m_cAllocated)
191 {
192 int hrc = grow(m_cAllocated + 16);
193 if (SUCCEEDED(hrc))
194 return hrc;
195 }
196 LPWSTR str = (LPWSTR)RTMemDup(pStr, (RTUtf16Len(pStr) + 1) * sizeof(m_paStrings[0][0]));
197 if (!str)
198 return E_OUTOFMEMORY;
199 m_paStrings[m_cUsed] = str;
200 ++m_cUsed;
201 return S_OK;
202}
203
204HRESULT VBoxDrvCfgStringList::grow(size_t a_cNew)
205{
206 NonStandardAssert(a_cNew >= m_cUsed);
207 if (a_cNew < m_cUsed)
208 return E_FAIL;
209 void *pvNew = RTMemReallocZ(m_paStrings, m_cUsed * sizeof(m_paStrings[0]), a_cNew * sizeof(m_paStrings[0]));
210 if (!pvNew)
211 return E_OUTOFMEMORY;
212 m_paStrings = (LPWSTR *)pvNew;
213 m_cAllocated = a_cNew;
214 return S_OK;
215}
216
217/*
218 * inf file manipulation API
219 */
220typedef bool (*PFNVBOXNETCFG_ENUMERATION_CALLBACK_T)(LPCWSTR lpszFileName, PVOID pContext);
221
222typedef struct INF_INFO_T
223{
224 LPCWSTR pwszClassName;
225 LPCWSTR pwszPnPId;
226} INF_INFO_T, *PINF_INFO_T;
227
228typedef struct INFENUM_CONTEXT_T
229{
230 INF_INFO_T InfInfo;
231 DWORD fFlags;
232 HRESULT hrc;
233} INFENUM_CONTEXT_T, *PINFENUM_CONTEXT_T;
234
235static HRESULT vboxDrvCfgInfQueryContext(HINF hInf, LPCWSTR pwszSection, LPCWSTR pwszKey, PINFCONTEXT pCtx)
236{
237 if (!SetupFindFirstLineW(hInf, pwszSection, pwszKey, pCtx))
238 {
239 DWORD dwErr = GetLastError();
240 NonStandardLogRelCrap((__FUNCTION__ ": SetupFindFirstLine failed WinEr (%Rwc) for Section(%ls), Key(%ls)\n",
241 dwErr, pwszSection, pwszKey));
242 return HRESULT_FROM_WIN32(dwErr);
243 }
244 return S_OK;
245}
246
247static HRESULT vboxDrvCfgInfQueryKeyValue(PINFCONTEXT pCtx, DWORD iValue, LPWSTR *ppwszValue, PDWORD pcwcValue)
248{
249 *ppwszValue = NULL;
250 if (pcwcValue)
251 *pcwcValue = 0;
252
253 DWORD cwcValue;
254 if (!SetupGetStringFieldW(pCtx, iValue, NULL, 0, &cwcValue))
255 {
256 DWORD dwErr = GetLastError();
257// NonStandardAssert(dwErr == ERROR_INSUFFICIENT_BUFFER);
258 if (dwErr != ERROR_INSUFFICIENT_BUFFER)
259 {
260 NonStandardLogFlowCrap((__FUNCTION__ ": SetupGetStringField failed WinEr (%Rwc) for iValue(%d)\n", dwErr, iValue));
261 return HRESULT_FROM_WIN32(dwErr);
262 }
263 }
264
265 LPWSTR pwszValue = (LPWSTR)RTMemAlloc(cwcValue * sizeof(pwszValue[0]));
266 NonStandardAssert(pwszValue);
267 if (!pwszValue)
268 {
269 NonStandardLogRelCrap((__FUNCTION__ ": SetCoTaskMemAlloc failed to alloc mem of size (%d), for iValue(%d)\n",
270 cwcValue * sizeof(pwszValue[0]), iValue));
271 return E_FAIL;
272 }
273
274 if (!SetupGetStringFieldW(pCtx, iValue, pwszValue, cwcValue, &cwcValue))
275 {
276 DWORD dwErr = GetLastError();
277 NonStandardLogRelCrap((__FUNCTION__ ": SetupGetStringField failed WinEr (%Rwc) for iValue(%d)\n", dwErr, iValue));
278 NonStandardAssertFailed();
279 RTMemFree(pwszValue);
280 return HRESULT_FROM_WIN32(dwErr);
281 }
282
283 *ppwszValue = pwszValue;
284 if (pcwcValue)
285 *pcwcValue = cwcValue;
286 return S_OK;
287}
288
289#if defined(RT_ARCH_AMD64)
290# define VBOXDRVCFG_ARCHSTR "amd64"
291#else
292# define VBOXDRVCFG_ARCHSTR "x86"
293#endif
294
295static HRESULT vboxDrvCfgInfQueryModelsSectionName(HINF hInf, LPWSTR *ppwszValue, PDWORD pcwcValue)
296{
297 *ppwszValue = NULL;
298 if (pcwcValue)
299 *pcwcValue = 0;
300
301 INFCONTEXT InfCtx;
302 HRESULT hrc = vboxDrvCfgInfQueryContext(hInf, L"Manufacturer", NULL, &InfCtx);
303 if (hrc != S_OK)
304 {
305 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgInfQueryContext for Manufacturer failed, hrc=0x%x\n", hrc));
306 return hrc;
307 }
308
309 LPWSTR pwszModels;
310 DWORD cwcModels;
311 hrc = vboxDrvCfgInfQueryKeyValue(&InfCtx, 1, &pwszModels, &cwcModels);
312 if (hrc != S_OK)
313 {
314 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue 1 for Manufacturer failed, hrc=0x%x\n", hrc));
315 return hrc;
316 }
317
318 LPWSTR pwszPlatform = NULL;
319 DWORD cwcPlatform = 0;
320 bool fArch = false;
321 bool fNt = false;
322
323 LPWSTR pwszPlatformCur;
324 DWORD cwcPlatformCur;
325 for (DWORD i = 2; (hrc = vboxDrvCfgInfQueryKeyValue(&InfCtx, i, &pwszPlatformCur, &cwcPlatformCur)) == S_OK; ++i)
326 {
327 if (RTUtf16ICmpAscii(pwszPlatformCur, "NT" VBOXDRVCFG_ARCHSTR) == 0)
328 fArch = true;
329 else
330 {
331 if (fNt || RTUtf16ICmpAscii(pwszPlatformCur, "NT") != 0)
332 {
333 RTMemFree(pwszPlatformCur);
334 pwszPlatformCur = NULL;
335 continue;
336 }
337 fNt = true;
338 }
339
340 cwcPlatform = cwcPlatformCur;
341 if (pwszPlatform)
342 RTMemFree(pwszPlatform);
343 pwszPlatform = pwszPlatformCur;
344 pwszPlatformCur = NULL;
345 }
346
347 hrc = S_OK;
348
349 LPWSTR pwszResult = NULL;
350 DWORD cwcResult = 0;
351 if (pwszPlatform)
352 {
353 pwszResult = (LPWSTR)RTMemAlloc((cwcModels + cwcPlatform) * sizeof(pwszResult[0]));
354 if (pwszResult)
355 {
356 memcpy(pwszResult, pwszModels, (cwcModels - 1) * sizeof(pwszResult[0]));
357 pwszResult[cwcModels - 1] = L'.';
358 memcpy(&pwszResult[cwcModels], pwszPlatform, cwcPlatform * sizeof(pwszResult[0]));
359 cwcResult = cwcModels + cwcPlatform;
360 }
361 else
362 hrc = E_OUTOFMEMORY;
363 }
364 else
365 {
366 pwszResult = pwszModels;
367 cwcResult = cwcModels;
368 pwszModels = NULL;
369 }
370
371 if (pwszModels)
372 RTMemFree(pwszModels);
373 if (pwszPlatform)
374 RTMemFree(pwszPlatform);
375
376 if (hrc == S_OK)
377 {
378 *ppwszValue = pwszResult;
379 if (pcwcValue)
380 *pcwcValue = cwcResult;
381 }
382
383 return hrc;
384}
385
386static HRESULT vboxDrvCfgInfQueryFirstPnPId(HINF hInf, LPWSTR *ppwszPnPId)
387{
388 *ppwszPnPId = NULL;
389
390 LPWSTR pwszModels;
391 HRESULT hrc = vboxDrvCfgInfQueryModelsSectionName(hInf, &pwszModels, NULL);
392 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryModelsSectionName returned pwszModels = (%ls)", pwszModels));
393 if (hrc != S_OK)
394 {
395 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for Manufacturer failed, hrc=0x%x\n", hrc));
396 return hrc;
397 }
398
399 LPWSTR pwszPnPId = NULL;
400 INFCONTEXT InfCtx;
401 hrc = vboxDrvCfgInfQueryContext(hInf, pwszModels, NULL, &InfCtx);
402 if (hrc == S_OK)
403 {
404 hrc = vboxDrvCfgInfQueryKeyValue(&InfCtx, 2, &pwszPnPId, NULL);
405 if (hrc == S_OK)
406 {
407 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for models (%ls) returned pwszPnPId (%ls)\n", pwszModels, pwszPnPId));
408 *ppwszPnPId = pwszPnPId;
409 }
410 else
411 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for models (%ls) failed, hrc=0x%x\n", pwszModels, hrc));
412 }
413 else
414 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryContext for models (%ls) failed, hrc=0x%x\n", pwszModels, hrc));
415
416 RTMemFree(pwszModels);
417 return hrc;
418}
419
420static bool vboxDrvCfgInfEnumerationCallback(LPCWSTR pwszFileName, PVOID pCtxt)
421{
422 PINFENUM_CONTEXT_T pContext = (PINFENUM_CONTEXT_T)pCtxt;
423 NonStandardLogRelCrap((__FUNCTION__": pwszFileName (%ls)\n", pwszFileName));
424 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.pwszClassName = (%ls)\n", pContext->InfInfo.pwszClassName));
425 HINF hInf = SetupOpenInfFileW(pwszFileName, pContext->InfInfo.pwszClassName, INF_STYLE_WIN4, NULL /*__in PUINT ErrorLine */);
426 if (hInf == INVALID_HANDLE_VALUE)
427 {
428 DWORD const dwErr = GetLastError();
429// NonStandardAssert(dwErr == ERROR_CLASS_MISMATCH);
430 if (dwErr != ERROR_CLASS_MISMATCH)
431 NonStandardLogCrap((__FUNCTION__ ": SetupOpenInfFileW err dwErr=%u\n", dwErr));
432 else
433 NonStandardLogCrap((__FUNCTION__ ": dwErr == ERROR_CLASS_MISMATCH\n"));
434 return true;
435 }
436
437 LPWSTR pwszPnPId;
438 HRESULT hrc = vboxDrvCfgInfQueryFirstPnPId(hInf, &pwszPnPId);
439 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId returned pwszPnPId = (%ls)\n", pwszPnPId));
440 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.pwszPnPId = (%ls)\n", pContext->InfInfo.pwszPnPId));
441 if (hrc == S_OK)
442 {
443 if (!RTUtf16ICmp(pContext->InfInfo.pwszPnPId, pwszPnPId))
444 {
445 /** @todo bird/2020-09-01: See the following during uninstallation with
446 * windbg attached (see DllMain trick):
447 *
448 * ModLoad: 00007ffa`73c20000 00007ffa`73c4f000 C:\WINDOWS\SYSTEM32\drvsetup.dll
449 * (1b238.1b254): Access violation - code c0000005 (first chance)
450 * First chance exceptions are reported before any exception handling.
451 * This exception may be expected and handled.
452 * KERNELBASE!WaitForMultipleObjectsEx+0x9e:
453 * 00007ffa`8247cb6e 458b74fd00 mov r14d,dword ptr [r13+rdi*8] ds:00000000`00000010=????????
454 * 0:006> k
455 * # Child-SP RetAddr Call Site
456 * 00 00000099`6e4fe7a0 00007ffa`73c2df46 KERNELBASE!WaitForMultipleObjectsEx+0x9e
457 * 01 00000099`6e4fea90 00007ffa`73c32ec2 drvsetup!pSetupStringTableEnum+0x3e
458 * 02 00000099`6e4feae0 00007ffa`73c2ae9d drvsetup!DrvUtilsUpdateInfoEnumDriverInfs+0x8e
459 * 03 00000099`6e4feb20 00007ffa`73c2b1cc drvsetup!DrvSetupUninstallDriverInternal+0x211
460 * 04 00000099`6e4febe0 00007ffa`83eb09d7 drvsetup!pDrvSetupUninstallDriver+0xfc
461 * 05 00000099`6e4fec30 00007ffa`83eb06a0 SETUPAPI!pSetupUninstallOEMInf+0x26b
462 * 06 00000099`6e4fef00 00007ffa`57a39fb7 SETUPAPI!SetupUninstallOEMInfW+0x170
463 * 07 00000099`6e4ff190 00007ffa`57a3ae0c MSID039!vboxDrvCfgInfEnumerationCallback+0xf7 [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 445]
464 * 08 00000099`6e4ff1c0 00007ffa`57a321e6 MSID039!VBoxDrvCfgInfUninstallAllSetupDi+0xfc [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 653]
465 * 09 (Inline Function) --------`-------- MSID039!_removeHostOnlyInterfaces+0x6c [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1523]
466 * 0a 00000099`6e4ff240 00007ffa`610f59d3 MSID039!RemoveHostOnlyInterfaces+0x76 [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1545]
467 * 0b 00000099`6e4ff270 00007ffa`610d80ac msi!CallCustomDllEntrypoint+0x2b
468 * 0c 00000099`6e4ff2e0 00007ffa`84567034 msi!CMsiCustomAction::CustomActionThread+0x34c
469 * 0d 00000099`6e4ff8d0 00007ffa`849a2651 KERNEL32!BaseThreadInitThunk+0x14
470 * 0e 00000099`6e4ff900 00000000`00000000 ntdll!RtlUserThreadStart+0x21
471 * 0:006> r
472 * rax=000000996e114000 rbx=0000000000000002 rcx=0000000000000002
473 * rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
474 * rip=00007ffa8247cb6e rsp=000000996e4fe7a0 rbp=0000000000000004
475 * r8=0000000000000000 r9=00000000ffffffff r10=0000000000000000
476 * r11=0000000000000246 r12=00000000ffffffff r13=0000000000000010
477 * r14=00007ffa73c32e00 r15=0000000000000001
478 * iopl=0 nv up ei ng nz ac pe cy
479 * cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010293
480 * KERNELBASE!WaitForMultipleObjectsEx+0x9e:
481 * 00007ffa`8247cb6e 458b74fd00 mov r14d,dword ptr [r13+rdi*8] ds:00000000`00000010=????????
482 *
483 * Happens with the filter driver too:
484 *
485 * (1b238.1b7e0): Access violation - code c0000005 (first chance)
486 * First chance exceptions are reported before any exception handling.
487 * This exception may be expected and handled.
488 * KERNELBASE!WaitForMultipleObjectsEx+0x9e:
489 * 00007ffa`8247cb6e 458b74fd00 mov r14d,dword ptr [r13+rdi*8] ds:00000000`00000010=????????
490 * 0:006> k
491 * # Child-SP RetAddr Call Site
492 * 00 00000099`6e4fe8c0 00007ffa`6558df46 KERNELBASE!WaitForMultipleObjectsEx+0x9e
493 * 01 00000099`6e4febb0 00007ffa`65592ec2 drvsetup!pSetupStringTableEnum+0x3e
494 * 02 00000099`6e4fec00 00007ffa`6558ae9d drvsetup!DrvUtilsUpdateInfoEnumDriverInfs+0x8e
495 * 03 00000099`6e4fec40 00007ffa`6558b1cc drvsetup!DrvSetupUninstallDriverInternal+0x211
496 * 04 00000099`6e4fed00 00007ffa`83eb09d7 drvsetup!pDrvSetupUninstallDriver+0xfc
497 * 05 00000099`6e4fed50 00007ffa`83eb06a0 SETUPAPI!pSetupUninstallOEMInf+0x26b
498 * 06 00000099`6e4ff020 00007ffa`57a39fb7 SETUPAPI!SetupUninstallOEMInfW+0x170
499 * 07 00000099`6e4ff2b0 00007ffa`57a3abaf MSI398C!vboxDrvCfgInfEnumerationCallback+0xf7 [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 445]
500 * 08 (Inline Function) --------`-------- MSI398C!vboxDrvCfgEnumFiles+0x4f [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 670]
501 * 09 00000099`6e4ff2e0 00007ffa`57a3792e MSI398C!VBoxDrvCfgInfUninstallAllF+0xdf [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 723]
502 * 0a 00000099`6e4ff7b0 00007ffa`57a33411 MSI398C!vboxNetCfgWinNetLwfUninstall+0x9e [E:\vbox\svn\trunk\src\VBox\HostDrivers\VBoxNetFlt\win\cfg\VBoxNetCfg.cpp @ 2249]
503 * 0b 00000099`6e4ff7e0 00007ffa`57a3263d MSI398C!_uninstallNetLwf+0x71 [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1206]
504 * 0c 00000099`6e4ff810 00007ffa`610f59d3 MSI398C!UninstallNetFlt+0xd [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1124]
505 * 0d 00000099`6e4ff840 00007ffa`610d80ac msi!CallCustomDllEntrypoint+0x2b
506 * 0e 00000099`6e4ff8b0 00007ffa`84567034 msi!CMsiCustomAction::CustomActionThread+0x34c
507 * 0f 00000099`6e4ffea0 00007ffa`849a2651 KERNEL32!BaseThreadInitThunk+0x14
508 * 10 00000099`6e4ffed0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
509 * 0:006> r
510 * rax=000000996e114000 rbx=0000000000000002 rcx=0000000000000002
511 * rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
512 * rip=00007ffa8247cb6e rsp=000000996e4fe8c0 rbp=0000000000000004
513 * r8=0000000000000000 r9=00000000ffffffff r10=0000000000000000
514 * r11=0000000000000246 r12=00000000ffffffff r13=0000000000000010
515 * r14=00007ffa65592e00 r15=0000000000000000
516 * iopl=0 nv up ei ng nz ac pe cy
517 * cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010293
518 * KERNELBASE!WaitForMultipleObjectsEx+0x9e:
519 * 00007ffa`8247cb6e 458b74fd00 mov r14d,dword ptr [r13+rdi*8] ds:00000000`00000010=????????
520 *
521 * BUGBUG
522 */
523#if 0
524 if (!SetupUninstallOEMInfW(pwszFileName, pContext->fFlags, /* could be SUOI_FORCEDELETE */ NULL /* Reserved */))
525#else /* Just in case the API doesn't catch it itself (seems it does on w10/19044). */
526 BOOL fRc = TRUE;
527 __try
528 {
529 fRc = SetupUninstallOEMInfW(pwszFileName, pContext->fFlags, /* could be SUOI_FORCEDELETE */ NULL /* Reserved */);
530 }
531 __except(hrc = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
532 {
533 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf raised an exception: %#x\n", hrc));
534 hrc = E_ABORT;
535 }
536 if (!fRc)
537#endif
538 {
539 DWORD const dwErr = GetLastError();
540 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf failed for file (%ls), dwErr=%u\n", pwszFileName, dwErr));
541 NonStandardAssertFailed();
542 hrc = HRESULT_FROM_WIN32( dwErr );
543 }
544 }
545
546 RTMemFree(pwszPnPId);
547 }
548 else
549 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId failed, hrc=0x%x\n", hrc));
550
551 SetupCloseInfFile(hInf);
552 return true;
553}
554
555
556#define VBOXDRVCFG_S_INFEXISTS (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS))
557
558static HRESULT vboxDrvCfgInfCopyEx(IN LPCWSTR pwszInfPath, IN DWORD fCopyStyle, OUT LPWSTR pwszDstName, IN DWORD cwcDstName,
559 OUT PDWORD pcwcDstNameRet, OUT LPWSTR *pwszDstNameComponent)
560{
561 /* Extract the director from pwszInfPath */
562 size_t cchPath = RTUtf16Len(pwszInfPath);
563 while (cchPath > 0 && !RTPATH_IS_SEP(pwszInfPath[cchPath - 1]))
564 cchPath--;
565
566 WCHAR *pwszMediaLocation = (WCHAR *)alloca(((cchPath) + 1) * sizeof(pwszMediaLocation[0]));
567 memcpy(pwszMediaLocation, pwszInfPath, cchPath * sizeof(pwszMediaLocation[0]));
568 pwszMediaLocation[cchPath] = '\0';
569
570
571 if (!SetupCopyOEMInfW(pwszInfPath, pwszMediaLocation, SPOST_PATH, fCopyStyle,
572 pwszDstName, cwcDstName, pcwcDstNameRet, pwszDstNameComponent))
573 {
574 DWORD const dwErr = GetLastError();
575 HRESULT hrc = HRESULT_FROM_WIN32(dwErr);
576 if (fCopyStyle != SP_COPY_REPLACEONLY || hrc != VBOXDRVCFG_S_INFEXISTS)
577 NonStandardLogRelCrap((__FUNCTION__ ": SetupCopyOEMInf fail dwErr=%u\n", dwErr));
578 return hrc;
579 }
580
581 return S_OK;
582}
583
584VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfInstall(IN LPCWSTR pwszInfPath)
585{
586 return vboxDrvCfgInfCopyEx(pwszInfPath, 0 /*fCopyStyle*/, NULL /*pwszDstName*/, 0 /*cwcDstName*/,
587 NULL /*pcwcDstNameRet*/, NULL /*pwszDstNameComponent*/);
588}
589
590VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstall(IN LPCWSTR pwszInfPath, DWORD fFlags)
591{
592 WCHAR wszDstInfName[MAX_PATH];
593 DWORD cwcDword = RT_ELEMENTS(wszDstInfName);
594 HRESULT hrc = vboxDrvCfgInfCopyEx(pwszInfPath, SP_COPY_REPLACEONLY, wszDstInfName, cwcDword, &cwcDword, NULL);
595 if (hrc == VBOXDRVCFG_S_INFEXISTS)
596 {
597 if (!SetupUninstallOEMInfW(wszDstInfName, fFlags, NULL /*Reserved*/))
598 {
599 DWORD dwErr = GetLastError();
600 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf failed for file (%ls), oem(%ls), dwErr=%u\n",
601 pwszInfPath, wszDstInfName, dwErr));
602 NonStandardAssertFailed();
603 return HRESULT_FROM_WIN32(dwErr);
604 }
605 }
606 return S_OK;
607}
608
609
610static HRESULT vboxDrvCfgCollectInfsSetupDi(const GUID *pGuid, LPCWSTR pwszPnPId, VBoxDrvCfgStringList &a_rList)
611{
612 DWORD dwErrRet = ERROR_SUCCESS;
613 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(pGuid, /*ClassGuid*/ NULL /*hwndParent*/);
614 if (hDevInfo != INVALID_HANDLE_VALUE)
615 {
616 /** @todo bird/2020-09-01: seeing this during uninstall when windbg is
617 * attached to msiexec.exe (see trick in DllMain):
618 *
619 * (1b238.1b254): Access violation - code c0000005 (first chance)
620 * First chance exceptions are reported before any exception handling.
621 * This exception may be expected and handled.
622 * SETUPAPI!SpSignVerifyInfFile+0x246:
623 * 00007ffa`83e3ee3e 663907 cmp word ptr [rdi],ax ds:00000000`00000000=????
624 * 0:006> k
625 * # Child-SP RetAddr Call Site
626 * 00 00000099`6e4f8340 00007ffa`83e1e765 SETUPAPI!SpSignVerifyInfFile+0x246
627 * 01 00000099`6e4f8420 00007ffa`83e9ebfd SETUPAPI!DrvSearchCallback+0x1155
628 * 02 00000099`6e4f9380 00007ffa`83e9eed3 SETUPAPI!InfCacheSearchDirectory+0x469
629 * 03 00000099`6e4f98b0 00007ffa`83e9f454 SETUPAPI!InfCacheSearchDirectoryRecursive+0xcf
630 * 04 00000099`6e4f9fe0 00007ffa`83e9da10 SETUPAPI!InfCacheSearchPath+0x1a0
631 * 05 00000099`6e4fa2b0 00007ffa`83e262a2 SETUPAPI!EnumDrvInfsInDirPathList+0x560
632 * 06 00000099`6e4fa3f0 00007ffa`57a39a21 SETUPAPI!SetupDiBuildDriverInfoList+0x1242
633 * 07 00000099`6e4fab10 00007ffa`57a3ad6e MSID039!vboxDrvCfgCollectInfsSetupDi+0x71 [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 526]
634 * 08 00000099`6e4ff1c0 00007ffa`57a321e6 MSID039!VBoxDrvCfgInfUninstallAllSetupDi+0x5e [E:\vbox\svn\trunk\src\VBox\HostDrivers\win\cfg\VBoxDrvCfg.cpp @ 633]
635 * 09 (Inline Function) --------`-------- MSID039!_removeHostOnlyInterfaces+0x6c [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1523]
636 * 0a 00000099`6e4ff240 00007ffa`610f59d3 MSID039!RemoveHostOnlyInterfaces+0x76 [E:\vbox\svn\trunk\src\VBox\Installer\win\InstallHelper\VBoxInstallHelper.cpp @ 1545]
637 * 0b 00000099`6e4ff270 00007ffa`610d80ac msi!CallCustomDllEntrypoint+0x2b
638 * 0c 00000099`6e4ff2e0 00007ffa`84567034 msi!CMsiCustomAction::CustomActionThread+0x34c
639 * 0d 00000099`6e4ff8d0 00007ffa`849a2651 KERNEL32!BaseThreadInitThunk+0x14
640 * 0e 00000099`6e4ff900 00000000`00000000 ntdll!RtlUserThreadStart+0x21
641 * 0:006> r
642 * rax=0000000000000000 rbx=0000000000000490 rcx=aa222a2675da0000
643 * rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
644 * rip=00007ffa83e3ee3e rsp=000000996e4f8340 rbp=000000996e4f9480
645 * r8=0000000000050004 r9=00007ffa83ef5418 r10=0000000000008000
646 * r11=000000996e4f76f0 r12=000000996e4f84c8 r13=0000000000000000
647 * r14=000000996e4f88d0 r15=0000000000000000
648 * iopl=0 nv up ei pl nz ac pe cy
649 * cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010213
650 * SETUPAPI!SpSignVerifyInfFile+0x246:
651 * 00007ffa`83e3ee3e 663907 cmp word ptr [rdi],ax ds:00000000`00000000=????
652 */
653#if 0
654 if (SetupDiBuildDriverInfoList(hDevInfo, NULL /*DeviceInfoData*/, SPDIT_CLASSDRIVER))
655#else /* Just in case the API doesn't catch it itself (seems it does on w10/19044). */
656 BOOL fRc = FALSE;
657 DWORD uXcpt = 0;
658 __try
659 {
660 fRc = SetupDiBuildDriverInfoList(hDevInfo, NULL /*DeviceInfoData*/, SPDIT_CLASSDRIVER);
661 }
662 __except(uXcpt = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
663 {
664 NonStandardLogRelCrap((__FUNCTION__ ": SetupDiBuildDriverInfoList raised an exception: %#x\n", uXcpt));
665 }
666 if (fRc)
667#endif
668 {
669 SP_DRVINFO_DATA DrvInfo;
670 DrvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
671
672 union
673 {
674 SP_DRVINFO_DETAIL_DATA_W s;
675 uint8_t ab[16384];
676 } DrvDetail;
677
678 /* Ensure zero terminated buffer: */
679 DrvDetail.ab[sizeof(DrvDetail) - 1] = '\0';
680 DrvDetail.ab[sizeof(DrvDetail) - 2] = '\0';
681
682 for (DWORD i = 0; dwErrRet == ERROR_SUCCESS; i++)
683 {
684 if (SetupDiEnumDriverInfo(hDevInfo, NULL /*DeviceInfoData*/, SPDIT_CLASSDRIVER /*DriverType*/,
685 i /*MemberIndex*/, &DrvInfo /*DriverInfoData*/))
686 {
687 DWORD dwReq = 0;
688 DrvDetail.s.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
689 if (SetupDiGetDriverInfoDetail(hDevInfo, NULL /*DeviceInfoData*/, &DrvInfo,
690 &DrvDetail.s, sizeof(DrvDetail) - 2 /*our terminator*/, &dwReq))
691 {
692 for (WCHAR *pwszHwId = DrvDetail.s.HardwareID;
693 *pwszHwId != '\0' && (uintptr_t)pwszHwId < (uintptr_t)&DrvDetail.ab[sizeof(DrvDetail)];
694 pwszHwId += RTUtf16Len(pwszHwId) + 1)
695 {
696 if (RTUtf16ICmp(pwszHwId, pwszPnPId) == 0)
697 {
698 NonStandardAssert(DrvDetail.s.InfFileName[0]);
699 if (DrvDetail.s.InfFileName[0])
700 {
701 HRESULT hrc = a_rList.add(DrvDetail.s.InfFileName);
702 NonStandardLogRelCrap((__FUNCTION__": %ls added to list (%#x)", DrvDetail.s.InfFileName, hrc));
703 if (hrc != S_OK)
704 {
705 dwErrRet = ERROR_OUTOFMEMORY;
706 break;
707 }
708 }
709 }
710 }
711 }
712 else
713 {
714 DWORD dwErr2 = GetLastError();
715 NonStandardLogRelCrap((__FUNCTION__": SetupDiGetDriverInfoDetail fail dwErr=%u, size(%d)", dwErr2, dwReq));
716// NonStandardAssertFailed();
717 }
718 }
719 else
720 {
721 DWORD dwErr2 = GetLastError();
722 if (dwErr2 == ERROR_NO_MORE_ITEMS)
723 {
724 NonStandardLogRelCrap((__FUNCTION__": dwErr == ERROR_NO_MORE_ITEMS -> search was finished "));
725 break;
726 }
727 NonStandardAssertFailed();
728 }
729 }
730
731 SetupDiDestroyDriverInfoList(hDevInfo, NULL /*DeviceInfoData*/, SPDIT_CLASSDRIVER);
732 }
733 else
734 {
735 dwErrRet = GetLastError();
736 NonStandardAssertFailed();
737 }
738
739 SetupDiDestroyDeviceInfoList(hDevInfo);
740 }
741 else
742 {
743 dwErrRet = GetLastError();
744 NonStandardAssertFailed();
745 }
746
747 return HRESULT_FROM_WIN32(dwErrRet);
748}
749
750#if 0
751VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInit()
752{
753 int rc = RTR3InitDll(0);
754 if (rc != VINF_SUCCESS)
755 {
756 NonStandardLogRelCrap(("Could not init IPRT!, rc (%d)\n", rc));
757 return E_FAIL;
758 }
759
760 return S_OK;
761}
762
763VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgTerm()
764{
765 return S_OK;
766}
767#endif
768
769VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllSetupDi(IN const GUID *pGuidClass, IN LPCWSTR pwszClassName,
770 IN LPCWSTR pwszPnPId, IN DWORD fFlags)
771{
772 VBoxDrvCfgStringList list(128);
773 HRESULT hrc = vboxDrvCfgCollectInfsSetupDi(pGuidClass, pwszPnPId, list);
774 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgCollectInfsSetupDi returned %d devices with PnPId %ls and class name %ls",
775 list.size(), pwszPnPId, pwszClassName));
776 if (hrc == S_OK)
777 {
778 INFENUM_CONTEXT_T Context;
779 Context.InfInfo.pwszClassName = pwszClassName;
780 Context.InfInfo.pwszPnPId = pwszPnPId;
781 Context.fFlags = fFlags;
782 Context.hrc = S_OK;
783 size_t const cItems = list.size();
784 for (size_t i = 0; i < cItems; ++i)
785 {
786 LPCWSTR pwszInf = list.get(i);
787
788 /* Find the start of the filename: */
789 size_t offFilename = RTUtf16Len(pwszInf);
790 while (offFilename > 0 && !RTPATH_IS_SEP(pwszInf[offFilename - 1]))
791 offFilename--;
792
793 vboxDrvCfgInfEnumerationCallback(&pwszInf[offFilename], &Context);
794 NonStandardLogRelCrap((__FUNCTION__": inf = %ls\n", pwszInf));
795 }
796 }
797 return hrc;
798}
799
800static HRESULT vboxDrvCfgEnumFiles(LPCWSTR pwszDirAndPattern, PFNVBOXNETCFG_ENUMERATION_CALLBACK_T pfnCallback, PVOID pContext)
801{
802 HRESULT hrc = S_OK;
803
804 WIN32_FIND_DATAW Data;
805 RT_ZERO(Data);
806 HANDLE hEnum = FindFirstFileW(pwszDirAndPattern, &Data);
807 if (hEnum != INVALID_HANDLE_VALUE)
808 {
809 for (;;)
810 {
811 if (!pfnCallback(Data.cFileName, pContext))
812 break;
813
814 /* next iteration */
815 RT_ZERO(Data);
816 BOOL fNext = FindNextFile(hEnum, &Data);
817 if (!fNext)
818 {
819 DWORD dwErr = GetLastError();
820 if (dwErr != ERROR_NO_MORE_FILES)
821 {
822 NonStandardLogRelCrap((__FUNCTION__": FindNextFile fail dwErr=%u\n", dwErr));
823 NonStandardAssertFailed();
824 hrc = HRESULT_FROM_WIN32(dwErr);
825 }
826 break;
827 }
828 }
829
830 FindClose(hEnum);
831 }
832 else
833 {
834 DWORD dwErr = GetLastError();
835 if (dwErr != ERROR_NO_MORE_FILES)
836 {
837 NonStandardLogRelCrap((__FUNCTION__": FindFirstFile fail dwErr=%u\n", dwErr));
838 NonStandardAssertFailed();
839 hrc = HRESULT_FROM_WIN32(dwErr);
840 }
841 }
842
843 return hrc;
844}
845
846VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllF(LPCWSTR pwszClassName, LPCWSTR pwszPnPId, DWORD fFlags)
847{
848 static WCHAR const s_wszFilter[] = L"\\inf\\oem*.inf";
849
850 HRESULT hrc;
851 WCHAR wszInfDirPath[MAX_PATH];
852 UINT cwcInput = RT_ELEMENTS(wszInfDirPath) - RT_ELEMENTS(s_wszFilter);
853 UINT cwcWindows = GetSystemWindowsDirectoryW(wszInfDirPath, cwcInput);
854 if (cwcWindows > 0 && cwcWindows < cwcInput)
855 {
856 RTUtf16Copy(&wszInfDirPath[cwcWindows], RT_ELEMENTS(wszInfDirPath) - cwcWindows, s_wszFilter);
857
858 INFENUM_CONTEXT_T Context;
859 Context.InfInfo.pwszClassName = pwszClassName;
860 Context.InfInfo.pwszPnPId = pwszPnPId;
861 Context.fFlags = fFlags;
862 Context.hrc = S_OK;
863 NonStandardLogRelCrap((__FUNCTION__": Calling vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context)"));
864 hrc = vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context);
865 NonStandardAssert(hrc == S_OK);
866 if (hrc == S_OK)
867 hrc = Context.hrc;
868 else
869 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgEnumFiles failed, hrc=0x%x\n", hrc));
870 }
871 else
872 {
873 NonStandardLogRelCrap((__FUNCTION__": GetSystemWindowsDirectory failed, cwcWindows=%u lasterr=%u\n", cwcWindows, GetLastError()));
874 NonStandardAssertFailed();
875 hrc = E_FAIL;
876 }
877
878 return hrc;
879
880}
881
882/* time intervals in milliseconds */
883/* max time to wait for the service to startup */
884#define VBOXDRVCFG_SVC_WAITSTART_TIME 10000
885/* sleep time before service status polls */
886#define VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD 100
887/* number of service start polls */
888#define VBOXDRVCFG_SVC_WAITSTART_RETRIES (VBOXDRVCFG_SVC_WAITSTART_TIME/VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD)
889
890VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgSvcStart(LPCWSTR pwszSvcName)
891{
892 SC_HANDLE hMgr = OpenSCManagerW(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
893 if (hMgr == NULL)
894 {
895 DWORD dwErr = GetLastError();
896 NonStandardLogRelCrap((__FUNCTION__": OpenSCManager failed, dwErr=%u\n", dwErr));
897 return HRESULT_FROM_WIN32(dwErr);
898 }
899
900 HRESULT hrc = S_OK;
901 SC_HANDLE hSvc = OpenServiceW(hMgr, pwszSvcName, SERVICE_QUERY_STATUS | SERVICE_START);
902 if (hSvc)
903 {
904 SERVICE_STATUS Status;
905 BOOL fRc = QueryServiceStatus(hSvc, &Status);
906 if (fRc)
907 {
908 if (Status.dwCurrentState != SERVICE_RUNNING && Status.dwCurrentState != SERVICE_START_PENDING)
909 {
910 NonStandardLogRelCrap(("Starting service (%ls)\n", pwszSvcName));
911
912 fRc = StartService(hSvc, 0, NULL);
913 if (!fRc)
914 {
915 DWORD dwErr = GetLastError();
916 NonStandardLogRelCrap((__FUNCTION__": StartService failed dwErr=%u\n", dwErr));
917 hrc = HRESULT_FROM_WIN32(dwErr);
918 }
919 }
920
921 if (fRc)
922 {
923 fRc = QueryServiceStatus(hSvc, &Status);
924 if (fRc)
925 {
926 if (Status.dwCurrentState == SERVICE_START_PENDING)
927 for (size_t i = 0; i < VBOXDRVCFG_SVC_WAITSTART_RETRIES; ++i)
928 {
929 Sleep(VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD);
930 fRc = QueryServiceStatus(hSvc, &Status);
931 if (!fRc)
932 {
933 DWORD dwErr = GetLastError();
934 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%u\n", dwErr));
935 hrc = HRESULT_FROM_WIN32(dwErr);
936 break;
937 }
938 if (Status.dwCurrentState != SERVICE_START_PENDING)
939 break;
940 }
941
942 if (hrc != S_OK || Status.dwCurrentState != SERVICE_RUNNING)
943 {
944 NonStandardLogRelCrap((__FUNCTION__": Failed to start the service\n"));
945 hrc = E_FAIL;
946 }
947 }
948 else
949 {
950 DWORD dwErr = GetLastError();
951 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%u\n", dwErr));
952 hrc = HRESULT_FROM_WIN32(dwErr);
953 }
954 }
955 }
956 else
957 {
958 DWORD dwErr = GetLastError();
959 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%u\n", dwErr));
960 hrc = HRESULT_FROM_WIN32(dwErr);
961 }
962
963 CloseServiceHandle(hSvc);
964 }
965 else
966 {
967 DWORD dwErr = GetLastError();
968 NonStandardLogRelCrap((__FUNCTION__": OpenServiceW failed, dwErr=%u\n", dwErr));
969 hrc = HRESULT_FROM_WIN32(dwErr);
970 }
971
972 CloseServiceHandle(hMgr);
973 return hrc;
974}
975
976
977HRESULT VBoxDrvCfgDrvUpdate(LPCWSTR pszwHwId, LPCWSTR psxwInf, BOOL *pfRebootRequired)
978{
979 if (pfRebootRequired)
980 *pfRebootRequired = FALSE;
981
982 WCHAR wszInfFullPath[MAX_PATH];
983 DWORD dwChars = GetFullPathNameW(psxwInf, MAX_PATH, wszInfFullPath, NULL /*lpFilePart*/);
984 if (!dwChars || dwChars >= MAX_PATH)
985 {
986 NonStandardLogCrap(("GetFullPathNameW failed, dwErr=%u, dwChars=%ld\n", GetLastError(), dwChars));
987 return E_INVALIDARG;
988 }
989
990 BOOL fRebootRequired = FALSE;
991 if (!UpdateDriverForPlugAndPlayDevicesW(NULL /*hwndParent*/, pszwHwId, wszInfFullPath, INSTALLFLAG_FORCE, &fRebootRequired))
992 {
993 DWORD dwErr = GetLastError();
994 NonStandardLogCrap(("UpdateDriverForPlugAndPlayDevicesW failed, dwErr=%u\n", dwErr));
995 return HRESULT_FROM_WIN32(dwErr);
996 }
997
998 if (fRebootRequired)
999 NonStandardLogCrap(("!!Driver Update: REBOOT REQUIRED!!\n"));
1000
1001 if (pfRebootRequired)
1002 *pfRebootRequired = fRebootRequired;
1003
1004 return S_OK;
1005}
1006
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