VirtualBox

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

Last change on this file since 60034 was 60034, checked in by vboxsync, 9 years ago

Support: logging fix

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