VirtualBox

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

Last change on this file since 69498 was 69498, checked in by vboxsync, 7 years ago

backed out r118835 as it incorrectly updated the 'This file is based on' file headers.

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