VirtualBox

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

Last change on this file since 50837 was 44529, checked in by vboxsync, 12 years ago

header (C) fixes

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