VirtualBox

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

Last change on this file since 69498 was 69498, checked in by vboxsync, 7 years ago

backed out r118835 as it incorrectly updated the 'This file is based on' file headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.1 KB
Line 
1/* $Id: VBoxDrvCfg.cpp 69498 2017-10-28 15:07:25Z vboxsync $ */
2/** @file
3 * VBoxDrvCfg.cpp - Windows Driver Manipulation API implementation
4 */
5
6/*
7 * Copyright (C) 2011-2016 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 * pHwId = pDrvDetail->HardwareID; pHwId && *pHwId && pHwId < (TCHAR*)(DetailBuf + sizeof(DetailBuf)/sizeof(DetailBuf[0])) ;pHwId += wcslen(pHwId) + 1)
502 {
503 if (!wcsicmp(pHwId, pPnPId))
504 {
505 NonStandardAssert(pDrvDetail->InfFileName[0]);
506 if (pDrvDetail->InfFileName)
507 {
508 list.add(pDrvDetail->InfFileName);
509 NonStandardLogRelCrap((__FUNCTION__": %S added to list", pDrvDetail->InfFileName));
510 }
511 }
512 }
513 }
514 else
515 {
516 DWORD dwErr = GetLastError();
517 NonStandardLogRelCrap((__FUNCTION__": SetupDiGetDriverInfoDetail fail dwErr=%ld, size(%d)", dwErr, dwReq));
518// NonStandardAssert(0);
519 }
520
521 }
522 else
523 {
524 DWORD dwErr = GetLastError();
525 if (dwErr == ERROR_NO_MORE_ITEMS)
526 {
527 NonStandardLogRelCrap((__FUNCTION__": dwErr == ERROR_NO_MORE_ITEMS -> search was finished "));
528 break;
529 }
530
531 NonStandardAssert(0);
532 }
533 }
534
535 SetupDiDestroyDriverInfoList(hDevInfo,
536 NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
537 SPDIT_CLASSDRIVER/*IN DWORD DriverType*/
538 );
539 }
540 else
541 {
542 dwErr = GetLastError();
543 NonStandardAssert(0);
544 }
545
546 SetupDiDestroyDeviceInfoList(hDevInfo);
547 }
548 else
549 {
550 dwErr = GetLastError();
551 NonStandardAssert(0);
552 }
553
554 return HRESULT_FROM_WIN32(dwErr);
555}
556
557#if 0
558VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInit()
559{
560 int rc = RTR3InitDll(0);
561 if (rc != VINF_SUCCESS)
562 {
563 NonStandardLogRelCrap(("Could not init IPRT!, rc (%d)\n", rc));
564 return E_FAIL;
565 }
566
567 return S_OK;
568}
569
570VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgTerm()
571{
572 return S_OK;
573}
574#endif
575
576VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllSetupDi(IN const GUID * pGuidClass, IN LPCWSTR lpszClassName, IN LPCWSTR lpszPnPId, IN DWORD Flags)
577{
578 VBoxDrvCfgStringList list(128);
579 HRESULT hr = vboxDrvCfgCollectInfsSetupDi(pGuidClass, lpszPnPId, list);
580 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgCollectInfsSetupDi returned %d devices with PnPId %S and class name %S", list.size(), lpszPnPId, lpszClassName));
581 if (hr == S_OK)
582 {
583 INFENUM_CONTEXT Context;
584 Context.InfInfo.lpszClassName = lpszClassName;
585 Context.InfInfo.lpszPnPId = lpszPnPId;
586 Context.Flags = Flags;
587 Context.hr = S_OK;
588 int size = list.size();
589 for (int i = 0; i < size; ++i)
590 {
591 LPCWSTR pInf = list.get(i);
592 const WCHAR* pRel = wcsrchr(pInf, '\\');
593 if (pRel)
594 ++pRel;
595 else
596 pRel = pInf;
597
598 vboxDrvCfgInfEnumerationCallback(pRel, &Context);
599 NonStandardLogRelCrap((__FUNCTION__": inf = %S\n", list.get(i)));
600 }
601 }
602 return hr;
603}
604
605static HRESULT vboxDrvCfgEnumFiles(LPCWSTR pPattern, PFNVBOXNETCFG_ENUMERATION_CALLBACK pfnCallback, PVOID pContext)
606{
607 WIN32_FIND_DATA Data;
608 memset(&Data, 0, sizeof(Data));
609 HRESULT hr = S_OK;
610
611 HANDLE hEnum = FindFirstFile(pPattern,&Data);
612 if (hEnum != INVALID_HANDLE_VALUE)
613 {
614
615 do
616 {
617 if (!pfnCallback(Data.cFileName, pContext))
618 {
619 break;
620 }
621
622 /* next iteration */
623 memset(&Data, 0, sizeof(Data));
624 BOOL bNext = FindNextFile(hEnum,&Data);
625 if (!bNext)
626 {
627 DWORD dwErr = GetLastError();
628 if (dwErr != ERROR_NO_MORE_FILES)
629 {
630 NonStandardLogRelCrap((__FUNCTION__": FindNextFile fail dwErr=%ld\n", dwErr));
631 NonStandardAssert(0);
632 hr = HRESULT_FROM_WIN32(dwErr);
633 }
634 break;
635 }
636 }while (true);
637 FindClose(hEnum);
638 }
639 else
640 {
641 DWORD dwErr = GetLastError();
642 if (dwErr != ERROR_NO_MORE_FILES)
643 {
644 NonStandardLogRelCrap((__FUNCTION__": FindFirstFile fail dwErr=%ld\n", dwErr));
645 NonStandardAssert(0);
646 hr = HRESULT_FROM_WIN32(dwErr);
647 }
648 }
649
650 return hr;
651}
652
653static bool vboxDrvCfgInfEnumerationCallback(LPCWSTR lpszFileName, PVOID pCtxt)
654{
655 PINFENUM_CONTEXT pContext = (PINFENUM_CONTEXT)pCtxt;
656 DWORD dwErr;
657 NonStandardLogRelCrap((__FUNCTION__": lpszFileName (%S)\n", lpszFileName));
658 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.lpszClassName = (%S)\n", pContext->InfInfo.lpszClassName));
659 HINF hInf = SetupOpenInfFileW(lpszFileName, pContext->InfInfo.lpszClassName, INF_STYLE_WIN4, NULL /*__in PUINT ErrorLine */);
660 if (hInf == INVALID_HANDLE_VALUE)
661 {
662 dwErr = GetLastError();
663// NonStandardAssert(dwErr == ERROR_CLASS_MISMATCH);
664 if (dwErr != ERROR_CLASS_MISMATCH)
665 {
666 NonStandardLogCrap((__FUNCTION__ ": SetupOpenInfFileW err dwErr=%ld\n", dwErr));
667 }
668 else
669 {
670 NonStandardLogCrap((__FUNCTION__ ": dwErr == ERROR_CLASS_MISMATCH\n"));
671 }
672 return true;
673 }
674
675 LPWSTR lpszPnPId;
676 HRESULT hr = vboxDrvCfgInfQueryFirstPnPId(hInf, &lpszPnPId);
677 NonStandardLogRelCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId returned lpszPnPId = (%S)\n", lpszPnPId));
678 NonStandardLogRelCrap((__FUNCTION__ ": pContext->InfInfo.lpszPnPId = (%S)\n", pContext->InfInfo.lpszPnPId));
679 if (hr == S_OK)
680 {
681 if (!wcsicmp(pContext->InfInfo.lpszPnPId, lpszPnPId))
682 {
683 if (!SetupUninstallOEMInfW(lpszFileName,
684 pContext->Flags, /*DWORD Flags could be SUOI_FORCEDELETE */
685 NULL /*__in PVOID Reserved == NULL */
686 ))
687 {
688 dwErr = GetLastError();
689 NonStandardLogRelCrap((__FUNCTION__ ": SetupUninstallOEMInf failed for file (%S), dwErr=%ld\n", lpszFileName, dwErr));
690 NonStandardAssert(0);
691 hr = HRESULT_FROM_WIN32( dwErr );
692 }
693 }
694
695 free(lpszPnPId);
696 }
697 else
698 {
699 NonStandardLogCrap((__FUNCTION__ ": vboxDrvCfgInfQueryFirstPnPId failed, hr=0x%x\n", hr));
700 }
701
702 SetupCloseInfFile(hInf);
703
704 return true;
705}
706
707VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllF(LPCWSTR lpszClassName, LPCWSTR lpszPnPId, DWORD Flags)
708{
709 static WCHAR const s_wszFilter[] = L"\\inf\\oem*.inf";
710 HRESULT hr;
711 WCHAR wszInfDirPath[MAX_PATH];
712 UINT cwcInput = RT_ELEMENTS(wszInfDirPath) - RT_ELEMENTS(s_wszFilter);
713 UINT cwcWindows = GetSystemWindowsDirectory(wszInfDirPath, cwcInput);
714 if (cwcWindows > 0 && cwcWindows < cwcInput)
715 {
716 wcscpy(&wszInfDirPath[cwcWindows], s_wszFilter);
717
718 INFENUM_CONTEXT Context;
719 Context.InfInfo.lpszClassName = lpszClassName;
720 Context.InfInfo.lpszPnPId = lpszPnPId;
721 Context.Flags = Flags;
722 Context.hr = S_OK;
723 NonStandardLogRelCrap((__FUNCTION__": Calling vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context)"));
724 hr = vboxDrvCfgEnumFiles(wszInfDirPath, vboxDrvCfgInfEnumerationCallback, &Context);
725 NonStandardAssert(hr == S_OK);
726 if (hr == S_OK)
727 {
728 hr = Context.hr;
729 }
730 else
731 {
732 NonStandardLogRelCrap((__FUNCTION__": vboxDrvCfgEnumFiles failed, hr=0x%x\n", hr));
733 }
734 }
735 else
736 {
737 NonStandardLogRelCrap((__FUNCTION__": GetSystemWindowsDirectory failed, cwcWindows=%u lasterr=%u\n", cwcWindows, GetLastError()));
738 NonStandardAssertFailed();
739 hr = E_FAIL;
740 }
741
742 return hr;
743
744}
745
746/* time intervals in milliseconds */
747/* max time to wait for the service to startup */
748#define VBOXDRVCFG_SVC_WAITSTART_TIME 10000
749/* sleep time before service status polls */
750#define VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD 100
751/* number of service start polls */
752#define VBOXDRVCFG_SVC_WAITSTART_RETRIES (VBOXDRVCFG_SVC_WAITSTART_TIME/VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD)
753
754VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgSvcStart(LPCWSTR lpszSvcName)
755{
756 SC_HANDLE hMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
757 if (hMgr == NULL)
758 {
759 DWORD dwErr = GetLastError();
760 NonStandardLogRelCrap((__FUNCTION__": OpenSCManager failed, dwErr=%ld\n", dwErr));
761 return HRESULT_FROM_WIN32(dwErr);
762 }
763
764 HRESULT hr = S_OK;
765 SC_HANDLE hSvc = OpenServiceW(hMgr, lpszSvcName, SERVICE_QUERY_STATUS | SERVICE_START);
766 if (hSvc)
767 {
768 do
769 {
770 SERVICE_STATUS Status;
771 BOOL fRc = QueryServiceStatus(hSvc, &Status);
772 if (!fRc)
773 {
774 DWORD dwErr = GetLastError();
775 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
776 hr = HRESULT_FROM_WIN32(dwErr);
777 break;
778 }
779
780 if (Status.dwCurrentState != SERVICE_RUNNING && Status.dwCurrentState != SERVICE_START_PENDING)
781 {
782 NonStandardLogRelCrap(("Starting service (%S)\n", lpszSvcName));
783
784 fRc = StartService(hSvc, 0, NULL);
785 if (!fRc)
786 {
787 DWORD dwErr = GetLastError();
788 NonStandardLogRelCrap((__FUNCTION__": StartService failed dwErr=%ld\n", dwErr));
789 hr = HRESULT_FROM_WIN32(dwErr);
790 break;
791 }
792 }
793
794 fRc = QueryServiceStatus(hSvc, &Status);
795 if (!fRc)
796 {
797 DWORD dwErr = GetLastError();
798 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
799 hr = HRESULT_FROM_WIN32(dwErr);
800 break;
801 }
802
803 if (Status.dwCurrentState == SERVICE_START_PENDING)
804 {
805 for (int i = 0; i < VBOXDRVCFG_SVC_WAITSTART_RETRIES; ++i)
806 {
807 Sleep(VBOXDRVCFG_SVC_WAITSTART_TIME_PERIOD);
808 fRc = QueryServiceStatus(hSvc, &Status);
809 if (!fRc)
810 {
811 DWORD dwErr = GetLastError();
812 NonStandardLogRelCrap((__FUNCTION__": QueryServiceStatus failed dwErr=%ld\n", dwErr));
813 hr = HRESULT_FROM_WIN32(dwErr);
814 break;
815 }
816 else if (Status.dwCurrentState != SERVICE_START_PENDING)
817 break;
818 }
819 }
820
821 if (hr != S_OK || Status.dwCurrentState != SERVICE_RUNNING)
822 {
823 NonStandardLogRelCrap((__FUNCTION__": Failed to start the service\n"));
824 hr = E_FAIL;
825 break;
826 }
827
828 } while (0);
829
830 CloseServiceHandle(hSvc);
831 }
832 else
833 {
834 DWORD dwErr = GetLastError();
835 NonStandardLogRelCrap((__FUNCTION__": OpenServiceW failed, dwErr=%ld\n", dwErr));
836 hr = HRESULT_FROM_WIN32(dwErr);
837 }
838
839 CloseServiceHandle(hMgr);
840
841 return hr;
842}
843
844
845HRESULT VBoxDrvCfgDrvUpdate(LPCWSTR pcszwHwId, LPCWSTR pcsxwInf, BOOL *pbRebootRequired)
846{
847 if (pbRebootRequired)
848 *pbRebootRequired = FALSE;
849 BOOL bRebootRequired = FALSE;
850 WCHAR InfFullPath[MAX_PATH];
851 DWORD dwChars = GetFullPathNameW(pcsxwInf,
852 sizeof (InfFullPath) / sizeof (InfFullPath[0]),
853 InfFullPath,
854 NULL /* LPTSTR *lpFilePart */
855 );
856 if (!dwChars || dwChars >= MAX_PATH)
857 {
858 NonStandardLogCrap(("GetFullPathNameW failed, dwErr=%ld, dwChars=%ld\n",
859 GetLastError(), dwChars));
860 return E_INVALIDARG;
861 }
862
863
864 if (!UpdateDriverForPlugAndPlayDevicesW(NULL, /* HWND hwndParent */
865 pcszwHwId,
866 InfFullPath,
867 INSTALLFLAG_FORCE,
868 &bRebootRequired))
869 {
870 DWORD dwErr = GetLastError();
871 NonStandardLogCrap(("UpdateDriverForPlugAndPlayDevicesW failed, dwErr=%ld\n",
872 dwErr));
873 return HRESULT_FROM_WIN32(dwErr);
874 }
875
876
877 if (bRebootRequired)
878 NonStandardLogCrap(("!!Driver Update: REBOOT REQUIRED!!\n", GetLastError(), dwChars));
879
880 if (pbRebootRequired)
881 *pbRebootRequired = bRebootRequired;
882
883 return S_OK;
884}
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