VirtualBox

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

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

HostDrivers/win: coding style

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