VirtualBox

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

Last change on this file since 54695 was 53038, checked in by vboxsync, 11 years ago

pr7489. Fixed RemoveHostOnlyInterfaces(). Function RemoveHostOnlyInterfaces() resumes deleting driver packages and inf files (not only devices) related to Host-only adapters again. UninstallNetAdp deletes Host-only driver packages(not devices) only. RemoveHostOnlyInterfaces is used during uninstallation, UninstallNetAdp is used during upgrade.

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

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