VirtualBox

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

Last change on this file since 67787 was 63311, checked in by vboxsync, 8 years ago

Use shlobj.h wrapper.

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