VirtualBox

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

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

Wrap ws2tcpip.h too.

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