VirtualBox

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

Last change on this file since 66372 was 65583, checked in by vboxsync, 8 years ago

Installer/NetAdp (bugref:7973) Prevent helper crash on host-only creation failure.

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