VirtualBox

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

Last change on this file since 94991 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.2 KB
Line 
1/* $Id: VBoxDrvCfg.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBoxDrvCfg.cpp - Windows Driver Manipulation API implementation
4 */
5
6/*
7 * Copyright (C) 2011-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <VBox/VBoxDrvCfg-win.h>
32
33#include <iprt/win/setupapi.h>
34#include <iprt/win/shlobj.h>
35
36#include <string.h>
37
38#include <stdlib.h>
39#include <malloc.h>
40#include <stdio.h>
41
42#include <Newdev.h>
43
44
45/*********************************************************************************************************************************
46* Global Variables *
47*********************************************************************************************************************************/
48static PFNVBOXDRVCFG_LOG g_pfnVBoxDrvCfgLog;
49static void *g_pvVBoxDrvCfgLog;
50
51static PFNVBOXDRVCFG_PANIC g_pfnVBoxDrvCfgPanic;
52static void *g_pvVBoxDrvCfgPanic;
53
54
55VBOXDRVCFG_DECL(void) VBoxDrvCfgLoggerSet(PFNVBOXDRVCFG_LOG pfnLog, void *pvLog)
56{
57 g_pfnVBoxDrvCfgLog = pfnLog;
58 g_pvVBoxDrvCfgLog = pvLog;
59}
60
61VBOXDRVCFG_DECL(void) VBoxDrvCfgPanicSet(PFNVBOXDRVCFG_PANIC pfnPanic, void *pvPanic)
62{
63 g_pfnVBoxDrvCfgPanic = pfnPanic;
64 g_pvVBoxDrvCfgPanic = pvPanic;
65}
66
67static void vboxDrvCfgLogRel(LPCSTR szString, ...)
68{
69 PFNVBOXDRVCFG_LOG pfnLog = g_pfnVBoxDrvCfgLog;
70 void * pvLog = g_pvVBoxDrvCfgLog;
71 if (pfnLog)
72 {
73 char szBuffer[4096] = {0};
74 va_list pArgList;
75 va_start(pArgList, szString);
76 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, pArgList);
77 va_end(pArgList);
78 pfnLog(VBOXDRVCFG_LOG_SEVERITY_REL, szBuffer, pvLog);
79 }
80}
81
82static void vboxDrvCfgLogRegular(LPCSTR szString, ...)
83{
84 PFNVBOXDRVCFG_LOG pfnLog = g_pfnVBoxDrvCfgLog;
85 void * pvLog = g_pvVBoxDrvCfgLog;
86 if (pfnLog)
87 {
88 char szBuffer[4096] = {0};
89 va_list pArgList;
90 va_start(pArgList, szString);
91 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, pArgList);
92 va_end(pArgList);
93 pfnLog(VBOXDRVCFG_LOG_SEVERITY_REGULAR, szBuffer, pvLog);
94 }
95}
96
97static void vboxDrvCfgLogFlow(LPCSTR szString, ...)
98{
99 PFNVBOXDRVCFG_LOG pfnLog = g_pfnVBoxDrvCfgLog;
100 void * pvLog = g_pvVBoxDrvCfgLog;
101 if (pfnLog)
102 {
103 char szBuffer[4096] = {0};
104 va_list pArgList;
105 va_start(pArgList, szString);
106 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, pArgList);
107 va_end(pArgList);
108 pfnLog(VBOXDRVCFG_LOG_SEVERITY_FLOW, szBuffer, pvLog);
109 }
110}
111
112static void vboxDrvCfgPanic()
113{
114 PFNVBOXDRVCFG_PANIC pfnPanic = g_pfnVBoxDrvCfgPanic;
115 void * pvPanic = g_pvVBoxDrvCfgPanic;
116 if (pfnPanic)
117 {
118 pfnPanic(pvPanic);
119 }
120}
121
122/* we do not use IPRT Logging because the lib is used in host installer and needs to
123 * post its msgs to MSI logger */
124#define NonStandardLogCrap(_m) do { vboxDrvCfgLogRegular _m ; } while (0)
125#define NonStandardLogFlowCrap(_m) do { vboxDrvCfgLogFlow _m ; } while (0)
126#define NonStandardLogRelCrap(_m) do { vboxDrvCfgLogRel _m ; } while (0)
127#define NonStandardAssertFailed() vboxDrvCfgPanic()
128#define NonStandardAssert(_m) do { \
129 if (RT_UNLIKELY(!(_m))) { vboxDrvCfgPanic(); } \
130 } while (0)
131
132
133class VBoxDrvCfgStringList
134{
135public:
136 VBoxDrvCfgStringList(int aSize);
137
138 ~VBoxDrvCfgStringList();
139
140 HRESULT add(LPWSTR pStr);
141
142 int size() {return mSize;}
143
144 LPWSTR get(int i) {return maList[i];}
145private:
146 HRESULT resize(int newSize);
147
148 LPWSTR *maList;
149 int mBufSize;
150 int mSize;
151};
152
153VBoxDrvCfgStringList::VBoxDrvCfgStringList(int aSize)
154{
155 maList = (LPWSTR*)malloc( sizeof(maList[0]) * aSize);
156 mBufSize = aSize;
157 mSize = 0;
158}
159
160VBoxDrvCfgStringList::~VBoxDrvCfgStringList()
161{
162 if (!mBufSize)
163 return;
164
165 for (int i = 0; i < mSize; ++i)
166 {
167 free(maList[i]);
168 }
169
170 free(maList);
171}
172
173HRESULT VBoxDrvCfgStringList::add(LPWSTR pStr)
174{
175 if (mSize == mBufSize)
176 {
177 int hr = resize(mBufSize+10);
178 if (SUCCEEDED(hr))
179 return hr;
180 }
181 size_t cStr = wcslen(pStr) + 1;
182 LPWSTR str = (LPWSTR)malloc( sizeof(maList[0][0]) * cStr);
183 memcpy(str, pStr, sizeof(maList[0][0]) * cStr);
184 maList[mSize] = str;
185 ++mSize;
186 return S_OK;
187}
188
189HRESULT VBoxDrvCfgStringList::resize(int newSize)
190{
191 NonStandardAssert(newSize >= mSize);
192 if (newSize < mSize)
193 return E_FAIL;
194 LPWSTR* pOld = maList;
195 maList = (LPWSTR*)malloc( sizeof(maList[0]) * newSize);
196 mBufSize = newSize;
197 memcpy(maList, pOld, mSize*sizeof(maList[0]));
198 free(pOld);
199 return S_OK;
200}
201
202/*
203 * inf file manipulation API
204 */
205typedef bool (*PFNVBOXNETCFG_ENUMERATION_CALLBACK) (LPCWSTR lpszFileName, PVOID pContext);
206
207typedef struct _INF_INFO
208{
209 LPCWSTR lpszClassName;
210 LPCWSTR lpszPnPId;
211} INF_INFO, *PINF_INFO;
212
213typedef struct _INFENUM_CONTEXT
214{
215 INF_INFO InfInfo;
216 DWORD Flags;
217 HRESULT hr;
218} INFENUM_CONTEXT, *PINFENUM_CONTEXT;
219
220static HRESULT vboxDrvCfgInfQueryContext(HINF hInf, LPCWSTR lpszSection, LPCWSTR lpszKey, PINFCONTEXT pCtx)
221{
222 if (!SetupFindFirstLineW(hInf, lpszSection, lpszKey, pCtx))
223 {
224 DWORD dwErr = GetLastError();
225 NonStandardLogRelCrap((__FUNCTION__ ": SetupFindFirstLine failed WinEr (%d) for Section(%S), Key(%S)\n", dwErr, lpszSection, lpszKey));
226 return HRESULT_FROM_WIN32(dwErr);
227 }
228 return S_OK;
229}
230
231static HRESULT vboxDrvCfgInfQueryKeyValue(PINFCONTEXT pCtx, DWORD iValue, LPWSTR *lppszValue, PDWORD pcValue)
232{
233 DWORD dwErr;
234 DWORD cValue;
235
236 if (!SetupGetStringFieldW(pCtx, iValue, NULL, 0, &cValue))
237 {
238 dwErr = GetLastError();
239// NonStandardAssert(dwErr == ERROR_INSUFFICIENT_BUFFER);
240 if (dwErr != ERROR_INSUFFICIENT_BUFFER)
241 {
242 NonStandardLogFlowCrap((__FUNCTION__ ": SetupGetStringField failed WinEr (%d) for iValue(%d)\n", dwErr, iValue));
243 return HRESULT_FROM_WIN32(dwErr);
244 }
245 }
246
247 LPWSTR lpszValue = (LPWSTR)malloc(cValue * sizeof (lpszValue[0]));
248 NonStandardAssert(lpszValue);
249 if (!lpszValue)
250 {
251 NonStandardLogRelCrap((__FUNCTION__ ": SetCoTaskMemAlloc failed to alloc mem of size (%d), for iValue(%d)\n", cValue * sizeof (lpszValue[0]), iValue));
252 return E_FAIL;
253 }
254
255 if (!SetupGetStringFieldW(pCtx, iValue, lpszValue, cValue, &cValue))
256 {
257 dwErr = GetLastError();
258 NonStandardLogRelCrap((__FUNCTION__ ": SetupGetStringField failed WinEr (%d) for iValue(%d)\n", dwErr, iValue));
259 NonStandardAssert(0);
260 free(lpszValue);
261 return HRESULT_FROM_WIN32(dwErr);
262 }
263
264 *lppszValue = lpszValue;
265 if (pcValue)
266 *pcValue = cValue;
267 return S_OK;
268}
269#if defined(RT_ARCH_AMD64)
270# define VBOXDRVCFG_ARCHSTR L"amd64"
271#else
272# define VBOXDRVCFG_ARCHSTR L"x86"
273#endif
274
275static HRESULT vboxDrvCfgInfQueryModelsSectionName(HINF hInf, LPWSTR *lppszValue, PDWORD pcValue)
276{
277 INFCONTEXT InfCtx;
278 LPWSTR lpszModels, lpszPlatform = NULL, lpszPlatformCur;
279 LPWSTR lpszResult = NULL;
280 DWORD cModels, cPlatform = 0, cPlatformCur, cResult = 0;
281 bool bNt = false, bArch = false /*, bOs = false */;
282
283 HRESULT hr = vboxDrvCfgInfQueryContext(hInf, L"Manufacturer", NULL, &InfCtx);
284 if (hr != S_OK)
285 {
286 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgInfQueryContext for Manufacturer failed, hr=0x%x\n", hr));
287 return hr;
288 }
289
290 hr = vboxDrvCfgInfQueryKeyValue(&InfCtx, 1, &lpszModels, &cModels);
291 if (hr != S_OK)
292 {
293 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue 1 for Manufacturer failed, hr=0x%x\n", hr));
294 return hr;
295 }
296
297 for (DWORD i = 2; (hr = vboxDrvCfgInfQueryKeyValue(&InfCtx, i, &lpszPlatformCur, &cPlatformCur)) == S_OK; ++i)
298 {
299 if (wcsicmp(lpszPlatformCur, L"NT" VBOXDRVCFG_ARCHSTR))
300 {
301 if (bNt)
302 {
303 free(lpszPlatformCur);
304 lpszPlatformCur = NULL;
305 continue;
306 }
307
308 if (wcsicmp(lpszPlatformCur, L"NT"))
309 {
310 free(lpszPlatformCur);
311 lpszPlatformCur = NULL;
312 continue;
313 }
314
315 bNt = true;
316 }
317 else
318 {
319 bArch = true;
320 }
321
322 cPlatform = cPlatformCur;
323 if(lpszPlatform)
324 free(lpszPlatform);
325 lpszPlatform = lpszPlatformCur;
326 lpszPlatformCur = NULL;
327 }
328
329 hr = S_OK;
330
331 if (lpszPlatform)
332 {
333 lpszResult = (LPWSTR)malloc((cModels + cPlatform) * sizeof (lpszResult[0]));
334 if (lpszResult)
335 {
336 memcpy(lpszResult, lpszModels, (cModels - 1) * sizeof (lpszResult[0]));
337 *(lpszResult + cModels - 1) = L'.';
338 memcpy(lpszResult + cModels, lpszPlatform, cPlatform * sizeof (lpszResult[0]));
339 cResult = cModels + cPlatform;
340 }
341 else
342 {
343 hr = E_FAIL;
344 }
345 }
346 else
347 {
348 lpszResult = lpszModels;
349 cResult = cModels;
350 lpszModels = NULL;
351 }
352
353 if (lpszModels)
354 free(lpszModels);
355 if (lpszPlatform)
356 free(lpszPlatform);
357
358 if (hr == S_OK)
359 {
360 *lppszValue = lpszResult;
361 if (pcValue)
362 *pcValue = cResult;
363 }
364
365 return hr;
366}
367
368static HRESULT vboxDrvCfgInfQueryFirstPnPId(HINF hInf, LPWSTR *lppszPnPId)
369{
370 *lppszPnPId = NULL;
371
372 LPWSTR lpszModels;
373 HRESULT hr = vboxDrvCfgInfQueryModelsSectionName(hInf, &lpszModels, NULL);
374 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryModelsSectionName returned lpszModels = (%S)", lpszModels));
375 if (hr != S_OK)
376 {
377 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for Manufacturer failed, hr=0x%x\n", hr));
378 return hr;
379 }
380
381 LPWSTR lpszPnPId = NULL;
382 INFCONTEXT InfCtx;
383 hr = vboxDrvCfgInfQueryContext(hInf, lpszModels, NULL, &InfCtx);
384 if (hr != S_OK)
385 {
386 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryContext for models (%S) failed, hr=0x%x\n", lpszModels, hr));
387 }
388 else
389 {
390 hr = vboxDrvCfgInfQueryKeyValue(&InfCtx, 2, &lpszPnPId, NULL);
391 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for models (%S) returned lpszPnPId (%S) \n", lpszModels, lpszPnPId));
392
393 if (hr != S_OK)
394 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgRegQueryKeyValue for models (%S) failed, hr=0x%x\n", lpszModels, hr));
395 }
396 /* free models string right away */
397 free(lpszModels);
398 if (hr != S_OK)
399 return hr;
400
401 *lppszPnPId = lpszPnPId;
402 return S_OK;
403}
404
405static bool vboxDrvCfgInfEnumerationCallback(LPCWSTR lpszFileName, PVOID pCtxt);
406
407#define VBOXDRVCFG_S_INFEXISTS (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS))
408
409static HRESULT vboxDrvCfgInfCopyEx(IN LPCWSTR lpszInfPath, IN DWORD fCopyStyle, OUT LPWSTR lpszDstName, IN DWORD cbDstName, OUT PDWORD pcbDstNameSize, OUT LPWSTR* lpszDstNameComponent)
410{
411 WCHAR aMediaLocation[_MAX_DIR];
412 WCHAR aDir[_MAX_DIR];
413
414 _wsplitpath(lpszInfPath, aMediaLocation, aDir, NULL, NULL);
415 wcscat(aMediaLocation, aDir);
416
417 if (!SetupCopyOEMInfW(lpszInfPath, aMediaLocation, SPOST_PATH, fCopyStyle,
418 lpszDstName, cbDstName, pcbDstNameSize,
419 lpszDstNameComponent))
420 {
421 DWORD dwErr = GetLastError();
422 HRESULT hr = HRESULT_FROM_WIN32(dwErr);
423 if (fCopyStyle != SP_COPY_REPLACEONLY || hr != VBOXDRVCFG_S_INFEXISTS)
424 {
425 NonStandardLogRelCrap((__FUNCTION__ ": SetupCopyOEMInf fail dwErr=%ld\n", dwErr));
426 }
427 return hr;
428 }
429
430 return S_OK;
431}
432
433static HRESULT vboxDrvCfgInfCopy(IN LPCWSTR lpszInfPath)
434{
435 return vboxDrvCfgInfCopyEx(lpszInfPath, 0, NULL, 0, NULL, NULL);
436}
437
438VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfInstall(IN LPCWSTR lpszInfPath)
439{
440 return vboxDrvCfgInfCopy(lpszInfPath);
441}
442
443VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstall(IN LPCWSTR lpszInfPath, DWORD fFlags)
444{
445 WCHAR DstInfName[MAX_PATH];
446 DWORD cbDword = sizeof (DstInfName);
447 HRESULT hr = vboxDrvCfgInfCopyEx(lpszInfPath, SP_COPY_REPLACEONLY, DstInfName, cbDword, &cbDword, NULL);
448 if (hr == VBOXDRVCFG_S_INFEXISTS)
449 {
450 if (!SetupUninstallOEMInfW(DstInfName, fFlags, NULL /*__in PVOID Reserved == NULL */))
451 {
452 DWORD dwErr = GetLastError();
453 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf failed for file (%S), oem(%S), dwErr=%ld\n", lpszInfPath, DstInfName, dwErr));
454 NonStandardAssert(0);
455 return HRESULT_FROM_WIN32(dwErr);
456 }
457 }
458 return S_OK;
459}
460
461
462static HRESULT vboxDrvCfgCollectInfsSetupDi(const GUID * pGuid, LPCWSTR pPnPId, VBoxDrvCfgStringList & list)
463{
464 DWORD dwErr = ERROR_SUCCESS;
465 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(
466 pGuid, /* IN LPGUID ClassGuid, OPTIONAL */
467 NULL /*IN HWND hwndParent OPTIONAL */
468 );
469 if (hDevInfo != INVALID_HANDLE_VALUE)
470 {
471 if (SetupDiBuildDriverInfoList(hDevInfo,
472 NULL, /*IN OUT PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
473 SPDIT_CLASSDRIVER /*IN DWORD DriverType*/
474 ))
475 {
476 SP_DRVINFO_DATA DrvInfo;
477 DrvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
478 char DetailBuf[16384];
479 PSP_DRVINFO_DETAIL_DATA pDrvDetail = (PSP_DRVINFO_DETAIL_DATA)DetailBuf;
480
481 for (DWORD i = 0; ; i++)
482 {
483 if (SetupDiEnumDriverInfo(hDevInfo,
484 NULL, /* IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
485 SPDIT_CLASSDRIVER , /*IN DWORD DriverType,*/
486 i, /*IN DWORD MemberIndex,*/
487 &DrvInfo /*OUT PSP_DRVINFO_DATA DriverInfoData*/
488 ))
489 {
490 DWORD dwReq;
491 pDrvDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
492 if (SetupDiGetDriverInfoDetail(
493 hDevInfo, /*IN HDEVINFO DeviceInfoSet,*/
494 NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
495 &DrvInfo, /*IN PSP_DRVINFO_DATA DriverInfoData,*/
496 pDrvDetail, /*OUT PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData, OPTIONAL*/
497 sizeof(DetailBuf), /*IN DWORD DriverInfoDetailDataSize,*/
498 &dwReq /*OUT PDWORD RequiredSize OPTIONAL*/
499 ))
500 {
501 for (WCHAR *pwszHwId = pDrvDetail->HardwareID;
502 pwszHwId && *pwszHwId && (uintptr_t)pwszHwId < (uintptr_t)DetailBuf + sizeof(DetailBuf);
503 pwszHwId += wcslen(pwszHwId) + 1)
504 {
505 if (!wcsicmp(pwszHwId, pPnPId))
506 {
507 NonStandardAssert(pDrvDetail->InfFileName[0]);
508 if (pDrvDetail->InfFileName)
509 {
510 list.add(pDrvDetail->InfFileName);
511 NonStandardLogRelCrap((__FUNCTION__": %S added to list", pDrvDetail->InfFileName));
512 }
513 }
514 }
515 }
516 else
517 {
518 DWORD dwErr2 = GetLastError();
519 NonStandardLogRelCrap((__FUNCTION__": SetupDiGetDriverInfoDetail fail dwErr=%ld, size(%d)", dwErr2, dwReq));
520// NonStandardAssert(0);
521 }
522
523 }
524 else
525 {
526 DWORD dwErr2 = GetLastError();
527 if (dwErr2 == ERROR_NO_MORE_ITEMS)
528 {
529 NonStandardLogRelCrap((__FUNCTION__": dwErr == ERROR_NO_MORE_ITEMS -> search was finished "));
530 break;
531 }
532
533 NonStandardAssert(0);
534 }
535 }
536
537 SetupDiDestroyDriverInfoList(hDevInfo,
538 NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
539 SPDIT_CLASSDRIVER/*IN DWORD DriverType*/
540 );
541 }
542 else
543 {
544 dwErr = GetLastError();
545 NonStandardAssert(0);
546 }
547
548 SetupDiDestroyDeviceInfoList(hDevInfo);
549 }
550 else
551 {
552 dwErr = GetLastError();
553 NonStandardAssert(0);
554 }
555
556 return HRESULT_FROM_WIN32(dwErr);
557}
558
559#if 0
560VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInit()
561{
562 int rc = RTR3InitDll(0);
563 if (rc != VINF_SUCCESS)
564 {
565 NonStandardLogRelCrap(("Could not init IPRT!, rc (%d)\n", rc));
566 return E_FAIL;
567 }
568
569 return S_OK;
570}
571
572VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgTerm()
573{
574 return S_OK;
575}
576#endif
577
578VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllSetupDi(IN const GUID * pGuidClass, IN LPCWSTR lpszClassName, IN LPCWSTR lpszPnPId, IN DWORD Flags)
579{
580 VBoxDrvCfgStringList list(128);
581 HRESULT hr = vboxDrvCfgCollectInfsSetupDi(pGuidClass, lpszPnPId, list);
582 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgCollectInfsSetupDi returned %d devices with PnPId %S and class name %S", list.size(), lpszPnPId, lpszClassName));
583 if (hr == S_OK)
584 {
585 INFENUM_CONTEXT Context;
586 Context.InfInfo.lpszClassName = lpszClassName;
587 Context.InfInfo.lpszPnPId = lpszPnPId;
588 Context.Flags = Flags;
589 Context.hr = S_OK;
590 int size = list.size();
591 for (int i = 0; i < size; ++i)
592 {
593 LPCWSTR pInf = list.get(i);
594 const WCHAR* pRel = wcsrchr(pInf, '\\');
595 if (pRel)
596 ++pRel;
597 else
598 pRel = pInf;
599
600 vboxDrvCfgInfEnumerationCallback(pRel, &Context);
601 NonStandardLogRelCrap((__FUNCTION__": inf = %S\n", list.get(i)));
602 }
603 }
604 return hr;
605}
606
607static HRESULT vboxDrvCfgEnumFiles(LPCWSTR pPattern, PFNVBOXNETCFG_ENUMERATION_CALLBACK pfnCallback, PVOID pContext)
608{
609 WIN32_FIND_DATA Data;
610 memset(&Data, 0, sizeof(Data));
611 HRESULT hr = S_OK;
612
613 HANDLE hEnum = FindFirstFile(pPattern,&Data);
614 if (hEnum != INVALID_HANDLE_VALUE)
615 {
616
617 do
618 {
619 if (!pfnCallback(Data.cFileName, pContext))
620 {
621 break;
622 }
623
624 /* next iteration */
625 memset(&Data, 0, sizeof(Data));
626 BOOL bNext = FindNextFile(hEnum,&Data);
627 if (!bNext)
628 {
629 DWORD dwErr = GetLastError();
630 if (dwErr != ERROR_NO_MORE_FILES)
631 {
632 NonStandardLogRelCrap((__FUNCTION__": FindNextFile fail dwErr=%ld\n", dwErr));
633 NonStandardAssert(0);
634 hr = HRESULT_FROM_WIN32(dwErr);
635 }
636 break;
637 }
638 }while (true);
639 FindClose(hEnum);
640 }
641 else
642 {
643 DWORD dwErr = GetLastError();
644 if (dwErr != ERROR_NO_MORE_FILES)
645 {
646 NonStandardLogRelCrap((__FUNCTION__": FindFirstFile fail dwErr=%ld\n", dwErr));
647 NonStandardAssert(0);
648 hr = HRESULT_FROM_WIN32(dwErr);
649 }
650 }
651
652 return hr;
653}
654
655static bool vboxDrvCfgInfEnumerationCallback(LPCWSTR lpszFileName, PVOID pCtxt)
656{
657 PINFENUM_CONTEXT pContext = (PINFENUM_CONTEXT)pCtxt;
658 DWORD dwErr;
659 NonStandardLogRelCrap((__FUNCTION__": lpszFileName (%S)\n", lpszFileName));
660 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.lpszClassName = (%S)\n", pContext->InfInfo.lpszClassName));
661 HINF hInf = SetupOpenInfFileW(lpszFileName, pContext->InfInfo.lpszClassName, INF_STYLE_WIN4, NULL /*__in PUINT ErrorLine */);
662 if (hInf == INVALID_HANDLE_VALUE)
663 {
664 dwErr = GetLastError();
665// NonStandardAssert(dwErr == ERROR_CLASS_MISMATCH);
666 if (dwErr != ERROR_CLASS_MISMATCH)
667 {
668 NonStandardLogCrap((__FUNCTION__ ": SetupOpenInfFileW err dwErr=%ld\n", dwErr));
669 }
670 else
671 {
672 NonStandardLogCrap((__FUNCTION__ ": dwErr == ERROR_CLASS_MISMATCH\n"));
673 }
674 return true;
675 }
676
677 LPWSTR lpszPnPId;
678 HRESULT hr = vboxDrvCfgInfQueryFirstPnPId(hInf, &lpszPnPId);
679 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId returned lpszPnPId = (%S)\n", lpszPnPId));
680 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.lpszPnPId = (%S)\n", pContext->InfInfo.lpszPnPId));
681 if (hr == S_OK)
682 {
683 if (!wcsicmp(pContext->InfInfo.lpszPnPId, lpszPnPId))
684 {
685 if (!SetupUninstallOEMInfW(lpszFileName,
686 pContext->Flags, /*DWORD Flags could be SUOI_FORCEDELETE */
687 NULL /*__in PVOID Reserved == NULL */
688 ))
689 {
690 dwErr = GetLastError();
691 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf failed for file (%S), dwErr=%ld\n", lpszFileName, dwErr));
692 NonStandardAssert(0);
693 hr = HRESULT_FROM_WIN32( dwErr );
694 }
695 }
696
697 free(lpszPnPId);
698 }
699 else
700 {
701 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId failed, hr=0x%x\n", hr));
702 }
703
704 SetupCloseInfFile(hInf);
705
706 return true;
707}
708
709VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllF(LPCWSTR lpszClassName, LPCWSTR lpszPnPId, DWORD Flags)
710{
711 static WCHAR const s_wszFilter[] = L"\\inf\\oem*.inf";
712 HRESULT hr;
713 WCHAR wszInfDirPath[MAX_PATH];
714 UINT cwcInput = RT_ELEMENTS(wszInfDirPath) - RT_ELEMENTS(s_wszFilter);
715 UINT cwcWindows = GetSystemWindowsDirectory(wszInfDirPath, cwcInput);
716 if (cwcWindows > 0 && cwcWindows < cwcInput)
717 {
718 wcscpy(&wszInfDirPath[cwcWindows], s_wszFilter);
719
720 INFENUM_CONTEXT Context;
721 Context.InfInfo.lpszClassName = lpszClassName;
722 Context.InfInfo.lpszPnPId = lpszPnPId;
723 Context.Flags = Flags;
724 Context.hr = S_OK;
725 NonStandardLogRelCrap((__FUNCTION__": Calling vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context)"));
726 hr = vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context);
727 NonStandardAssert(hr == S_OK);
728 if (hr == S_OK)
729 {
730 hr = Context.hr;
731 }
732 else
733 {
734 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgEnumFiles failed, hr=0x%x\n", hr));
735 }
736 }
737 else
738 {
739 NonStandardLogRelCrap((__FUNCTION__": GetSystemWindowsDirectory failed, cwcWindows=%u lasterr=%u\n", cwcWindows, GetLastError()));
740 NonStandardAssertFailed();
741 hr = E_FAIL;
742 }
743
744 return hr;
745
746}
747
748/* time intervals in milliseconds */
749/* max time to wait for the service to startup */
750#define VBOXDRVCFG_SVC_WAITSTART_TIME 10000
751/* sleep time before service status polls */
752#define VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD 100
753/* number of service start polls */
754#define VBOXDRVCFG_SVC_WAITSTART_RETRIES (VBOXDRVCFG_SVC_WAITSTART_TIME/VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD)
755
756VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgSvcStart(LPCWSTR lpszSvcName)
757{
758 SC_HANDLE hMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
759 if (hMgr == NULL)
760 {
761 DWORD dwErr = GetLastError();
762 NonStandardLogRelCrap((__FUNCTION__": OpenSCManager failed, dwErr=%ld\n", dwErr));
763 return HRESULT_FROM_WIN32(dwErr);
764 }
765
766 HRESULT hr = S_OK;
767 SC_HANDLE hSvc = OpenServiceW(hMgr, lpszSvcName, SERVICE_QUERY_STATUS | SERVICE_START);
768 if (hSvc)
769 {
770 do
771 {
772 SERVICE_STATUS Status;
773 BOOL fRc = QueryServiceStatus(hSvc, &Status);
774 if (!fRc)
775 {
776 DWORD dwErr = GetLastError();
777 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
778 hr = HRESULT_FROM_WIN32(dwErr);
779 break;
780 }
781
782 if (Status.dwCurrentState != SERVICE_RUNNING && Status.dwCurrentState != SERVICE_START_PENDING)
783 {
784 NonStandardLogRelCrap(("Starting service (%S)\n", lpszSvcName));
785
786 fRc = StartService(hSvc, 0, NULL);
787 if (!fRc)
788 {
789 DWORD dwErr = GetLastError();
790 NonStandardLogRelCrap((__FUNCTION__": StartService failed dwErr=%ld\n", dwErr));
791 hr = HRESULT_FROM_WIN32(dwErr);
792 break;
793 }
794 }
795
796 fRc = QueryServiceStatus(hSvc, &Status);
797 if (!fRc)
798 {
799 DWORD dwErr = GetLastError();
800 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
801 hr = HRESULT_FROM_WIN32(dwErr);
802 break;
803 }
804
805 if (Status.dwCurrentState == SERVICE_START_PENDING)
806 {
807 for (int i = 0; i < VBOXDRVCFG_SVC_WAITSTART_RETRIES; ++i)
808 {
809 Sleep(VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD);
810 fRc = QueryServiceStatus(hSvc, &Status);
811 if (!fRc)
812 {
813 DWORD dwErr = GetLastError();
814 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
815 hr = HRESULT_FROM_WIN32(dwErr);
816 break;
817 }
818 else if (Status.dwCurrentState != SERVICE_START_PENDING)
819 break;
820 }
821 }
822
823 if (hr != S_OK || Status.dwCurrentState != SERVICE_RUNNING)
824 {
825 NonStandardLogRelCrap((__FUNCTION__": Failed to start the service\n"));
826 hr = E_FAIL;
827 break;
828 }
829
830 } while (0);
831
832 CloseServiceHandle(hSvc);
833 }
834 else
835 {
836 DWORD dwErr = GetLastError();
837 NonStandardLogRelCrap((__FUNCTION__": OpenServiceW failed, dwErr=%ld\n", dwErr));
838 hr = HRESULT_FROM_WIN32(dwErr);
839 }
840
841 CloseServiceHandle(hMgr);
842
843 return hr;
844}
845
846
847HRESULT VBoxDrvCfgDrvUpdate(LPCWSTR pcszwHwId, LPCWSTR pcsxwInf, BOOL *pbRebootRequired)
848{
849 if (pbRebootRequired)
850 *pbRebootRequired = FALSE;
851 BOOL bRebootRequired = FALSE;
852 WCHAR InfFullPath[MAX_PATH];
853 DWORD dwChars = GetFullPathNameW(pcsxwInf,
854 sizeof (InfFullPath) / sizeof (InfFullPath[0]),
855 InfFullPath,
856 NULL /* LPTSTR *lpFilePart */
857 );
858 if (!dwChars || dwChars >= MAX_PATH)
859 {
860 NonStandardLogCrap(("GetFullPathNameW failed, dwErr=%ld, dwChars=%ld\n",
861 GetLastError(), dwChars));
862 return E_INVALIDARG;
863 }
864
865
866 if (!UpdateDriverForPlugAndPlayDevicesW(NULL, /* HWND hwndParent */
867 pcszwHwId,
868 InfFullPath,
869 INSTALLFLAG_FORCE,
870 &bRebootRequired))
871 {
872 DWORD dwErr = GetLastError();
873 NonStandardLogCrap(("UpdateDriverForPlugAndPlayDevicesW failed, dwErr=%ld\n",
874 dwErr));
875 return HRESULT_FROM_WIN32(dwErr);
876 }
877
878
879 if (bRebootRequired)
880 NonStandardLogCrap(("!!Driver Update: REBOOT REQUIRED!!\n", GetLastError(), dwChars));
881
882 if (pbRebootRequired)
883 *pbRebootRequired = bRebootRequired;
884
885 return S_OK;
886}
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