VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp@ 38791

Last change on this file since 38791 was 38791, checked in by vboxsync, 13 years ago

VBoxInstallHelper.cpp,++: Clean up TCHAR/WCHAR mess - just use WCHAR, forget TCHAR.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.1 KB
Line 
1/* $Id: VBoxNetCfg.cpp 38791 2011-09-19 13:21:31Z vboxsync $ */
2/** @file
3 * VBoxNetCfg.cpp - Network Configuration API.
4 */
5/*
6 * Copyright (C) 2011 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/VBoxNetCfg-win.h"
17#include "VBox/VBoxDrvCfg-win.h"
18
19#define _WIN32_DCOM
20
21#include <iphlpapi.h>
22
23#include <devguid.h>
24#include <stdio.h>
25#include <regstr.h>
26#include <shlobj.h>
27#include <cfgmgr32.h>
28#include <tchar.h>
29#include <objbase.h>
30
31#include <crtdbg.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <Wbemidl.h>
36#include <comdef.h>
37
38
39#ifndef Assert /** @todo r=bird: where would this be defined? */
40//# ifdef DEBUG
41//# define Assert(_expr) assert(_expr)
42//# else
43//# define Assert(_expr) do{ }while (0)
44//# endif
45# define Assert _ASSERT
46# define AssertMsg(expr, msg) do{}while (0)
47#endif
48static LOG_ROUTINE g_Logger = NULL;
49
50static VOID DoLogging(LPCSTR szString, ...);
51#define NonStandardLog DoLogging
52#define NonStandardLogFlow(x) DoLogging x
53
54#define DbgLog /** @todo r=bird: What does this do? */
55
56#define VBOX_NETCFG_LOCK_TIME_OUT 5000 /** @todo r=bird: What does this do? */
57
58
59static HRESULT vboxNetCfgWinINetCfgLock(IN INetCfg *pNetCfg,
60 IN LPCWSTR pszwClientDescription,
61 IN DWORD cmsTimeout,
62 OUT LPWSTR *ppszwClientDescription)
63{
64 INetCfgLock *pLock;
65 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
66 if (FAILED(hr))
67 {
68 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
69 return hr;
70 }
71
72 hr = pLock->AcquireWriteLock(cmsTimeout, pszwClientDescription, ppszwClientDescription);
73 if (hr == S_FALSE)
74 {
75 NonStandardLogFlow(("Write lock busy\n"));
76 }
77 else if (FAILED(hr))
78 {
79 NonStandardLogFlow(("AcquireWriteLock failed, hr (0x%x)\n", hr));
80 }
81
82 pLock->Release();
83 return hr;
84}
85
86static HRESULT vboxNetCfgWinINetCfgUnlock(IN INetCfg *pNetCfg)
87{
88 INetCfgLock *pLock;
89 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
90 if (FAILED(hr))
91 {
92 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
93 return hr;
94 }
95
96 hr = pLock->ReleaseWriteLock();
97 if (FAILED(hr))
98 NonStandardLogFlow(("ReleaseWriteLock failed, hr (0x%x)\n", hr));
99
100 pLock->Release();
101 return hr;
102}
103
104VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinQueryINetCfg(OUT INetCfg **ppNetCfg,
105 IN BOOL fGetWriteLock,
106 IN LPCWSTR pszwClientDescription,
107 IN DWORD cmsTimeout,
108 OUT LPWSTR *ppszwClientDescription)
109{
110 INetCfg *pNetCfg;
111 HRESULT hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNetCfg);
112 if (FAILED(hr))
113 {
114 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
115 return hr;
116 }
117
118 if (fGetWriteLock)
119 {
120 hr = vboxNetCfgWinINetCfgLock(pNetCfg, pszwClientDescription, cmsTimeout, ppszwClientDescription);
121 if (hr == S_FALSE)
122 {
123 NonStandardLogFlow(("Write lock is busy\n", hr));
124 hr = NETCFG_E_NO_WRITE_LOCK;
125 }
126 }
127
128 if (SUCCEEDED(hr))
129 {
130 hr = pNetCfg->Initialize(NULL);
131 if (SUCCEEDED(hr))
132 {
133 *ppNetCfg = pNetCfg;
134 return S_OK;
135 }
136 else
137 NonStandardLogFlow(("Initialize failed, hr (0x%x)\n", hr));
138 }
139
140 pNetCfg->Release();
141 return hr;
142}
143
144VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinReleaseINetCfg(IN INetCfg *pNetCfg, IN BOOL fHasWriteLock)
145{
146 HRESULT hr = pNetCfg->Uninitialize();
147 if (FAILED(hr))
148 {
149 NonStandardLogFlow(("Uninitialize failed, hr (0x%x)\n", hr));
150 return hr;
151 }
152
153 if (fHasWriteLock)
154 {
155 hr = vboxNetCfgWinINetCfgUnlock(pNetCfg);
156 if (FAILED(hr))
157 NonStandardLogFlow(("vboxNetCfgWinINetCfgUnlock failed, hr (0x%x)\n", hr));
158 }
159
160 pNetCfg->Release();
161 return hr;
162}
163
164static HRESULT vboxNetCfgWinGetComponentByGuidEnum(IEnumNetCfgComponent *pEnumNcc,
165 IN const GUID *pGuid,
166 OUT INetCfgComponent **ppNcc)
167{
168 HRESULT hr = pEnumNcc->Reset();
169 if (FAILED(hr))
170 {
171 NonStandardLogFlow(("Reset failed, hr (0x%x)\n", hr));
172 return hr;
173 }
174
175 INetCfgComponent *pNcc;
176 while ((hr = pEnumNcc->Next(1, &pNcc, NULL)) == S_OK)
177 {
178 ULONG uComponentStatus;
179 hr = pNcc->GetDeviceStatus(&uComponentStatus);
180 if (SUCCEEDED(hr))
181 {
182 if (uComponentStatus == 0)
183 {
184 GUID NccGuid;
185 hr = pNcc->GetInstanceGuid(&NccGuid);
186
187 if (SUCCEEDED(hr))
188 {
189 if (NccGuid == *pGuid)
190 {
191 /* found the needed device */
192 *ppNcc = pNcc;
193 break;
194 }
195 }
196 else
197 NonStandardLogFlow(("GetInstanceGuid failed, hr (0x%x)\n", hr));
198 }
199 }
200
201 pNcc->Release();
202 }
203 return hr;
204}
205
206VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc,
207 IN const GUID *pguidClass,
208 IN const GUID * pComponentGuid,
209 OUT INetCfgComponent **ppncc)
210{
211 IEnumNetCfgComponent *pEnumNcc;
212 HRESULT hr = pNc->EnumComponents(pguidClass, &pEnumNcc);
213
214 if (SUCCEEDED(hr))
215 {
216 hr = vboxNetCfgWinGetComponentByGuidEnum(pEnumNcc, pComponentGuid, ppncc);
217 if (hr == S_FALSE)
218 {
219 NonStandardLogFlow(("Component not found\n"));
220 }
221 else if (FAILED(hr))
222 {
223 NonStandardLogFlow(("vboxNetCfgWinGetComponentByGuidEnum failed, hr (0x%x)\n", hr));
224 }
225 pEnumNcc->Release();
226 }
227 else
228 NonStandardLogFlow(("EnumComponents failed, hr (0x%x)\n", hr));
229 return hr;
230}
231
232static HRESULT vboxNetCfgWinQueryInstaller(IN INetCfg *pNetCfg, IN const GUID *pguidClass, INetCfgClassSetup **ppSetup)
233{
234 HRESULT hr = pNetCfg->QueryNetCfgClass(pguidClass, IID_INetCfgClassSetup, (void**)ppSetup);
235 if (FAILED(hr))
236 NonStandardLogFlow(("QueryNetCfgClass failed, hr (0x%x)\n", hr));
237 return hr;
238}
239
240VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
241 OUT INetCfgComponent **ppComponent)
242{
243 INetCfgClassSetup *pSetup;
244 HRESULT hr = vboxNetCfgWinQueryInstaller(pNetCfg, pguidClass, &pSetup);
245 if (FAILED(hr))
246 {
247 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
248 return hr;
249 }
250
251 OBO_TOKEN Token;
252 ZeroMemory(&Token, sizeof (Token));
253 Token.Type = OBO_USER;
254
255 hr = pSetup->Install(pszwComponentId, &Token,
256 0, /* IN DWORD dwSetupFlags */
257 0, /* IN DWORD dwUpgradeFromBuildNo */
258 NULL, /* IN LPCWSTR pszwAnswerFile */
259 NULL, /* IN LPCWSTR pszwAnswerSections */
260 ppComponent);
261 if (SUCCEEDED(hr))
262 {
263 /* ignore the apply failure */
264 HRESULT tmpHr = pNetCfg->Apply();
265 Assert(tmpHr == S_OK);
266 if (tmpHr != S_OK)
267 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", tmpHr));
268 }
269 else
270 NonStandardLogFlow(("Install failed, hr (0x%x)\n", hr));
271
272 pSetup->Release();
273 return hr;
274}
275
276/** @todo r=bird: This function is not in the header file, why is it
277 * exported? */
278VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallInfAndComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
279 IN LPCWSTR const *apInfPaths, IN UINT cInfPaths,
280 OUT INetCfgComponent **ppComponent)
281{
282 HRESULT hr = S_OK;
283 UINT i = 0;
284
285 NonStandardLogFlow(("Installing %u INF files ...\n", cInfPaths));
286
287 for (; i < cInfPaths; i++)
288 {
289 NonStandardLogFlow(("Installing INF file \"%ws\" ...\n", apInfPaths[i]));
290 hr = VBoxDrvCfgInfInstall(apInfPaths[i]);
291 if (FAILED(hr))
292 {
293 NonStandardLogFlow(("VBoxNetCfgWinInfInstall failed, hr (0x%x)\n", hr));
294 break;
295 }
296 }
297
298 if (SUCCEEDED(hr))
299 {
300 hr = VBoxNetCfgWinInstallComponent(pNetCfg, pszwComponentId, pguidClass, ppComponent);
301 if (FAILED(hr))
302 NonStandardLogFlow(("VBoxNetCfgWinInstallComponent failed, hr (0x%x)\n", hr));
303 }
304
305 if (FAILED(hr))
306 {
307 for (UINT j = i - 1; j != 0; j--)
308 VBoxDrvCfgInfUninstall(apInfPaths[j], 0);
309 }
310
311 return hr;
312}
313
314VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUninstallComponent(IN INetCfg *pNetCfg, IN INetCfgComponent *pComponent)
315{
316 GUID GuidClass;
317 HRESULT hr = pComponent->GetClassGuid(&GuidClass);
318 if (FAILED(hr))
319 {
320 NonStandardLogFlow(("GetClassGuid failed, hr (0x%x)\n", hr));
321 return hr;
322 }
323
324 INetCfgClassSetup *pSetup = NULL;
325 hr = vboxNetCfgWinQueryInstaller(pNetCfg, &GuidClass, &pSetup);
326 if (FAILED(hr))
327 {
328 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
329 return hr;
330 }
331
332 OBO_TOKEN Token;
333 ZeroMemory(&Token, sizeof(Token));
334 Token.Type = OBO_USER;
335
336 hr = pSetup->DeInstall(pComponent, &Token, NULL /* OUT LPWSTR *pmszwRefs */);
337 if (SUCCEEDED(hr))
338 {
339 hr = pNetCfg->Apply();
340 if (FAILED(hr))
341 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", hr));
342 }
343 else
344 NonStandardLogFlow(("DeInstall failed, hr (0x%x)\n", hr));
345
346 if (pSetup)
347 pSetup->Release();
348 return hr;
349}
350
351typedef BOOL (*VBOXNETCFGWIN_NETCFGENUM_CALLBACK) (IN INetCfg *pNetCfg, IN INetCfgComponent *pNetCfgComponent, PVOID pContext);
352
353static HRESULT vboxNetCfgWinEnumNetCfgComponents(IN INetCfg *pNetCfg,
354 IN const GUID *pguidClass,
355 VBOXNETCFGWIN_NETCFGENUM_CALLBACK callback,
356 PVOID pContext)
357{
358 IEnumNetCfgComponent *pEnumComponent;
359 HRESULT hr = pNetCfg->EnumComponents(pguidClass, &pEnumComponent);
360 if (SUCCEEDED(hr))
361 {
362 INetCfgComponent *pNetCfgComponent;
363 hr = pEnumComponent->Reset();
364 do
365 {
366 hr = pEnumComponent->Next(1, &pNetCfgComponent, NULL);
367 if (hr == S_OK)
368 {
369// ULONG uComponentStatus;
370// hr = pNcc->GetDeviceStatus(&uComponentStatus);
371// if (SUCCEEDED(hr))
372 BOOL fResult = FALSE;
373 if (pNetCfgComponent)
374 {
375 if (pContext)
376 fResult = callback(pNetCfg, pNetCfgComponent, pContext);
377 pNetCfgComponent->Release();
378 }
379
380 if (!fResult)
381 break;
382 }
383 else
384 {
385 if (hr == S_FALSE)
386 {
387 hr = S_OK;
388 }
389 else
390 NonStandardLogFlow(("Next failed, hr (0x%x)\n", hr));
391 break;
392 }
393 } while (true);
394 pEnumComponent->Release();
395 }
396 return hr;
397}
398
399static BOOL vboxNetCfgWinRemoveAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
400{
401 HRESULT hr = S_OK;
402 SP_REMOVEDEVICE_PARAMS rmdParams;
403
404 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
405 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
406 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
407 rmdParams.HwProfile = 0;
408
409 if (SetupDiSetClassInstallParams(hDevInfo,pDev,&rmdParams.ClassInstallHeader,sizeof(rmdParams)))
410 {
411 if (SetupDiSetSelectedDevice (hDevInfo, pDev))
412 {
413 if (SetupDiCallClassInstaller(DIF_REMOVE,hDevInfo,pDev))
414 {
415 SP_DEVINSTALL_PARAMS devParams;
416 devParams.cbSize = sizeof(devParams);
417 if (SetupDiGetDeviceInstallParams(hDevInfo,pDev,&devParams))
418 {
419 if (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))
420 {
421 hr = S_FALSE;
422 NonStandardLog(("!!!REBOOT REQUIRED!!!\n"));
423 }
424 }
425 }
426 else
427 {
428 DWORD dwErr = GetLastError();
429 NonStandardLogFlow(("SetupDiCallClassInstaller failed with %ld\n", dwErr));
430 hr = HRESULT_FROM_WIN32(dwErr);
431 }
432 }
433 else
434 {
435 DWORD dwErr = GetLastError();
436 NonStandardLogFlow(("SetupDiSetSelectedDevice failed with %ld\n", dwErr));
437 hr = HRESULT_FROM_WIN32(dwErr);
438 }
439 }
440 else
441 {
442 DWORD dwErr = GetLastError();
443 NonStandardLogFlow(("SetupDiSetClassInstallParams failed with %ld\n", dwErr));
444 hr = HRESULT_FROM_WIN32(dwErr);
445 }
446
447 return TRUE;
448}
449
450typedef BOOL (*VBOXNETCFGWIN_NETENUM_CALLBACK) (HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext);
451VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPCWSTR pPnPId, VBOXNETCFGWIN_NETENUM_CALLBACK callback, PVOID pContext)
452{
453 DWORD winEr;
454 HRESULT hr = S_OK;
455
456 HDEVINFO hDevInfo = SetupDiGetClassDevsExW(
457 &GUID_DEVCLASS_NET,
458 NULL, /* IN PCTSTR Enumerator, OPTIONAL*/
459 NULL, /*IN HWND hwndParent, OPTIONAL*/
460 DIGCF_PRESENT, /*IN DWORD Flags,*/
461 NULL, /*IN HDEVINFO DeviceInfoSet, OPTIONAL*/
462 NULL, /*IN PCTSTR MachineName, OPTIONAL*/
463 NULL /*IN PVOID Reserved*/
464 );
465 if (hDevInfo != INVALID_HANDLE_VALUE)
466 {
467 DWORD iDev = 0;
468 SP_DEVINFO_DATA Dev;
469 PBYTE pBuffer = NULL;
470 DWORD cbBuffer = 0;
471 DWORD cbRequired = 0;
472 BOOL bEnumCompleted;
473 size_t cPnPId = wcslen(pPnPId);
474
475 Dev.cbSize = sizeof(Dev);
476
477 for (; bEnumCompleted = SetupDiEnumDeviceInfo(hDevInfo, iDev, &Dev); iDev++)
478 {
479 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
480 SPDRP_HARDWAREID, /* IN DWORD Property,*/
481 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
482 pBuffer, /*OUT PBYTE PropertyBuffer,*/
483 cbBuffer, /* IN DWORD PropertyBufferSize,*/
484 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
485 ))
486 {
487 winEr = GetLastError();
488 if (winEr != ERROR_INSUFFICIENT_BUFFER)
489 {
490 NonStandardLogFlow(("SetupDiGetDeviceRegistryPropertyW (1) failed winErr(%d)\n", winEr));
491 hr = HRESULT_FROM_WIN32(winEr);
492 break;
493 }
494
495 if (pBuffer)
496 free(pBuffer);
497
498 pBuffer = (PBYTE)malloc(cbRequired);
499 cbBuffer = cbRequired;
500
501 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
502 SPDRP_HARDWAREID, /* IN DWORD Property,*/
503 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
504 pBuffer, /*OUT PBYTE PropertyBuffer,*/
505 cbBuffer, /* IN DWORD PropertyBufferSize,*/
506 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
507 ))
508 {
509 winEr = GetLastError();
510 NonStandardLogFlow(("SetupDiGetDeviceRegistryPropertyW (2) failed winErr(%d)\n", winEr));
511 hr = HRESULT_FROM_WIN32(winEr);
512 break;
513 }
514 }
515
516 PWCHAR pCurId = (PWCHAR)pBuffer;
517 size_t cCurId = wcslen(pCurId);
518 if (cCurId >= cPnPId)
519 {
520 pCurId += cCurId - cPnPId;
521 if (!wcsnicmp(pCurId, pPnPId, cPnPId))
522 {
523
524 if (!callback(hDevInfo,&Dev,pContext))
525 break;
526 }
527 }
528
529 }
530
531 if (pBuffer)
532 free(pBuffer);
533
534 if (bEnumCompleted)
535 {
536 winEr = GetLastError();
537 hr = winEr == ERROR_NO_MORE_ITEMS ? S_OK : HRESULT_FROM_WIN32(winEr);
538 }
539
540 SetupDiDestroyDeviceInfoList(hDevInfo);
541 }
542 else
543 {
544 DWORD winEr = GetLastError();
545 NonStandardLogFlow(("SetupDiGetClassDevsExW failed winErr(%d)\n", winEr));
546 hr = HRESULT_FROM_WIN32(winEr);
547 }
548
549 return hr;
550}
551
552VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(IN LPCWSTR lpszPnPId)
553{
554 return VBoxNetCfgWinEnumNetDevices(lpszPnPId, vboxNetCfgWinRemoveAllNetDevicesOfIdCallback, NULL);
555}
556
557/*
558 * logging
559 */
560static VOID DoLogging(LPCSTR szString, ...)
561{
562 LOG_ROUTINE pRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
563 if (pRoutine)
564 {
565 char szBuffer[4096] = {0};
566 va_list pArgList;
567 va_start(pArgList, szString);
568 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, pArgList);
569 va_end(pArgList);
570
571 pRoutine(szBuffer);
572 }
573}
574
575VBOXNETCFGWIN_DECL(VOID) VBoxNetCfgWinSetLogging(IN LOG_ROUTINE pfnLog)
576{
577 *((void * volatile *)&g_Logger) = pfnLog;
578}
579
580/*
581 * IP configuration API
582 */
583/* network settings config */
584/**
585 * Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
586 */
587template <class C>
588class ComStrongRef
589{
590protected:
591
592 static void addref (C *p) { p->AddRef(); }
593 static void release (C *p) { p->Release(); }
594};
595
596
597/**
598 * Base template for smart COM pointers. Not intended to be used directly.
599 */
600template <class C, template <class> class RefOps = ComStrongRef>
601class ComPtrBase : protected RefOps <C>
602{
603public:
604
605 /* special template to disable AddRef()/Release() */
606 template <class I>
607 class NoAddRefRelease : public I
608 {
609 private:
610#if !defined (VBOX_WITH_XPCOM)
611 STDMETHOD_(ULONG, AddRef)() = 0;
612 STDMETHOD_(ULONG, Release)() = 0;
613#else /* !defined (VBOX_WITH_XPCOM) */
614 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
615 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
616#endif /* !defined (VBOX_WITH_XPCOM) */
617 };
618
619protected:
620
621 ComPtrBase () : p (NULL) {}
622 ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
623 ComPtrBase (C *that_p) : p (that_p) { addref(); }
624
625 ~ComPtrBase() { release(); }
626
627 ComPtrBase &operator= (const ComPtrBase &that)
628 {
629 safe_assign (that.p);
630 return *this;
631 }
632
633 ComPtrBase &operator= (C *that_p)
634 {
635 safe_assign (that_p);
636 return *this;
637 }
638
639public:
640
641 void setNull()
642 {
643 release();
644 p = NULL;
645 }
646
647 bool isNull() const
648 {
649 return (p == NULL);
650 }
651
652 bool operator! () const { return isNull(); }
653
654 bool operator< (C* that_p) const { return p < that_p; }
655 bool operator== (C* that_p) const { return p == that_p; }
656
657 template <class I>
658 bool equalsTo (I *aThat) const
659 {
660 return ComPtrEquals (p, aThat);
661 }
662
663 template <class OC>
664 bool equalsTo (const ComPtrBase <OC> &oc) const
665 {
666 return equalsTo ((OC *) oc);
667 }
668
669 /** Intended to pass instances as in parameters to interface methods */
670 operator C* () const { return p; }
671
672 /**
673 * Dereferences the instance (redirects the -> operator to the managed
674 * pointer).
675 */
676 NoAddRefRelease <C> *operator-> () const
677 {
678 AssertMsg (p, ("Managed pointer must not be null\n"));
679 return (NoAddRefRelease <C> *) p;
680 }
681
682 template <class I>
683 HRESULT queryInterfaceTo (I **pp) const
684 {
685 if (pp)
686 {
687 if (p)
688 {
689 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
690 }
691 else
692 {
693 *pp = NULL;
694 return S_OK;
695 }
696 }
697
698 return E_INVALIDARG;
699 }
700
701 /** Intended to pass instances as out parameters to interface methods */
702 C **asOutParam()
703 {
704 setNull();
705 return &p;
706 }
707
708private:
709
710 void addref()
711 {
712 if (p)
713 RefOps <C>::addref (p);
714 }
715
716 void release()
717 {
718 if (p)
719 RefOps <C>::release (p);
720 }
721
722 void safe_assign (C *that_p)
723 {
724 /* be aware of self-assignment */
725 if (that_p)
726 RefOps <C>::addref (that_p);
727 release();
728 p = that_p;
729 }
730
731 C *p;
732};
733
734/**
735 * Smart COM pointer wrapper that automatically manages refcounting of
736 * interface pointers.
737 *
738 * @param I COM interface class
739 */
740template <class I, template <class> class RefOps = ComStrongRef>
741class ComPtr : public ComPtrBase <I, RefOps>
742{
743 typedef ComPtrBase <I, RefOps> Base;
744
745public:
746
747 ComPtr () : Base() {}
748 ComPtr (const ComPtr &that) : Base(that) {}
749 ComPtr &operator= (const ComPtr &that)
750 {
751 Base::operator= (that);
752 return *this;
753 }
754
755 template <class OI>
756 ComPtr (OI *that_p) : Base () { operator= (that_p); }
757
758 /* specialization for I */
759 ComPtr (I *that_p) : Base (that_p) {}
760
761 template <class OC>
762 ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
763
764 template <class OI>
765 ComPtr &operator= (OI *that_p)
766 {
767 if (that_p)
768 that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
769 else
770 Base::setNull();
771 return *this;
772 }
773
774 /* specialization for I */
775 ComPtr &operator=(I *that_p)
776 {
777 Base::operator= (that_p);
778 return *this;
779 }
780
781 template <class OC>
782 ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
783 {
784 return operator= ((OC *) oc);
785 }
786};
787
788static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const GUID * pGuid, IWbemClassObject **pAdapterConfig)
789{
790 HRESULT hr;
791 WCHAR aQueryString[256];
792 WCHAR GuidString[50];
793
794 int length = StringFromGUID2(*pGuid, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
795 if (length)
796 {
797 swprintf(aQueryString, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", GuidString);
798 IEnumWbemClassObject* pEnumerator = NULL;
799 hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(aQueryString), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
800 if (SUCCEEDED(hr))
801 {
802 IWbemClassObject *pclsObj;
803 ULONG uReturn = 0;
804
805 if (pEnumerator)
806 {
807 HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
808
809 if (SUCCEEDED(hr))
810 {
811 if (uReturn)
812 {
813 pEnumerator->Release();
814 *pAdapterConfig = pclsObj;
815 hr = S_OK;
816 return hr;
817 }
818 else
819 {
820 hr = S_FALSE;
821 }
822 }
823
824 pEnumerator->Release();
825 }
826 }
827 else
828 NonStandardLogFlow(("ExecQuery failed (0x%x)\n", hr));
829 }
830 else
831 {
832 DWORD winEr = GetLastError();
833 NonStandardLogFlow(("StringFromGUID2 failed winEr (%d)\n", winEr));
834 hr = HRESULT_FROM_WIN32( winEr );
835 }
836
837 return hr;
838}
839
840static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
841{
842 VARIANT vtServiceName;
843 BOOL bIsHostOnly = FALSE;
844 VariantInit(&vtServiceName);
845
846 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0, &vtServiceName, 0, 0);
847 if (SUCCEEDED(hr))
848 {
849 *pbIsHostOnly = (bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp"));
850
851 VariantClear(&vtServiceName);
852 }
853
854 return hr;
855}
856
857static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
858{
859 VARIANT vtIp;
860 HRESULT hr;
861 VariantInit(&vtIp);
862
863 *pIpv4 = 0;
864 *pMaskv4 = 0;
865
866 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
867 if (SUCCEEDED(hr))
868 {
869 if (vtIp.vt == (VT_ARRAY | VT_BSTR))
870 {
871 VARIANT vtMask;
872 VariantInit(&vtMask);
873 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
874 if (SUCCEEDED(hr))
875 {
876 if (vtMask.vt == (VT_ARRAY | VT_BSTR))
877 {
878 SAFEARRAY * pIpArray = vtIp.parray;
879 SAFEARRAY * pMaskArray = vtMask.parray;
880 if (pIpArray && pMaskArray)
881 {
882 BSTR pCurIp;
883 BSTR pCurMask;
884 for (LONG i = 0;
885 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
886 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
887 i++)
888 {
889 bstr_t ip(pCurIp);
890
891 ULONG Ipv4 = inet_addr((char*)(ip));
892 if (Ipv4 != INADDR_NONE)
893 {
894 *pIpv4 = Ipv4;
895 bstr_t mask(pCurMask);
896 *pMaskv4 = inet_addr((char*)(mask));
897 break;
898 }
899 }
900 }
901 }
902 else
903 {
904 *pIpv4 = 0;
905 *pMaskv4 = 0;
906 }
907
908 VariantClear(&vtMask);
909 }
910 }
911 else
912 {
913 *pIpv4 = 0;
914 *pMaskv4 = 0;
915 }
916
917 VariantClear(&vtIp);
918 }
919
920 return hr;
921}
922
923
924static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
925{
926 VARIANT vtIp;
927 HRESULT hr;
928 VariantInit(&vtIp);
929
930 *pFound = false;
931
932 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
933 if (SUCCEEDED(hr))
934 {
935 VARIANT vtMask;
936 VariantInit(&vtMask);
937 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
938 if (SUCCEEDED(hr))
939 {
940 SAFEARRAY * pIpArray = vtIp.parray;
941 SAFEARRAY * pMaskArray = vtMask.parray;
942 if (pIpArray && pMaskArray)
943 {
944 BSTR pIp, pMask;
945 for (LONG k = 0;
946 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
947 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
948 k++)
949 {
950 BSTR pCurIp;
951 BSTR pCurMask;
952 for (LONG i = 0;
953 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
954 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
955 i++)
956 {
957 if (!wcsicmp(pCurIp, pIp))
958 {
959 if (!wcsicmp(pCurMask, pMask))
960 *pFound = true;
961 break;
962 }
963 }
964 }
965 }
966
967
968 VariantClear(&vtMask);
969 }
970
971 VariantClear(&vtIp);
972 }
973
974 return hr;
975}
976
977static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
978{
979 /* on Vista we need to wait for the address to get applied */
980 /* wait for the address to appear in the list */
981 HRESULT hr = S_OK;
982 ULONG i;
983 *pFound = false;
984 ComPtr <IWbemClassObject> pAdapterConfig;
985 for (i = 0;
986 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
987 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
988 && !(*pFound)
989 && i < sec2Wait/6;
990 i++)
991 {
992 Sleep(6000);
993 }
994
995 return hr;
996}
997
998static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
999{
1000 IWbemLocator *pLoc = NULL;
1001 HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
1002 if (SUCCEEDED(hr))
1003 {
1004 IWbemServices *pSvc = NULL;
1005 hr = pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), /* [in] const BSTR strNetworkResource */
1006 NULL, /* [in] const BSTR strUser */
1007 NULL, /* [in] const BSTR strPassword */
1008 0, /* [in] const BSTR strLocale */
1009 NULL, /* [in] LONG lSecurityFlags */
1010 0, /* [in] const BSTR strAuthority */
1011 0, /* [in] IWbemContext* pCtx */
1012 &pSvc /* [out] IWbemServices** ppNamespace */);
1013 if (SUCCEEDED(hr))
1014 {
1015 hr = CoSetProxyBlanket(pSvc, /* IUnknown * pProxy */
1016 RPC_C_AUTHN_WINNT, /* DWORD dwAuthnSvc */
1017 RPC_C_AUTHZ_NONE, /* DWORD dwAuthzSvc */
1018 NULL, /* WCHAR * pServerPrincName */
1019 RPC_C_AUTHN_LEVEL_CALL, /* DWORD dwAuthnLevel */
1020 RPC_C_IMP_LEVEL_IMPERSONATE, /* DWORD dwImpLevel */
1021 NULL, /* RPC_AUTH_IDENTITY_HANDLE pAuthInfo */
1022 EOAC_NONE /* DWORD dwCapabilities */
1023 );
1024 if (SUCCEEDED(hr))
1025 {
1026 *ppSvc = pSvc;
1027 /* do not need it any more */
1028 pLoc->Release();
1029 return hr;
1030 }
1031 else
1032 NonStandardLogFlow(("CoSetProxyBlanket failed, hr (0x%x)\n", hr));
1033
1034 pSvc->Release();
1035 }
1036 else
1037 NonStandardLogFlow(("ConnectServer failed, hr (0x%x)\n", hr));
1038 pLoc->Release();
1039 }
1040 else
1041 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
1042 return hr;
1043}
1044
1045static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
1046{
1047 VARIANT index;
1048 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
1049 if (SUCCEEDED(hr))
1050 {
1051 WCHAR strIndex[8];
1052 swprintf(strIndex, L"%u", index.uintVal);
1053 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
1054 }
1055 else
1056 NonStandardLogFlow(("Get failed, hr (0x%x)\n", hr));
1057 return hr;
1058}
1059
1060static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
1061 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
1062 IWbemClassObject** ppOutParams
1063 )
1064{
1065 HRESULT hr = S_OK;
1066 ComPtr<IWbemClassObject> pInParamsDefinition;
1067 ComPtr<IWbemClassObject> pClassInstance;
1068
1069 if (cArgs)
1070 {
1071 hr = pClass->GetMethod(MethodName, 0, pInParamsDefinition.asOutParam(), NULL);
1072 if (SUCCEEDED(hr))
1073 {
1074 hr = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
1075 if (SUCCEEDED(hr))
1076 {
1077 for (UINT i = 0; i < cArgs; i++)
1078 {
1079 hr = pClassInstance->Put(pArgNames[i], 0,
1080 pArgs[i], 0);
1081 if (FAILED(hr))
1082 break;
1083 }
1084 }
1085 }
1086 }
1087
1088 if (SUCCEEDED(hr))
1089 {
1090 IWbemClassObject* pOutParams = NULL;
1091 hr = pSvc->ExecMethod(ObjPath, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
1092 if (SUCCEEDED(hr))
1093 {
1094 *ppOutParams = pOutParams;
1095 }
1096 }
1097
1098 return hr;
1099}
1100
1101static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
1102{
1103 HRESULT hr;
1104 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
1105 if (pIpArray)
1106 {
1107 for (UINT i = 0; i < cIp; i++)
1108 {
1109 char* addr = inet_ntoa(aIp[i]);
1110 BSTR val = bstr_t(addr).copy();
1111 long aIndex[1];
1112 aIndex[0] = i;
1113 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1114 if (FAILED(hr))
1115 {
1116 SysFreeString(val);
1117 SafeArrayDestroy(pIpArray);
1118 break;
1119 }
1120 }
1121
1122 if (SUCCEEDED(hr))
1123 {
1124 *ppArray = pIpArray;
1125 }
1126 }
1127 else
1128 hr = HRESULT_FROM_WIN32(GetLastError());
1129
1130 return hr;
1131}
1132
1133static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
1134{
1135 HRESULT hr;
1136 SAFEARRAY *pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
1137 if (pIpArray)
1138 {
1139 BSTR val = bstr_t(Ip, false).copy();
1140 long aIndex[1];
1141 aIndex[0] = 0;
1142 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1143 if (FAILED(hr))
1144 {
1145 SysFreeString(val);
1146 SafeArrayDestroy(pIpArray);
1147 }
1148
1149 if (SUCCEEDED(hr))
1150 {
1151 *ppArray = pIpArray;
1152 }
1153 }
1154 else
1155 hr = HRESULT_FROM_WIN32(GetLastError());
1156
1157 return hr;
1158}
1159
1160
1161static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
1162{
1163 HRESULT hr;
1164 VariantInit(pIpAddresses);
1165 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1166 SAFEARRAY *pIpArray;
1167 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
1168 if (SUCCEEDED(hr))
1169 {
1170 pIpAddresses->parray = pIpArray;
1171 }
1172 return hr;
1173}
1174
1175static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
1176{
1177 HRESULT hr;
1178 VariantInit(pIpAddresses);
1179 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1180 SAFEARRAY *pIpArray;
1181 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
1182 if (SUCCEEDED(hr))
1183 {
1184 pIpAddresses->parray = pIpArray;
1185 }
1186 return hr;
1187}
1188
1189static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
1190{
1191 ComPtr<IWbemClassObject> pClass;
1192 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1193 HRESULT hr;
1194 if (ClassName)
1195 {
1196 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1197 if (SUCCEEDED(hr))
1198 {
1199 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
1200 LPVARIANT args[] = {pIp, pMask};
1201 ComPtr<IWbemClassObject> pOutParams;
1202
1203 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
1204 if (SUCCEEDED(hr))
1205 {
1206 VARIANT varReturnValue;
1207 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1208 &varReturnValue, NULL, 0);
1209 Assert(SUCCEEDED(hr));
1210 if (SUCCEEDED(hr))
1211 {
1212// Assert(varReturnValue.vt == VT_UINT);
1213 int winEr = varReturnValue.uintVal;
1214 switch (winEr)
1215 {
1216 case 0:
1217 {
1218 hr = S_OK;
1219// bool bFound;
1220// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
1221 }
1222 break;
1223 default:
1224 hr = HRESULT_FROM_WIN32( winEr );
1225 break;
1226 }
1227 }
1228 }
1229 }
1230 SysFreeString(ClassName);
1231 }
1232 else
1233 hr = HRESULT_FROM_WIN32(GetLastError());
1234
1235 return hr;
1236}
1237
1238
1239static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
1240{
1241 VARIANT ipAddresses;
1242 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
1243 if (SUCCEEDED(hr))
1244 {
1245 VARIANT ipMasks;
1246 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
1247 if (SUCCEEDED(hr))
1248 {
1249 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1250 VariantClear(&ipMasks);
1251 }
1252 VariantClear(&ipAddresses);
1253 }
1254 return hr;
1255}
1256
1257static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
1258{
1259 VARIANT ipAddresses;
1260 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
1261 if (SUCCEEDED(hr))
1262 {
1263 VARIANT ipMasks;
1264 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
1265 if (SUCCEEDED(hr))
1266 {
1267 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1268 VariantClear(&ipMasks);
1269 }
1270 VariantClear(&ipAddresses);
1271 }
1272 return hr;
1273}
1274
1275/* win API allows to set gw metrics as well, we are not setting them */
1276static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
1277{
1278 ComPtr<IWbemClassObject> pClass;
1279 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1280 HRESULT hr;
1281 if (ClassName)
1282 {
1283 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1284 if (SUCCEEDED(hr))
1285 {
1286 LPWSTR argNames[] = {L"DefaultIPGateway"};
1287 LPVARIANT args[] = {pGw};
1288 ComPtr<IWbemClassObject> pOutParams;
1289
1290 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
1291 if (SUCCEEDED(hr))
1292 {
1293 VARIANT varReturnValue;
1294 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1295 Assert(SUCCEEDED(hr));
1296 if (SUCCEEDED(hr))
1297 {
1298// Assert(varReturnValue.vt == VT_UINT);
1299 int winEr = varReturnValue.uintVal;
1300 switch (winEr)
1301 {
1302 case 0:
1303 hr = S_OK;
1304 break;
1305 default:
1306 hr = HRESULT_FROM_WIN32( winEr );
1307 break;
1308 }
1309 }
1310 }
1311 }
1312 SysFreeString(ClassName);
1313 }
1314 else
1315 hr = HRESULT_FROM_WIN32(GetLastError());
1316
1317 return hr;
1318}
1319
1320/* win API allows to set gw metrics as well, we are not setting them */
1321static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
1322{
1323 VARIANT gwais;
1324 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
1325 if (SUCCEEDED(hr))
1326 {
1327 netIfWinSetGateways(pSvc, ObjPath, &gwais);
1328 VariantClear(&gwais);
1329 }
1330 return hr;
1331}
1332
1333/* win API allows to set gw metrics as well, we are not setting them */
1334static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
1335{
1336 VARIANT vGw;
1337 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
1338 if (SUCCEEDED(hr))
1339 {
1340 netIfWinSetGateways(pSvc, ObjPath, &vGw);
1341 VariantClear(&vGw);
1342 }
1343 return hr;
1344}
1345
1346static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
1347{
1348 ComPtr<IWbemClassObject> pClass;
1349 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1350 HRESULT hr;
1351 if (ClassName)
1352 {
1353 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1354 if (SUCCEEDED(hr))
1355 {
1356 ComPtr<IWbemClassObject> pOutParams;
1357
1358 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
1359 if (SUCCEEDED(hr))
1360 {
1361 VARIANT varReturnValue;
1362 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1363 &varReturnValue, NULL, 0);
1364 Assert(SUCCEEDED(hr));
1365 if (SUCCEEDED(hr))
1366 {
1367// Assert(varReturnValue.vt == VT_UINT);
1368 int winEr = varReturnValue.uintVal;
1369 switch (winEr)
1370 {
1371 case 0:
1372 hr = S_OK;
1373 break;
1374 default:
1375 hr = HRESULT_FROM_WIN32( winEr );
1376 break;
1377 }
1378 }
1379 }
1380 }
1381 SysFreeString(ClassName);
1382 }
1383 else
1384 hr = HRESULT_FROM_WIN32(GetLastError());
1385
1386 return hr;
1387}
1388
1389static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
1390{
1391 ComPtr<IWbemClassObject> pClass;
1392 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1393 HRESULT hr;
1394 if (ClassName)
1395 {
1396 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1397 if (SUCCEEDED(hr))
1398 {
1399 ComPtr<IWbemClassObject> pOutParams;
1400
1401 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1402 if (SUCCEEDED(hr))
1403 {
1404 VARIANT varReturnValue;
1405 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1406 Assert(SUCCEEDED(hr));
1407 if (SUCCEEDED(hr))
1408 {
1409// Assert(varReturnValue.vt == VT_UINT);
1410 int winEr = varReturnValue.uintVal;
1411 if (winEr == 0)
1412 {
1413 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1414 if (SUCCEEDED(hr))
1415 {
1416 VARIANT varReturnValue;
1417 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1418 Assert(SUCCEEDED(hr));
1419 if (SUCCEEDED(hr))
1420 {
1421 // Assert(varReturnValue.vt == VT_UINT);
1422 int winEr = varReturnValue.uintVal;
1423 if (winEr == 0)
1424 hr = S_OK;
1425 else
1426 hr = HRESULT_FROM_WIN32( winEr );
1427 }
1428 }
1429 }
1430 else
1431 hr = HRESULT_FROM_WIN32( winEr );
1432 }
1433 }
1434 }
1435 SysFreeString(ClassName);
1436 }
1437 else
1438 hr = HRESULT_FROM_WIN32(GetLastError());
1439
1440 return hr;
1441}
1442
1443static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
1444{
1445 VARIANT vtEnabled;
1446 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1447 if (SUCCEEDED(hr))
1448 *pEnabled = vtEnabled.boolVal;
1449 return hr;
1450}
1451
1452VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(IN const GUID * pGuid, OUT PADAPTER_SETTINGS pSettings)
1453{
1454 HRESULT hr;
1455 ComPtr <IWbemServices> pSvc;
1456 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1457 if (SUCCEEDED(hr))
1458 {
1459 ComPtr <IWbemClassObject> pAdapterConfig;
1460 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1461 if (SUCCEEDED(hr))
1462 {
1463 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
1464 if (SUCCEEDED(hr))
1465 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
1466 }
1467 }
1468
1469 return hr;
1470}
1471
1472VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
1473{
1474 HRESULT hr;
1475 ComPtr <IWbemServices> pSvc;
1476 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1477 if (SUCCEEDED(hr))
1478 {
1479 ComPtr <IWbemClassObject> pAdapterConfig;
1480 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1481 if (SUCCEEDED(hr))
1482 {
1483 VARIANT vtEnabled;
1484 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1485 if (SUCCEEDED(hr))
1486 *pEnabled = vtEnabled.boolVal;
1487 }
1488 }
1489
1490 return hr;
1491}
1492
1493VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(IN const GUID *pGuid, IN ULONG ip, IN ULONG mask)
1494{
1495 HRESULT hr;
1496 ComPtr <IWbemServices> pSvc;
1497 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1498 if (SUCCEEDED(hr))
1499 {
1500 ComPtr <IWbemClassObject> pAdapterConfig;
1501 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1502 if (SUCCEEDED(hr))
1503 {
1504 BOOL bIsHostOnly;
1505 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1506 if (SUCCEEDED(hr))
1507 {
1508 if (bIsHostOnly)
1509 {
1510 in_addr aIp[1];
1511 in_addr aMask[1];
1512 aIp[0].S_un.S_addr = ip;
1513 aMask[0].S_un.S_addr = mask;
1514
1515 BSTR ObjPath;
1516 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1517 if (SUCCEEDED(hr))
1518 {
1519 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
1520 if (SUCCEEDED(hr))
1521 {
1522#if 0
1523 in_addr aGw[1];
1524 aGw[0].S_un.S_addr = gw;
1525 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
1526 if (SUCCEEDED(hr))
1527#endif
1528 {
1529 }
1530 }
1531 SysFreeString(ObjPath);
1532 }
1533 }
1534 else
1535 {
1536 hr = E_FAIL;
1537 }
1538 }
1539 }
1540 }
1541
1542 return hr;
1543}
1544
1545#if 0
1546static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
1547{
1548 HRESULT hr;
1549 ComPtr <IWbemServices> pSvc;
1550 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1551 if (SUCCEEDED(hr))
1552 {
1553 ComPtr <IWbemClassObject> pAdapterConfig;
1554 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1555 if (SUCCEEDED(hr))
1556 {
1557 BSTR ObjPath;
1558 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1559 if (SUCCEEDED(hr))
1560 {
1561 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
1562 if (SUCCEEDED(hr))
1563 {
1564 if (aIPV6DefaultGateway)
1565 {
1566 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
1567 }
1568 if (SUCCEEDED(hr))
1569 {
1570// hr = netIfWinUpdateConfig(pIf);
1571 }
1572 }
1573 SysFreeString(ObjPath);
1574 }
1575 }
1576 }
1577
1578 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1579}
1580
1581static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1582{
1583 RTNETADDRIPV6 Mask;
1584 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
1585 if (RT_SUCCESS(rc))
1586 {
1587 Bstr maskStr = composeIPv6Address(&Mask);
1588 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
1589 }
1590 return rc;
1591}
1592#endif
1593
1594VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(IN const GUID *pGuid)
1595{
1596 HRESULT hr;
1597 ComPtr <IWbemServices> pSvc;
1598 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1599 if (SUCCEEDED(hr))
1600 {
1601 ComPtr <IWbemClassObject> pAdapterConfig;
1602 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1603 if (SUCCEEDED(hr))
1604 {
1605 BOOL bIsHostOnly;
1606 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1607 if (SUCCEEDED(hr))
1608 {
1609 if (bIsHostOnly)
1610 {
1611 BSTR ObjPath;
1612 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1613 if (SUCCEEDED(hr))
1614 {
1615 hr = netIfWinEnableDHCP(pSvc, ObjPath);
1616 if (SUCCEEDED(hr))
1617 {
1618// hr = netIfWinUpdateConfig(pIf);
1619 }
1620 SysFreeString(ObjPath);
1621 }
1622 }
1623 else
1624 {
1625 hr = E_FAIL;
1626 }
1627 }
1628 }
1629 }
1630
1631
1632 return hr;
1633}
1634
1635VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(IN const GUID *pGuid)
1636{
1637 HRESULT hr;
1638 ComPtr <IWbemServices> pSvc;
1639 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1640 if (SUCCEEDED(hr))
1641 {
1642 ComPtr <IWbemClassObject> pAdapterConfig;
1643 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1644 if (SUCCEEDED(hr))
1645 {
1646 BOOL bIsHostOnly;
1647 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1648 if (SUCCEEDED(hr))
1649 {
1650 if (bIsHostOnly)
1651 {
1652 BSTR ObjPath;
1653 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1654 if (SUCCEEDED(hr))
1655 {
1656 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
1657 if (SUCCEEDED(hr))
1658 {
1659// hr = netIfWinUpdateConfig(pIf);
1660 }
1661 SysFreeString(ObjPath);
1662 }
1663 }
1664 else
1665 {
1666 hr = E_FAIL;
1667 }
1668 }
1669 }
1670 }
1671
1672
1673 return hr;
1674}
1675
1676typedef bool (*PFNVBOXNETCFG_IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
1677
1678static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, PFNVBOXNETCFG_IPSETTINGS_CALLBACK pfnCallback, PVOID pContext)
1679{
1680 PIP_ADAPTER_ADDRESSES pAdapter;
1681 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1682 {
1683 PIP_ADAPTER_UNICAST_ADDRESS pAddr = pAdapter->FirstUnicastAddress;
1684 PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix;
1685
1686 if (pAddr && pPrefix)
1687 {
1688 do
1689 {
1690 bool fIPFound, fMaskFound;
1691 fIPFound = fMaskFound = false;
1692 ULONG ip, mask;
1693 for (; pAddr && !fIPFound; pAddr = pAddr->Next)
1694 {
1695 switch (pAddr->Address.lpSockaddr->sa_family)
1696 {
1697 case AF_INET:
1698 fIPFound = true;
1699 memcpy(&ip,
1700 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1701 sizeof(ip));
1702 break;
1703// case AF_INET6:
1704// break;
1705 }
1706 }
1707
1708 for (; pPrefix && !fMaskFound; pPrefix = pPrefix->Next)
1709 {
1710 switch (pPrefix->Address.lpSockaddr->sa_family)
1711 {
1712 case AF_INET:
1713 if (!pPrefix->PrefixLength || pPrefix->PrefixLength > 31) /* in case the ip helper API is queried while NetCfg write lock is held */
1714 break; /* the address values can contain illegal values */
1715 fMaskFound = true;
1716 mask = (~(((ULONG)~0) >> pPrefix->PrefixLength));
1717 mask = htonl(mask);
1718 break;
1719// case AF_INET6:
1720// break;
1721 }
1722 }
1723
1724 if (!fIPFound || !fMaskFound)
1725 break;
1726
1727 if (!pfnCallback(ip, mask, pContext))
1728 return;
1729 } while (true);
1730 }
1731 }
1732}
1733
1734typedef struct _IPPROBE_CONTEXT
1735{
1736 ULONG Prefix;
1737 bool bConflict;
1738}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
1739
1740#define IPPROBE_INIT(_pContext, _addr) \
1741 ((_pContext)->bConflict = false, \
1742 (_pContext)->Prefix = _addr)
1743
1744#define IPPROBE_INIT_STR(_pContext, _straddr) \
1745 IPROBE_INIT(_pContext, inet_addr(_straddr))
1746
1747static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
1748{
1749 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
1750
1751 if ((ip & mask) == (pProbe->Prefix & mask))
1752 {
1753 pProbe->bConflict = true;
1754 return false;
1755 }
1756
1757 return true;
1758}
1759
1760VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(OUT PULONG pNetIp, OUT PULONG pNetMask)
1761{
1762 DWORD dwRc;
1763 HRESULT hr = S_OK;
1764 /*
1765 * Most of the hosts probably have less than 10 adapters,
1766 * so we'll mostly succeed from the first attempt.
1767 */
1768 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
1769 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
1770 if (!pAddresses)
1771 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1772 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1773 if (dwRc == ERROR_BUFFER_OVERFLOW)
1774 {
1775 /* Impressive! More than 10 adapters! Get more memory and try again. */
1776 free(pAddresses);
1777 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
1778 if (!pAddresses)
1779 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1780 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1781 }
1782 if (dwRc == NO_ERROR)
1783 {
1784 IPPROBE_CONTEXT Context;
1785 const ULONG ip192168 = inet_addr("192.168.0.0");
1786 srand(GetTickCount());
1787
1788 *pNetIp = 0;
1789 *pNetMask = 0;
1790
1791 for (int i = 0; i < 255; i++)
1792 {
1793 ULONG ipProbe = rand()*255/RAND_MAX;
1794 ipProbe = ip192168 | (ipProbe << 16);
1795 IPPROBE_INIT(&Context, ipProbe);
1796 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
1797 if (!Context.bConflict)
1798 {
1799 *pNetIp = ipProbe;
1800 *pNetMask = inet_addr("255.255.255.0");
1801 break;
1802 }
1803 }
1804 if (*pNetIp == 0)
1805 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
1806 }
1807 else
1808 NonStandardLogFlow(("GetAdaptersAddresses err (%d)\n", dwRc));
1809
1810 if (pAddresses)
1811 free(pAddresses);
1812
1813 if (dwRc != NO_ERROR)
1814 {
1815 hr = HRESULT_FROM_WIN32(dwRc);
1816 }
1817
1818 return hr;
1819}
1820
1821/*
1822 * convenience functions to perform netflt/adp manipulations
1823 */
1824#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
1825#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
1826
1827static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
1828{
1829 INetCfgComponent * pNcc = NULL;
1830 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
1831 if (hr == S_OK)
1832 {
1833 NonStandardLog("NetFlt is installed currently, uninstalling ...\n");
1834
1835 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
1836
1837 pNcc->Release();
1838 }
1839 else if (hr == S_FALSE)
1840 {
1841 NonStandardLog("NetFlt is not installed currently\n");
1842 hr = S_OK;
1843 }
1844 else
1845 {
1846 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
1847 hr = S_OK;
1848 }
1849
1850 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
1851 VBoxDrvCfgInfUninstallAllF(L"Net", VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
1852
1853 return hr;
1854}
1855
1856VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
1857{
1858 return vboxNetCfgWinNetFltUninstall(pNc, 0);
1859}
1860
1861VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc,
1862 IN LPCWSTR const *apInfFullPaths, IN UINT cInfFullPaths)
1863{
1864 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
1865 if (SUCCEEDED(hr))
1866 {
1867 NonStandardLog("NetFlt will be installed ...\n");
1868 hr = VBoxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
1869 &GUID_DEVCLASS_NETSERVICE,
1870 apInfFullPaths,
1871 cInfFullPaths,
1872 NULL);
1873 }
1874 return hr;
1875}
1876
1877#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
1878VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
1879{
1880 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
1881 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
1882 ULONG cbSufSize = 0;
1883
1884 if (pSuffix)
1885 {
1886 cbSize += (ULONG)wcslen(pSuffix) * 2;
1887 cbSize += 2; /* for space */
1888 }
1889
1890 if (*pcbBuf < cbSize)
1891 {
1892 *pcbBuf = cbSize;
1893 return E_FAIL;
1894 }
1895
1896 wcscpy(pBuf, VBOX_CONNECTION_NAME);
1897 if (pSuffix)
1898 {
1899 wcscat(pBuf, L" ");
1900 wcscat(pBuf, pSuffix);
1901 }
1902
1903 return S_OK;
1904}
1905
1906static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority(IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
1907{
1908 INetCfgComponentBindings *pNetCfgBindings;
1909 GUID *pGuid = (GUID*)pContext;
1910
1911 /* Get component's binding. */
1912 HRESULT hr = pNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pNetCfgBindings);
1913 if (SUCCEEDED(hr))
1914 {
1915 /* Get binding path enumerator reference. */
1916 IEnumNetCfgBindingPath *pEnumNetCfgBindPath;
1917 hr = pNetCfgBindings->EnumBindingPaths(EBP_BELOW, &pEnumNetCfgBindPath);
1918 if (SUCCEEDED(hr))
1919 {
1920 bool bFoundIface = false;
1921 hr = pEnumNetCfgBindPath->Reset();
1922 do
1923 {
1924 INetCfgBindingPath *pNetCfgBindPath;
1925 hr = pEnumNetCfgBindPath->Next(1, &pNetCfgBindPath, NULL);
1926 if (hr == S_OK)
1927 {
1928 IEnumNetCfgBindingInterface *pEnumNetCfgBindIface;
1929 hr = pNetCfgBindPath->EnumBindingInterfaces(&pEnumNetCfgBindIface);
1930 if (hr == S_OK)
1931 {
1932 pEnumNetCfgBindIface->Reset();
1933 do
1934 {
1935 INetCfgBindingInterface *pNetCfgBindIfce;
1936 hr = pEnumNetCfgBindIface->Next(1, &pNetCfgBindIfce, NULL);
1937 if (hr == S_OK)
1938 {
1939 INetCfgComponent *pNetCfgCompo;
1940 hr = pNetCfgBindIfce->GetLowerComponent(&pNetCfgCompo);
1941 if (hr == S_OK)
1942 {
1943 ULONG uComponentStatus;
1944 hr = pNetCfgCompo->GetDeviceStatus(&uComponentStatus);
1945 if (hr == S_OK)
1946 {
1947 GUID guid;
1948 hr = pNetCfgCompo->GetInstanceGuid(&guid);
1949 if ( hr == S_OK
1950 && guid == *pGuid)
1951 {
1952 hr = pNetCfgBindings->MoveAfter(pNetCfgBindPath, NULL);
1953 if (FAILED(hr))
1954 NonStandardLogFlow(("Unable to move interface, hr (0x%x)\n", hr));
1955 bFoundIface = true;
1956 }
1957 }
1958 pNetCfgCompo->Release();
1959 }
1960 else
1961 NonStandardLogFlow(("GetLowerComponent failed, hr (0x%x)\n", hr));
1962 pNetCfgBindIfce->Release();
1963 }
1964 else
1965 {
1966 if (hr == S_FALSE) /* No more binding interfaces? */
1967 hr = S_OK;
1968 else
1969 NonStandardLogFlow(("Next binding interface failed, hr (0x%x)\n", hr));
1970 break;
1971 }
1972 } while (!bFoundIface);
1973 pEnumNetCfgBindIface->Release();
1974 }
1975 else
1976 NonStandardLogFlow(("EnumBindingInterfaces failed, hr (0x%x)\n", hr));
1977 pNetCfgBindPath->Release();
1978 }
1979 else
1980 {
1981 if (hr = S_FALSE) /* No more binding paths? */
1982 hr = S_OK;
1983 else
1984 NonStandardLogFlow(("Next bind path failed, hr (0x%x)\n", hr));
1985 break;
1986 }
1987 } while (!bFoundIface);
1988 pEnumNetCfgBindPath->Release();
1989 }
1990 else
1991 NonStandardLogFlow(("EnumBindingPaths failed, hr (0x%x)\n", hr));
1992 pNetCfgBindings->Release();
1993 }
1994 else
1995 NonStandardLogFlow(("QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr));
1996 return TRUE;
1997}
1998
1999static UINT WINAPI vboxNetCfgWinPspFileCallback(
2000 PVOID Context,
2001 UINT Notification,
2002 UINT_PTR Param1,
2003 UINT_PTR Param2
2004 )
2005{
2006 switch (Notification)
2007 {
2008 case SPFILENOTIFY_TARGETNEWER:
2009 case SPFILENOTIFY_TARGETEXISTS:
2010 return TRUE;
2011 }
2012 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2013}
2014
2015/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
2016/*
2017 Copyright 2004 by the Massachusetts Institute of Technology
2018
2019 All rights reserved.
2020
2021 Permission to use, copy, modify, and distribute this software and its
2022 documentation for any purpose and without fee is hereby granted,
2023 provided that the above copyright notice appear in all copies and that
2024 both that copyright notice and this permission notice appear in
2025 supporting documentation, and that the name of the Massachusetts
2026 Institute of Technology (M.I.T.) not be used in advertising or publicity
2027 pertaining to distribution of the software without specific, written
2028 prior permission.
2029
2030 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2031 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2032 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2033 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2034 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2035 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036 SOFTWARE.
2037*/
2038
2039
2040#define NETSHELL_LIBRARY _T("netshell.dll")
2041
2042/**
2043 * Use the IShellFolder API to rename the connection.
2044 */
2045static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
2046{
2047 /* This is the GUID for the network connections folder. It is constant.
2048 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
2049 const GUID CLSID_NetworkConnections = {
2050 0x7007ACC7, 0x3202, 0x11D1, {
2051 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
2052 }
2053 };
2054
2055 LPITEMIDLIST pidl = NULL;
2056 IShellFolder *pShellFolder = NULL;
2057 HRESULT hr;
2058
2059 /* Build the display name in the form "::{GUID}". */
2060 if (wcslen(wGuid) >= MAX_PATH)
2061 return E_INVALIDARG;
2062 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
2063 swprintf(szAdapterGuid, L"::%ls", wGuid);
2064
2065 /* Create an instance of the network connections folder. */
2066 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
2067 CLSCTX_INPROC_SERVER, IID_IShellFolder,
2068 reinterpret_cast<LPVOID *>(&pShellFolder));
2069 /* Parse the display name. */
2070 if (SUCCEEDED (hr))
2071 {
2072 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
2073 &pidl, NULL);
2074 }
2075 if (SUCCEEDED (hr))
2076 {
2077 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
2078 &pidl);
2079 }
2080
2081 CoTaskMemFree (pidl);
2082
2083 if (pShellFolder)
2084 pShellFolder->Release();
2085
2086 return hr;
2087}
2088
2089VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
2090{
2091 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
2092 lpHrRenameConnection RenameConnectionFunc = NULL;
2093 HRESULT status;
2094
2095 /* First try the IShellFolder interface, which was unimplemented
2096 * for the network connections folder before XP. */
2097 status = rename_shellfolder (pGuid, NewName);
2098 if (status == E_NOTIMPL)
2099 {
2100/** @todo that code doesn't seem to work! */
2101 /* The IShellFolder interface is not implemented on this platform.
2102 * Try the (undocumented) HrRenameConnection API in the netshell
2103 * library. */
2104 CLSID clsid;
2105 HINSTANCE hNetShell;
2106 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
2107 if (FAILED(status))
2108 return E_FAIL;
2109 hNetShell = LoadLibrary (NETSHELL_LIBRARY);
2110 if (hNetShell == NULL)
2111 return E_FAIL;
2112 RenameConnectionFunc =
2113 (lpHrRenameConnection) GetProcAddress (hNetShell,
2114 "HrRenameConnection");
2115 if (RenameConnectionFunc == NULL)
2116 {
2117 FreeLibrary (hNetShell);
2118 return E_FAIL;
2119 }
2120 status = RenameConnectionFunc (&clsid, NewName);
2121 FreeLibrary (hNetShell);
2122 }
2123 if (FAILED (status))
2124 return status;
2125
2126 return S_OK;
2127}
2128
2129#define DRIVERHWID _T("sun_VBoxNetAdp")
2130
2131#define SetErrBreak(strAndArgs) \
2132 if (1) { \
2133 hrc = E_FAIL; \
2134 NonStandardLog strAndArgs; \
2135 break; \
2136 } else do {} while (0)
2137
2138VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg)
2139{
2140 HRESULT hrc = S_OK;
2141
2142 do
2143 {
2144 TCHAR lszPnPInstanceId [512] = {0};
2145
2146 /* We have to find the device instance ID through a registry search */
2147
2148 HKEY hkeyNetwork = 0;
2149 HKEY hkeyConnection = 0;
2150
2151 do
2152 {
2153 WCHAR strRegLocation [256];
2154 WCHAR GuidString[50];
2155
2156 int length = StringFromGUID2(*pGUID, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
2157 if (!length)
2158 SetErrBreak(("Failed to create a Guid string"));
2159
2160 swprintf (strRegLocation,
2161 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
2162 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
2163 GuidString);
2164
2165 LONG status;
2166 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
2167 KEY_READ, &hkeyNetwork);
2168 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
2169 SetErrBreak (("Host interface network is not found in registry (%S) [1]",
2170 strRegLocation));
2171
2172 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
2173 KEY_READ, &hkeyConnection);
2174 if ((status != ERROR_SUCCESS) || !hkeyConnection)
2175 SetErrBreak (("Host interface network is not found in registry (%S) [2]",
2176 strRegLocation));
2177
2178 DWORD len = sizeof (lszPnPInstanceId);
2179 DWORD dwKeyType;
2180 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2181 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2182 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2183 SetErrBreak (("Host interface network is not found in registry (%S) [3]",
2184 strRegLocation));
2185 }
2186 while (0);
2187
2188 if (hkeyConnection)
2189 RegCloseKey (hkeyConnection);
2190 if (hkeyNetwork)
2191 RegCloseKey (hkeyNetwork);
2192
2193 if (FAILED (hrc))
2194 break;
2195
2196 /*
2197 * Now we are going to enumerate all network devices and
2198 * wait until we encounter the right device instance ID
2199 */
2200
2201 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2202
2203 do
2204 {
2205 BOOL ok;
2206 DWORD ret = 0;
2207 GUID netGuid;
2208 SP_DEVINFO_DATA DeviceInfoData;
2209 DWORD index = 0;
2210 BOOL found = FALSE;
2211 DWORD size = 0;
2212
2213 /* initialize the structure size */
2214 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2215
2216 /* copy the net class GUID */
2217 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2218
2219 /* return a device info set contains all installed devices of the Net class */
2220 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2221
2222 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2223 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2224
2225 /* enumerate the driver info list */
2226 while (TRUE)
2227 {
2228 TCHAR *deviceHwid;
2229
2230 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2231
2232 if (!ok)
2233 {
2234 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2235 break;
2236 else
2237 {
2238 index++;
2239 continue;
2240 }
2241 }
2242
2243 /* try to get the hardware ID registry property */
2244 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2245 &DeviceInfoData,
2246 SPDRP_HARDWAREID,
2247 NULL,
2248 NULL,
2249 0,
2250 &size);
2251 if (!ok)
2252 {
2253 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2254 {
2255 index++;
2256 continue;
2257 }
2258
2259 deviceHwid = (TCHAR *) malloc (size);
2260 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2261 &DeviceInfoData,
2262 SPDRP_HARDWAREID,
2263 NULL,
2264 (PBYTE)deviceHwid,
2265 size,
2266 NULL);
2267 if (!ok)
2268 {
2269 free (deviceHwid);
2270 deviceHwid = NULL;
2271 index++;
2272 continue;
2273 }
2274 }
2275 else
2276 {
2277 /* something is wrong. This shouldn't have worked with a NULL buffer */
2278 index++;
2279 continue;
2280 }
2281
2282 for (TCHAR *t = deviceHwid;
2283 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2284 t += _tcslen (t) + 1)
2285 {
2286 if (!_tcsicmp (DRIVERHWID, t))
2287 {
2288 /* get the device instance ID */
2289 TCHAR devID [MAX_DEVICE_ID_LEN];
2290 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2291 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2292 {
2293 /* compare to what we determined before */
2294 if (wcscmp(devID, lszPnPInstanceId) == 0)
2295 {
2296 found = TRUE;
2297 break;
2298 }
2299 }
2300 }
2301 }
2302
2303 if (deviceHwid)
2304 {
2305 free (deviceHwid);
2306 deviceHwid = NULL;
2307 }
2308
2309 if (found)
2310 break;
2311
2312 index++;
2313 }
2314
2315 if (found == FALSE)
2316 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
2317 GetLastError()));
2318
2319 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2320 if (!ok)
2321 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2322 GetLastError()));
2323
2324 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2325 if (!ok)
2326 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2327 GetLastError()));
2328 }
2329 while (0);
2330
2331 /* clean up the device info set */
2332 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2333 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2334
2335 if (FAILED (hrc))
2336 break;
2337 }
2338 while (0);
2339
2340 return hrc;
2341}
2342
2343VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
2344 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
2345{
2346 HRESULT hrc = S_OK;
2347
2348 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2349 SP_DEVINFO_DATA DeviceInfoData;
2350 PVOID pQueueCallbackContext = NULL;
2351 DWORD ret = 0;
2352 BOOL found = FALSE;
2353 BOOL registered = FALSE;
2354 BOOL destroyList = FALSE;
2355 WCHAR pWCfgGuidString [50];
2356 WCHAR DevName[256];
2357
2358 do
2359 {
2360 GUID netGuid;
2361 SP_DRVINFO_DATA DriverInfoData;
2362 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2363 TCHAR className [MAX_PATH];
2364 DWORD index = 0;
2365 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2366 /* for our purposes, 2k buffer is more
2367 * than enough to obtain the hardware ID
2368 * of the VBoxNetAdp driver. */
2369 DWORD detailBuf [2048];
2370
2371 HKEY hkey = NULL;
2372 DWORD cbSize;
2373 DWORD dwValueType;
2374
2375 /* initialize the structure size */
2376 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2377 DriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
2378
2379 /* copy the net class GUID */
2380 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2381
2382 /* create an empty device info set associated with the net class GUID */
2383 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
2384 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2385 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
2386 GetLastError()));
2387
2388 /* get the class name from GUID */
2389 BOOL fResult = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2390 if (!fResult)
2391 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
2392 GetLastError()));
2393
2394 /* create a device info element and add the new device instance
2395 * key to registry */
2396 fResult = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2397 DICD_GENERATE_ID, &DeviceInfoData);
2398 if (!fResult)
2399 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
2400 GetLastError()));
2401
2402 /* select the newly created device info to be the currently
2403 selected member */
2404 fResult = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2405 if (!fResult)
2406 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2407 GetLastError()));
2408
2409 if (pInfPath)
2410 {
2411 /* get the device install parameters and disable filecopy */
2412 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2413 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2414 &DeviceInstallParams);
2415 if (fResult)
2416 {
2417 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2418 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2419 if (pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2420 {
2421 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2422
2423 if (bIsInfPathFile)
2424 {
2425 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2426 }
2427
2428 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2429 &DeviceInstallParams);
2430 if (!fResult)
2431 {
2432 DWORD winEr = GetLastError();
2433 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2434 break;
2435 }
2436 }
2437 else
2438 {
2439 NonStandardLogFlow(("SetupDiSetDeviceInstallParams faileed: INF path is too long\n"));
2440 break;
2441 }
2442 }
2443 else
2444 {
2445 DWORD winEr = GetLastError();
2446 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2447 }
2448 }
2449
2450 /* build a list of class drivers */
2451 fResult = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2452 SPDIT_CLASSDRIVER);
2453 if (!fResult)
2454 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
2455 GetLastError()));
2456
2457 destroyList = TRUE;
2458
2459 /* enumerate the driver info list */
2460 while (TRUE)
2461 {
2462 BOOL ret;
2463
2464 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2465 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2466
2467 /* if the function failed and GetLastError() returned
2468 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2469 * list. Otherwise there was something wrong with this
2470 * particular driver. */
2471 if (!ret)
2472 {
2473 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2474 break;
2475 else
2476 {
2477 index++;
2478 continue;
2479 }
2480 }
2481
2482 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2483 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2484
2485 /* if we successfully find the hardware ID and it turns out to
2486 * be the one for the loopback driver, then we are done. */
2487 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2488 &DeviceInfoData,
2489 &DriverInfoData,
2490 pDriverInfoDetail,
2491 sizeof (detailBuf),
2492 NULL))
2493 {
2494 TCHAR * t;
2495
2496 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2497 * whole list and see if there is a match somewhere. */
2498 t = pDriverInfoDetail->HardwareID;
2499 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2500 {
2501 if (!_tcsicmp(t, DRIVERHWID))
2502 break;
2503
2504 t += _tcslen(t) + 1;
2505 }
2506
2507 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2508 {
2509 found = TRUE;
2510 break;
2511 }
2512 }
2513
2514 index ++;
2515 }
2516
2517 if (!found)
2518 SetErrBreak(("Could not find Host Interface Networking driver! Please reinstall"));
2519
2520 /* set the loopback driver to be the currently selected */
2521 fResult = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2522 &DriverInfoData);
2523 if (!fResult)
2524 SetErrBreak(("SetupDiSetSelectedDriver failed (0x%08X)",
2525 GetLastError()));
2526
2527 /* register the phantom device to prepare for install */
2528 fResult = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2529 &DeviceInfoData);
2530 if (!fResult)
2531 {
2532 DWORD err = GetLastError();
2533 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
2534 err));
2535 }
2536
2537 /* registered, but remove if errors occur in the following code */
2538 registered = TRUE;
2539
2540 /* ask the installer if we can install the device */
2541 fResult = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2542 &DeviceInfoData);
2543 if (!fResult)
2544 {
2545 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2546 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2547 GetLastError()));
2548 /* that's fine */
2549 }
2550
2551 /* get the device install parameters and disable filecopy */
2552 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2553 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2554 &DeviceInstallParams);
2555 if (fResult)
2556 {
2557 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2558 if (pQueueCallbackContext)
2559 {
2560 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2561 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2562 fResult = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2563 &DeviceInstallParams);
2564 if (!fResult)
2565 {
2566 DWORD winEr = GetLastError();
2567 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2568 }
2569 Assert(fResult);
2570 }
2571 else
2572 {
2573 DWORD winEr = GetLastError();
2574 NonStandardLogFlow(("SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr));
2575 }
2576 }
2577 else
2578 {
2579 DWORD winEr = GetLastError();
2580 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2581 }
2582
2583 /* install the files first */
2584 fResult = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2585 &DeviceInfoData);
2586 if (!fResult)
2587 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2588 GetLastError()));
2589 /* get the device install parameters and disable filecopy */
2590 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2591 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2592 &DeviceInstallParams);
2593 if (fResult)
2594 {
2595 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2596 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2597 &DeviceInstallParams);
2598 if (!fResult)
2599 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
2600 GetLastError()));
2601 }
2602
2603 /*
2604 * Register any device-specific co-installers for this device,
2605 */
2606 fResult = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
2607 hDeviceInfo,
2608 &DeviceInfoData);
2609 if (!fResult)
2610 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2611 GetLastError()));
2612
2613 /*
2614 * install any installer-specified interfaces.
2615 * and then do the real install
2616 */
2617 fResult = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
2618 hDeviceInfo,
2619 &DeviceInfoData);
2620 if (!fResult)
2621 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2622 GetLastError()));
2623
2624 fResult = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
2625 hDeviceInfo,
2626 &DeviceInfoData);
2627 if (!fResult)
2628 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2629 GetLastError()));
2630
2631 /* Figure out NetCfgInstanceId */
2632 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
2633 &DeviceInfoData,
2634 DICS_FLAG_GLOBAL,
2635 0,
2636 DIREG_DRV,
2637 KEY_READ);
2638 if (hkey == INVALID_HANDLE_VALUE)
2639 SetErrBreak (("SetupDiOpenDevRegKey failed (0x%08X)",
2640 GetLastError()));
2641
2642 cbSize = sizeof (pWCfgGuidString);
2643 DWORD ret;
2644 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2645 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2646
2647 RegCloseKey (hkey);
2648
2649 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2650 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2651 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2652 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2653 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2654 NULL /*OUT PDWORD RequiredSize OPTIONAL*/))
2655 {
2656 int err = GetLastError();
2657 if (err != ERROR_INVALID_DATA)
2658 {
2659 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2660 err));
2661 }
2662
2663 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2664 SPDRP_DEVICEDESC, /* IN DWORD Property,*/
2665 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2666 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2667 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2668 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2669 ))
2670 {
2671 err = GetLastError();
2672 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2673 err));
2674 }
2675 }
2676 }
2677 while (0);
2678
2679 /*
2680 * cleanup
2681 */
2682 if (pQueueCallbackContext)
2683 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2684
2685 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2686 {
2687 /* an error has occurred, but the device is registered, we must remove it */
2688 if (ret != 0 && registered)
2689 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2690
2691 found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
2692
2693 /* destroy the driver info list */
2694 if (destroyList)
2695 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
2696 SPDIT_CLASSDRIVER);
2697 /* clean up the device info set */
2698 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2699 }
2700
2701 /* return the network connection GUID on success */
2702 if (SUCCEEDED(hrc))
2703 {
2704 WCHAR ConnectoinName[128];
2705 ULONG cbName = sizeof(ConnectoinName);
2706
2707 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(DevName, ConnectoinName, &cbName);
2708 if (SUCCEEDED(hr))
2709 hr = VBoxNetCfgWinRenameConnection(pWCfgGuidString, ConnectoinName);
2710
2711 if (lppszName)
2712 {
2713 *lppszName = SysAllocString((const OLECHAR *) DevName);
2714 if (!*lppszName)
2715 {
2716 NonStandardLogFlow(("SysAllocString failed\n"));
2717 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2718 }
2719 }
2720
2721 if (pGuid)
2722 {
2723 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID)pGuid);
2724 if (FAILED(hrc))
2725 NonStandardLogFlow(("CLSIDFromString failed, hrc (0x%x)\n", hrc));
2726 }
2727
2728 INetCfg *pNetCfg = NULL;
2729 LPWSTR lpszApp = NULL;
2730 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, TRUE, L"VirtualBox Host-Only Creation",
2731 30 * 1000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec. */
2732 /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
2733 &lpszApp);
2734 if (hr == S_OK)
2735 {
2736 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2737 &GUID_DEVCLASS_NETSERVICE,
2738 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2739 pGuid);
2740 if (SUCCEEDED(hr))
2741 {
2742 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2743 &GUID_DEVCLASS_NETTRANS,
2744 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2745 pGuid);
2746 if (SUCCEEDED(hr))
2747 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2748 &GUID_DEVCLASS_NETCLIENT,
2749 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2750 pGuid);
2751 }
2752
2753 if (SUCCEEDED(hr))
2754 {
2755 hr = pNetCfg->Apply();
2756 }
2757 else
2758 NonStandardLogFlow(("Enumeration failed, hr 0x%x\n", hr));
2759 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
2760 }
2761 else if (hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
2762 {
2763 NonStandardLogFlow(("Application %ws is holding the lock, failed\n", lpszApp));
2764 CoTaskMemFree(lpszApp);
2765 }
2766 else
2767 NonStandardLogFlow(("VBoxNetCfgWinQueryINetCfg failed, hr 0x%x\n", hr));
2768 }
2769 return hrc;
2770}
2771
2772#undef SetErrBreak
2773
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