VirtualBox

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

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

hostdrivers/VBoxNetFlt/cfg: fix for ​bugref:8335: added dynamic resolving of Net Win API functions to be able to run on WinXP. It will not add default metric value on WinXP.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 124.8 KB
Line 
1/* $Id: VBoxNetCfg.cpp 60620 2016-04-21 12:12:08Z vboxsync $ */
2/** @file
3 * VBoxNetCfg.cpp - Network Configuration API.
4 */
5/*
6 * Copyright (C) 2011-2015 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16#include "VBox/VBoxNetCfg-win.h"
17#include "VBox/VBoxDrvCfg-win.h"
18
19#define _WIN32_DCOM
20
21
22#include <devguid.h>
23#include <stdio.h>
24#include <regstr.h>
25#include <shlobj.h>
26#include <cfgmgr32.h>
27#include <tchar.h>
28#include <objbase.h>
29
30#include <crtdbg.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <Wbemidl.h>
35#include <comdef.h>
36
37#include <winsock2.h>
38#include <Ws2tcpip.h>
39#include <ws2ipdef.h>
40#include <netioapi.h>
41#include <iphlpapi.h>
42
43
44#ifndef Assert /** @todo r=bird: where would this be defined? */
45//# ifdef DEBUG
46//# define Assert(_expr) assert(_expr)
47//# else
48//# define Assert(_expr) do{ }while (0)
49//# endif
50# define Assert _ASSERT
51# define AssertMsg(expr, msg) do{}while (0)
52#endif
53static LOG_ROUTINE g_Logger = NULL;
54
55static VOID DoLogging(LPCSTR szString, ...);
56#define NonStandardLog DoLogging
57#define NonStandardLogFlow(x) DoLogging x
58
59#define DbgLog /** @todo r=bird: What does this do? */
60
61#define VBOX_NETCFG_LOCK_TIME_OUT 5000 /** @todo r=bird: What does this do? */
62
63
64/*
65* Wrappers for HelpAPI functions
66*/
67typedef void FNINITIALIZEIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
68typedef FNINITIALIZEIPINTERFACEENTRY *PFNINITIALIZEIPINTERFACEENTRY;
69
70typedef NETIOAPI_API FNGETIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
71typedef FNGETIPINTERFACEENTRY *PFNGETIPINTERFACEENTRY;
72
73typedef NETIOAPI_API FNSETIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
74typedef FNSETIPINTERFACEENTRY *PFNSETIPINTERFACEENTRY;
75
76static PFNINITIALIZEIPINTERFACEENTRY g_pfnInitializeIpInterfaceEntry = NULL;
77static PFNGETIPINTERFACEENTRY g_pfnGetIpInterfaceEntry = NULL;
78static PFNSETIPINTERFACEENTRY g_pfnSetIpInterfaceEntry = NULL;
79
80
81/*
82* Forward declaration for using vboxNetCfgWinSetupMetric()
83*/
84HRESULT vboxNetCfgWinSetupMetric(IN HKEY hKey);
85HRESULT vboxNetCfgWinGetInterfaceLUID(IN HKEY hKey, OUT NET_LUID* pLUID);
86
87
88/*
89 * For some weird reason we do not want to use IPRT here, hence the following
90 * function provides a replacement for BstrFmt.
91 */
92static bstr_t bstr_printf(const char *cszFmt, ...)
93{
94 char szBuffer[4096];
95 szBuffer[sizeof(szBuffer) - 1] = 0; /* Make sure the string will be null-terminated */
96 va_list va;
97 va_start(va, cszFmt);
98 _vsnprintf(szBuffer, sizeof(szBuffer) - 1, cszFmt, va);
99 va_end(va);
100 return bstr_t(szBuffer);
101}
102
103static HRESULT vboxNetCfgWinINetCfgLock(IN INetCfg *pNetCfg,
104 IN LPCWSTR pszwClientDescription,
105 IN DWORD cmsTimeout,
106 OUT LPWSTR *ppszwClientDescription)
107{
108 INetCfgLock *pLock;
109 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
110 if (FAILED(hr))
111 {
112 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
113 return hr;
114 }
115
116 hr = pLock->AcquireWriteLock(cmsTimeout, pszwClientDescription, ppszwClientDescription);
117 if (hr == S_FALSE)
118 {
119 NonStandardLogFlow(("Write lock busy\n"));
120 }
121 else if (FAILED(hr))
122 {
123 NonStandardLogFlow(("AcquireWriteLock failed, hr (0x%x)\n", hr));
124 }
125
126 pLock->Release();
127 return hr;
128}
129
130static HRESULT vboxNetCfgWinINetCfgUnlock(IN INetCfg *pNetCfg)
131{
132 INetCfgLock *pLock;
133 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
134 if (FAILED(hr))
135 {
136 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
137 return hr;
138 }
139
140 hr = pLock->ReleaseWriteLock();
141 if (FAILED(hr))
142 NonStandardLogFlow(("ReleaseWriteLock failed, hr (0x%x)\n", hr));
143
144 pLock->Release();
145 return hr;
146}
147
148VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinQueryINetCfg(OUT INetCfg **ppNetCfg,
149 IN BOOL fGetWriteLock,
150 IN LPCWSTR pszwClientDescription,
151 IN DWORD cmsTimeout,
152 OUT LPWSTR *ppszwClientDescription)
153{
154 INetCfg *pNetCfg;
155 HRESULT hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNetCfg);
156 if (FAILED(hr))
157 {
158 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
159 return hr;
160 }
161
162 if (fGetWriteLock)
163 {
164 hr = vboxNetCfgWinINetCfgLock(pNetCfg, pszwClientDescription, cmsTimeout, ppszwClientDescription);
165 if (hr == S_FALSE)
166 {
167 NonStandardLogFlow(("Write lock is busy\n", hr));
168 hr = NETCFG_E_NO_WRITE_LOCK;
169 }
170 }
171
172 if (SUCCEEDED(hr))
173 {
174 hr = pNetCfg->Initialize(NULL);
175 if (SUCCEEDED(hr))
176 {
177 *ppNetCfg = pNetCfg;
178 return S_OK;
179 }
180 else
181 NonStandardLogFlow(("Initialize failed, hr (0x%x)\n", hr));
182 }
183
184 pNetCfg->Release();
185 return hr;
186}
187
188VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinReleaseINetCfg(IN INetCfg *pNetCfg, IN BOOL fHasWriteLock)
189{
190 if (!pNetCfg) /* If network config has been released already, just bail out. */
191 {
192 NonStandardLogFlow(("Warning: No network config given but write lock is set to TRUE\n"));
193 return S_OK;
194 }
195
196 HRESULT hr = pNetCfg->Uninitialize();
197 if (FAILED(hr))
198 {
199 NonStandardLogFlow(("Uninitialize failed, hr (0x%x)\n", hr));
200 /* Try to release the write lock below. */
201 }
202
203 if (fHasWriteLock)
204 {
205 HRESULT hr2 = vboxNetCfgWinINetCfgUnlock(pNetCfg);
206 if (FAILED(hr2))
207 NonStandardLogFlow(("vboxNetCfgWinINetCfgUnlock failed, hr (0x%x)\n", hr2));
208 if (SUCCEEDED(hr))
209 hr = hr2;
210 }
211
212 pNetCfg->Release();
213 return hr;
214}
215
216static HRESULT vboxNetCfgWinGetComponentByGuidEnum(IEnumNetCfgComponent *pEnumNcc,
217 IN const GUID *pGuid,
218 OUT INetCfgComponent **ppNcc)
219{
220 HRESULT hr = pEnumNcc->Reset();
221 if (FAILED(hr))
222 {
223 NonStandardLogFlow(("Reset failed, hr (0x%x)\n", hr));
224 return hr;
225 }
226
227 INetCfgComponent *pNcc;
228 while ((hr = pEnumNcc->Next(1, &pNcc, NULL)) == S_OK)
229 {
230 ULONG uComponentStatus;
231 hr = pNcc->GetDeviceStatus(&uComponentStatus);
232 if (SUCCEEDED(hr))
233 {
234 if (uComponentStatus == 0)
235 {
236 GUID NccGuid;
237 hr = pNcc->GetInstanceGuid(&NccGuid);
238
239 if (SUCCEEDED(hr))
240 {
241 if (NccGuid == *pGuid)
242 {
243 /* found the needed device */
244 *ppNcc = pNcc;
245 break;
246 }
247 }
248 else
249 NonStandardLogFlow(("GetInstanceGuid failed, hr (0x%x)\n", hr));
250 }
251 }
252
253 pNcc->Release();
254 }
255 return hr;
256}
257
258VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc,
259 IN const GUID *pguidClass,
260 IN const GUID * pComponentGuid,
261 OUT INetCfgComponent **ppncc)
262{
263 IEnumNetCfgComponent *pEnumNcc;
264 HRESULT hr = pNc->EnumComponents(pguidClass, &pEnumNcc);
265
266 if (SUCCEEDED(hr))
267 {
268 hr = vboxNetCfgWinGetComponentByGuidEnum(pEnumNcc, pComponentGuid, ppncc);
269 if (hr == S_FALSE)
270 {
271 NonStandardLogFlow(("Component not found\n"));
272 }
273 else if (FAILED(hr))
274 {
275 NonStandardLogFlow(("vboxNetCfgWinGetComponentByGuidEnum failed, hr (0x%x)\n", hr));
276 }
277 pEnumNcc->Release();
278 }
279 else
280 NonStandardLogFlow(("EnumComponents failed, hr (0x%x)\n", hr));
281 return hr;
282}
283
284static HRESULT vboxNetCfgWinQueryInstaller(IN INetCfg *pNetCfg, IN const GUID *pguidClass, INetCfgClassSetup **ppSetup)
285{
286 HRESULT hr = pNetCfg->QueryNetCfgClass(pguidClass, IID_INetCfgClassSetup, (void**)ppSetup);
287 if (FAILED(hr))
288 NonStandardLogFlow(("QueryNetCfgClass failed, hr (0x%x)\n", hr));
289 return hr;
290}
291
292VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
293 OUT INetCfgComponent **ppComponent)
294{
295 INetCfgClassSetup *pSetup;
296 HRESULT hr = vboxNetCfgWinQueryInstaller(pNetCfg, pguidClass, &pSetup);
297 if (FAILED(hr))
298 {
299 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
300 return hr;
301 }
302
303 OBO_TOKEN Token;
304 ZeroMemory(&Token, sizeof (Token));
305 Token.Type = OBO_USER;
306 INetCfgComponent* pTempComponent = NULL;
307
308 hr = pSetup->Install(pszwComponentId, &Token,
309 0, /* IN DWORD dwSetupFlags */
310 0, /* IN DWORD dwUpgradeFromBuildNo */
311 NULL, /* IN LPCWSTR pszwAnswerFile */
312 NULL, /* IN LPCWSTR pszwAnswerSections */
313 &pTempComponent);
314 if (SUCCEEDED(hr))
315 {
316 if (pTempComponent != NULL)
317 {
318 HKEY hkey;
319 HRESULT res;
320
321 /*
322 * Set default metric value of interface to fix multicast issue
323 * See @bugref{6379} for details.
324 */
325 res = pTempComponent->OpenParamKey(&hkey);
326 if(SUCCEEDED(res) && hkey != NULL)
327 res = vboxNetCfgWinSetupMetric(hkey);
328 if (FAILED(res))
329 {
330 /*
331 * The setting of Metric is not very important functionality,
332 * So we will not break installation process due to this error.
333 */
334 NonStandardLogFlow(("VBoxNetCfgWinInstallComponent Warning! "
335 "vboxNetCfgWinSetupMetric failed, default metric "
336 "for new interface will not be set, hr (0x%x)\n", res));
337 }
338 if (ppComponent != NULL)
339 *ppComponent = pTempComponent;
340 else
341 pTempComponent->Release();
342 }
343
344 /* ignore the apply failure */
345 HRESULT tmpHr = pNetCfg->Apply();
346 Assert(tmpHr == S_OK);
347 if (tmpHr != S_OK)
348 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", tmpHr));
349 }
350 else
351 NonStandardLogFlow(("Install failed, hr (0x%x)\n", hr));
352
353 pSetup->Release();
354 return hr;
355}
356
357static HRESULT vboxNetCfgWinInstallInfAndComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
358 IN LPCWSTR const *apInfPaths, IN UINT cInfPaths,
359 OUT INetCfgComponent **ppComponent)
360{
361 HRESULT hr = S_OK;
362 UINT cFilesProcessed = 0;
363
364 NonStandardLogFlow(("Installing %u INF files ...\n", cInfPaths));
365
366 for (; cFilesProcessed < cInfPaths; cFilesProcessed++)
367 {
368 NonStandardLogFlow(("Installing INF file \"%ws\" ...\n", apInfPaths[cFilesProcessed]));
369 hr = VBoxDrvCfgInfInstall(apInfPaths[cFilesProcessed]);
370 if (FAILED(hr))
371 {
372 NonStandardLogFlow(("VBoxNetCfgWinInfInstall failed, hr (0x%x)\n", hr));
373 break;
374 }
375 }
376
377 if (SUCCEEDED(hr))
378 {
379 hr = VBoxNetCfgWinInstallComponent(pNetCfg, pszwComponentId, pguidClass, ppComponent);
380 if (FAILED(hr))
381 NonStandardLogFlow(("VBoxNetCfgWinInstallComponent failed, hr (0x%x)\n", hr));
382 }
383
384 if (FAILED(hr))
385 {
386 NonStandardLogFlow(("Installation failed, rolling back installation set ...\n"));
387
388 do
389 {
390 HRESULT hr2 = VBoxDrvCfgInfUninstall(apInfPaths[cFilesProcessed], 0);
391 if (FAILED(hr2))
392 NonStandardLogFlow(("VBoxDrvCfgInfUninstall failed, hr (0x%x)\n", hr2));
393 /* Keep going. */
394 if (!cFilesProcessed)
395 break;
396 } while (cFilesProcessed--);
397
398 NonStandardLogFlow(("Rollback complete\n"));
399 }
400
401 return hr;
402}
403
404VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUninstallComponent(IN INetCfg *pNetCfg, IN INetCfgComponent *pComponent)
405{
406 GUID GuidClass;
407 HRESULT hr = pComponent->GetClassGuid(&GuidClass);
408 if (FAILED(hr))
409 {
410 NonStandardLogFlow(("GetClassGuid failed, hr (0x%x)\n", hr));
411 return hr;
412 }
413
414 INetCfgClassSetup *pSetup = NULL;
415 hr = vboxNetCfgWinQueryInstaller(pNetCfg, &GuidClass, &pSetup);
416 if (FAILED(hr))
417 {
418 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
419 return hr;
420 }
421
422 OBO_TOKEN Token;
423 ZeroMemory(&Token, sizeof(Token));
424 Token.Type = OBO_USER;
425
426 hr = pSetup->DeInstall(pComponent, &Token, NULL /* OUT LPWSTR *pmszwRefs */);
427 if (SUCCEEDED(hr))
428 {
429 hr = pNetCfg->Apply();
430 if (FAILED(hr))
431 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", hr));
432 }
433 else
434 NonStandardLogFlow(("DeInstall failed, hr (0x%x)\n", hr));
435
436 if (pSetup)
437 pSetup->Release();
438 return hr;
439}
440
441typedef BOOL (*VBOXNETCFGWIN_NETCFGENUM_CALLBACK) (IN INetCfg *pNetCfg, IN INetCfgComponent *pNetCfgComponent, PVOID pContext);
442
443static HRESULT vboxNetCfgWinEnumNetCfgComponents(IN INetCfg *pNetCfg,
444 IN const GUID *pguidClass,
445 VBOXNETCFGWIN_NETCFGENUM_CALLBACK callback,
446 PVOID pContext)
447{
448 IEnumNetCfgComponent *pEnumComponent;
449 HRESULT hr = pNetCfg->EnumComponents(pguidClass, &pEnumComponent);
450 if (SUCCEEDED(hr))
451 {
452 INetCfgComponent *pNetCfgComponent;
453 hr = pEnumComponent->Reset();
454 do
455 {
456 hr = pEnumComponent->Next(1, &pNetCfgComponent, NULL);
457 if (hr == S_OK)
458 {
459// ULONG uComponentStatus;
460// hr = pNcc->GetDeviceStatus(&uComponentStatus);
461// if (SUCCEEDED(hr))
462 BOOL fResult = FALSE;
463 if (pNetCfgComponent)
464 {
465 if (pContext)
466 fResult = callback(pNetCfg, pNetCfgComponent, pContext);
467 pNetCfgComponent->Release();
468 }
469
470 if (!fResult)
471 break;
472 }
473 else
474 {
475 if (hr == S_FALSE)
476 {
477 hr = S_OK;
478 }
479 else
480 NonStandardLogFlow(("Next failed, hr (0x%x)\n", hr));
481 break;
482 }
483 } while (true);
484 pEnumComponent->Release();
485 }
486 return hr;
487}
488
489/*
490 * Forward declarations of functions used in vboxNetCfgWinRemoveAllNetDevicesOfIdCallback.
491 */
492VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf);
493VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection(LPWSTR pGuid, PCWSTR NewName);
494
495static BOOL vboxNetCfgWinRemoveAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
496{
497 SP_REMOVEDEVICE_PARAMS rmdParams;
498 memset(&rmdParams, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
499 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
500 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
501 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
502
503 if (SetupDiSetClassInstallParams(hDevInfo,pDev,
504 &rmdParams.ClassInstallHeader, sizeof(rmdParams)))
505 {
506 if (SetupDiSetSelectedDevice(hDevInfo, pDev))
507 {
508#ifndef VBOXNETCFG_DELAYEDRENAME
509 /* Figure out NetCfgInstanceId. */
510 HKEY hKey = SetupDiOpenDevRegKey(hDevInfo,
511 pDev,
512 DICS_FLAG_GLOBAL,
513 0,
514 DIREG_DRV,
515 KEY_READ);
516 if (hKey == INVALID_HANDLE_VALUE)
517 {
518 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiOpenDevRegKey failed with error %ld\n",
519 GetLastError()));
520 }
521 else
522 {
523 WCHAR wszCfgGuidString[50] = { L'' };
524 DWORD cbSize = sizeof(wszCfgGuidString);
525 DWORD dwValueType;
526 DWORD ret = RegQueryValueExW(hKey, L"NetCfgInstanceId", NULL,
527 &dwValueType, (LPBYTE)wszCfgGuidString, &cbSize);
528 if (ret == ERROR_SUCCESS)
529 {
530 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Processing device ID \"%S\"\n",
531 wszCfgGuidString));
532
533 /* Figure out device name. */
534 WCHAR wszDevName[256], wszTempName[256];
535 ULONG cbName = sizeof(wszTempName);
536
537 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDev,
538 SPDRP_FRIENDLYNAME, /* IN DWORD Property,*/
539 NULL, /* OUT PDWORD PropertyRegDataType, OPTIONAL*/
540 (PBYTE)wszDevName, /* OUT PBYTE PropertyBuffer,*/
541 sizeof(wszDevName), /* IN DWORD PropertyBufferSize,*/
542 NULL /* OUT PDWORD RequiredSize OPTIONAL*/))
543 {
544 /*
545 * Rename the connection before removing the device. This will
546 * hopefully prevent an error when we will be attempting
547 * to rename a newly created connection (see @bugref{6740}).
548 */
549 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(wszDevName, wszTempName, &cbName);
550 wcscat_s(wszTempName, sizeof(wszTempName), L" removed");
551 if (SUCCEEDED(hr))
552 hr = VBoxNetCfgWinRenameConnection(wszCfgGuidString, wszTempName);
553 //NonStandardLogFlow(("VBoxNetCfgWinRenameConnection(%S,%S) => 0x%x\n", pWCfgGuidString, TempName, hr_tmp));
554 }
555 else
556 {
557 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Failed to get friendly name for device \"%S\"\n",
558 wszCfgGuidString));
559 }
560 }
561 else
562 {
563 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Querying instance ID failed with %d\n",
564 ret));
565 }
566
567 RegCloseKey(hKey);
568 }
569#endif /* VBOXNETCFG_DELAYEDRENAME */
570
571 if (SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, pDev))
572 {
573 SP_DEVINSTALL_PARAMS devParams;
574 memset(&devParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
575 devParams.cbSize = sizeof(devParams);
576
577 if (SetupDiGetDeviceInstallParams(hDevInfo, pDev, &devParams))
578 {
579 if ( (devParams.Flags & DI_NEEDRESTART)
580 || (devParams.Flags & DI_NEEDREBOOT))
581 {
582 NonStandardLog(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: A reboot is required\n"));
583 }
584 }
585 else
586 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiGetDeviceInstallParams failed with %ld\n",
587 GetLastError()));
588 }
589 else
590 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiCallClassInstaller failed with %ld\n",
591 GetLastError()));
592 }
593 else
594 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetSelectedDevice failed with %ld\n",
595 GetLastError()));
596 }
597 else
598 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetClassInstallParams failed with %ld\n",
599 GetLastError()));
600
601 /* Continue enumeration. */
602 return TRUE;
603}
604
605typedef struct VBOXNECTFGWINPROPCHANGE
606{
607 VBOXNECTFGWINPROPCHANGE_TYPE enmPcType;
608 HRESULT hr;
609} VBOXNECTFGWINPROPCHANGE ,*PVBOXNECTFGWINPROPCHANGE;
610
611static BOOL vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
612{
613 PVBOXNECTFGWINPROPCHANGE pPc = (PVBOXNECTFGWINPROPCHANGE)pContext;
614
615 SP_PROPCHANGE_PARAMS PcParams;
616 memset (&PcParams, 0, sizeof (PcParams));
617 PcParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
618 PcParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
619 PcParams.Scope = DICS_FLAG_GLOBAL;
620
621 switch(pPc->enmPcType)
622 {
623 case VBOXNECTFGWINPROPCHANGE_TYPE_DISABLE:
624 PcParams.StateChange = DICS_DISABLE;
625 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Change type (DICS_DISABLE): %d\n", pPc->enmPcType));
626 break;
627 case VBOXNECTFGWINPROPCHANGE_TYPE_ENABLE:
628 PcParams.StateChange = DICS_ENABLE;
629 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Change type (DICS_ENABLE): %d\n", pPc->enmPcType));
630 break;
631 default:
632 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Unexpected prop change type: %d\n", pPc->enmPcType));
633 pPc->hr = E_INVALIDARG;
634 return FALSE;
635 }
636
637 if (SetupDiSetClassInstallParams(hDevInfo, pDev, &PcParams.ClassInstallHeader, sizeof(PcParams)))
638 {
639 if (SetupDiSetSelectedDevice(hDevInfo, pDev))
640 {
641 if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, pDev))
642 {
643 SP_DEVINSTALL_PARAMS devParams;
644 devParams.cbSize = sizeof(devParams);
645 if (SetupDiGetDeviceInstallParams(hDevInfo,pDev,&devParams))
646 {
647 if ( (devParams.Flags & DI_NEEDRESTART)
648 || (devParams.Flags & DI_NEEDREBOOT))
649 {
650 NonStandardLog(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: A reboot is required\n"));
651 }
652 }
653 else
654 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: SetupDiGetDeviceInstallParams failed with %ld\n",
655 GetLastError()));
656 }
657 else
658 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: SetupDiCallClassInstaller failed with %ld\n",
659 GetLastError()));
660 }
661 else
662 NonStandardLogFlow(("SetupDiSetSelectedDevice failed with %ld\n", GetLastError()));
663 }
664 else
665 NonStandardLogFlow(("SetupDiSetClassInstallParams failed with %ld\n", GetLastError()));
666
667 /* Continue enumeration. */
668 return TRUE;
669}
670
671typedef BOOL (*VBOXNETCFGWIN_NETENUM_CALLBACK) (HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext);
672VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPCWSTR pwszPnPId,
673 VBOXNETCFGWIN_NETENUM_CALLBACK callback, PVOID pContext)
674{
675 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Searching for: %S\n", pwszPnPId));
676
677 HRESULT hr;
678 HDEVINFO hDevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET,
679 NULL, /* IN PCTSTR Enumerator, OPTIONAL */
680 NULL, /* IN HWND hwndParent, OPTIONAL */
681 DIGCF_PRESENT, /* IN DWORD Flags,*/
682 NULL, /* IN HDEVINFO DeviceInfoSet, OPTIONAL */
683 NULL, /* IN PCTSTR MachineName, OPTIONAL */
684 NULL /* IN PVOID Reserved */);
685 if (hDevInfo != INVALID_HANDLE_VALUE)
686 {
687 DWORD winEr;
688
689 DWORD dwDevId = 0;
690 size_t cPnPId = wcslen(pwszPnPId);
691
692 PBYTE pBuffer = NULL;
693
694 for (;;)
695 {
696 SP_DEVINFO_DATA Dev;
697 memset(&Dev, 0, sizeof(SP_DEVINFO_DATA));
698 Dev.cbSize = sizeof(SP_DEVINFO_DATA);
699
700 if (!SetupDiEnumDeviceInfo(hDevInfo, dwDevId, &Dev))
701 {
702 winEr = GetLastError();
703 if (winEr == ERROR_NO_MORE_ITEMS)
704 winEr = ERROR_SUCCESS;
705 break;
706 }
707
708 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Enumerating device %ld ... \n", dwDevId));
709 dwDevId++;
710
711 if (pBuffer)
712 free(pBuffer);
713 pBuffer = NULL;
714 DWORD cbBuffer = 0;
715 DWORD cbRequired = 0;
716
717 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &Dev,
718 SPDRP_HARDWAREID, /* IN DWORD Property */
719 NULL, /* OUT PDWORD PropertyRegDataType OPTIONAL */
720 pBuffer, /* OUT PBYTE PropertyBuffer */
721 cbBuffer, /* IN DWORD PropertyBufferSize */
722 &cbRequired /* OUT PDWORD RequiredSize OPTIONAL */))
723 {
724 winEr = GetLastError();
725 if (winEr != ERROR_INSUFFICIENT_BUFFER)
726 {
727 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (1) failed with %ld\n", winEr));
728 break;
729 }
730
731 pBuffer = (PBYTE)malloc(cbRequired);
732 if (!pBuffer)
733 {
734 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Out of memory allocating %ld bytes\n",
735 cbRequired));
736 winEr = ERROR_OUTOFMEMORY;
737 break;
738 }
739
740 cbBuffer = cbRequired;
741
742 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
743 SPDRP_HARDWAREID, /* IN DWORD Property */
744 NULL, /* OUT PDWORD PropertyRegDataType, OPTIONAL */
745 pBuffer, /* OUT PBYTE PropertyBuffer */
746 cbBuffer, /* IN DWORD PropertyBufferSize */
747 &cbRequired /* OUT PDWORD RequiredSize OPTIONAL */))
748 {
749 winEr = GetLastError();
750 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (2) failed with %ld\n",
751 winEr));
752 break;
753 }
754 }
755
756 PWSTR pCurId = (PWSTR)pBuffer;
757 size_t cCurId = wcslen(pCurId);
758
759 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Device %ld: %S\n", dwDevId, pCurId));
760
761 if (cCurId >= cPnPId)
762 {
763 NonStandardLogFlow(("!wcsnicmp(pCurId = (%S), pwszPnPId = (%S), cPnPId = (%d))\n", pCurId, pwszPnPId, cPnPId));
764
765 pCurId += cCurId - cPnPId;
766 if (!wcsnicmp(pCurId, pwszPnPId, cPnPId))
767 {
768 if (!callback(hDevInfo, &Dev, pContext))
769 break;
770 }
771 }
772 }
773
774 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Found %ld devices total\n", dwDevId));
775
776 if (pBuffer)
777 free(pBuffer);
778
779 hr = HRESULT_FROM_WIN32(winEr);
780
781 SetupDiDestroyDeviceInfoList(hDevInfo);
782 }
783 else
784 {
785 DWORD winEr = GetLastError();
786 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetClassDevsExW failed with %ld\n", winEr));
787 hr = HRESULT_FROM_WIN32(winEr);
788 }
789
790 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Ended with hr (0x%x)\n", hr));
791 return hr;
792}
793
794VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(IN LPCWSTR lpszPnPId)
795{
796 return VBoxNetCfgWinEnumNetDevices(lpszPnPId, vboxNetCfgWinRemoveAllNetDevicesOfIdCallback, NULL);
797}
798
799VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinPropChangeAllNetDevicesOfId(IN LPCWSTR lpszPnPId, VBOXNECTFGWINPROPCHANGE_TYPE enmPcType)
800{
801 VBOXNECTFGWINPROPCHANGE Pc;
802 Pc.enmPcType = enmPcType;
803 Pc.hr = S_OK;
804 NonStandardLogFlow(("Calling VBoxNetCfgWinEnumNetDevices with lpszPnPId =(%S) and vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback\n", lpszPnPId));
805
806 HRESULT hr = VBoxNetCfgWinEnumNetDevices(lpszPnPId, vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback, &Pc);
807 if (!SUCCEEDED(hr))
808 {
809 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices failed 0x%x\n", hr));
810 return hr;
811 }
812
813 if (!SUCCEEDED(Pc.hr))
814 {
815 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback failed 0x%x\n", Pc.hr));
816 return Pc.hr;
817 }
818
819 return S_OK;
820}
821
822/*
823 * logging
824 */
825static VOID DoLogging(LPCSTR szString, ...)
826{
827 LOG_ROUTINE pfnRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
828 if (pfnRoutine)
829 {
830 char szBuffer[4096] = {0};
831 va_list va;
832 va_start(va, szString);
833 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, va);
834 va_end(va);
835
836 pfnRoutine(szBuffer);
837 }
838}
839
840VBOXNETCFGWIN_DECL(VOID) VBoxNetCfgWinSetLogging(IN LOG_ROUTINE pfnLog)
841{
842 *((void * volatile *)&g_Logger) = pfnLog;
843}
844
845/*
846 * IP configuration API
847 */
848/* network settings config */
849/**
850 * Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
851 */
852template <class C>
853class ComStrongRef
854{
855protected:
856
857 static void addref (C *p) { p->AddRef(); }
858 static void release (C *p) { p->Release(); }
859};
860
861
862/**
863 * Base template for smart COM pointers. Not intended to be used directly.
864 */
865template <class C, template <class> class RefOps = ComStrongRef>
866class ComPtrBase : protected RefOps <C>
867{
868public:
869
870 /* special template to disable AddRef()/Release() */
871 template <class I>
872 class NoAddRefRelease : public I
873 {
874 private:
875#if !defined (VBOX_WITH_XPCOM)
876 STDMETHOD_(ULONG, AddRef)() = 0;
877 STDMETHOD_(ULONG, Release)() = 0;
878#else /* !defined (VBOX_WITH_XPCOM) */
879 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
880 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
881#endif /* !defined (VBOX_WITH_XPCOM) */
882 };
883
884protected:
885
886 ComPtrBase () : p (NULL) {}
887 ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
888 ComPtrBase (C *that_p) : p (that_p) { addref(); }
889
890 ~ComPtrBase() { release(); }
891
892 ComPtrBase &operator= (const ComPtrBase &that)
893 {
894 safe_assign (that.p);
895 return *this;
896 }
897
898 ComPtrBase &operator= (C *that_p)
899 {
900 safe_assign (that_p);
901 return *this;
902 }
903
904public:
905
906 void setNull()
907 {
908 release();
909 p = NULL;
910 }
911
912 bool isNull() const
913 {
914 return (p == NULL);
915 }
916
917 bool operator! () const { return isNull(); }
918
919 bool operator< (C* that_p) const { return p < that_p; }
920 bool operator== (C* that_p) const { return p == that_p; }
921
922 template <class I>
923 bool equalsTo (I *aThat) const
924 {
925 return ComPtrEquals (p, aThat);
926 }
927
928 template <class OC>
929 bool equalsTo (const ComPtrBase <OC> &oc) const
930 {
931 return equalsTo ((OC *) oc);
932 }
933
934 /** Intended to pass instances as in parameters to interface methods */
935 operator C* () const { return p; }
936
937 /**
938 * Dereferences the instance (redirects the -> operator to the managed
939 * pointer).
940 */
941 NoAddRefRelease <C> *operator-> () const
942 {
943 AssertMsg (p, ("Managed pointer must not be null\n"));
944 return (NoAddRefRelease <C> *) p;
945 }
946
947 template <class I>
948 HRESULT queryInterfaceTo (I **pp) const
949 {
950 if (pp)
951 {
952 if (p)
953 {
954 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
955 }
956 else
957 {
958 *pp = NULL;
959 return S_OK;
960 }
961 }
962
963 return E_INVALIDARG;
964 }
965
966 /** Intended to pass instances as out parameters to interface methods */
967 C **asOutParam()
968 {
969 setNull();
970 return &p;
971 }
972
973private:
974
975 void addref()
976 {
977 if (p)
978 RefOps <C>::addref (p);
979 }
980
981 void release()
982 {
983 if (p)
984 RefOps <C>::release (p);
985 }
986
987 void safe_assign (C *that_p)
988 {
989 /* be aware of self-assignment */
990 if (that_p)
991 RefOps <C>::addref (that_p);
992 release();
993 p = that_p;
994 }
995
996 C *p;
997};
998
999/**
1000 * Smart COM pointer wrapper that automatically manages refcounting of
1001 * interface pointers.
1002 *
1003 * @param I COM interface class
1004 */
1005template <class I, template <class> class RefOps = ComStrongRef>
1006class ComPtr : public ComPtrBase <I, RefOps>
1007{
1008 typedef ComPtrBase <I, RefOps> Base;
1009
1010public:
1011
1012 ComPtr () : Base() {}
1013 ComPtr (const ComPtr &that) : Base(that) {}
1014 ComPtr &operator= (const ComPtr &that)
1015 {
1016 Base::operator= (that);
1017 return *this;
1018 }
1019
1020 template <class OI>
1021 ComPtr (OI *that_p) : Base () { operator= (that_p); }
1022
1023 /* specialization for I */
1024 ComPtr (I *that_p) : Base (that_p) {}
1025
1026 template <class OC>
1027 ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
1028
1029 template <class OI>
1030 ComPtr &operator= (OI *that_p)
1031 {
1032 if (that_p)
1033 that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
1034 else
1035 Base::setNull();
1036 return *this;
1037 }
1038
1039 /* specialization for I */
1040 ComPtr &operator=(I *that_p)
1041 {
1042 Base::operator= (that_p);
1043 return *this;
1044 }
1045
1046 template <class OC>
1047 ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
1048 {
1049 return operator= ((OC *) oc);
1050 }
1051};
1052
1053static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const GUID * pGuid, IWbemClassObject **pAdapterConfig)
1054{
1055 HRESULT hr;
1056 WCHAR wszQuery[256];
1057 WCHAR wszGuid[50];
1058
1059 int length = StringFromGUID2(*pGuid, wszGuid, RT_ELEMENTS(wszGuid));
1060 if (length)
1061 {
1062 swprintf(wszQuery, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", wszGuid);
1063 IEnumWbemClassObject* pEnumerator = NULL;
1064 hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(wszQuery), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
1065 NULL, &pEnumerator);
1066 if (SUCCEEDED(hr))
1067 {
1068 if (pEnumerator)
1069 {
1070 IWbemClassObject *pclsObj;
1071 ULONG uReturn = 0;
1072 hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
1073 NonStandardLogFlow(("netIfWinFindAdapterClassById: IEnumWbemClassObject::Next -> hr=0x%x pclsObj=%p uReturn=%u 42=%u\n",
1074 hr, (void *)pclsObj, uReturn, 42));
1075 if (SUCCEEDED(hr))
1076 {
1077 if (uReturn && pclsObj != NULL)
1078 {
1079 *pAdapterConfig = pclsObj;
1080 pEnumerator->Release();
1081 NonStandardLogFlow(("netIfWinFindAdapterClassById: S_OK and %p\n", *pAdapterConfig));
1082 return S_OK;
1083 }
1084
1085 hr = E_FAIL;
1086 }
1087
1088 pEnumerator->Release();
1089 }
1090 else
1091 {
1092 NonStandardLogFlow(("ExecQuery returned no enumerator\n"));
1093 hr = E_FAIL;
1094 }
1095 }
1096 else
1097 NonStandardLogFlow(("ExecQuery failed (0x%x)\n", hr));
1098 }
1099 else
1100 {
1101 DWORD winEr = GetLastError();
1102 hr = HRESULT_FROM_WIN32( winEr );
1103 if (SUCCEEDED(hr))
1104 hr = E_FAIL;
1105 NonStandardLogFlow(("StringFromGUID2 failed winEr=%u, hr=0x%x\n", winEr, hr));
1106 }
1107
1108 NonStandardLogFlow(("netIfWinFindAdapterClassById: 0x%x and %p\n", hr, *pAdapterConfig));
1109 return hr;
1110}
1111
1112static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
1113{
1114 VARIANT vtServiceName;
1115 BOOL bIsHostOnly = FALSE;
1116 VariantInit(&vtServiceName);
1117
1118 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0 /*lFlags*/, &vtServiceName, NULL /*pvtType*/, NULL /*plFlavor*/);
1119 if (SUCCEEDED(hr))
1120 {
1121 *pbIsHostOnly = bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp");
1122
1123 VariantClear(&vtServiceName);
1124 }
1125
1126 return hr;
1127}
1128
1129static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
1130{
1131 VARIANT vtIp;
1132 HRESULT hr;
1133 VariantInit(&vtIp);
1134
1135 *pIpv4 = 0;
1136 *pMaskv4 = 0;
1137
1138 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
1139 if (SUCCEEDED(hr))
1140 {
1141 if (vtIp.vt == (VT_ARRAY | VT_BSTR))
1142 {
1143 VARIANT vtMask;
1144 VariantInit(&vtMask);
1145 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
1146 if (SUCCEEDED(hr))
1147 {
1148 if (vtMask.vt == (VT_ARRAY | VT_BSTR))
1149 {
1150 SAFEARRAY * pIpArray = vtIp.parray;
1151 SAFEARRAY * pMaskArray = vtMask.parray;
1152 if (pIpArray && pMaskArray)
1153 {
1154 BSTR pCurIp;
1155 BSTR pCurMask;
1156 for (LONG i = 0;
1157 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
1158 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
1159 i++)
1160 {
1161 bstr_t ip(pCurIp);
1162
1163 ULONG Ipv4 = inet_addr((char*)(ip));
1164 if (Ipv4 != INADDR_NONE)
1165 {
1166 *pIpv4 = Ipv4;
1167 bstr_t mask(pCurMask);
1168 *pMaskv4 = inet_addr((char*)(mask));
1169 break;
1170 }
1171 }
1172 }
1173 }
1174 else
1175 {
1176 *pIpv4 = 0;
1177 *pMaskv4 = 0;
1178 }
1179
1180 VariantClear(&vtMask);
1181 }
1182 }
1183 else
1184 {
1185 *pIpv4 = 0;
1186 *pMaskv4 = 0;
1187 }
1188
1189 VariantClear(&vtIp);
1190 }
1191
1192 return hr;
1193}
1194
1195
1196static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
1197{
1198 VARIANT vtIp;
1199 HRESULT hr;
1200 VariantInit(&vtIp);
1201
1202 *pFound = false;
1203
1204 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
1205 if (SUCCEEDED(hr))
1206 {
1207 VARIANT vtMask;
1208 VariantInit(&vtMask);
1209 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
1210 if (SUCCEEDED(hr))
1211 {
1212 SAFEARRAY * pIpArray = vtIp.parray;
1213 SAFEARRAY * pMaskArray = vtMask.parray;
1214 if (pIpArray && pMaskArray)
1215 {
1216 BSTR pIp, pMask;
1217 for (LONG k = 0;
1218 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
1219 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
1220 k++)
1221 {
1222 BSTR pCurIp;
1223 BSTR pCurMask;
1224 for (LONG i = 0;
1225 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
1226 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
1227 i++)
1228 {
1229 if (!wcsicmp(pCurIp, pIp))
1230 {
1231 if (!wcsicmp(pCurMask, pMask))
1232 *pFound = true;
1233 break;
1234 }
1235 }
1236 }
1237 }
1238
1239
1240 VariantClear(&vtMask);
1241 }
1242
1243 VariantClear(&vtIp);
1244 }
1245
1246 return hr;
1247}
1248
1249static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
1250{
1251 /* on Vista we need to wait for the address to get applied */
1252 /* wait for the address to appear in the list */
1253 HRESULT hr = S_OK;
1254 ULONG i;
1255 *pFound = false;
1256 ComPtr <IWbemClassObject> pAdapterConfig;
1257 for (i = 0;
1258 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
1259 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
1260 && !(*pFound)
1261 && i < sec2Wait/6;
1262 i++)
1263 {
1264 Sleep(6000);
1265 }
1266
1267 return hr;
1268}
1269
1270static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
1271{
1272 IWbemLocator *pLoc = NULL;
1273 HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
1274 if (SUCCEEDED(hr))
1275 {
1276 IWbemServices *pSvc = NULL;
1277 hr = pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), /* [in] const BSTR strNetworkResource */
1278 NULL, /* [in] const BSTR strUser */
1279 NULL, /* [in] const BSTR strPassword */
1280 0, /* [in] const BSTR strLocale */
1281 NULL, /* [in] LONG lSecurityFlags */
1282 0, /* [in] const BSTR strAuthority */
1283 0, /* [in] IWbemContext* pCtx */
1284 &pSvc /* [out] IWbemServices** ppNamespace */);
1285 if (SUCCEEDED(hr))
1286 {
1287 hr = CoSetProxyBlanket(pSvc, /* IUnknown * pProxy */
1288 RPC_C_AUTHN_WINNT, /* DWORD dwAuthnSvc */
1289 RPC_C_AUTHZ_NONE, /* DWORD dwAuthzSvc */
1290 NULL, /* WCHAR * pServerPrincName */
1291 RPC_C_AUTHN_LEVEL_CALL, /* DWORD dwAuthnLevel */
1292 RPC_C_IMP_LEVEL_IMPERSONATE, /* DWORD dwImpLevel */
1293 NULL, /* RPC_AUTH_IDENTITY_HANDLE pAuthInfo */
1294 EOAC_NONE /* DWORD dwCapabilities */
1295 );
1296 if (SUCCEEDED(hr))
1297 {
1298 *ppSvc = pSvc;
1299 /* do not need it any more */
1300 pLoc->Release();
1301 return hr;
1302 }
1303 else
1304 NonStandardLogFlow(("CoSetProxyBlanket failed, hr (0x%x)\n", hr));
1305
1306 pSvc->Release();
1307 }
1308 else
1309 NonStandardLogFlow(("ConnectServer failed, hr (0x%x)\n", hr));
1310 pLoc->Release();
1311 }
1312 else
1313 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
1314 return hr;
1315}
1316
1317static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
1318{
1319 VARIANT index;
1320 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
1321 if (SUCCEEDED(hr))
1322 {
1323 WCHAR strIndex[8];
1324 swprintf(strIndex, L"%u", index.uintVal);
1325 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
1326 }
1327 else
1328 NonStandardLogFlow(("Get failed, hr (0x%x)\n", hr));
1329 return hr;
1330}
1331
1332static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
1333 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
1334 IWbemClassObject** ppOutParams
1335 )
1336{
1337 HRESULT hr = S_OK;
1338 ComPtr<IWbemClassObject> pInParamsDefinition;
1339 ComPtr<IWbemClassObject> pClassInstance;
1340
1341 if (cArgs)
1342 {
1343 hr = pClass->GetMethod(MethodName, 0, pInParamsDefinition.asOutParam(), NULL);
1344 if (SUCCEEDED(hr))
1345 {
1346 hr = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
1347 if (SUCCEEDED(hr))
1348 {
1349 for (UINT i = 0; i < cArgs; i++)
1350 {
1351 hr = pClassInstance->Put(pArgNames[i], 0,
1352 pArgs[i], 0);
1353 if (FAILED(hr))
1354 break;
1355 }
1356 }
1357 }
1358 }
1359
1360 if (SUCCEEDED(hr))
1361 {
1362 IWbemClassObject* pOutParams = NULL;
1363 hr = pSvc->ExecMethod(ObjPath, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
1364 if (SUCCEEDED(hr))
1365 {
1366 *ppOutParams = pOutParams;
1367 }
1368 }
1369
1370 return hr;
1371}
1372
1373static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
1374{
1375 HRESULT hr;
1376 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
1377 if (pIpArray)
1378 {
1379 for (UINT i = 0; i < cIp; i++)
1380 {
1381 char* addr = inet_ntoa(aIp[i]);
1382 BSTR val = bstr_t(addr).copy();
1383 long aIndex[1];
1384 aIndex[0] = i;
1385 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1386 if (FAILED(hr))
1387 {
1388 SysFreeString(val);
1389 SafeArrayDestroy(pIpArray);
1390 break;
1391 }
1392 }
1393
1394 if (SUCCEEDED(hr))
1395 {
1396 *ppArray = pIpArray;
1397 }
1398 }
1399 else
1400 hr = HRESULT_FROM_WIN32(GetLastError());
1401
1402 return hr;
1403}
1404
1405static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
1406{
1407 HRESULT hr;
1408 SAFEARRAY *pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
1409 if (pIpArray)
1410 {
1411 BSTR val = bstr_t(Ip, false).copy();
1412 long aIndex[1];
1413 aIndex[0] = 0;
1414 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1415 if (FAILED(hr))
1416 {
1417 SysFreeString(val);
1418 SafeArrayDestroy(pIpArray);
1419 }
1420
1421 if (SUCCEEDED(hr))
1422 {
1423 *ppArray = pIpArray;
1424 }
1425 }
1426 else
1427 hr = HRESULT_FROM_WIN32(GetLastError());
1428
1429 return hr;
1430}
1431
1432
1433static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
1434{
1435 HRESULT hr;
1436 VariantInit(pIpAddresses);
1437 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1438 SAFEARRAY *pIpArray;
1439 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
1440 if (SUCCEEDED(hr))
1441 {
1442 pIpAddresses->parray = pIpArray;
1443 }
1444 return hr;
1445}
1446
1447static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
1448{
1449 HRESULT hr;
1450 VariantInit(pIpAddresses);
1451 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1452 SAFEARRAY *pIpArray;
1453 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
1454 if (SUCCEEDED(hr))
1455 {
1456 pIpAddresses->parray = pIpArray;
1457 }
1458 return hr;
1459}
1460
1461static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
1462{
1463 ComPtr<IWbemClassObject> pClass;
1464 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1465 HRESULT hr;
1466 if (ClassName)
1467 {
1468 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1469 if (SUCCEEDED(hr))
1470 {
1471 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
1472 LPVARIANT args[] = {pIp, pMask};
1473 ComPtr<IWbemClassObject> pOutParams;
1474
1475 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
1476 if (SUCCEEDED(hr))
1477 {
1478 VARIANT varReturnValue;
1479 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1480 &varReturnValue, NULL, 0);
1481 Assert(SUCCEEDED(hr));
1482 if (SUCCEEDED(hr))
1483 {
1484// Assert(varReturnValue.vt == VT_UINT);
1485 int winEr = varReturnValue.uintVal;
1486 switch (winEr)
1487 {
1488 case 0:
1489 {
1490 hr = S_OK;
1491// bool bFound;
1492// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
1493 }
1494 break;
1495 default:
1496 hr = HRESULT_FROM_WIN32( winEr );
1497 break;
1498 }
1499 }
1500 }
1501 }
1502 SysFreeString(ClassName);
1503 }
1504 else
1505 hr = HRESULT_FROM_WIN32(GetLastError());
1506
1507 return hr;
1508}
1509
1510
1511static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
1512{
1513 VARIANT ipAddresses;
1514 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
1515 if (SUCCEEDED(hr))
1516 {
1517 VARIANT ipMasks;
1518 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
1519 if (SUCCEEDED(hr))
1520 {
1521 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1522 VariantClear(&ipMasks);
1523 }
1524 VariantClear(&ipAddresses);
1525 }
1526 return hr;
1527}
1528
1529static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
1530{
1531 VARIANT ipAddresses;
1532 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
1533 if (SUCCEEDED(hr))
1534 {
1535 VARIANT ipMasks;
1536 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
1537 if (SUCCEEDED(hr))
1538 {
1539 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1540 VariantClear(&ipMasks);
1541 }
1542 VariantClear(&ipAddresses);
1543 }
1544 return hr;
1545}
1546
1547/* win API allows to set gw metrics as well, we are not setting them */
1548static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
1549{
1550 ComPtr<IWbemClassObject> pClass;
1551 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1552 HRESULT hr;
1553 if (ClassName)
1554 {
1555 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1556 if (SUCCEEDED(hr))
1557 {
1558 LPWSTR argNames[] = {L"DefaultIPGateway"};
1559 LPVARIANT args[] = {pGw};
1560 ComPtr<IWbemClassObject> pOutParams;
1561
1562 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
1563 if (SUCCEEDED(hr))
1564 {
1565 VARIANT varReturnValue;
1566 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1567 Assert(SUCCEEDED(hr));
1568 if (SUCCEEDED(hr))
1569 {
1570// Assert(varReturnValue.vt == VT_UINT);
1571 int winEr = varReturnValue.uintVal;
1572 switch (winEr)
1573 {
1574 case 0:
1575 hr = S_OK;
1576 break;
1577 default:
1578 hr = HRESULT_FROM_WIN32( winEr );
1579 break;
1580 }
1581 }
1582 }
1583 }
1584 SysFreeString(ClassName);
1585 }
1586 else
1587 hr = HRESULT_FROM_WIN32(GetLastError());
1588
1589 return hr;
1590}
1591
1592/* win API allows to set gw metrics as well, we are not setting them */
1593static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
1594{
1595 VARIANT gwais;
1596 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
1597 if (SUCCEEDED(hr))
1598 {
1599 netIfWinSetGateways(pSvc, ObjPath, &gwais);
1600 VariantClear(&gwais);
1601 }
1602 return hr;
1603}
1604
1605/* win API allows to set gw metrics as well, we are not setting them */
1606static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
1607{
1608 VARIANT vGw;
1609 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
1610 if (SUCCEEDED(hr))
1611 {
1612 netIfWinSetGateways(pSvc, ObjPath, &vGw);
1613 VariantClear(&vGw);
1614 }
1615 return hr;
1616}
1617
1618static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
1619{
1620 ComPtr<IWbemClassObject> pClass;
1621 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1622 HRESULT hr;
1623 if (ClassName)
1624 {
1625 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1626 if (SUCCEEDED(hr))
1627 {
1628 ComPtr<IWbemClassObject> pOutParams;
1629
1630 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
1631 if (SUCCEEDED(hr))
1632 {
1633 VARIANT varReturnValue;
1634 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1635 &varReturnValue, NULL, 0);
1636 Assert(SUCCEEDED(hr));
1637 if (SUCCEEDED(hr))
1638 {
1639// Assert(varReturnValue.vt == VT_UINT);
1640 int winEr = varReturnValue.uintVal;
1641 switch (winEr)
1642 {
1643 case 0:
1644 hr = S_OK;
1645 break;
1646 default:
1647 hr = HRESULT_FROM_WIN32( winEr );
1648 break;
1649 }
1650 }
1651 }
1652 }
1653 SysFreeString(ClassName);
1654 }
1655 else
1656 hr = HRESULT_FROM_WIN32(GetLastError());
1657
1658 return hr;
1659}
1660
1661static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
1662{
1663 ComPtr<IWbemClassObject> pClass;
1664 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1665 HRESULT hr;
1666 if (ClassName)
1667 {
1668 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1669 if (SUCCEEDED(hr))
1670 {
1671 ComPtr<IWbemClassObject> pOutParams;
1672
1673 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1674 if (SUCCEEDED(hr))
1675 {
1676 VARIANT varReturnValue;
1677 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1678 Assert(SUCCEEDED(hr));
1679 if (SUCCEEDED(hr))
1680 {
1681// Assert(varReturnValue.vt == VT_UINT);
1682 int winEr = varReturnValue.uintVal;
1683 if (winEr == 0)
1684 {
1685 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1686 if (SUCCEEDED(hr))
1687 {
1688 VARIANT varReturnValue;
1689 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1690 Assert(SUCCEEDED(hr));
1691 if (SUCCEEDED(hr))
1692 {
1693 // Assert(varReturnValue.vt == VT_UINT);
1694 int winEr = varReturnValue.uintVal;
1695 if (winEr == 0)
1696 hr = S_OK;
1697 else
1698 hr = HRESULT_FROM_WIN32( winEr );
1699 }
1700 }
1701 }
1702 else
1703 hr = HRESULT_FROM_WIN32( winEr );
1704 }
1705 }
1706 }
1707 SysFreeString(ClassName);
1708 }
1709 else
1710 hr = HRESULT_FROM_WIN32(GetLastError());
1711
1712 return hr;
1713}
1714
1715static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
1716{
1717 VARIANT vtEnabled;
1718 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1719 if (SUCCEEDED(hr))
1720 *pEnabled = vtEnabled.boolVal;
1721 return hr;
1722}
1723
1724VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(IN const GUID * pGuid, OUT PADAPTER_SETTINGS pSettings)
1725{
1726 HRESULT hr;
1727 ComPtr <IWbemServices> pSvc;
1728 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1729 if (SUCCEEDED(hr))
1730 {
1731 ComPtr<IWbemClassObject> pAdapterConfig;
1732 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1733 if (SUCCEEDED(hr))
1734 {
1735 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
1736 if (SUCCEEDED(hr))
1737 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
1738 }
1739 }
1740
1741 return hr;
1742}
1743
1744VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
1745{
1746 HRESULT hr;
1747 ComPtr <IWbemServices> pSvc;
1748 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1749 if (SUCCEEDED(hr))
1750 {
1751 ComPtr<IWbemClassObject> pAdapterConfig;
1752 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1753 if (SUCCEEDED(hr))
1754 {
1755 VARIANT vtEnabled;
1756 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1757 if (SUCCEEDED(hr))
1758 *pEnabled = vtEnabled.boolVal;
1759 }
1760 }
1761
1762 return hr;
1763}
1764
1765VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(IN const GUID *pGuid, IN ULONG ip, IN ULONG mask)
1766{
1767 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: ip=0x%x mask=0x%x\n", ip, mask));
1768 ComPtr<IWbemServices> pSvc;
1769 HRESULT hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1770 if (SUCCEEDED(hr))
1771 {
1772 ComPtr<IWbemClassObject> pAdapterConfig;
1773 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1774 if (SUCCEEDED(hr))
1775 {
1776 BOOL bIsHostOnly;
1777 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1778 if (SUCCEEDED(hr))
1779 {
1780 if (bIsHostOnly)
1781 {
1782 in_addr aIp[1];
1783 in_addr aMask[1];
1784 aIp[0].S_un.S_addr = ip;
1785 aMask[0].S_un.S_addr = mask;
1786
1787 BSTR ObjPath;
1788 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1789 if (SUCCEEDED(hr))
1790 {
1791 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
1792 if (SUCCEEDED(hr))
1793 {
1794#if 0
1795 in_addr aGw[1];
1796 aGw[0].S_un.S_addr = gw;
1797 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
1798 if (SUCCEEDED(hr))
1799#endif
1800 {
1801 }
1802 }
1803 SysFreeString(ObjPath);
1804 }
1805 }
1806 else
1807 {
1808 hr = E_FAIL;
1809 }
1810 }
1811 }
1812 }
1813
1814 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: returns 0x%x\n", hr));
1815 return hr;
1816}
1817
1818#if 0
1819static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
1820{
1821 HRESULT hr;
1822 ComPtr <IWbemServices> pSvc;
1823 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1824 if (SUCCEEDED(hr))
1825 {
1826 ComPtr<IWbemClassObject> pAdapterConfig;
1827 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1828 if (SUCCEEDED(hr))
1829 {
1830 BSTR ObjPath;
1831 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1832 if (SUCCEEDED(hr))
1833 {
1834 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
1835 if (SUCCEEDED(hr))
1836 {
1837 if (aIPV6DefaultGateway)
1838 {
1839 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
1840 }
1841 if (SUCCEEDED(hr))
1842 {
1843// hr = netIfWinUpdateConfig(pIf);
1844 }
1845 }
1846 SysFreeString(ObjPath);
1847 }
1848 }
1849 }
1850
1851 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1852}
1853
1854static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1855{
1856 RTNETADDRIPV6 Mask;
1857 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
1858 if (RT_SUCCESS(rc))
1859 {
1860 Bstr maskStr = composeIPv6Address(&Mask);
1861 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
1862 }
1863 return rc;
1864}
1865#endif
1866
1867VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(IN const GUID *pGuid)
1868{
1869 HRESULT hr;
1870 ComPtr <IWbemServices> pSvc;
1871 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1872 if (SUCCEEDED(hr))
1873 {
1874 ComPtr<IWbemClassObject> pAdapterConfig;
1875 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1876 if (SUCCEEDED(hr))
1877 {
1878 BOOL bIsHostOnly;
1879 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1880 if (SUCCEEDED(hr))
1881 {
1882 if (bIsHostOnly)
1883 {
1884 BSTR ObjPath;
1885 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1886 if (SUCCEEDED(hr))
1887 {
1888 hr = netIfWinEnableDHCP(pSvc, ObjPath);
1889 if (SUCCEEDED(hr))
1890 {
1891// hr = netIfWinUpdateConfig(pIf);
1892 }
1893 SysFreeString(ObjPath);
1894 }
1895 }
1896 else
1897 {
1898 hr = E_FAIL;
1899 }
1900 }
1901 }
1902 }
1903
1904
1905 return hr;
1906}
1907
1908VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(IN const GUID *pGuid)
1909{
1910 HRESULT hr;
1911 ComPtr <IWbemServices> pSvc;
1912 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1913 if (SUCCEEDED(hr))
1914 {
1915 ComPtr<IWbemClassObject> pAdapterConfig;
1916 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1917 if (SUCCEEDED(hr))
1918 {
1919 BOOL bIsHostOnly;
1920 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1921 if (SUCCEEDED(hr))
1922 {
1923 if (bIsHostOnly)
1924 {
1925 BSTR ObjPath;
1926 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1927 if (SUCCEEDED(hr))
1928 {
1929 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
1930 if (SUCCEEDED(hr))
1931 {
1932 //hr = netIfWinUpdateConfig(pIf);
1933 }
1934 SysFreeString(ObjPath);
1935 }
1936 }
1937 else
1938 {
1939 hr = E_FAIL;
1940 }
1941 }
1942 }
1943 }
1944
1945
1946 return hr;
1947}
1948
1949static const char *vboxNetCfgWinAddrToStr(char *pszBuf, LPSOCKADDR pAddr)
1950{
1951 switch (pAddr->sa_family)
1952 {
1953 case AF_INET:
1954 sprintf(pszBuf, "%d.%d.%d.%d",
1955 ((PSOCKADDR_IN)pAddr)->sin_addr.S_un.S_un_b.s_b1,
1956 ((PSOCKADDR_IN)pAddr)->sin_addr.S_un.S_un_b.s_b2,
1957 ((PSOCKADDR_IN)pAddr)->sin_addr.S_un.S_un_b.s_b3,
1958 ((PSOCKADDR_IN)pAddr)->sin_addr.S_un.S_un_b.s_b4);
1959 break;
1960 case AF_INET6:
1961 sprintf(pszBuf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
1962 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[0], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[1],
1963 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[2], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[3],
1964 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[4], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[5],
1965 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[6], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[7],
1966 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[8], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[9],
1967 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[10], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[11],
1968 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[12], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[13],
1969 ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[14], ((PSOCKADDR_IN6)pAddr)->sin6_addr.s6_addr[15]);
1970 break;
1971 default:
1972 strcpy(pszBuf, "unknown");
1973 break;
1974 }
1975 return pszBuf;
1976}
1977
1978typedef bool (*PFNVBOXNETCFG_IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
1979
1980static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, PFNVBOXNETCFG_IPSETTINGS_CALLBACK pfnCallback, PVOID pContext)
1981{
1982 PIP_ADAPTER_ADDRESSES pAdapter;
1983 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1984 {
1985 char szBuf[80];
1986
1987 NonStandardLogFlow(("+- Enumerating adapter '%ls' %s\n", pAdapter->FriendlyName, pAdapter->AdapterName));
1988 for (PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
1989 {
1990 const char *pcszAddress = vboxNetCfgWinAddrToStr(szBuf, pPrefix->Address.lpSockaddr);
1991 /* We are concerned with IPv4 only, ignore the rest. */
1992 if (pPrefix->Address.lpSockaddr->sa_family != AF_INET)
1993 {
1994 NonStandardLogFlow(("| +- %s %d: not IPv4, ignoring\n", pcszAddress, pPrefix->PrefixLength));
1995 continue;
1996 }
1997 /* Ignore invalid prefixes as well as host addresses. */
1998 if (pPrefix->PrefixLength < 1 || pPrefix->PrefixLength > 31)
1999 {
2000 NonStandardLogFlow(("| +- %s %d: host or broadcast, ignoring\n", pcszAddress, pPrefix->PrefixLength));
2001 continue;
2002 }
2003 /* Ignore multicast and beyond. */
2004 ULONG ip = ((struct sockaddr_in *)pPrefix->Address.lpSockaddr)->sin_addr.s_addr;
2005 if ((ip & 0xF0) > 224)
2006 {
2007 NonStandardLogFlow(("| +- %s %d: multicast, ignoring\n", pcszAddress, pPrefix->PrefixLength));
2008 continue;
2009 }
2010 ULONG mask = htonl((~(((ULONG)~0) >> pPrefix->PrefixLength)));
2011 bool fContinue = pfnCallback(ip, mask, pContext);
2012 if (!fContinue)
2013 {
2014 NonStandardLogFlow(("| +- %s %d: CONFLICT!\n", pcszAddress, pPrefix->PrefixLength));
2015 return;
2016 }
2017 else
2018 NonStandardLogFlow(("| +- %s %d: no conflict, moving on\n", pcszAddress, pPrefix->PrefixLength));
2019 }
2020 }
2021}
2022
2023typedef struct _IPPROBE_CONTEXT
2024{
2025 ULONG Prefix;
2026 bool bConflict;
2027}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
2028
2029#define IPPROBE_INIT(_pContext, _addr) \
2030 ((_pContext)->bConflict = false, \
2031 (_pContext)->Prefix = _addr)
2032
2033#define IPPROBE_INIT_STR(_pContext, _straddr) \
2034 IPROBE_INIT(_pContext, inet_addr(_straddr))
2035
2036static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
2037{
2038 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
2039
2040 if ((ip & mask) == (pProbe->Prefix & mask))
2041 {
2042 pProbe->bConflict = true;
2043 return false;
2044 }
2045
2046 return true;
2047}
2048
2049VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(OUT PULONG pNetIp, OUT PULONG pNetMask)
2050{
2051 DWORD dwRc;
2052 HRESULT hr = S_OK;
2053 /*
2054 * MSDN recommends to pre-allocate a 15KB buffer.
2055 */
2056 ULONG uBufLen = 15 * 1024;
2057 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
2058 if (!pAddresses)
2059 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2060 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
2061 if (dwRc == ERROR_BUFFER_OVERFLOW)
2062 {
2063 /* Impressive! More than 10 adapters! Get more memory and try again. */
2064 free(pAddresses);
2065 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
2066 if (!pAddresses)
2067 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2068 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
2069 }
2070 if (dwRc == NO_ERROR)
2071 {
2072 IPPROBE_CONTEXT Context;
2073 const ULONG ip192168 = inet_addr("192.168.0.0");
2074 srand(GetTickCount());
2075
2076 *pNetIp = 0;
2077 *pNetMask = 0;
2078
2079 for (int i = 0; i < 255; i++)
2080 {
2081 ULONG ipProbe = rand()*255/RAND_MAX;
2082 ipProbe = ip192168 | (ipProbe << 16);
2083 unsigned char *a = (unsigned char *)&ipProbe;
2084 NonStandardLogFlow(("probing %d.%d.%d.%d\n", a[0], a[1], a[2], a[3]));
2085 IPPROBE_INIT(&Context, ipProbe);
2086 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
2087 if (!Context.bConflict)
2088 {
2089 NonStandardLogFlow(("found unused net %d.%d.%d.%d\n", a[0], a[1], a[2], a[3]));
2090 *pNetIp = ipProbe;
2091 *pNetMask = inet_addr("255.255.255.0");
2092 break;
2093 }
2094 }
2095 if (*pNetIp == 0)
2096 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
2097 }
2098 else
2099 NonStandardLogFlow(("GetAdaptersAddresses err (%d)\n", dwRc));
2100
2101 if (pAddresses)
2102 free(pAddresses);
2103
2104 if (dwRc != NO_ERROR)
2105 {
2106 hr = HRESULT_FROM_WIN32(dwRc);
2107 }
2108
2109 return hr;
2110}
2111
2112/*
2113 * convenience functions to perform netflt/adp manipulations
2114 */
2115#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
2116#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
2117
2118static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2119{
2120 INetCfgComponent *pNcc = NULL;
2121 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
2122 if (hr == S_OK)
2123 {
2124 NonStandardLog("NetFlt is installed currently, uninstalling ...\n");
2125
2126 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
2127 NonStandardLogFlow(("NetFlt component uninstallation ended with hr (0x%x)\n", hr));
2128
2129 pNcc->Release();
2130 }
2131 else if (hr == S_FALSE)
2132 {
2133 NonStandardLog("NetFlt is not installed currently\n");
2134 }
2135 else
2136 {
2137 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
2138 }
2139
2140 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
2141 VBoxDrvCfgInfUninstallAllF(L"Net", VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
2142
2143 return hr;
2144}
2145
2146VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
2147{
2148 return vboxNetCfgWinNetFltUninstall(pNc, 0);
2149}
2150
2151VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc,
2152 IN LPCWSTR const *apInfFullPaths, IN UINT cInfFullPaths)
2153{
2154 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
2155 if (SUCCEEDED(hr))
2156 {
2157 NonStandardLog("NetFlt will be installed ...\n");
2158 hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
2159 &GUID_DEVCLASS_NETSERVICE,
2160 apInfFullPaths,
2161 cInfFullPaths,
2162 NULL);
2163 }
2164 return hr;
2165}
2166
2167#define VBOXNETCFGWIN_NETADP_ID L"sun_VBoxNetAdp"
2168static HRESULT vboxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, LPCWSTR pwszId, DWORD InfRmFlags)
2169{
2170 HRESULT hr = S_OK;
2171 NonStandardLog("Finding NetAdp driver package and trying to uninstall it ...\n");
2172
2173 VBoxDrvCfgInfUninstallAllF(L"Net", pwszId, InfRmFlags);
2174 NonStandardLog("NetAdp is not installed currently\n");
2175 return hr;
2176}
2177
2178VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, IN LPCWSTR pwszId)
2179{
2180 return vboxNetCfgWinNetAdpUninstall(pNc, pwszId, SUOI_FORCEDELETE);
2181}
2182
2183VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpInstall(IN INetCfg *pNc,
2184 IN LPCWSTR const pInfFullPath)
2185{
2186 NonStandardLog("NetAdp will be installed ...\n");
2187 HRESULT hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETADP_ID,
2188 &GUID_DEVCLASS_NET,
2189 &pInfFullPath,
2190 1,
2191 NULL);
2192 return hr;
2193}
2194
2195#define VBOXNETCFGWIN_NETLWF_ID L"oracle_VBoxNetLwf"
2196
2197static HRESULT vboxNetCfgWinNetLwfUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2198{
2199 INetCfgComponent * pNcc = NULL;
2200 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETLWF_ID, &pNcc);
2201 if (hr == S_OK)
2202 {
2203 NonStandardLog("NetLwf is installed currently, uninstalling ...\n");
2204
2205 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
2206
2207 pNcc->Release();
2208 }
2209 else if (hr == S_FALSE)
2210 {
2211 NonStandardLog("NetLwf is not installed currently\n");
2212 hr = S_OK;
2213 }
2214 else
2215 {
2216 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
2217 hr = S_OK;
2218 }
2219
2220 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETLWF_ID, InfRmFlags);
2221
2222 return hr;
2223}
2224
2225VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfUninstall(IN INetCfg *pNc)
2226{
2227 return vboxNetCfgWinNetLwfUninstall(pNc, 0);
2228}
2229
2230static void VBoxNetCfgWinFilterLimitWorkaround(void)
2231{
2232 /*
2233 * Need to check if the system has a limit of installed filter drivers. If it
2234 * has, bump the limit to 14, which the maximum value supported by Windows 7.
2235 * Note that we only touch the limit if it is set to the default value (8).
2236 * See @bugref{7899}.
2237 */
2238 HKEY hNetKey;
2239 DWORD dwMaxNumFilters = 0;
2240 DWORD cbMaxNumFilters = sizeof(dwMaxNumFilters);
2241 LONG hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
2242 _T("SYSTEM\\CurrentControlSet\\Control\\Network"),
2243 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hNetKey);
2244 if (SUCCEEDED(hr))
2245 {
2246 hr = RegQueryValueEx(hNetKey, _T("MaxNumFilters"), NULL, NULL,
2247 (LPBYTE)&dwMaxNumFilters, &cbMaxNumFilters);
2248 if (SUCCEEDED(hr) && cbMaxNumFilters == sizeof(dwMaxNumFilters) && dwMaxNumFilters == 8)
2249 {
2250 dwMaxNumFilters = 14;
2251 hr = RegSetValueEx(hNetKey, _T("MaxNumFilters"), 0, REG_DWORD,
2252 (LPBYTE)&dwMaxNumFilters, sizeof(dwMaxNumFilters));
2253 if (SUCCEEDED(hr))
2254 NonStandardLog("Adjusted the installed filter limit to 14...\n");
2255 else
2256 NonStandardLog("Failed to set MaxNumFilters, error code 0x%x\n", hr);
2257 }
2258 RegCloseKey(hNetKey);
2259 }
2260 else
2261 {
2262 NonStandardLog("Failed to open network key, error code 0x%x\n", hr);
2263 }
2264
2265}
2266
2267VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfInstall(IN INetCfg *pNc,
2268 IN LPCWSTR const pInfFullPath)
2269{
2270 HRESULT hr = vboxNetCfgWinNetLwfUninstall(pNc, SUOI_FORCEDELETE);
2271 if (SUCCEEDED(hr))
2272 {
2273 VBoxNetCfgWinFilterLimitWorkaround();
2274 NonStandardLog("NetLwf will be installed ...\n");
2275 hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETLWF_ID,
2276 &GUID_DEVCLASS_NETSERVICE,
2277 &pInfFullPath,
2278 1,
2279 NULL);
2280 }
2281 return hr;
2282}
2283
2284#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
2285VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
2286{
2287 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
2288 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
2289 ULONG cbSufSize = 0;
2290
2291 if (pSuffix)
2292 {
2293 cbSize += (ULONG)wcslen(pSuffix) * 2;
2294 cbSize += 2; /* for space */
2295 }
2296
2297 if (*pcbBuf < cbSize)
2298 {
2299 *pcbBuf = cbSize;
2300 return E_FAIL;
2301 }
2302
2303 wcscpy(pBuf, VBOX_CONNECTION_NAME);
2304 if (pSuffix)
2305 {
2306 wcscat(pBuf, L" ");
2307 wcscat(pBuf, pSuffix);
2308 }
2309
2310 return S_OK;
2311}
2312
2313static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority(IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
2314{
2315 INetCfgComponentBindings *pNetCfgBindings;
2316 GUID *pGuid = (GUID*)pContext;
2317
2318 /* Get component's binding. */
2319 HRESULT hr = pNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pNetCfgBindings);
2320 if (SUCCEEDED(hr))
2321 {
2322 /* Get binding path enumerator reference. */
2323 IEnumNetCfgBindingPath *pEnumNetCfgBindPath;
2324 hr = pNetCfgBindings->EnumBindingPaths(EBP_BELOW, &pEnumNetCfgBindPath);
2325 if (SUCCEEDED(hr))
2326 {
2327 bool bFoundIface = false;
2328 hr = pEnumNetCfgBindPath->Reset();
2329 do
2330 {
2331 INetCfgBindingPath *pNetCfgBindPath;
2332 hr = pEnumNetCfgBindPath->Next(1, &pNetCfgBindPath, NULL);
2333 if (hr == S_OK)
2334 {
2335 IEnumNetCfgBindingInterface *pEnumNetCfgBindIface;
2336 hr = pNetCfgBindPath->EnumBindingInterfaces(&pEnumNetCfgBindIface);
2337 if (hr == S_OK)
2338 {
2339 pEnumNetCfgBindIface->Reset();
2340 do
2341 {
2342 INetCfgBindingInterface *pNetCfgBindIfce;
2343 hr = pEnumNetCfgBindIface->Next(1, &pNetCfgBindIfce, NULL);
2344 if (hr == S_OK)
2345 {
2346 INetCfgComponent *pNetCfgCompo;
2347 hr = pNetCfgBindIfce->GetLowerComponent(&pNetCfgCompo);
2348 if (hr == S_OK)
2349 {
2350 ULONG uComponentStatus;
2351 hr = pNetCfgCompo->GetDeviceStatus(&uComponentStatus);
2352 if (hr == S_OK)
2353 {
2354 GUID guid;
2355 hr = pNetCfgCompo->GetInstanceGuid(&guid);
2356 if ( hr == S_OK
2357 && guid == *pGuid)
2358 {
2359 hr = pNetCfgBindings->MoveAfter(pNetCfgBindPath, NULL);
2360 if (FAILED(hr))
2361 NonStandardLogFlow(("Unable to move interface, hr (0x%x)\n", hr));
2362 bFoundIface = true;
2363 /*
2364 * Enable binding paths for host-only adapters bound to bridged filter
2365 * (see @bugref{8140}).
2366 */
2367 HRESULT hr2;
2368 LPWSTR pwszHwId = NULL;
2369 if ((hr2 = pNcc->GetId(&pwszHwId)) != S_OK)
2370 NonStandardLogFlow(("Failed to get HW ID, hr (0x%x)\n", hr2));
2371 else if (_wcsnicmp(pwszHwId, VBOXNETCFGWIN_NETLWF_ID,
2372 sizeof(VBOXNETCFGWIN_NETLWF_ID)/2))
2373 NonStandardLogFlow(("Ignoring component %ls\n", pwszHwId));
2374 else if ((hr2 = pNetCfgBindPath->IsEnabled()) != S_FALSE)
2375 NonStandardLogFlow(("Already enabled binding path, hr (0x%x)\n", hr2));
2376 else if ((hr2 = pNetCfgBindPath->Enable(TRUE)) != S_OK)
2377 NonStandardLogFlow(("Failed to enable binding path, hr (0x%x)\n", hr2));
2378 else
2379 NonStandardLogFlow(("Enabled binding path\n"));
2380 if (pwszHwId)
2381 CoTaskMemFree(pwszHwId);
2382 }
2383 }
2384 pNetCfgCompo->Release();
2385 }
2386 else
2387 NonStandardLogFlow(("GetLowerComponent failed, hr (0x%x)\n", hr));
2388 pNetCfgBindIfce->Release();
2389 }
2390 else
2391 {
2392 if (hr == S_FALSE) /* No more binding interfaces? */
2393 hr = S_OK;
2394 else
2395 NonStandardLogFlow(("Next binding interface failed, hr (0x%x)\n", hr));
2396 break;
2397 }
2398 } while (!bFoundIface);
2399 pEnumNetCfgBindIface->Release();
2400 }
2401 else
2402 NonStandardLogFlow(("EnumBindingInterfaces failed, hr (0x%x)\n", hr));
2403 pNetCfgBindPath->Release();
2404 }
2405 else
2406 {
2407 if (hr == S_FALSE) /* No more binding paths? */
2408 hr = S_OK;
2409 else
2410 NonStandardLogFlow(("Next bind path failed, hr (0x%x)\n", hr));
2411 break;
2412 }
2413 } while (!bFoundIface);
2414 pEnumNetCfgBindPath->Release();
2415 }
2416 else
2417 NonStandardLogFlow(("EnumBindingPaths failed, hr (0x%x)\n", hr));
2418 pNetCfgBindings->Release();
2419 }
2420 else
2421 NonStandardLogFlow(("QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr));
2422 return TRUE;
2423}
2424
2425static UINT WINAPI vboxNetCfgWinPspFileCallback(
2426 PVOID Context,
2427 UINT Notification,
2428 UINT_PTR Param1,
2429 UINT_PTR Param2
2430 )
2431{
2432 switch (Notification)
2433 {
2434 case SPFILENOTIFY_TARGETNEWER:
2435 case SPFILENOTIFY_TARGETEXISTS:
2436 return TRUE;
2437 }
2438 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2439}
2440
2441/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
2442/*
2443 Copyright 2004 by the Massachusetts Institute of Technology
2444
2445 All rights reserved.
2446
2447 Permission to use, copy, modify, and distribute this software and its
2448 documentation for any purpose and without fee is hereby granted,
2449 provided that the above copyright notice appear in all copies and that
2450 both that copyright notice and this permission notice appear in
2451 supporting documentation, and that the name of the Massachusetts
2452 Institute of Technology (M.I.T.) not be used in advertising or publicity
2453 pertaining to distribution of the software without specific, written
2454 prior permission.
2455
2456 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2457 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2458 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2459 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2460 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2461 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2462 SOFTWARE.
2463*/
2464
2465
2466/**
2467 * Use the IShellFolder API to rename the connection.
2468 */
2469static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
2470{
2471 /* This is the GUID for the network connections folder. It is constant.
2472 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
2473 const GUID CLSID_NetworkConnections = {
2474 0x7007ACC7, 0x3202, 0x11D1, {
2475 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
2476 }
2477 };
2478
2479 LPITEMIDLIST pidl = NULL;
2480 IShellFolder *pShellFolder = NULL;
2481 HRESULT hr;
2482
2483 /* Build the display name in the form "::{GUID}". */
2484 if (wcslen(wGuid) >= MAX_PATH)
2485 return E_INVALIDARG;
2486 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
2487 swprintf(szAdapterGuid, L"::%ls", wGuid);
2488
2489 /* Create an instance of the network connections folder. */
2490 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
2491 CLSCTX_INPROC_SERVER, IID_IShellFolder,
2492 reinterpret_cast<LPVOID *>(&pShellFolder));
2493 /* Parse the display name. */
2494 if (SUCCEEDED (hr))
2495 {
2496 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
2497 &pidl, NULL);
2498 }
2499 if (SUCCEEDED (hr))
2500 {
2501 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
2502 &pidl);
2503 }
2504
2505 CoTaskMemFree (pidl);
2506
2507 if (pShellFolder)
2508 pShellFolder->Release();
2509
2510 return hr;
2511}
2512
2513/**
2514 * Loads a system DLL.
2515 *
2516 * @returns Module handle or NULL
2517 * @param pszName The DLL name.
2518 */
2519static HMODULE loadSystemDll(const char *pszName)
2520{
2521 char szPath[MAX_PATH];
2522 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
2523 size_t cbName = strlen(pszName) + 1;
2524 if (cchPath + 1 + cbName > sizeof(szPath))
2525 return NULL;
2526 szPath[cchPath] = '\\';
2527 memcpy(&szPath[cchPath + 1], pszName, cbName);
2528 return LoadLibraryA(szPath);
2529}
2530
2531VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
2532{
2533 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
2534 lpHrRenameConnection RenameConnectionFunc = NULL;
2535 HRESULT status;
2536
2537 /* First try the IShellFolder interface, which was unimplemented
2538 * for the network connections folder before XP. */
2539 status = rename_shellfolder (pGuid, NewName);
2540 if (status == E_NOTIMPL)
2541 {
2542/** @todo that code doesn't seem to work! */
2543 /* The IShellFolder interface is not implemented on this platform.
2544 * Try the (undocumented) HrRenameConnection API in the netshell
2545 * library. */
2546 CLSID clsid;
2547 HINSTANCE hNetShell;
2548 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
2549 if (FAILED(status))
2550 return E_FAIL;
2551 hNetShell = loadSystemDll("netshell.dll");
2552 if (hNetShell == NULL)
2553 return E_FAIL;
2554 RenameConnectionFunc =
2555 (lpHrRenameConnection) GetProcAddress (hNetShell,
2556 "HrRenameConnection");
2557 if (RenameConnectionFunc == NULL)
2558 {
2559 FreeLibrary (hNetShell);
2560 return E_FAIL;
2561 }
2562 status = RenameConnectionFunc (&clsid, NewName);
2563 FreeLibrary (hNetShell);
2564 }
2565 if (FAILED (status))
2566 return status;
2567
2568 return S_OK;
2569}
2570
2571#define DRIVERHWID _T("sun_VBoxNetAdp")
2572
2573#define SetErrBreak(strAndArgs) \
2574 if (1) { \
2575 hrc = E_FAIL; \
2576 NonStandardLog strAndArgs; \
2577 bstrError = bstr_printf strAndArgs; \
2578 break; \
2579 } else do {} while (0)
2580
2581VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg)
2582{
2583 HRESULT hrc = S_OK;
2584 bstr_t bstrError;
2585
2586 do
2587 {
2588 TCHAR lszPnPInstanceId [512] = {0};
2589
2590 /* We have to find the device instance ID through a registry search */
2591
2592 HKEY hkeyNetwork = 0;
2593 HKEY hkeyConnection = 0;
2594
2595 do
2596 {
2597 WCHAR strRegLocation [256];
2598 WCHAR wszGuid[50];
2599
2600 int length = StringFromGUID2(*pGUID, wszGuid, RT_ELEMENTS(wszGuid));
2601 if (!length)
2602 SetErrBreak(("Failed to create a Guid string"));
2603
2604 swprintf (strRegLocation,
2605 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
2606 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
2607 wszGuid);
2608
2609 LONG status;
2610 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
2611 KEY_READ, &hkeyNetwork);
2612 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
2613 SetErrBreak (("Host interface network is not found in registry (%S) [1]",
2614 strRegLocation));
2615
2616 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
2617 KEY_READ, &hkeyConnection);
2618 if ((status != ERROR_SUCCESS) || !hkeyConnection)
2619 SetErrBreak (("Host interface network is not found in registry (%S) [2]",
2620 strRegLocation));
2621
2622 DWORD len = sizeof (lszPnPInstanceId);
2623 DWORD dwKeyType;
2624 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2625 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2626 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2627 SetErrBreak (("Host interface network is not found in registry (%S) [3]",
2628 strRegLocation));
2629 }
2630 while (0);
2631
2632 if (hkeyConnection)
2633 RegCloseKey (hkeyConnection);
2634 if (hkeyNetwork)
2635 RegCloseKey (hkeyNetwork);
2636
2637 if (FAILED (hrc))
2638 break;
2639
2640 /*
2641 * Now we are going to enumerate all network devices and
2642 * wait until we encounter the right device instance ID
2643 */
2644
2645 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2646
2647 do
2648 {
2649 BOOL ok;
2650 DWORD ret = 0;
2651 GUID netGuid;
2652 SP_DEVINFO_DATA DeviceInfoData;
2653 DWORD index = 0;
2654 BOOL found = FALSE;
2655 DWORD size = 0;
2656
2657 /* initialize the structure size */
2658 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2659
2660 /* copy the net class GUID */
2661 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2662
2663 /* return a device info set contains all installed devices of the Net class */
2664 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2665
2666 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2667 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2668
2669 /* enumerate the driver info list */
2670 while (TRUE)
2671 {
2672 TCHAR *deviceHwid;
2673
2674 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2675
2676 if (!ok)
2677 {
2678 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2679 break;
2680 else
2681 {
2682 index++;
2683 continue;
2684 }
2685 }
2686
2687 /* try to get the hardware ID registry property */
2688 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2689 &DeviceInfoData,
2690 SPDRP_HARDWAREID,
2691 NULL,
2692 NULL,
2693 0,
2694 &size);
2695 if (!ok)
2696 {
2697 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2698 {
2699 index++;
2700 continue;
2701 }
2702
2703 deviceHwid = (TCHAR *) malloc (size);
2704 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2705 &DeviceInfoData,
2706 SPDRP_HARDWAREID,
2707 NULL,
2708 (PBYTE)deviceHwid,
2709 size,
2710 NULL);
2711 if (!ok)
2712 {
2713 free (deviceHwid);
2714 deviceHwid = NULL;
2715 index++;
2716 continue;
2717 }
2718 }
2719 else
2720 {
2721 /* something is wrong. This shouldn't have worked with a NULL buffer */
2722 index++;
2723 continue;
2724 }
2725
2726 for (TCHAR *t = deviceHwid;
2727 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2728 t += _tcslen (t) + 1)
2729 {
2730 if (!_tcsicmp (DRIVERHWID, t))
2731 {
2732 /* get the device instance ID */
2733 TCHAR devId[MAX_DEVICE_ID_LEN];
2734 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2735 devId, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2736 {
2737 /* compare to what we determined before */
2738 if (wcscmp(devId, lszPnPInstanceId) == 0)
2739 {
2740 found = TRUE;
2741 break;
2742 }
2743 }
2744 }
2745 }
2746
2747 if (deviceHwid)
2748 {
2749 free (deviceHwid);
2750 deviceHwid = NULL;
2751 }
2752
2753 if (found)
2754 break;
2755
2756 index++;
2757 }
2758
2759 if (found == FALSE)
2760 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
2761 GetLastError()));
2762
2763 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2764 if (!ok)
2765 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2766 GetLastError()));
2767
2768 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2769 if (!ok)
2770 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2771 GetLastError()));
2772 }
2773 while (0);
2774
2775 /* clean up the device info set */
2776 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2777 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2778
2779 if (FAILED (hrc))
2780 break;
2781 }
2782 while (0);
2783
2784 if (pErrMsg && bstrError.length())
2785 *pErrMsg = bstrError.Detach();
2786
2787 return hrc;
2788}
2789
2790VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUpdateHostOnlyNetworkInterface(LPCWSTR pcsxwInf, BOOL *pbRebootRequired, LPCWSTR pcsxwId)
2791{
2792 return VBoxDrvCfgDrvUpdate(pcsxwId, pcsxwInf, pbRebootRequired);
2793}
2794
2795static const char *vboxNetCfgWinGetStateText(DWORD dwState)
2796{
2797 switch (dwState)
2798 {
2799 case SERVICE_STOPPED: return "is not running";
2800 case SERVICE_STOP_PENDING: return "is stopping";
2801 case SERVICE_CONTINUE_PENDING: return "continue is pending";
2802 case SERVICE_PAUSE_PENDING: return "pause is pending";
2803 case SERVICE_PAUSED: return "is paused";
2804 case SERVICE_RUNNING: return "is running";
2805 case SERVICE_START_PENDING: return "is starting";
2806 }
2807 return "state is invalid";
2808}
2809
2810static DWORD vboxNetCfgWinGetNetSetupState(SC_HANDLE hService)
2811{
2812 SERVICE_STATUS status;
2813 status.dwCurrentState = SERVICE_RUNNING;
2814 if (hService) {
2815 if (QueryServiceStatus(hService, &status))
2816 NonStandardLogFlow(("NetSetupSvc %s\n", vboxNetCfgWinGetStateText(status.dwCurrentState)));
2817 else
2818 NonStandardLogFlow(("QueryServiceStatus failed (0x%x)\n", GetLastError()));
2819 }
2820 return status.dwCurrentState;
2821}
2822
2823DECLINLINE(bool) vboxNetCfgWinIsNetSetupRunning(SC_HANDLE hService)
2824{
2825 return vboxNetCfgWinGetNetSetupState(hService) == SERVICE_RUNNING;
2826}
2827
2828DECLINLINE(bool) vboxNetCfgWinIsNetSetupStopped(SC_HANDLE hService)
2829{
2830 return vboxNetCfgWinGetNetSetupState(hService) == SERVICE_STOPPED;
2831}
2832
2833static HRESULT vboxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
2834 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
2835{
2836 HRESULT hrc = S_OK;
2837
2838 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2839 SP_DEVINFO_DATA DeviceInfoData;
2840 PVOID pQueueCallbackContext = NULL;
2841 DWORD ret = 0;
2842 BOOL registered = FALSE;
2843 BOOL destroyList = FALSE;
2844 WCHAR pWCfgGuidString [50];
2845 WCHAR DevName[256];
2846 HKEY hkey = (HKEY)INVALID_HANDLE_VALUE;
2847 bstr_t bstrError;
2848
2849 do
2850 {
2851 BOOL found = FALSE;
2852 GUID netGuid;
2853 SP_DRVINFO_DATA DriverInfoData;
2854 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2855 TCHAR className [MAX_PATH];
2856 DWORD index = 0;
2857 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2858 /* for our purposes, 2k buffer is more
2859 * than enough to obtain the hardware ID
2860 * of the VBoxNetAdp driver. */
2861 DWORD detailBuf [2048];
2862
2863 DWORD cbSize;
2864 DWORD dwValueType;
2865
2866 /* initialize the structure size */
2867 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2868 DriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
2869
2870 /* copy the net class GUID */
2871 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2872
2873 /* create an empty device info set associated with the net class GUID */
2874 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
2875 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2876 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
2877 GetLastError()));
2878
2879 /* get the class name from GUID */
2880 BOOL fResult = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2881 if (!fResult)
2882 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
2883 GetLastError()));
2884
2885 /* create a device info element and add the new device instance
2886 * key to registry */
2887 fResult = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2888 DICD_GENERATE_ID, &DeviceInfoData);
2889 if (!fResult)
2890 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
2891 GetLastError()));
2892
2893 /* select the newly created device info to be the currently
2894 selected member */
2895 fResult = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2896 if (!fResult)
2897 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2898 GetLastError()));
2899
2900 if (pInfPath)
2901 {
2902 /* get the device install parameters and disable filecopy */
2903 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2904 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2905 &DeviceInstallParams);
2906 if (fResult)
2907 {
2908 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2909 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2910 if (pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2911 {
2912 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2913
2914 if (bIsInfPathFile)
2915 {
2916 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2917 }
2918
2919 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2920 &DeviceInstallParams);
2921 if (!fResult)
2922 {
2923 DWORD winEr = GetLastError();
2924 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2925 break;
2926 }
2927 }
2928 else
2929 {
2930 NonStandardLogFlow(("SetupDiSetDeviceInstallParams faileed: INF path is too long\n"));
2931 break;
2932 }
2933 }
2934 else
2935 {
2936 DWORD winEr = GetLastError();
2937 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2938 }
2939 }
2940
2941 /* build a list of class drivers */
2942 fResult = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2943 SPDIT_CLASSDRIVER);
2944 if (!fResult)
2945 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
2946 GetLastError()));
2947
2948 destroyList = TRUE;
2949
2950 /* enumerate the driver info list */
2951 while (TRUE)
2952 {
2953 BOOL ret;
2954
2955 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2956 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2957
2958 /* if the function failed and GetLastError() returned
2959 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2960 * list. Otherwise there was something wrong with this
2961 * particular driver. */
2962 if (!ret)
2963 {
2964 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2965 break;
2966 else
2967 {
2968 index++;
2969 continue;
2970 }
2971 }
2972
2973 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2974 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2975
2976 /* if we successfully find the hardware ID and it turns out to
2977 * be the one for the loopback driver, then we are done. */
2978 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2979 &DeviceInfoData,
2980 &DriverInfoData,
2981 pDriverInfoDetail,
2982 sizeof (detailBuf),
2983 NULL))
2984 {
2985 TCHAR * t;
2986
2987 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2988 * whole list and see if there is a match somewhere. */
2989 t = pDriverInfoDetail->HardwareID;
2990 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2991 {
2992 if (!_tcsicmp(t, DRIVERHWID))
2993 break;
2994
2995 t += _tcslen(t) + 1;
2996 }
2997
2998 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2999 {
3000 found = TRUE;
3001 break;
3002 }
3003 }
3004
3005 index ++;
3006 }
3007
3008 if (!found)
3009 SetErrBreak(("Could not find Host Interface Networking driver! Please reinstall"));
3010
3011 /* set the loopback driver to be the currently selected */
3012 fResult = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
3013 &DriverInfoData);
3014 if (!fResult)
3015 SetErrBreak(("SetupDiSetSelectedDriver failed (0x%08X)",
3016 GetLastError()));
3017
3018 /* register the phantom device to prepare for install */
3019 fResult = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
3020 &DeviceInfoData);
3021 if (!fResult)
3022 {
3023 DWORD err = GetLastError();
3024 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
3025 err));
3026 }
3027
3028 /* registered, but remove if errors occur in the following code */
3029 registered = TRUE;
3030
3031 /* ask the installer if we can install the device */
3032 fResult = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
3033 &DeviceInfoData);
3034 if (!fResult)
3035 {
3036 if (GetLastError() != ERROR_DI_DO_DEFAULT)
3037 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
3038 GetLastError()));
3039 /* that's fine */
3040 }
3041
3042 /* get the device install parameters and disable filecopy */
3043 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
3044 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
3045 &DeviceInstallParams);
3046 if (fResult)
3047 {
3048 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
3049 if (pQueueCallbackContext)
3050 {
3051 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
3052 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
3053 fResult = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
3054 &DeviceInstallParams);
3055 if (!fResult)
3056 {
3057 DWORD winEr = GetLastError();
3058 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
3059 }
3060 Assert(fResult);
3061 }
3062 else
3063 {
3064 DWORD winEr = GetLastError();
3065 NonStandardLogFlow(("SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr));
3066 }
3067 }
3068 else
3069 {
3070 DWORD winEr = GetLastError();
3071 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
3072 }
3073
3074 /* install the files first */
3075 fResult = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
3076 &DeviceInfoData);
3077 if (!fResult)
3078 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
3079 GetLastError()));
3080 /* get the device install parameters and disable filecopy */
3081 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
3082 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
3083 &DeviceInstallParams);
3084 if (fResult)
3085 {
3086 DeviceInstallParams.Flags |= DI_NOFILECOPY;
3087 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
3088 &DeviceInstallParams);
3089 if (!fResult)
3090 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
3091 GetLastError()));
3092 }
3093
3094 /*
3095 * Register any device-specific co-installers for this device,
3096 */
3097 fResult = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
3098 hDeviceInfo,
3099 &DeviceInfoData);
3100 if (!fResult)
3101 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
3102 GetLastError()));
3103
3104 /*
3105 * install any installer-specified interfaces.
3106 * and then do the real install
3107 */
3108 fResult = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
3109 hDeviceInfo,
3110 &DeviceInfoData);
3111 if (!fResult)
3112 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
3113 GetLastError()));
3114
3115 fResult = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
3116 hDeviceInfo,
3117 &DeviceInfoData);
3118 if (!fResult)
3119 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
3120 GetLastError()));
3121
3122 /* Figure out NetCfgInstanceId */
3123 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
3124 &DeviceInfoData,
3125 DICS_FLAG_GLOBAL,
3126 0,
3127 DIREG_DRV,
3128 KEY_READ);
3129 if (hkey == INVALID_HANDLE_VALUE)
3130 SetErrBreak(("SetupDiOpenDevRegKey failed (0x%08X)", GetLastError()));
3131
3132 /* Query the instance ID; on Windows 10, the registry key may take a short
3133 * while to appear. Microsoft recommends waiting for up to 5 seconds, but
3134 * we want to be on the safe side, so let's wait for 20 seconds. Waiting
3135 * longer is harmful as network setup service will shut down after a period
3136 * of inactivity.
3137 */
3138 for (int retries = 0; retries < 2 * 20; ++retries)
3139 {
3140 cbSize = sizeof(pWCfgGuidString);
3141 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
3142 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
3143 /* As long as the return code is FILE_NOT_FOUND, sleep and retry. */
3144 if (ret == ERROR_FILE_NOT_FOUND)
3145 Sleep(500); /* half second */
3146 else
3147 break;
3148 }
3149
3150 if (ret == ERROR_FILE_NOT_FOUND)
3151 {
3152 hrc = E_ABORT;
3153 break;
3154 }
3155
3156 if (ret != ERROR_SUCCESS)
3157 SetErrBreak(("Querying NetCfgInstanceId failed (0x%08X)", ret));
3158
3159 /*
3160 * Set default metric value of interface to fix multicast issue
3161 * See @bugref{6379} for details.
3162 */
3163 HRESULT hSMRes = vboxNetCfgWinSetupMetric(hkey);
3164 if (FAILED(hSMRes))
3165 {
3166 /*
3167 * The setting of Metric is not very important functionality,
3168 * So we will not break installation process due to this error.
3169 */
3170 NonStandardLogFlow(("vboxNetCfgWinCreateHostOnlyNetworkInterface Warning! "
3171 "vboxNetCfgWinSetupMetric failed, default metric "
3172 "for new interface will not be set, hr (0x%x)\n", hSMRes));
3173 }
3174
3175#ifndef VBOXNETCFG_DELAYEDRENAME
3176 /*
3177 * We need to query the device name after we have succeeded in querying its
3178 * instance ID to avoid similar waiting-and-retrying loop (see @bugref{7973}).
3179 */
3180 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
3181 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
3182 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
3183 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
3184 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
3185 NULL /*OUT PDWORD RequiredSize OPTIONAL*/))
3186 {
3187 int err = GetLastError();
3188 if (err != ERROR_INVALID_DATA)
3189 {
3190 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
3191 err));
3192 }
3193
3194 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
3195 SPDRP_DEVICEDESC, /* IN DWORD Property,*/
3196 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
3197 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
3198 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
3199 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
3200 ))
3201 {
3202 err = GetLastError();
3203 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
3204 err));
3205 }
3206 }
3207#else /* !VBOXNETCFG_DELAYEDRENAME */
3208 /* Re-use DevName for device instance id retrieval. */
3209 if (!SetupDiGetDeviceInstanceId(hDeviceInfo, &DeviceInfoData, DevName, RT_ELEMENTS(DevName), &cbSize))
3210 SetErrBreak (("SetupDiGetDeviceInstanceId failed (0x%08X)",
3211 GetLastError()));
3212#endif /* !VBOXNETCFG_DELAYEDRENAME */
3213 }
3214 while (0);
3215
3216 /*
3217 * cleanup
3218 */
3219 if (hkey != INVALID_HANDLE_VALUE)
3220 RegCloseKey (hkey);
3221
3222 if (pQueueCallbackContext)
3223 SetupTermDefaultQueueCallback(pQueueCallbackContext);
3224
3225 if (hDeviceInfo != INVALID_HANDLE_VALUE)
3226 {
3227 /* an error has occurred, but the device is registered, we must remove it */
3228 if (ret != 0 && registered)
3229 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
3230
3231 SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
3232
3233 /* destroy the driver info list */
3234 if (destroyList)
3235 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
3236 SPDIT_CLASSDRIVER);
3237 /* clean up the device info set */
3238 SetupDiDestroyDeviceInfoList (hDeviceInfo);
3239 }
3240
3241 /* return the network connection GUID on success */
3242 if (SUCCEEDED(hrc))
3243 {
3244 HRESULT hr;
3245 INetCfg *pNetCfg = NULL;
3246 LPWSTR lpszApp = NULL;
3247#ifndef VBOXNETCFG_DELAYEDRENAME
3248 WCHAR ConnectionName[128];
3249 ULONG cbName = sizeof(ConnectionName);
3250
3251 hr = VBoxNetCfgWinGenHostonlyConnectionName(DevName, ConnectionName, &cbName);
3252 if (SUCCEEDED(hr))
3253 hr = VBoxNetCfgWinRenameConnection(pWCfgGuidString, ConnectionName);
3254#endif
3255 if (lppszName)
3256 {
3257 *lppszName = SysAllocString((const OLECHAR *) DevName);
3258 if (!*lppszName)
3259 {
3260 NonStandardLogFlow(("SysAllocString failed\n"));
3261 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3262 }
3263 }
3264
3265 if (pGuid)
3266 {
3267 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID)pGuid);
3268 if (FAILED(hrc))
3269 NonStandardLogFlow(("CLSIDFromString failed, hrc (0x%x)\n", hrc));
3270 }
3271
3272 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, TRUE, L"VirtualBox Host-Only Creation",
3273 30 * 1000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec. */
3274 /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
3275 &lpszApp);
3276 if (hr == S_OK)
3277 {
3278 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3279 &GUID_DEVCLASS_NETSERVICE,
3280 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3281 pGuid);
3282 if (SUCCEEDED(hr))
3283 {
3284 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3285 &GUID_DEVCLASS_NETTRANS,
3286 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3287 pGuid);
3288 if (SUCCEEDED(hr))
3289 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3290 &GUID_DEVCLASS_NETCLIENT,
3291 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3292 pGuid);
3293 }
3294
3295 if (SUCCEEDED(hr))
3296 {
3297 hr = pNetCfg->Apply();
3298 }
3299 else
3300 NonStandardLogFlow(("Enumeration failed, hr 0x%x\n", hr));
3301 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
3302 }
3303 else if (hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
3304 {
3305 NonStandardLogFlow(("Application %ws is holding the lock, failed\n", lpszApp));
3306 CoTaskMemFree(lpszApp);
3307 }
3308 else
3309 NonStandardLogFlow(("VBoxNetCfgWinQueryINetCfg failed, hr 0x%x\n", hr));
3310 }
3311
3312 if (pErrMsg && bstrError.length())
3313 *pErrMsg = bstrError.Detach();
3314
3315 return hrc;
3316}
3317
3318VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
3319 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
3320{
3321 HRESULT hrc = vboxNetCfgWinCreateHostOnlyNetworkInterface(pInfPath, bIsInfPathFile, pGuid, lppszName, pErrMsg);
3322 if (hrc == E_ABORT)
3323 {
3324 NonStandardLogFlow(("Timed out while waiting for NetCfgInstanceId, try again immediately...\n"));
3325 /*
3326 * This is the first time we fail to obtain NetCfgInstanceId, let us
3327 * retry it once. It is needed to handle the situation when network
3328 * setup fails to recognize the arrival of our device node while it
3329 * is busy removing another host-only interface, and it gets stuck
3330 * with no matching network interface created for our device node.
3331 * See @bugref{7973} for details.
3332 */
3333 hrc = vboxNetCfgWinCreateHostOnlyNetworkInterface(pInfPath, bIsInfPathFile, pGuid, lppszName, pErrMsg);
3334 if (hrc == E_ABORT)
3335 {
3336 NonStandardLogFlow(("Timed out again while waiting for NetCfgInstanceId, try again after a while...\n"));
3337 /*
3338 * This is the second time we fail to obtain NetCfgInstanceId, let us
3339 * retry it once more. This time we wait to network setup service
3340 * to go down before retrying. Hopefully it will resolve all error
3341 * conditions. See @bugref{7973} for details.
3342 */
3343
3344 SC_HANDLE hSCM = NULL;
3345 SC_HANDLE hService = NULL;
3346
3347 hSCM = OpenSCManager(NULL, NULL, GENERIC_READ);
3348 if (hSCM)
3349 {
3350 hService = OpenService(hSCM, _T("NetSetupSvc"), GENERIC_READ);
3351 if (hService)
3352 {
3353 for (int retries = 0; retries < 60 && !vboxNetCfgWinIsNetSetupStopped(hService); ++retries)
3354 Sleep(1000);
3355 CloseServiceHandle(hService);
3356 hrc = vboxNetCfgWinCreateHostOnlyNetworkInterface(pInfPath, bIsInfPathFile, pGuid, lppszName, pErrMsg);
3357 }
3358 else
3359 NonStandardLogFlow(("OpenService failed (0x%x)\n", GetLastError()));
3360 CloseServiceHandle(hSCM);
3361 }
3362 else
3363 NonStandardLogFlow(("OpenSCManager failed (0x%x)", GetLastError()));
3364 /* Give up and report the error. */
3365 if (hrc == E_ABORT)
3366 {
3367 bstr_t bstrError = bstr_printf("Querying NetCfgInstanceId failed (0x%08X)", ERROR_FILE_NOT_FOUND);
3368 *pErrMsg = bstrError.Detach();
3369 hrc = E_FAIL;
3370 }
3371 }
3372 }
3373 return hrc;
3374}
3375
3376
3377HRESULT vboxLoadIpHelpFunctions(HINSTANCE& pIpHlpInstance)
3378{
3379 Assert(pIpHlpInstance != NULL);
3380
3381 pIpHlpInstance = loadSystemDll("Iphlpapi.dll");
3382 if (pIpHlpInstance == NULL)
3383 return E_FAIL;
3384
3385 g_pfnInitializeIpInterfaceEntry =
3386 (PFNINITIALIZEIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "InitializeIpInterfaceEntry");
3387 Assert(g_pfnInitializeIpInterfaceEntry);
3388
3389 if (g_pfnInitializeIpInterfaceEntry)
3390 {
3391 g_pfnGetIpInterfaceEntry =
3392 (PFNGETIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "GetIpInterfaceEntry");
3393 Assert(g_pfnGetIpInterfaceEntry);
3394 }
3395
3396 if (g_pfnGetIpInterfaceEntry)
3397 {
3398 g_pfnSetIpInterfaceEntry =
3399 (PFNSETIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "SetIpInterfaceEntry");
3400 Assert(g_pfnSetIpInterfaceEntry);
3401 }
3402
3403 if (g_pfnInitializeIpInterfaceEntry == NULL)
3404 {
3405 FreeLibrary(pIpHlpInstance);
3406 pIpHlpInstance = NULL;
3407 return E_FAIL;
3408 }
3409
3410 return S_OK;
3411}
3412
3413
3414HRESULT vboxNetCfgWinGetLoopbackMetric(OUT int* Metric)
3415{
3416 HRESULT rc = S_OK;
3417 MIB_IPINTERFACE_ROW row;
3418
3419 Assert(g_pfnInitializeIpInterfaceEntry != NULL);
3420 Assert(g_pfnGetIpInterfaceEntry != NULL);
3421
3422 g_pfnInitializeIpInterfaceEntry(&row);
3423 row.Family = AF_INET;
3424 row.InterfaceLuid.Info.IfType = IF_TYPE_SOFTWARE_LOOPBACK;
3425
3426 rc = g_pfnGetIpInterfaceEntry(&row);
3427 if (rc != 0)
3428 return E_FAIL;
3429
3430 *Metric = row.Metric;
3431
3432 return rc;
3433}
3434
3435
3436HRESULT vboxNetCfgWinSetInterfaceMetric(
3437 IN NET_LUID* pInterfaceLuid,
3438 IN DWORD metric)
3439{
3440 MIB_IPINTERFACE_ROW newRow;
3441
3442 Assert(g_pfnInitializeIpInterfaceEntry != NULL);
3443 Assert(g_pfnSetIpInterfaceEntry != NULL);
3444
3445 g_pfnInitializeIpInterfaceEntry(&newRow);
3446 // identificate the interface to change
3447 newRow.InterfaceLuid = *pInterfaceLuid;
3448 newRow.Family = AF_INET;
3449 // changed settings
3450 newRow.UseAutomaticMetric = false;
3451 newRow.Metric = metric;
3452
3453 // change settings
3454 return g_pfnSetIpInterfaceEntry(&newRow);
3455}
3456
3457
3458HRESULT vboxNetCfgWinGetInterfaceLUID(IN HKEY hKey, OUT NET_LUID* pLUID)
3459{
3460 HRESULT res = S_OK;
3461 DWORD luidIndex = 0;
3462 DWORD ifType = 0;
3463 DWORD cbSize = sizeof(luidIndex);
3464 DWORD dwValueType = REG_DWORD;
3465
3466 if (pLUID == NULL)
3467 return E_INVALIDARG;
3468
3469 res = RegQueryValueExW(hKey, L"NetLuidIndex", NULL,
3470 &dwValueType, (LPBYTE)&luidIndex, &cbSize);
3471 if (FAILED(res))
3472 return res;
3473
3474 cbSize = sizeof(ifType);
3475 dwValueType = REG_DWORD;
3476 res = RegQueryValueExW(hKey, L"*IfType", NULL,
3477 &dwValueType, (LPBYTE)&ifType, &cbSize);
3478 if (FAILED(res))
3479 return res;
3480
3481 ZeroMemory(pLUID, sizeof(NET_LUID));
3482 pLUID->Info.IfType = ifType;
3483 pLUID->Info.NetLuidIndex = luidIndex;
3484
3485 return res;
3486}
3487
3488
3489HRESULT vboxNetCfgWinSetupMetric(IN HKEY hKey)
3490{
3491 HRESULT rc = S_OK;
3492 HINSTANCE hModule = NULL;
3493 NET_LUID luid;
3494 int loopbackMetric;
3495
3496 rc = vboxLoadIpHelpFunctions(hModule);
3497
3498 if(SUCCEEDED(rc))
3499 rc = vboxNetCfgWinGetInterfaceLUID(hKey, &luid);
3500
3501 if(SUCCEEDED(rc))
3502 rc = vboxNetCfgWinGetLoopbackMetric(&loopbackMetric);
3503
3504 if(SUCCEEDED(rc))
3505 rc = vboxNetCfgWinSetInterfaceMetric(&luid, loopbackMetric - 1);
3506
3507 g_pfnInitializeIpInterfaceEntry = NULL;
3508 g_pfnSetIpInterfaceEntry = NULL;
3509 g_pfnGetIpInterfaceEntry = NULL;
3510
3511 FreeLibrary(hModule);
3512 return rc;
3513}
3514#ifdef VBOXNETCFG_DELAYEDRENAME
3515VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameHostOnlyConnection(IN const GUID *pGuid, IN LPCWSTR pwszId, OUT BSTR *pDevName)
3516{
3517 HRESULT hr = S_OK;
3518 WCHAR wszDevName[256];
3519 WCHAR wszConnectionNewName[128];
3520 ULONG cbName = sizeof(wszConnectionNewName);
3521
3522 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET, NULL);
3523 if (hDevInfo != INVALID_HANDLE_VALUE)
3524 {
3525 SP_DEVINFO_DATA DevInfoData;
3526
3527 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
3528 if (SetupDiOpenDeviceInfo(hDevInfo, pwszId, NULL, 0, &DevInfoData))
3529 {
3530 DWORD err = ERROR_SUCCESS;
3531 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
3532 SPDRP_FRIENDLYNAME, NULL,
3533 (PBYTE)wszDevName, RT_ELEMENTS(wszDevName), NULL))
3534 {
3535 err = GetLastError();
3536 if (err == ERROR_INVALID_DATA)
3537 {
3538 err = SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
3539 SPDRP_DEVICEDESC, NULL,
3540 (PBYTE)wszDevName, RT_ELEMENTS(wszDevName), NULL)
3541 ? ERROR_SUCCESS
3542 : GetLastError();
3543 }
3544 }
3545 if (err == ERROR_SUCCESS)
3546 {
3547 hr = VBoxNetCfgWinGenHostonlyConnectionName(wszDevName, wszConnectionNewName, &cbName);
3548 if (SUCCEEDED(hr))
3549 {
3550 WCHAR wszGuid[50];
3551 int cbWGuid = StringFromGUID2(*pGuid, wszGuid, RT_ELEMENTS(wszGuid));
3552 if (cbWGuid)
3553 {
3554 hr = VBoxNetCfgWinRenameConnection(wszGuid, wszConnectionNewName);
3555 if (FAILED(hr))
3556 NonStandardLogFlow(("VBoxNetCfgWinRenameHostOnlyConnection: VBoxNetCfgWinRenameConnection failed (0x%x)\n", hr));
3557 }
3558 else
3559 {
3560 err = GetLastError();
3561 hr = HRESULT_FROM_WIN32(err);
3562 if (SUCCEEDED(hr))
3563 hr = E_FAIL;
3564 NonStandardLogFlow(("StringFromGUID2 failed err=%u, hr=0x%x\n", err, hr));
3565 }
3566 }
3567 else
3568 NonStandardLogFlow(("VBoxNetCfgWinRenameHostOnlyConnection: VBoxNetCfgWinGenHostonlyConnectionName failed (0x%x)\n", hr));
3569 if (SUCCEEDED(hr) && pDevName)
3570 {
3571 *pDevName = SysAllocString((const OLECHAR *)wszDevName);
3572 if (!*pDevName)
3573 {
3574 NonStandardLogFlow(("SysAllocString failed\n"));
3575 hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3576 }
3577 }
3578 }
3579 else
3580 {
3581 hr = HRESULT_FROM_WIN32(err);
3582 NonStandardLogFlow(("VBoxNetCfgWinRenameHostOnlyConnection: SetupDiGetDeviceRegistryPropertyW failed (0x%x)\n", err));
3583 }
3584 }
3585 else
3586 {
3587 DWORD err = GetLastError();
3588 hr = HRESULT_FROM_WIN32(err);
3589 NonStandardLogFlow(("VBoxNetCfgWinRenameHostOnlyConnection: SetupDiOpenDeviceInfo failed (0x%x)\n", err));
3590 }
3591 SetupDiDestroyDeviceInfoList(hDevInfo);
3592 }
3593
3594 return hr;
3595}
3596#endif /* VBOXNETCFG_DELAYEDRENAME */
3597
3598#undef SetErrBreak
3599
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