VirtualBox

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

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

netIfWinFindAdapterClassById: hr variable shadowing causing a success status code to be return on failure. Also, don't use S_FALSE as SUCCEEDED() returns true for it and would cause NULL pointer accesses as well.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.4 KB
Line 
1/* $Id: VBoxNetCfg.cpp 38797 2011-09-20 09:37:07Z 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 pfnRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
563 if (pfnRoutine)
564 {
565 char szBuffer[4096] = {0};
566 va_list va;
567 va_start(va, szString);
568 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, va);
569 va_end(va);
570
571 pfnRoutine(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 wszQuery[256];
792 WCHAR wszGuid[50];
793
794 int length = StringFromGUID2(*pGuid, wszGuid, RT_ELEMENTS(wszGuid));
795 if (length)
796 {
797 swprintf(wszQuery, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", wszGuid);
798 IEnumWbemClassObject* pEnumerator = NULL;
799 hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(wszQuery), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
800 NULL, &pEnumerator);
801 if (SUCCEEDED(hr))
802 {
803 if (pEnumerator)
804 {
805 IWbemClassObject *pclsObj;
806 ULONG uReturn = 0;
807 hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
808 NonStandardLogFlow(("netIfWinFindAdapterClassById: IEnumWbemClassObject::Next -> hr=0x%x pclsObj=%p uReturn=%u 42=%u\n",
809 hr, (void *)pclsObj, uReturn, 42));
810 if (SUCCEEDED(hr))
811 {
812 if (uReturn && pclsObj != NULL)
813 {
814 *pAdapterConfig = pclsObj;
815 pEnumerator->Release();
816 NonStandardLogFlow(("netIfWinFindAdapterClassById: S_OK and %p\n", *pAdapterConfig));
817 return S_OK;
818 }
819
820 hr = E_FAIL;
821 }
822
823 pEnumerator->Release();
824 }
825 else
826 {
827 NonStandardLogFlow(("ExecQuery returned no enumerator\n"));
828 hr = E_FAIL;
829 }
830 }
831 else
832 NonStandardLogFlow(("ExecQuery failed (0x%x)\n", hr));
833 }
834 else
835 {
836 DWORD winEr = GetLastError();
837 hr = HRESULT_FROM_WIN32( winEr );
838 if (SUCCEEDED(hr))
839 hr = E_FAIL;
840 NonStandardLogFlow(("StringFromGUID2 failed winEr=%u, hr=0x%x\n", winEr, hr));
841 }
842
843 NonStandardLogFlow(("netIfWinFindAdapterClassById: 0x%x and %p\n", hr, *pAdapterConfig));
844 return hr;
845}
846
847static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
848{
849 VARIANT vtServiceName;
850 BOOL bIsHostOnly = FALSE;
851 VariantInit(&vtServiceName);
852
853 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0 /*lFlags*/, &vtServiceName, NULL /*pvtType*/, NULL /*plFlavor*/);
854 if (SUCCEEDED(hr))
855 {
856 *pbIsHostOnly = bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp");
857
858 VariantClear(&vtServiceName);
859 }
860
861 return hr;
862}
863
864static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
865{
866 VARIANT vtIp;
867 HRESULT hr;
868 VariantInit(&vtIp);
869
870 *pIpv4 = 0;
871 *pMaskv4 = 0;
872
873 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
874 if (SUCCEEDED(hr))
875 {
876 if (vtIp.vt == (VT_ARRAY | VT_BSTR))
877 {
878 VARIANT vtMask;
879 VariantInit(&vtMask);
880 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
881 if (SUCCEEDED(hr))
882 {
883 if (vtMask.vt == (VT_ARRAY | VT_BSTR))
884 {
885 SAFEARRAY * pIpArray = vtIp.parray;
886 SAFEARRAY * pMaskArray = vtMask.parray;
887 if (pIpArray && pMaskArray)
888 {
889 BSTR pCurIp;
890 BSTR pCurMask;
891 for (LONG i = 0;
892 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
893 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
894 i++)
895 {
896 bstr_t ip(pCurIp);
897
898 ULONG Ipv4 = inet_addr((char*)(ip));
899 if (Ipv4 != INADDR_NONE)
900 {
901 *pIpv4 = Ipv4;
902 bstr_t mask(pCurMask);
903 *pMaskv4 = inet_addr((char*)(mask));
904 break;
905 }
906 }
907 }
908 }
909 else
910 {
911 *pIpv4 = 0;
912 *pMaskv4 = 0;
913 }
914
915 VariantClear(&vtMask);
916 }
917 }
918 else
919 {
920 *pIpv4 = 0;
921 *pMaskv4 = 0;
922 }
923
924 VariantClear(&vtIp);
925 }
926
927 return hr;
928}
929
930
931static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
932{
933 VARIANT vtIp;
934 HRESULT hr;
935 VariantInit(&vtIp);
936
937 *pFound = false;
938
939 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
940 if (SUCCEEDED(hr))
941 {
942 VARIANT vtMask;
943 VariantInit(&vtMask);
944 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
945 if (SUCCEEDED(hr))
946 {
947 SAFEARRAY * pIpArray = vtIp.parray;
948 SAFEARRAY * pMaskArray = vtMask.parray;
949 if (pIpArray && pMaskArray)
950 {
951 BSTR pIp, pMask;
952 for (LONG k = 0;
953 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
954 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
955 k++)
956 {
957 BSTR pCurIp;
958 BSTR pCurMask;
959 for (LONG i = 0;
960 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
961 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
962 i++)
963 {
964 if (!wcsicmp(pCurIp, pIp))
965 {
966 if (!wcsicmp(pCurMask, pMask))
967 *pFound = true;
968 break;
969 }
970 }
971 }
972 }
973
974
975 VariantClear(&vtMask);
976 }
977
978 VariantClear(&vtIp);
979 }
980
981 return hr;
982}
983
984static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
985{
986 /* on Vista we need to wait for the address to get applied */
987 /* wait for the address to appear in the list */
988 HRESULT hr = S_OK;
989 ULONG i;
990 *pFound = false;
991 ComPtr <IWbemClassObject> pAdapterConfig;
992 for (i = 0;
993 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
994 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
995 && !(*pFound)
996 && i < sec2Wait/6;
997 i++)
998 {
999 Sleep(6000);
1000 }
1001
1002 return hr;
1003}
1004
1005static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
1006{
1007 IWbemLocator *pLoc = NULL;
1008 HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
1009 if (SUCCEEDED(hr))
1010 {
1011 IWbemServices *pSvc = NULL;
1012 hr = pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), /* [in] const BSTR strNetworkResource */
1013 NULL, /* [in] const BSTR strUser */
1014 NULL, /* [in] const BSTR strPassword */
1015 0, /* [in] const BSTR strLocale */
1016 NULL, /* [in] LONG lSecurityFlags */
1017 0, /* [in] const BSTR strAuthority */
1018 0, /* [in] IWbemContext* pCtx */
1019 &pSvc /* [out] IWbemServices** ppNamespace */);
1020 if (SUCCEEDED(hr))
1021 {
1022 hr = CoSetProxyBlanket(pSvc, /* IUnknown * pProxy */
1023 RPC_C_AUTHN_WINNT, /* DWORD dwAuthnSvc */
1024 RPC_C_AUTHZ_NONE, /* DWORD dwAuthzSvc */
1025 NULL, /* WCHAR * pServerPrincName */
1026 RPC_C_AUTHN_LEVEL_CALL, /* DWORD dwAuthnLevel */
1027 RPC_C_IMP_LEVEL_IMPERSONATE, /* DWORD dwImpLevel */
1028 NULL, /* RPC_AUTH_IDENTITY_HANDLE pAuthInfo */
1029 EOAC_NONE /* DWORD dwCapabilities */
1030 );
1031 if (SUCCEEDED(hr))
1032 {
1033 *ppSvc = pSvc;
1034 /* do not need it any more */
1035 pLoc->Release();
1036 return hr;
1037 }
1038 else
1039 NonStandardLogFlow(("CoSetProxyBlanket failed, hr (0x%x)\n", hr));
1040
1041 pSvc->Release();
1042 }
1043 else
1044 NonStandardLogFlow(("ConnectServer failed, hr (0x%x)\n", hr));
1045 pLoc->Release();
1046 }
1047 else
1048 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
1049 return hr;
1050}
1051
1052static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
1053{
1054 VARIANT index;
1055 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
1056 if (SUCCEEDED(hr))
1057 {
1058 WCHAR strIndex[8];
1059 swprintf(strIndex, L"%u", index.uintVal);
1060 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
1061 }
1062 else
1063 NonStandardLogFlow(("Get failed, hr (0x%x)\n", hr));
1064 return hr;
1065}
1066
1067static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
1068 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
1069 IWbemClassObject** ppOutParams
1070 )
1071{
1072 HRESULT hr = S_OK;
1073 ComPtr<IWbemClassObject> pInParamsDefinition;
1074 ComPtr<IWbemClassObject> pClassInstance;
1075
1076 if (cArgs)
1077 {
1078 hr = pClass->GetMethod(MethodName, 0, pInParamsDefinition.asOutParam(), NULL);
1079 if (SUCCEEDED(hr))
1080 {
1081 hr = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
1082 if (SUCCEEDED(hr))
1083 {
1084 for (UINT i = 0; i < cArgs; i++)
1085 {
1086 hr = pClassInstance->Put(pArgNames[i], 0,
1087 pArgs[i], 0);
1088 if (FAILED(hr))
1089 break;
1090 }
1091 }
1092 }
1093 }
1094
1095 if (SUCCEEDED(hr))
1096 {
1097 IWbemClassObject* pOutParams = NULL;
1098 hr = pSvc->ExecMethod(ObjPath, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
1099 if (SUCCEEDED(hr))
1100 {
1101 *ppOutParams = pOutParams;
1102 }
1103 }
1104
1105 return hr;
1106}
1107
1108static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
1109{
1110 HRESULT hr;
1111 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
1112 if (pIpArray)
1113 {
1114 for (UINT i = 0; i < cIp; i++)
1115 {
1116 char* addr = inet_ntoa(aIp[i]);
1117 BSTR val = bstr_t(addr).copy();
1118 long aIndex[1];
1119 aIndex[0] = i;
1120 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1121 if (FAILED(hr))
1122 {
1123 SysFreeString(val);
1124 SafeArrayDestroy(pIpArray);
1125 break;
1126 }
1127 }
1128
1129 if (SUCCEEDED(hr))
1130 {
1131 *ppArray = pIpArray;
1132 }
1133 }
1134 else
1135 hr = HRESULT_FROM_WIN32(GetLastError());
1136
1137 return hr;
1138}
1139
1140static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
1141{
1142 HRESULT hr;
1143 SAFEARRAY *pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
1144 if (pIpArray)
1145 {
1146 BSTR val = bstr_t(Ip, false).copy();
1147 long aIndex[1];
1148 aIndex[0] = 0;
1149 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1150 if (FAILED(hr))
1151 {
1152 SysFreeString(val);
1153 SafeArrayDestroy(pIpArray);
1154 }
1155
1156 if (SUCCEEDED(hr))
1157 {
1158 *ppArray = pIpArray;
1159 }
1160 }
1161 else
1162 hr = HRESULT_FROM_WIN32(GetLastError());
1163
1164 return hr;
1165}
1166
1167
1168static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
1169{
1170 HRESULT hr;
1171 VariantInit(pIpAddresses);
1172 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1173 SAFEARRAY *pIpArray;
1174 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
1175 if (SUCCEEDED(hr))
1176 {
1177 pIpAddresses->parray = pIpArray;
1178 }
1179 return hr;
1180}
1181
1182static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
1183{
1184 HRESULT hr;
1185 VariantInit(pIpAddresses);
1186 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1187 SAFEARRAY *pIpArray;
1188 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
1189 if (SUCCEEDED(hr))
1190 {
1191 pIpAddresses->parray = pIpArray;
1192 }
1193 return hr;
1194}
1195
1196static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
1197{
1198 ComPtr<IWbemClassObject> pClass;
1199 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1200 HRESULT hr;
1201 if (ClassName)
1202 {
1203 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1204 if (SUCCEEDED(hr))
1205 {
1206 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
1207 LPVARIANT args[] = {pIp, pMask};
1208 ComPtr<IWbemClassObject> pOutParams;
1209
1210 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
1211 if (SUCCEEDED(hr))
1212 {
1213 VARIANT varReturnValue;
1214 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1215 &varReturnValue, NULL, 0);
1216 Assert(SUCCEEDED(hr));
1217 if (SUCCEEDED(hr))
1218 {
1219// Assert(varReturnValue.vt == VT_UINT);
1220 int winEr = varReturnValue.uintVal;
1221 switch (winEr)
1222 {
1223 case 0:
1224 {
1225 hr = S_OK;
1226// bool bFound;
1227// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
1228 }
1229 break;
1230 default:
1231 hr = HRESULT_FROM_WIN32( winEr );
1232 break;
1233 }
1234 }
1235 }
1236 }
1237 SysFreeString(ClassName);
1238 }
1239 else
1240 hr = HRESULT_FROM_WIN32(GetLastError());
1241
1242 return hr;
1243}
1244
1245
1246static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
1247{
1248 VARIANT ipAddresses;
1249 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
1250 if (SUCCEEDED(hr))
1251 {
1252 VARIANT ipMasks;
1253 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
1254 if (SUCCEEDED(hr))
1255 {
1256 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1257 VariantClear(&ipMasks);
1258 }
1259 VariantClear(&ipAddresses);
1260 }
1261 return hr;
1262}
1263
1264static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
1265{
1266 VARIANT ipAddresses;
1267 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
1268 if (SUCCEEDED(hr))
1269 {
1270 VARIANT ipMasks;
1271 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
1272 if (SUCCEEDED(hr))
1273 {
1274 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1275 VariantClear(&ipMasks);
1276 }
1277 VariantClear(&ipAddresses);
1278 }
1279 return hr;
1280}
1281
1282/* win API allows to set gw metrics as well, we are not setting them */
1283static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
1284{
1285 ComPtr<IWbemClassObject> pClass;
1286 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1287 HRESULT hr;
1288 if (ClassName)
1289 {
1290 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1291 if (SUCCEEDED(hr))
1292 {
1293 LPWSTR argNames[] = {L"DefaultIPGateway"};
1294 LPVARIANT args[] = {pGw};
1295 ComPtr<IWbemClassObject> pOutParams;
1296
1297 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
1298 if (SUCCEEDED(hr))
1299 {
1300 VARIANT varReturnValue;
1301 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1302 Assert(SUCCEEDED(hr));
1303 if (SUCCEEDED(hr))
1304 {
1305// Assert(varReturnValue.vt == VT_UINT);
1306 int winEr = varReturnValue.uintVal;
1307 switch (winEr)
1308 {
1309 case 0:
1310 hr = S_OK;
1311 break;
1312 default:
1313 hr = HRESULT_FROM_WIN32( winEr );
1314 break;
1315 }
1316 }
1317 }
1318 }
1319 SysFreeString(ClassName);
1320 }
1321 else
1322 hr = HRESULT_FROM_WIN32(GetLastError());
1323
1324 return hr;
1325}
1326
1327/* win API allows to set gw metrics as well, we are not setting them */
1328static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
1329{
1330 VARIANT gwais;
1331 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
1332 if (SUCCEEDED(hr))
1333 {
1334 netIfWinSetGateways(pSvc, ObjPath, &gwais);
1335 VariantClear(&gwais);
1336 }
1337 return hr;
1338}
1339
1340/* win API allows to set gw metrics as well, we are not setting them */
1341static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
1342{
1343 VARIANT vGw;
1344 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
1345 if (SUCCEEDED(hr))
1346 {
1347 netIfWinSetGateways(pSvc, ObjPath, &vGw);
1348 VariantClear(&vGw);
1349 }
1350 return hr;
1351}
1352
1353static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
1354{
1355 ComPtr<IWbemClassObject> pClass;
1356 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1357 HRESULT hr;
1358 if (ClassName)
1359 {
1360 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1361 if (SUCCEEDED(hr))
1362 {
1363 ComPtr<IWbemClassObject> pOutParams;
1364
1365 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
1366 if (SUCCEEDED(hr))
1367 {
1368 VARIANT varReturnValue;
1369 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1370 &varReturnValue, NULL, 0);
1371 Assert(SUCCEEDED(hr));
1372 if (SUCCEEDED(hr))
1373 {
1374// Assert(varReturnValue.vt == VT_UINT);
1375 int winEr = varReturnValue.uintVal;
1376 switch (winEr)
1377 {
1378 case 0:
1379 hr = S_OK;
1380 break;
1381 default:
1382 hr = HRESULT_FROM_WIN32( winEr );
1383 break;
1384 }
1385 }
1386 }
1387 }
1388 SysFreeString(ClassName);
1389 }
1390 else
1391 hr = HRESULT_FROM_WIN32(GetLastError());
1392
1393 return hr;
1394}
1395
1396static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
1397{
1398 ComPtr<IWbemClassObject> pClass;
1399 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1400 HRESULT hr;
1401 if (ClassName)
1402 {
1403 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1404 if (SUCCEEDED(hr))
1405 {
1406 ComPtr<IWbemClassObject> pOutParams;
1407
1408 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1409 if (SUCCEEDED(hr))
1410 {
1411 VARIANT varReturnValue;
1412 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1413 Assert(SUCCEEDED(hr));
1414 if (SUCCEEDED(hr))
1415 {
1416// Assert(varReturnValue.vt == VT_UINT);
1417 int winEr = varReturnValue.uintVal;
1418 if (winEr == 0)
1419 {
1420 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1421 if (SUCCEEDED(hr))
1422 {
1423 VARIANT varReturnValue;
1424 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1425 Assert(SUCCEEDED(hr));
1426 if (SUCCEEDED(hr))
1427 {
1428 // Assert(varReturnValue.vt == VT_UINT);
1429 int winEr = varReturnValue.uintVal;
1430 if (winEr == 0)
1431 hr = S_OK;
1432 else
1433 hr = HRESULT_FROM_WIN32( winEr );
1434 }
1435 }
1436 }
1437 else
1438 hr = HRESULT_FROM_WIN32( winEr );
1439 }
1440 }
1441 }
1442 SysFreeString(ClassName);
1443 }
1444 else
1445 hr = HRESULT_FROM_WIN32(GetLastError());
1446
1447 return hr;
1448}
1449
1450static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
1451{
1452 VARIANT vtEnabled;
1453 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1454 if (SUCCEEDED(hr))
1455 *pEnabled = vtEnabled.boolVal;
1456 return hr;
1457}
1458
1459VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(IN const GUID * pGuid, OUT PADAPTER_SETTINGS pSettings)
1460{
1461 HRESULT hr;
1462 ComPtr <IWbemServices> pSvc;
1463 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1464 if (SUCCEEDED(hr))
1465 {
1466 ComPtr<IWbemClassObject> pAdapterConfig;
1467 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1468 if (SUCCEEDED(hr))
1469 {
1470 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
1471 if (SUCCEEDED(hr))
1472 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
1473 }
1474 }
1475
1476 return hr;
1477}
1478
1479VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
1480{
1481 HRESULT hr;
1482 ComPtr <IWbemServices> pSvc;
1483 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1484 if (SUCCEEDED(hr))
1485 {
1486 ComPtr<IWbemClassObject> pAdapterConfig;
1487 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1488 if (SUCCEEDED(hr))
1489 {
1490 VARIANT vtEnabled;
1491 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1492 if (SUCCEEDED(hr))
1493 *pEnabled = vtEnabled.boolVal;
1494 }
1495 }
1496
1497 return hr;
1498}
1499
1500VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(IN const GUID *pGuid, IN ULONG ip, IN ULONG mask)
1501{
1502 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: ip=0x%x mask=0x%x", ip, mask));
1503 ComPtr<IWbemServices> pSvc;
1504 HRESULT hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1505 if (SUCCEEDED(hr))
1506 {
1507 ComPtr<IWbemClassObject> pAdapterConfig;
1508 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1509 if (SUCCEEDED(hr))
1510 {
1511 BOOL bIsHostOnly;
1512 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1513 if (SUCCEEDED(hr))
1514 {
1515 if (bIsHostOnly)
1516 {
1517 in_addr aIp[1];
1518 in_addr aMask[1];
1519 aIp[0].S_un.S_addr = ip;
1520 aMask[0].S_un.S_addr = mask;
1521
1522 BSTR ObjPath;
1523 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1524 if (SUCCEEDED(hr))
1525 {
1526 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
1527 if (SUCCEEDED(hr))
1528 {
1529#if 0
1530 in_addr aGw[1];
1531 aGw[0].S_un.S_addr = gw;
1532 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
1533 if (SUCCEEDED(hr))
1534#endif
1535 {
1536 }
1537 }
1538 SysFreeString(ObjPath);
1539 }
1540 }
1541 else
1542 {
1543 hr = E_FAIL;
1544 }
1545 }
1546 }
1547 }
1548
1549 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: returns 0x%x", hr));
1550 return hr;
1551}
1552
1553#if 0
1554static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
1555{
1556 HRESULT hr;
1557 ComPtr <IWbemServices> pSvc;
1558 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1559 if (SUCCEEDED(hr))
1560 {
1561 ComPtr<IWbemClassObject> pAdapterConfig;
1562 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1563 if (SUCCEEDED(hr))
1564 {
1565 BSTR ObjPath;
1566 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1567 if (SUCCEEDED(hr))
1568 {
1569 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
1570 if (SUCCEEDED(hr))
1571 {
1572 if (aIPV6DefaultGateway)
1573 {
1574 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
1575 }
1576 if (SUCCEEDED(hr))
1577 {
1578// hr = netIfWinUpdateConfig(pIf);
1579 }
1580 }
1581 SysFreeString(ObjPath);
1582 }
1583 }
1584 }
1585
1586 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1587}
1588
1589static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1590{
1591 RTNETADDRIPV6 Mask;
1592 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
1593 if (RT_SUCCESS(rc))
1594 {
1595 Bstr maskStr = composeIPv6Address(&Mask);
1596 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
1597 }
1598 return rc;
1599}
1600#endif
1601
1602VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(IN const GUID *pGuid)
1603{
1604 HRESULT hr;
1605 ComPtr <IWbemServices> pSvc;
1606 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1607 if (SUCCEEDED(hr))
1608 {
1609 ComPtr<IWbemClassObject> pAdapterConfig;
1610 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1611 if (SUCCEEDED(hr))
1612 {
1613 BOOL bIsHostOnly;
1614 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1615 if (SUCCEEDED(hr))
1616 {
1617 if (bIsHostOnly)
1618 {
1619 BSTR ObjPath;
1620 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1621 if (SUCCEEDED(hr))
1622 {
1623 hr = netIfWinEnableDHCP(pSvc, ObjPath);
1624 if (SUCCEEDED(hr))
1625 {
1626// hr = netIfWinUpdateConfig(pIf);
1627 }
1628 SysFreeString(ObjPath);
1629 }
1630 }
1631 else
1632 {
1633 hr = E_FAIL;
1634 }
1635 }
1636 }
1637 }
1638
1639
1640 return hr;
1641}
1642
1643VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(IN const GUID *pGuid)
1644{
1645 HRESULT hr;
1646 ComPtr <IWbemServices> pSvc;
1647 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1648 if (SUCCEEDED(hr))
1649 {
1650 ComPtr<IWbemClassObject> pAdapterConfig;
1651 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1652 if (SUCCEEDED(hr))
1653 {
1654 BOOL bIsHostOnly;
1655 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1656 if (SUCCEEDED(hr))
1657 {
1658 if (bIsHostOnly)
1659 {
1660 BSTR ObjPath;
1661 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1662 if (SUCCEEDED(hr))
1663 {
1664 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
1665 if (SUCCEEDED(hr))
1666 {
1667 //hr = netIfWinUpdateConfig(pIf);
1668 }
1669 SysFreeString(ObjPath);
1670 }
1671 }
1672 else
1673 {
1674 hr = E_FAIL;
1675 }
1676 }
1677 }
1678 }
1679
1680
1681 return hr;
1682}
1683
1684typedef bool (*PFNVBOXNETCFG_IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
1685
1686static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, PFNVBOXNETCFG_IPSETTINGS_CALLBACK pfnCallback, PVOID pContext)
1687{
1688 PIP_ADAPTER_ADDRESSES pAdapter;
1689 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1690 {
1691 PIP_ADAPTER_UNICAST_ADDRESS pAddr = pAdapter->FirstUnicastAddress;
1692 PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix;
1693
1694 if (pAddr && pPrefix)
1695 {
1696 do
1697 {
1698 bool fIPFound, fMaskFound;
1699 fIPFound = fMaskFound = false;
1700 ULONG ip, mask;
1701 for (; pAddr && !fIPFound; pAddr = pAddr->Next)
1702 {
1703 switch (pAddr->Address.lpSockaddr->sa_family)
1704 {
1705 case AF_INET:
1706 fIPFound = true;
1707 memcpy(&ip,
1708 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1709 sizeof(ip));
1710 break;
1711// case AF_INET6:
1712// break;
1713 }
1714 }
1715
1716 for (; pPrefix && !fMaskFound; pPrefix = pPrefix->Next)
1717 {
1718 switch (pPrefix->Address.lpSockaddr->sa_family)
1719 {
1720 case AF_INET:
1721 if (!pPrefix->PrefixLength || pPrefix->PrefixLength > 31) /* in case the ip helper API is queried while NetCfg write lock is held */
1722 break; /* the address values can contain illegal values */
1723 fMaskFound = true;
1724 mask = (~(((ULONG)~0) >> pPrefix->PrefixLength));
1725 mask = htonl(mask);
1726 break;
1727// case AF_INET6:
1728// break;
1729 }
1730 }
1731
1732 if (!fIPFound || !fMaskFound)
1733 break;
1734
1735 if (!pfnCallback(ip, mask, pContext))
1736 return;
1737 } while (true);
1738 }
1739 }
1740}
1741
1742typedef struct _IPPROBE_CONTEXT
1743{
1744 ULONG Prefix;
1745 bool bConflict;
1746}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
1747
1748#define IPPROBE_INIT(_pContext, _addr) \
1749 ((_pContext)->bConflict = false, \
1750 (_pContext)->Prefix = _addr)
1751
1752#define IPPROBE_INIT_STR(_pContext, _straddr) \
1753 IPROBE_INIT(_pContext, inet_addr(_straddr))
1754
1755static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
1756{
1757 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
1758
1759 if ((ip & mask) == (pProbe->Prefix & mask))
1760 {
1761 pProbe->bConflict = true;
1762 return false;
1763 }
1764
1765 return true;
1766}
1767
1768VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(OUT PULONG pNetIp, OUT PULONG pNetMask)
1769{
1770 DWORD dwRc;
1771 HRESULT hr = S_OK;
1772 /*
1773 * Most of the hosts probably have less than 10 adapters,
1774 * so we'll mostly succeed from the first attempt.
1775 */
1776 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
1777 PIP_ADAPTER_ADDRESSES 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 if (dwRc == ERROR_BUFFER_OVERFLOW)
1782 {
1783 /* Impressive! More than 10 adapters! Get more memory and try again. */
1784 free(pAddresses);
1785 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
1786 if (!pAddresses)
1787 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1788 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1789 }
1790 if (dwRc == NO_ERROR)
1791 {
1792 IPPROBE_CONTEXT Context;
1793 const ULONG ip192168 = inet_addr("192.168.0.0");
1794 srand(GetTickCount());
1795
1796 *pNetIp = 0;
1797 *pNetMask = 0;
1798
1799 for (int i = 0; i < 255; i++)
1800 {
1801 ULONG ipProbe = rand()*255/RAND_MAX;
1802 ipProbe = ip192168 | (ipProbe << 16);
1803 IPPROBE_INIT(&Context, ipProbe);
1804 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
1805 if (!Context.bConflict)
1806 {
1807 *pNetIp = ipProbe;
1808 *pNetMask = inet_addr("255.255.255.0");
1809 break;
1810 }
1811 }
1812 if (*pNetIp == 0)
1813 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
1814 }
1815 else
1816 NonStandardLogFlow(("GetAdaptersAddresses err (%d)\n", dwRc));
1817
1818 if (pAddresses)
1819 free(pAddresses);
1820
1821 if (dwRc != NO_ERROR)
1822 {
1823 hr = HRESULT_FROM_WIN32(dwRc);
1824 }
1825
1826 return hr;
1827}
1828
1829/*
1830 * convenience functions to perform netflt/adp manipulations
1831 */
1832#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
1833#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
1834
1835static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
1836{
1837 INetCfgComponent * pNcc = NULL;
1838 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
1839 if (hr == S_OK)
1840 {
1841 NonStandardLog("NetFlt is installed currently, uninstalling ...\n");
1842
1843 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
1844
1845 pNcc->Release();
1846 }
1847 else if (hr == S_FALSE)
1848 {
1849 NonStandardLog("NetFlt is not installed currently\n");
1850 hr = S_OK;
1851 }
1852 else
1853 {
1854 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
1855 hr = S_OK;
1856 }
1857
1858 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
1859 VBoxDrvCfgInfUninstallAllF(L"Net", VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
1860
1861 return hr;
1862}
1863
1864VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
1865{
1866 return vboxNetCfgWinNetFltUninstall(pNc, 0);
1867}
1868
1869VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc,
1870 IN LPCWSTR const *apInfFullPaths, IN UINT cInfFullPaths)
1871{
1872 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
1873 if (SUCCEEDED(hr))
1874 {
1875 NonStandardLog("NetFlt will be installed ...\n");
1876 hr = VBoxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
1877 &GUID_DEVCLASS_NETSERVICE,
1878 apInfFullPaths,
1879 cInfFullPaths,
1880 NULL);
1881 }
1882 return hr;
1883}
1884
1885#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
1886VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
1887{
1888 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
1889 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
1890 ULONG cbSufSize = 0;
1891
1892 if (pSuffix)
1893 {
1894 cbSize += (ULONG)wcslen(pSuffix) * 2;
1895 cbSize += 2; /* for space */
1896 }
1897
1898 if (*pcbBuf < cbSize)
1899 {
1900 *pcbBuf = cbSize;
1901 return E_FAIL;
1902 }
1903
1904 wcscpy(pBuf, VBOX_CONNECTION_NAME);
1905 if (pSuffix)
1906 {
1907 wcscat(pBuf, L" ");
1908 wcscat(pBuf, pSuffix);
1909 }
1910
1911 return S_OK;
1912}
1913
1914static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority(IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
1915{
1916 INetCfgComponentBindings *pNetCfgBindings;
1917 GUID *pGuid = (GUID*)pContext;
1918
1919 /* Get component's binding. */
1920 HRESULT hr = pNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pNetCfgBindings);
1921 if (SUCCEEDED(hr))
1922 {
1923 /* Get binding path enumerator reference. */
1924 IEnumNetCfgBindingPath *pEnumNetCfgBindPath;
1925 hr = pNetCfgBindings->EnumBindingPaths(EBP_BELOW, &pEnumNetCfgBindPath);
1926 if (SUCCEEDED(hr))
1927 {
1928 bool bFoundIface = false;
1929 hr = pEnumNetCfgBindPath->Reset();
1930 do
1931 {
1932 INetCfgBindingPath *pNetCfgBindPath;
1933 hr = pEnumNetCfgBindPath->Next(1, &pNetCfgBindPath, NULL);
1934 if (hr == S_OK)
1935 {
1936 IEnumNetCfgBindingInterface *pEnumNetCfgBindIface;
1937 hr = pNetCfgBindPath->EnumBindingInterfaces(&pEnumNetCfgBindIface);
1938 if (hr == S_OK)
1939 {
1940 pEnumNetCfgBindIface->Reset();
1941 do
1942 {
1943 INetCfgBindingInterface *pNetCfgBindIfce;
1944 hr = pEnumNetCfgBindIface->Next(1, &pNetCfgBindIfce, NULL);
1945 if (hr == S_OK)
1946 {
1947 INetCfgComponent *pNetCfgCompo;
1948 hr = pNetCfgBindIfce->GetLowerComponent(&pNetCfgCompo);
1949 if (hr == S_OK)
1950 {
1951 ULONG uComponentStatus;
1952 hr = pNetCfgCompo->GetDeviceStatus(&uComponentStatus);
1953 if (hr == S_OK)
1954 {
1955 GUID guid;
1956 hr = pNetCfgCompo->GetInstanceGuid(&guid);
1957 if ( hr == S_OK
1958 && guid == *pGuid)
1959 {
1960 hr = pNetCfgBindings->MoveAfter(pNetCfgBindPath, NULL);
1961 if (FAILED(hr))
1962 NonStandardLogFlow(("Unable to move interface, hr (0x%x)\n", hr));
1963 bFoundIface = true;
1964 }
1965 }
1966 pNetCfgCompo->Release();
1967 }
1968 else
1969 NonStandardLogFlow(("GetLowerComponent failed, hr (0x%x)\n", hr));
1970 pNetCfgBindIfce->Release();
1971 }
1972 else
1973 {
1974 if (hr == S_FALSE) /* No more binding interfaces? */
1975 hr = S_OK;
1976 else
1977 NonStandardLogFlow(("Next binding interface failed, hr (0x%x)\n", hr));
1978 break;
1979 }
1980 } while (!bFoundIface);
1981 pEnumNetCfgBindIface->Release();
1982 }
1983 else
1984 NonStandardLogFlow(("EnumBindingInterfaces failed, hr (0x%x)\n", hr));
1985 pNetCfgBindPath->Release();
1986 }
1987 else
1988 {
1989 if (hr = S_FALSE) /* No more binding paths? */
1990 hr = S_OK;
1991 else
1992 NonStandardLogFlow(("Next bind path failed, hr (0x%x)\n", hr));
1993 break;
1994 }
1995 } while (!bFoundIface);
1996 pEnumNetCfgBindPath->Release();
1997 }
1998 else
1999 NonStandardLogFlow(("EnumBindingPaths failed, hr (0x%x)\n", hr));
2000 pNetCfgBindings->Release();
2001 }
2002 else
2003 NonStandardLogFlow(("QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr));
2004 return TRUE;
2005}
2006
2007static UINT WINAPI vboxNetCfgWinPspFileCallback(
2008 PVOID Context,
2009 UINT Notification,
2010 UINT_PTR Param1,
2011 UINT_PTR Param2
2012 )
2013{
2014 switch (Notification)
2015 {
2016 case SPFILENOTIFY_TARGETNEWER:
2017 case SPFILENOTIFY_TARGETEXISTS:
2018 return TRUE;
2019 }
2020 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2021}
2022
2023/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
2024/*
2025 Copyright 2004 by the Massachusetts Institute of Technology
2026
2027 All rights reserved.
2028
2029 Permission to use, copy, modify, and distribute this software and its
2030 documentation for any purpose and without fee is hereby granted,
2031 provided that the above copyright notice appear in all copies and that
2032 both that copyright notice and this permission notice appear in
2033 supporting documentation, and that the name of the Massachusetts
2034 Institute of Technology (M.I.T.) not be used in advertising or publicity
2035 pertaining to distribution of the software without specific, written
2036 prior permission.
2037
2038 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2039 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2040 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2041 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2042 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2043 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2044 SOFTWARE.
2045*/
2046
2047
2048#define NETSHELL_LIBRARY _T("netshell.dll")
2049
2050/**
2051 * Use the IShellFolder API to rename the connection.
2052 */
2053static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
2054{
2055 /* This is the GUID for the network connections folder. It is constant.
2056 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
2057 const GUID CLSID_NetworkConnections = {
2058 0x7007ACC7, 0x3202, 0x11D1, {
2059 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
2060 }
2061 };
2062
2063 LPITEMIDLIST pidl = NULL;
2064 IShellFolder *pShellFolder = NULL;
2065 HRESULT hr;
2066
2067 /* Build the display name in the form "::{GUID}". */
2068 if (wcslen(wGuid) >= MAX_PATH)
2069 return E_INVALIDARG;
2070 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
2071 swprintf(szAdapterGuid, L"::%ls", wGuid);
2072
2073 /* Create an instance of the network connections folder. */
2074 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
2075 CLSCTX_INPROC_SERVER, IID_IShellFolder,
2076 reinterpret_cast<LPVOID *>(&pShellFolder));
2077 /* Parse the display name. */
2078 if (SUCCEEDED (hr))
2079 {
2080 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
2081 &pidl, NULL);
2082 }
2083 if (SUCCEEDED (hr))
2084 {
2085 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
2086 &pidl);
2087 }
2088
2089 CoTaskMemFree (pidl);
2090
2091 if (pShellFolder)
2092 pShellFolder->Release();
2093
2094 return hr;
2095}
2096
2097VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
2098{
2099 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
2100 lpHrRenameConnection RenameConnectionFunc = NULL;
2101 HRESULT status;
2102
2103 /* First try the IShellFolder interface, which was unimplemented
2104 * for the network connections folder before XP. */
2105 status = rename_shellfolder (pGuid, NewName);
2106 if (status == E_NOTIMPL)
2107 {
2108/** @todo that code doesn't seem to work! */
2109 /* The IShellFolder interface is not implemented on this platform.
2110 * Try the (undocumented) HrRenameConnection API in the netshell
2111 * library. */
2112 CLSID clsid;
2113 HINSTANCE hNetShell;
2114 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
2115 if (FAILED(status))
2116 return E_FAIL;
2117 hNetShell = LoadLibrary (NETSHELL_LIBRARY);
2118 if (hNetShell == NULL)
2119 return E_FAIL;
2120 RenameConnectionFunc =
2121 (lpHrRenameConnection) GetProcAddress (hNetShell,
2122 "HrRenameConnection");
2123 if (RenameConnectionFunc == NULL)
2124 {
2125 FreeLibrary (hNetShell);
2126 return E_FAIL;
2127 }
2128 status = RenameConnectionFunc (&clsid, NewName);
2129 FreeLibrary (hNetShell);
2130 }
2131 if (FAILED (status))
2132 return status;
2133
2134 return S_OK;
2135}
2136
2137#define DRIVERHWID _T("sun_VBoxNetAdp")
2138
2139#define SetErrBreak(strAndArgs) \
2140 if (1) { \
2141 hrc = E_FAIL; \
2142 NonStandardLog strAndArgs; \
2143 break; \
2144 } else do {} while (0)
2145
2146VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg)
2147{
2148 HRESULT hrc = S_OK;
2149
2150 do
2151 {
2152 TCHAR lszPnPInstanceId [512] = {0};
2153
2154 /* We have to find the device instance ID through a registry search */
2155
2156 HKEY hkeyNetwork = 0;
2157 HKEY hkeyConnection = 0;
2158
2159 do
2160 {
2161 WCHAR strRegLocation [256];
2162 WCHAR wszGuid[50];
2163
2164 int length = StringFromGUID2(*pGUID, wszGuid, RT_ELEMENTS(wszGuid));
2165 if (!length)
2166 SetErrBreak(("Failed to create a Guid string"));
2167
2168 swprintf (strRegLocation,
2169 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
2170 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
2171 wszGuid);
2172
2173 LONG status;
2174 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
2175 KEY_READ, &hkeyNetwork);
2176 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
2177 SetErrBreak (("Host interface network is not found in registry (%S) [1]",
2178 strRegLocation));
2179
2180 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
2181 KEY_READ, &hkeyConnection);
2182 if ((status != ERROR_SUCCESS) || !hkeyConnection)
2183 SetErrBreak (("Host interface network is not found in registry (%S) [2]",
2184 strRegLocation));
2185
2186 DWORD len = sizeof (lszPnPInstanceId);
2187 DWORD dwKeyType;
2188 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2189 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2190 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2191 SetErrBreak (("Host interface network is not found in registry (%S) [3]",
2192 strRegLocation));
2193 }
2194 while (0);
2195
2196 if (hkeyConnection)
2197 RegCloseKey (hkeyConnection);
2198 if (hkeyNetwork)
2199 RegCloseKey (hkeyNetwork);
2200
2201 if (FAILED (hrc))
2202 break;
2203
2204 /*
2205 * Now we are going to enumerate all network devices and
2206 * wait until we encounter the right device instance ID
2207 */
2208
2209 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2210
2211 do
2212 {
2213 BOOL ok;
2214 DWORD ret = 0;
2215 GUID netGuid;
2216 SP_DEVINFO_DATA DeviceInfoData;
2217 DWORD index = 0;
2218 BOOL found = FALSE;
2219 DWORD size = 0;
2220
2221 /* initialize the structure size */
2222 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2223
2224 /* copy the net class GUID */
2225 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2226
2227 /* return a device info set contains all installed devices of the Net class */
2228 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2229
2230 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2231 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2232
2233 /* enumerate the driver info list */
2234 while (TRUE)
2235 {
2236 TCHAR *deviceHwid;
2237
2238 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2239
2240 if (!ok)
2241 {
2242 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2243 break;
2244 else
2245 {
2246 index++;
2247 continue;
2248 }
2249 }
2250
2251 /* try to get the hardware ID registry property */
2252 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2253 &DeviceInfoData,
2254 SPDRP_HARDWAREID,
2255 NULL,
2256 NULL,
2257 0,
2258 &size);
2259 if (!ok)
2260 {
2261 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2262 {
2263 index++;
2264 continue;
2265 }
2266
2267 deviceHwid = (TCHAR *) malloc (size);
2268 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2269 &DeviceInfoData,
2270 SPDRP_HARDWAREID,
2271 NULL,
2272 (PBYTE)deviceHwid,
2273 size,
2274 NULL);
2275 if (!ok)
2276 {
2277 free (deviceHwid);
2278 deviceHwid = NULL;
2279 index++;
2280 continue;
2281 }
2282 }
2283 else
2284 {
2285 /* something is wrong. This shouldn't have worked with a NULL buffer */
2286 index++;
2287 continue;
2288 }
2289
2290 for (TCHAR *t = deviceHwid;
2291 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2292 t += _tcslen (t) + 1)
2293 {
2294 if (!_tcsicmp (DRIVERHWID, t))
2295 {
2296 /* get the device instance ID */
2297 TCHAR devID [MAX_DEVICE_ID_LEN];
2298 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2299 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2300 {
2301 /* compare to what we determined before */
2302 if (wcscmp(devID, lszPnPInstanceId) == 0)
2303 {
2304 found = TRUE;
2305 break;
2306 }
2307 }
2308 }
2309 }
2310
2311 if (deviceHwid)
2312 {
2313 free (deviceHwid);
2314 deviceHwid = NULL;
2315 }
2316
2317 if (found)
2318 break;
2319
2320 index++;
2321 }
2322
2323 if (found == FALSE)
2324 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
2325 GetLastError()));
2326
2327 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2328 if (!ok)
2329 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2330 GetLastError()));
2331
2332 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2333 if (!ok)
2334 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2335 GetLastError()));
2336 }
2337 while (0);
2338
2339 /* clean up the device info set */
2340 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2341 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2342
2343 if (FAILED (hrc))
2344 break;
2345 }
2346 while (0);
2347
2348 return hrc;
2349}
2350
2351VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
2352 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
2353{
2354 HRESULT hrc = S_OK;
2355
2356 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2357 SP_DEVINFO_DATA DeviceInfoData;
2358 PVOID pQueueCallbackContext = NULL;
2359 DWORD ret = 0;
2360 BOOL found = FALSE;
2361 BOOL registered = FALSE;
2362 BOOL destroyList = FALSE;
2363 WCHAR pWCfgGuidString [50];
2364 WCHAR DevName[256];
2365
2366 do
2367 {
2368 GUID netGuid;
2369 SP_DRVINFO_DATA DriverInfoData;
2370 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2371 TCHAR className [MAX_PATH];
2372 DWORD index = 0;
2373 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2374 /* for our purposes, 2k buffer is more
2375 * than enough to obtain the hardware ID
2376 * of the VBoxNetAdp driver. */
2377 DWORD detailBuf [2048];
2378
2379 HKEY hkey = NULL;
2380 DWORD cbSize;
2381 DWORD dwValueType;
2382
2383 /* initialize the structure size */
2384 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2385 DriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
2386
2387 /* copy the net class GUID */
2388 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2389
2390 /* create an empty device info set associated with the net class GUID */
2391 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
2392 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2393 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
2394 GetLastError()));
2395
2396 /* get the class name from GUID */
2397 BOOL fResult = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2398 if (!fResult)
2399 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
2400 GetLastError()));
2401
2402 /* create a device info element and add the new device instance
2403 * key to registry */
2404 fResult = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2405 DICD_GENERATE_ID, &DeviceInfoData);
2406 if (!fResult)
2407 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
2408 GetLastError()));
2409
2410 /* select the newly created device info to be the currently
2411 selected member */
2412 fResult = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2413 if (!fResult)
2414 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2415 GetLastError()));
2416
2417 if (pInfPath)
2418 {
2419 /* get the device install parameters and disable filecopy */
2420 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2421 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2422 &DeviceInstallParams);
2423 if (fResult)
2424 {
2425 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2426 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2427 if (pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2428 {
2429 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2430
2431 if (bIsInfPathFile)
2432 {
2433 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2434 }
2435
2436 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2437 &DeviceInstallParams);
2438 if (!fResult)
2439 {
2440 DWORD winEr = GetLastError();
2441 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2442 break;
2443 }
2444 }
2445 else
2446 {
2447 NonStandardLogFlow(("SetupDiSetDeviceInstallParams faileed: INF path is too long\n"));
2448 break;
2449 }
2450 }
2451 else
2452 {
2453 DWORD winEr = GetLastError();
2454 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2455 }
2456 }
2457
2458 /* build a list of class drivers */
2459 fResult = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2460 SPDIT_CLASSDRIVER);
2461 if (!fResult)
2462 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
2463 GetLastError()));
2464
2465 destroyList = TRUE;
2466
2467 /* enumerate the driver info list */
2468 while (TRUE)
2469 {
2470 BOOL ret;
2471
2472 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2473 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2474
2475 /* if the function failed and GetLastError() returned
2476 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2477 * list. Otherwise there was something wrong with this
2478 * particular driver. */
2479 if (!ret)
2480 {
2481 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2482 break;
2483 else
2484 {
2485 index++;
2486 continue;
2487 }
2488 }
2489
2490 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2491 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2492
2493 /* if we successfully find the hardware ID and it turns out to
2494 * be the one for the loopback driver, then we are done. */
2495 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2496 &DeviceInfoData,
2497 &DriverInfoData,
2498 pDriverInfoDetail,
2499 sizeof (detailBuf),
2500 NULL))
2501 {
2502 TCHAR * t;
2503
2504 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2505 * whole list and see if there is a match somewhere. */
2506 t = pDriverInfoDetail->HardwareID;
2507 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2508 {
2509 if (!_tcsicmp(t, DRIVERHWID))
2510 break;
2511
2512 t += _tcslen(t) + 1;
2513 }
2514
2515 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2516 {
2517 found = TRUE;
2518 break;
2519 }
2520 }
2521
2522 index ++;
2523 }
2524
2525 if (!found)
2526 SetErrBreak(("Could not find Host Interface Networking driver! Please reinstall"));
2527
2528 /* set the loopback driver to be the currently selected */
2529 fResult = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2530 &DriverInfoData);
2531 if (!fResult)
2532 SetErrBreak(("SetupDiSetSelectedDriver failed (0x%08X)",
2533 GetLastError()));
2534
2535 /* register the phantom device to prepare for install */
2536 fResult = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2537 &DeviceInfoData);
2538 if (!fResult)
2539 {
2540 DWORD err = GetLastError();
2541 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
2542 err));
2543 }
2544
2545 /* registered, but remove if errors occur in the following code */
2546 registered = TRUE;
2547
2548 /* ask the installer if we can install the device */
2549 fResult = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2550 &DeviceInfoData);
2551 if (!fResult)
2552 {
2553 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2554 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2555 GetLastError()));
2556 /* that's fine */
2557 }
2558
2559 /* get the device install parameters and disable filecopy */
2560 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2561 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2562 &DeviceInstallParams);
2563 if (fResult)
2564 {
2565 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2566 if (pQueueCallbackContext)
2567 {
2568 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2569 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2570 fResult = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2571 &DeviceInstallParams);
2572 if (!fResult)
2573 {
2574 DWORD winEr = GetLastError();
2575 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2576 }
2577 Assert(fResult);
2578 }
2579 else
2580 {
2581 DWORD winEr = GetLastError();
2582 NonStandardLogFlow(("SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr));
2583 }
2584 }
2585 else
2586 {
2587 DWORD winEr = GetLastError();
2588 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2589 }
2590
2591 /* install the files first */
2592 fResult = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2593 &DeviceInfoData);
2594 if (!fResult)
2595 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2596 GetLastError()));
2597 /* get the device install parameters and disable filecopy */
2598 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2599 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2600 &DeviceInstallParams);
2601 if (fResult)
2602 {
2603 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2604 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2605 &DeviceInstallParams);
2606 if (!fResult)
2607 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
2608 GetLastError()));
2609 }
2610
2611 /*
2612 * Register any device-specific co-installers for this device,
2613 */
2614 fResult = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
2615 hDeviceInfo,
2616 &DeviceInfoData);
2617 if (!fResult)
2618 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2619 GetLastError()));
2620
2621 /*
2622 * install any installer-specified interfaces.
2623 * and then do the real install
2624 */
2625 fResult = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
2626 hDeviceInfo,
2627 &DeviceInfoData);
2628 if (!fResult)
2629 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2630 GetLastError()));
2631
2632 fResult = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
2633 hDeviceInfo,
2634 &DeviceInfoData);
2635 if (!fResult)
2636 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2637 GetLastError()));
2638
2639 /* Figure out NetCfgInstanceId */
2640 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
2641 &DeviceInfoData,
2642 DICS_FLAG_GLOBAL,
2643 0,
2644 DIREG_DRV,
2645 KEY_READ);
2646 if (hkey == INVALID_HANDLE_VALUE)
2647 SetErrBreak(("SetupDiOpenDevRegKey failed (0x%08X)", GetLastError()));
2648
2649 cbSize = sizeof(pWCfgGuidString);
2650 DWORD ret;
2651 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2652 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2653
2654 RegCloseKey (hkey);
2655
2656 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2657 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2658 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2659 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2660 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2661 NULL /*OUT PDWORD RequiredSize OPTIONAL*/))
2662 {
2663 int err = GetLastError();
2664 if (err != ERROR_INVALID_DATA)
2665 {
2666 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2667 err));
2668 }
2669
2670 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2671 SPDRP_DEVICEDESC, /* IN DWORD Property,*/
2672 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2673 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2674 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2675 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2676 ))
2677 {
2678 err = GetLastError();
2679 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2680 err));
2681 }
2682 }
2683 }
2684 while (0);
2685
2686 /*
2687 * cleanup
2688 */
2689 if (pQueueCallbackContext)
2690 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2691
2692 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2693 {
2694 /* an error has occurred, but the device is registered, we must remove it */
2695 if (ret != 0 && registered)
2696 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2697
2698 found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
2699
2700 /* destroy the driver info list */
2701 if (destroyList)
2702 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
2703 SPDIT_CLASSDRIVER);
2704 /* clean up the device info set */
2705 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2706 }
2707
2708 /* return the network connection GUID on success */
2709 if (SUCCEEDED(hrc))
2710 {
2711 WCHAR ConnectoinName[128];
2712 ULONG cbName = sizeof(ConnectoinName);
2713
2714 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(DevName, ConnectoinName, &cbName);
2715 if (SUCCEEDED(hr))
2716 hr = VBoxNetCfgWinRenameConnection(pWCfgGuidString, ConnectoinName);
2717
2718 if (lppszName)
2719 {
2720 *lppszName = SysAllocString((const OLECHAR *) DevName);
2721 if (!*lppszName)
2722 {
2723 NonStandardLogFlow(("SysAllocString failed\n"));
2724 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2725 }
2726 }
2727
2728 if (pGuid)
2729 {
2730 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID)pGuid);
2731 if (FAILED(hrc))
2732 NonStandardLogFlow(("CLSIDFromString failed, hrc (0x%x)\n", hrc));
2733 }
2734
2735 INetCfg *pNetCfg = NULL;
2736 LPWSTR lpszApp = NULL;
2737 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, TRUE, L"VirtualBox Host-Only Creation",
2738 30 * 1000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec. */
2739 /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
2740 &lpszApp);
2741 if (hr == S_OK)
2742 {
2743 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2744 &GUID_DEVCLASS_NETSERVICE,
2745 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2746 pGuid);
2747 if (SUCCEEDED(hr))
2748 {
2749 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2750 &GUID_DEVCLASS_NETTRANS,
2751 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2752 pGuid);
2753 if (SUCCEEDED(hr))
2754 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
2755 &GUID_DEVCLASS_NETCLIENT,
2756 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2757 pGuid);
2758 }
2759
2760 if (SUCCEEDED(hr))
2761 {
2762 hr = pNetCfg->Apply();
2763 }
2764 else
2765 NonStandardLogFlow(("Enumeration failed, hr 0x%x\n", hr));
2766 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
2767 }
2768 else if (hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
2769 {
2770 NonStandardLogFlow(("Application %ws is holding the lock, failed\n", lpszApp));
2771 CoTaskMemFree(lpszApp);
2772 }
2773 else
2774 NonStandardLogFlow(("VBoxNetCfgWinQueryINetCfg failed, hr 0x%x\n", hr));
2775 }
2776 return hrc;
2777}
2778
2779#undef SetErrBreak
2780
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette