VirtualBox

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

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

spaces

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