1 | /* $Id: VBoxDrvCfg.cpp 106061 2024-09-16 14:03:52Z 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-2024 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 | *********************************************************************************************************************************/
|
---|
60 | static PFNVBOXDRVCFGLOG g_pfnVBoxDrvCfgLog;
|
---|
61 | static void *g_pvVBoxDrvCfgLog;
|
---|
62 |
|
---|
63 | static PFNVBOXDRVCFGPANIC g_pfnVBoxDrvCfgPanic;
|
---|
64 | static void *g_pvVBoxDrvCfgPanic;
|
---|
65 |
|
---|
66 |
|
---|
67 | VBOXDRVCFG_DECL(void) VBoxDrvCfgLoggerSet(PFNVBOXDRVCFGLOG pfnLog, void *pvLog)
|
---|
68 | {
|
---|
69 | g_pfnVBoxDrvCfgLog = pfnLog;
|
---|
70 | g_pvVBoxDrvCfgLog = pvLog;
|
---|
71 | }
|
---|
72 |
|
---|
73 | VBOXDRVCFG_DECL(void) VBoxDrvCfgPanicSet(PFNVBOXDRVCFGPANIC pfnPanic, void *pvPanic)
|
---|
74 | {
|
---|
75 | g_pfnVBoxDrvCfgPanic = pfnPanic;
|
---|
76 | g_pvVBoxDrvCfgPanic = pvPanic;
|
---|
77 | }
|
---|
78 |
|
---|
79 | static 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 |
|
---|
94 | static 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 |
|
---|
109 | static 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 |
|
---|
124 | static 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 | */
|
---|
148 | class VBoxDrvCfgStringList
|
---|
149 | {
|
---|
150 | public:
|
---|
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; }
|
---|
159 | private:
|
---|
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 |
|
---|
168 | VBoxDrvCfgStringList::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 |
|
---|
175 | VBoxDrvCfgStringList::~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 |
|
---|
188 | HRESULT 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 |
|
---|
204 | HRESULT 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 | */
|
---|
220 | typedef bool (*PFNVBOXNETCFG_ENUMERATION_CALLBACK_T)(LPCWSTR lpszFileName, PVOID pContext);
|
---|
221 |
|
---|
222 | typedef struct INF_INFO_T
|
---|
223 | {
|
---|
224 | LPCWSTR pwszClassName;
|
---|
225 | LPCWSTR pwszPnPId;
|
---|
226 | } INF_INFO_T, *PINF_INFO_T;
|
---|
227 |
|
---|
228 | typedef struct INFENUM_CONTEXT_T
|
---|
229 | {
|
---|
230 | INF_INFO_T InfInfo;
|
---|
231 | DWORD fFlags;
|
---|
232 | HRESULT hrc;
|
---|
233 | } INFENUM_CONTEXT_T, *PINFENUM_CONTEXT_T;
|
---|
234 |
|
---|
235 | static 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 |
|
---|
247 | static 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 |
|
---|
295 | static 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 |
|
---|
386 | static 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 |
|
---|
420 | static 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 |
|
---|
558 | static 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 |
|
---|
584 | VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfInstall(IN LPCWSTR pwszInfPath)
|
---|
585 | {
|
---|
586 | return vboxDrvCfgInfCopyEx(pwszInfPath, 0 /*fCopyStyle*/, NULL /*pwszDstName*/, 0 /*cwcDstName*/,
|
---|
587 | NULL /*pcwcDstNameRet*/, NULL /*pwszDstNameComponent*/);
|
---|
588 | }
|
---|
589 |
|
---|
590 | VBOXDRVCFG_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 |
|
---|
610 | static 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
|
---|
751 | VBOXDRVCFG_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 |
|
---|
763 | VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgTerm()
|
---|
764 | {
|
---|
765 | return S_OK;
|
---|
766 | }
|
---|
767 | #endif
|
---|
768 |
|
---|
769 | VBOXDRVCFG_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 |
|
---|
800 | static 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 |
|
---|
846 | VBOXDRVCFG_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 |
|
---|
890 | VBOXDRVCFG_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 |
|
---|
977 | HRESULT 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 |
|
---|