VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/NetIf-win.cpp@ 76900

Last change on this file since 76900 was 76592, checked in by vboxsync, 6 years ago

Main: Don't use Logging.h.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 73.0 KB
Line 
1/* $Id: NetIf-win.cpp 76592 2019-01-01 20:13:07Z vboxsync $ */
2/** @file
3 * Main - NetIfList, Windows implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23#define LOG_GROUP LOG_GROUP_MAIN_HOST
24
25#define NETIF_WITHOUT_NETCFG
26
27#include <iprt/errcore.h>
28#include <list>
29
30#define _WIN32_DCOM
31#include <iprt/win/winsock2.h>
32#include <iprt/win/ws2tcpip.h>
33#include <iprt/win/windows.h>
34#include <tchar.h>
35
36#ifdef VBOX_WITH_NETFLT
37# include "VBox/VBoxNetCfg-win.h"
38# include "devguid.h"
39#endif
40
41#include <iprt/win/iphlpapi.h>
42#include <iprt/win/ntddndis.h>
43
44#include "LoggingNew.h"
45#include "HostNetworkInterfaceImpl.h"
46#include "ProgressImpl.h"
47#include "VirtualBoxImpl.h"
48#include "netif.h"
49#include "ThreadTask.h"
50
51#ifdef VBOX_WITH_NETFLT
52#include <Wbemidl.h>
53#include <comdef.h>
54
55#include "svchlp.h"
56
57#include <shellapi.h>
58#define INITGUID
59#include <guiddef.h>
60#include <devguid.h>
61#include <iprt/win/objbase.h>
62#include <iprt/win/setupapi.h>
63#include <iprt/win/shlobj.h>
64#include <cfgmgr32.h>
65
66#define VBOX_APP_NAME L"VirtualBox"
67
68static int getDefaultInterfaceIndex()
69{
70 PMIB_IPFORWARDTABLE pIpTable;
71 DWORD dwSize = sizeof(MIB_IPFORWARDTABLE) * 20;
72 DWORD dwRC = NO_ERROR;
73 int iIndex = -1;
74
75 pIpTable = (MIB_IPFORWARDTABLE *)RTMemAlloc(dwSize);
76 if (GetIpForwardTable(pIpTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
77 {
78 RTMemFree(pIpTable);
79 pIpTable = (MIB_IPFORWARDTABLE *)RTMemAlloc(dwSize);
80 if (!pIpTable)
81 return -1;
82 }
83 dwRC = GetIpForwardTable(pIpTable, &dwSize, 0);
84 if (dwRC == NO_ERROR)
85 {
86 for (unsigned int i = 0; i < pIpTable->dwNumEntries; i++)
87 if (pIpTable->table[i].dwForwardDest == 0)
88 {
89 iIndex = pIpTable->table[i].dwForwardIfIndex;
90 break;
91 }
92 }
93 RTMemFree(pIpTable);
94 return iIndex;
95}
96
97static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo, int iDefault)
98{
99 RT_NOREF(strName);
100
101 /*
102 * Most of the hosts probably have less than 10 adapters,
103 * so we'll mostly succeed from the first attempt.
104 */
105 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
106 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
107 if (!pAddresses)
108 return VERR_NO_MEMORY;
109 DWORD dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
110 if (dwRc == ERROR_BUFFER_OVERFLOW)
111 {
112 /* Impressive! More than 10 adapters! Get more memory and try again. */
113 RTMemFree(pAddresses);
114 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
115 if (!pAddresses)
116 return VERR_NO_MEMORY;
117 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
118 }
119 if (dwRc == NO_ERROR)
120 {
121 PIP_ADAPTER_ADDRESSES pAdapter;
122 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
123 {
124 char *pszUuid = RTStrDup(pAdapter->AdapterName);
125 size_t len = strlen(pszUuid) - 1;
126 if (pszUuid[0] == '{' && pszUuid[len] == '}')
127 {
128 pszUuid[len] = 0;
129 if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1))
130 {
131 bool fIPFound, fIPv6Found;
132 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
133 fIPFound = fIPv6Found = false;
134 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
135 {
136 switch (pAddr->Address.lpSockaddr->sa_family)
137 {
138 case AF_INET:
139 if (!fIPFound)
140 {
141 fIPFound = true;
142 memcpy(&pInfo->IPAddress,
143 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
144 sizeof(pInfo->IPAddress));
145 }
146 break;
147 case AF_INET6:
148 if (!fIPv6Found)
149 {
150 fIPv6Found = true;
151 memcpy(&pInfo->IPv6Address,
152 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
153 sizeof(pInfo->IPv6Address));
154 }
155 break;
156 }
157 }
158 PIP_ADAPTER_PREFIX pPrefix;
159 fIPFound = fIPv6Found = false;
160 for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
161 {
162 switch (pPrefix->Address.lpSockaddr->sa_family)
163 {
164 case AF_INET:
165 if (!fIPFound)
166 {
167 if (pPrefix->PrefixLength <= sizeof(pInfo->IPNetMask) * 8)
168 {
169 fIPFound = true;
170 RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
171 }
172 else
173 LogFunc(("Unexpected IPv4 prefix length of %d\n",
174 pPrefix->PrefixLength));
175 }
176 break;
177 case AF_INET6:
178 if (!fIPv6Found)
179 {
180 if (pPrefix->PrefixLength <= sizeof(pInfo->IPv6NetMask) * 8)
181 {
182 fIPv6Found = true;
183 RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
184 }
185 else
186 LogFunc(("Unexpected IPv6 prefix length of %d\n",
187 pPrefix->PrefixLength));
188 }
189 break;
190 }
191 }
192 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
193 LogFunc(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
194 else
195 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
196 pInfo->enmMediumType = NETIF_T_ETHERNET;
197 pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
198 pInfo->fIsDefault = (pAdapter->IfIndex == (DWORD)iDefault);
199 RTStrFree(pszUuid);
200 break;
201 }
202 }
203 RTStrFree(pszUuid);
204 }
205
206 ADAPTER_SETTINGS Settings;
207 HRESULT hr = VBoxNetCfgWinGetAdapterSettings((const GUID *)guid.raw(), &Settings);
208 if (hr == S_OK)
209 {
210 if (Settings.ip)
211 {
212 pInfo->IPAddress.u = Settings.ip;
213 pInfo->IPNetMask.u = Settings.mask;
214 }
215 pInfo->fDhcpEnabled = Settings.bDhcp;
216 }
217 else
218 {
219 pInfo->fDhcpEnabled = false;
220 }
221 }
222 RTMemFree(pAddresses);
223
224 return VINF_SUCCESS;
225}
226
227/* svc helper func */
228
229struct StaticIpConfig
230{
231 ULONG IPAddress;
232 ULONG IPNetMask;
233};
234
235struct StaticIpV6Config
236{
237 BSTR IPV6Address;
238 ULONG IPV6NetMaskLength;
239};
240
241class NetworkInterfaceHelperClientData : public ThreadVoidData
242{
243public:
244 NetworkInterfaceHelperClientData(){};
245 ~NetworkInterfaceHelperClientData(){};
246
247 SVCHlpMsg::Code msgCode;
248 /* for SVCHlpMsg::CreateHostOnlyNetworkInterface */
249 Bstr name;
250 ComObjPtr<HostNetworkInterface> iface;
251 ComObjPtr<VirtualBox> vBox;
252 /* for SVCHlpMsg::RemoveHostOnlyNetworkInterface */
253 Guid guid;
254
255 union
256 {
257 StaticIpConfig StaticIP;
258 StaticIpV6Config StaticIPV6;
259 } u;
260
261};
262
263static HRESULT netIfNetworkInterfaceHelperClient(SVCHlpClient *aClient,
264 Progress *aProgress,
265 void *aUser, int *aVrc)
266{
267 LogFlowFuncEnter();
268 LogFlowFunc(("aClient={%p}, aProgress={%p}, aUser={%p}\n",
269 aClient, aProgress, aUser));
270
271 AssertReturn( (aClient == NULL && aProgress == NULL && aVrc == NULL)
272 || (aClient != NULL && aProgress != NULL && aVrc != NULL),
273 E_POINTER);
274 AssertReturn(aUser, E_POINTER);
275
276 NetworkInterfaceHelperClientData* d = static_cast<NetworkInterfaceHelperClientData *>(aUser);
277
278 if (aClient == NULL)
279 {
280 /* "cleanup only" mode, just return (it will free aUser) */
281 return S_OK;
282 }
283
284 HRESULT rc = S_OK;
285 int vrc = VINF_SUCCESS;
286
287 switch (d->msgCode)
288 {
289 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
290 {
291 LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
292 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
293
294 /* write message and parameters */
295 vrc = aClient->write(d->msgCode);
296 if (RT_FAILURE(vrc)) break;
297// vrc = aClient->write(Utf8Str(d->name));
298// if (RT_FAILURE(vrc)) break;
299
300 /* wait for a reply */
301 bool endLoop = false;
302 while (!endLoop)
303 {
304 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
305
306 vrc = aClient->read(reply);
307 if (RT_FAILURE(vrc)) break;
308
309 switch (reply)
310 {
311 case SVCHlpMsg::CreateHostOnlyNetworkInterface_OK:
312 {
313 /* read the GUID */
314 Guid guid;
315 Utf8Str name;
316 vrc = aClient->read(name);
317 if (RT_FAILURE(vrc)) break;
318 vrc = aClient->read(guid);
319 if (RT_FAILURE(vrc)) break;
320
321 LogFlowFunc(("Network connection GUID = {%RTuuid}\n", guid.raw()));
322
323 /* initialize the object returned to the caller by
324 * CreateHostOnlyNetworkInterface() */
325 rc = d->iface->init(Bstr(name), Bstr(name), guid, HostNetworkInterfaceType_HostOnly);
326 if (SUCCEEDED(rc))
327 {
328 rc = d->iface->i_setVirtualBox(d->vBox);
329 if (SUCCEEDED(rc))
330 {
331 rc = d->iface->updateConfig();
332 }
333 }
334 endLoop = true;
335 break;
336 }
337 case SVCHlpMsg::Error:
338 {
339 /* read the error message */
340 Utf8Str errMsg;
341 vrc = aClient->read(errMsg);
342 if (RT_FAILURE(vrc)) break;
343
344 rc = E_FAIL;
345 d->iface->setError(E_FAIL, errMsg.c_str());
346 endLoop = true;
347 break;
348 }
349 default:
350 {
351 endLoop = true;
352 rc = E_FAIL;/// @todo ComAssertMsgFailedBreak((
353 //"Invalid message code %d (%08lX)\n",
354 //reply, reply),
355 //rc = E_FAIL);
356 }
357 }
358 }
359
360 break;
361 }
362 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
363 {
364 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
365 LogFlowFunc(("Network connection GUID = {%RTuuid}\n", d->guid.raw()));
366
367 /* write message and parameters */
368 vrc = aClient->write(d->msgCode);
369 if (RT_FAILURE(vrc)) break;
370 vrc = aClient->write(d->guid);
371 if (RT_FAILURE(vrc)) break;
372
373 /* wait for a reply */
374 bool endLoop = false;
375 while (!endLoop)
376 {
377 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
378
379 vrc = aClient->read(reply);
380 if (RT_FAILURE(vrc)) break;
381
382 switch (reply)
383 {
384 case SVCHlpMsg::OK:
385 {
386 /* no parameters */
387 rc = S_OK;
388 endLoop = true;
389 break;
390 }
391 case SVCHlpMsg::Error:
392 {
393 /* read the error message */
394 Utf8Str errMsg;
395 vrc = aClient->read(errMsg);
396 if (RT_FAILURE(vrc)) break;
397
398 rc = E_FAIL;
399 d->iface->setError(E_FAIL, errMsg.c_str());
400 endLoop = true;
401 break;
402 }
403 default:
404 {
405 endLoop = true;
406 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
407 //"Invalid message code %d (%08lX)\n",
408 //reply, reply),
409 //rc = E_FAIL);
410 }
411 }
412 }
413
414 break;
415 }
416 case SVCHlpMsg::EnableDynamicIpConfig: /* see usage in code */
417 {
418 LogFlowFunc(("EnableDynamicIpConfig:\n"));
419 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
420
421 /* write message and parameters */
422 vrc = aClient->write(d->msgCode);
423 if (RT_FAILURE(vrc)) break;
424 vrc = aClient->write(d->guid);
425 if (RT_FAILURE(vrc)) break;
426
427 /* wait for a reply */
428 bool endLoop = false;
429 while (!endLoop)
430 {
431 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
432
433 vrc = aClient->read(reply);
434 if (RT_FAILURE(vrc)) break;
435
436 switch (reply)
437 {
438 case SVCHlpMsg::OK:
439 {
440 /* no parameters */
441 rc = d->iface->updateConfig();
442 endLoop = true;
443 break;
444 }
445 case SVCHlpMsg::Error:
446 {
447 /* read the error message */
448 Utf8Str errMsg;
449 vrc = aClient->read(errMsg);
450 if (RT_FAILURE(vrc)) break;
451
452 rc = E_FAIL;
453 d->iface->setError(E_FAIL, errMsg.c_str());
454 endLoop = true;
455 break;
456 }
457 default:
458 {
459 endLoop = true;
460 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
461 //"Invalid message code %d (%08lX)\n",
462 //reply, reply),
463 //rc = E_FAIL);
464 }
465 }
466 }
467
468 break;
469 }
470 case SVCHlpMsg::EnableStaticIpConfig: /* see usage in code */
471 {
472 LogFlowFunc(("EnableStaticIpConfig:\n"));
473 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
474
475 /* write message and parameters */
476 vrc = aClient->write(d->msgCode);
477 if (RT_FAILURE(vrc)) break;
478 vrc = aClient->write(d->guid);
479 if (RT_FAILURE(vrc)) break;
480 vrc = aClient->write(d->u.StaticIP.IPAddress);
481 if (RT_FAILURE(vrc)) break;
482 vrc = aClient->write(d->u.StaticIP.IPNetMask);
483 if (RT_FAILURE(vrc)) break;
484
485 /* wait for a reply */
486 bool endLoop = false;
487 while (!endLoop)
488 {
489 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
490
491 vrc = aClient->read(reply);
492 if (RT_FAILURE(vrc)) break;
493
494 switch (reply)
495 {
496 case SVCHlpMsg::OK:
497 {
498 /* no parameters */
499 rc = d->iface->updateConfig();
500 endLoop = true;
501 break;
502 }
503 case SVCHlpMsg::Error:
504 {
505 /* read the error message */
506 Utf8Str errMsg;
507 vrc = aClient->read(errMsg);
508 if (RT_FAILURE(vrc)) break;
509
510 rc = E_FAIL;
511 d->iface->setError(E_FAIL, errMsg.c_str());
512 endLoop = true;
513 break;
514 }
515 default:
516 {
517 endLoop = true;
518 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
519 //"Invalid message code %d (%08lX)\n",
520 //reply, reply),
521 //rc = E_FAIL);
522 }
523 }
524 }
525
526 break;
527 }
528 case SVCHlpMsg::EnableStaticIpConfigV6: /* see usage in code */
529 {
530 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
531 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
532
533 /* write message and parameters */
534 vrc = aClient->write(d->msgCode);
535 if (RT_FAILURE(vrc)) break;
536 vrc = aClient->write(d->guid);
537 if (RT_FAILURE(vrc)) break;
538 vrc = aClient->write(Utf8Str(d->u.StaticIPV6.IPV6Address));
539 if (RT_FAILURE(vrc)) break;
540 vrc = aClient->write(d->u.StaticIPV6.IPV6NetMaskLength);
541 if (RT_FAILURE(vrc)) break;
542
543 /* wait for a reply */
544 bool endLoop = false;
545 while (!endLoop)
546 {
547 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
548
549 vrc = aClient->read(reply);
550 if (RT_FAILURE(vrc)) break;
551
552 switch (reply)
553 {
554 case SVCHlpMsg::OK:
555 {
556 /* no parameters */
557 rc = d->iface->updateConfig();
558 endLoop = true;
559 break;
560 }
561 case SVCHlpMsg::Error:
562 {
563 /* read the error message */
564 Utf8Str errMsg;
565 vrc = aClient->read(errMsg);
566 if (RT_FAILURE(vrc)) break;
567
568 rc = E_FAIL;
569 d->iface->setError(E_FAIL, errMsg.c_str());
570 endLoop = true;
571 break;
572 }
573 default:
574 {
575 endLoop = true;
576 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
577 //"Invalid message code %d (%08lX)\n",
578 //reply, reply),
579 //rc = E_FAIL);
580 }
581 }
582 }
583
584 break;
585 }
586 case SVCHlpMsg::DhcpRediscover: /* see usage in code */
587 {
588 LogFlowFunc(("DhcpRediscover:\n"));
589 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
590
591 /* write message and parameters */
592 vrc = aClient->write(d->msgCode);
593 if (RT_FAILURE(vrc)) break;
594 vrc = aClient->write(d->guid);
595 if (RT_FAILURE(vrc)) break;
596
597 /* wait for a reply */
598 bool endLoop = false;
599 while (!endLoop)
600 {
601 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
602
603 vrc = aClient->read(reply);
604 if (RT_FAILURE(vrc)) break;
605
606 switch (reply)
607 {
608 case SVCHlpMsg::OK:
609 {
610 /* no parameters */
611 rc = d->iface->updateConfig();
612 endLoop = true;
613 break;
614 }
615 case SVCHlpMsg::Error:
616 {
617 /* read the error message */
618 Utf8Str errMsg;
619 vrc = aClient->read(errMsg);
620 if (RT_FAILURE(vrc)) break;
621
622 rc = E_FAIL;
623 d->iface->setError(E_FAIL, errMsg.c_str());
624 endLoop = true;
625 break;
626 }
627 default:
628 {
629 endLoop = true;
630 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
631 //"Invalid message code %d (%08lX)\n",
632 //reply, reply),
633 //rc = E_FAIL);
634 }
635 }
636 }
637
638 break;
639 }
640 default:
641 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
642// "Invalid message code %d (%08lX)\n",
643// d->msgCode, d->msgCode),
644// rc = E_FAIL);
645 }
646
647 if (aVrc)
648 *aVrc = vrc;
649
650 LogFlowFunc(("rc=0x%08X, vrc=%Rrc\n", rc, vrc));
651 LogFlowFuncLeave();
652 return rc;
653}
654
655
656int netIfNetworkInterfaceHelperServer(SVCHlpClient *aClient,
657 SVCHlpMsg::Code aMsgCode)
658{
659 LogFlowFuncEnter();
660 LogFlowFunc(("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode));
661
662 AssertReturn(aClient, VERR_INVALID_POINTER);
663
664 int vrc = VINF_SUCCESS;
665 HRESULT hrc;
666
667 switch (aMsgCode)
668 {
669 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
670 {
671 LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
672
673// Utf8Str name;
674// vrc = aClient->read(name);
675// if (RT_FAILURE(vrc)) break;
676
677 Guid guid;
678 Utf8Str errMsg;
679 Bstr name;
680 Bstr bstrErr;
681
682#ifdef VBOXNETCFG_DELAYEDRENAME
683 Bstr devId;
684 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), devId.asOutParam(),
685 bstrErr.asOutParam());
686#else /* !VBOXNETCFG_DELAYEDRENAME */
687 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), name.asOutParam(),
688 bstrErr.asOutParam());
689#endif /* !VBOXNETCFG_DELAYEDRENAME */
690
691 if (hrc == S_OK)
692 {
693 ULONG ip, mask;
694 hrc = VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(&ip, &mask);
695 if (hrc == S_OK)
696 {
697 /* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip,
698 * i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */
699 ip = ip | (1 << 24);
700 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID*)guid.raw(), ip, mask);
701 if (hrc != S_OK)
702 LogRel(("VBoxNetCfgWinEnableStaticIpConfig failed (0x%x)\n", hrc));
703 }
704 else
705 LogRel(("VBoxNetCfgWinGenHostOnlyNetworkNetworkIp failed (0x%x)\n", hrc));
706#ifdef VBOXNETCFG_DELAYEDRENAME
707 hrc = VBoxNetCfgWinRenameHostOnlyConnection((const GUID*)guid.raw(), devId.raw(), name.asOutParam());
708 if (hrc != S_OK)
709 LogRel(("VBoxNetCfgWinRenameHostOnlyConnection failed, error = 0x%x", hrc));
710#endif /* VBOXNETCFG_DELAYEDRENAME */
711 /* write success followed by GUID */
712 vrc = aClient->write(SVCHlpMsg::CreateHostOnlyNetworkInterface_OK);
713 if (RT_FAILURE(vrc)) break;
714 vrc = aClient->write(Utf8Str(name));
715 if (RT_FAILURE(vrc)) break;
716 vrc = aClient->write(guid);
717 if (RT_FAILURE(vrc)) break;
718 }
719 else
720 {
721 vrc = VERR_GENERAL_FAILURE;
722 errMsg = Utf8Str(bstrErr);
723 /* write failure followed by error message */
724 if (errMsg.isEmpty())
725 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
726 vrc = aClient->write(SVCHlpMsg::Error);
727 if (RT_FAILURE(vrc)) break;
728 vrc = aClient->write(errMsg);
729 if (RT_FAILURE(vrc)) break;
730 }
731
732 break;
733 }
734 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
735 {
736 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
737
738 Guid guid;
739 Bstr bstrErr;
740
741 vrc = aClient->read(guid);
742 if (RT_FAILURE(vrc)) break;
743
744 Utf8Str errMsg;
745 hrc = VBoxNetCfgWinRemoveHostOnlyNetworkInterface((const GUID*)guid.raw(), bstrErr.asOutParam());
746
747 if (hrc == S_OK)
748 {
749 /* write parameter-less success */
750 vrc = aClient->write(SVCHlpMsg::OK);
751 if (RT_FAILURE(vrc)) break;
752 }
753 else
754 {
755 vrc = VERR_GENERAL_FAILURE;
756 errMsg = Utf8Str(bstrErr);
757 /* write failure followed by error message */
758 if (errMsg.isEmpty())
759 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
760 vrc = aClient->write(SVCHlpMsg::Error);
761 if (RT_FAILURE(vrc)) break;
762 vrc = aClient->write(errMsg);
763 if (RT_FAILURE(vrc)) break;
764 }
765
766 break;
767 }
768 case SVCHlpMsg::EnableStaticIpConfigV6:
769 {
770 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
771
772 Guid guid;
773 Utf8Str ipV6;
774 ULONG maskLengthV6;
775 vrc = aClient->read(guid);
776 if (RT_FAILURE(vrc)) break;
777 vrc = aClient->read(ipV6);
778 if (RT_FAILURE(vrc)) break;
779 vrc = aClient->read(maskLengthV6);
780 if (RT_FAILURE(vrc)) break;
781
782 Utf8Str errMsg;
783 vrc = VERR_NOT_IMPLEMENTED;
784
785 if (RT_SUCCESS(vrc))
786 {
787 /* write success followed by GUID */
788 vrc = aClient->write(SVCHlpMsg::OK);
789 if (RT_FAILURE(vrc)) break;
790 }
791 else
792 {
793 /* write failure followed by error message */
794 if (errMsg.isEmpty())
795 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
796 vrc = aClient->write(SVCHlpMsg::Error);
797 if (RT_FAILURE(vrc)) break;
798 vrc = aClient->write(errMsg);
799 if (RT_FAILURE(vrc)) break;
800 }
801
802 break;
803 }
804 case SVCHlpMsg::EnableStaticIpConfig:
805 {
806 LogFlowFunc(("EnableStaticIpConfig:\n"));
807
808 Guid guid;
809 ULONG ip, mask;
810 vrc = aClient->read(guid);
811 if (RT_FAILURE(vrc)) break;
812 vrc = aClient->read(ip);
813 if (RT_FAILURE(vrc)) break;
814 vrc = aClient->read(mask);
815 if (RT_FAILURE(vrc)) break;
816
817 Utf8Str errMsg;
818 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID *)guid.raw(), ip, mask);
819
820 if (hrc == S_OK)
821 {
822 /* write success followed by GUID */
823 vrc = aClient->write(SVCHlpMsg::OK);
824 if (RT_FAILURE(vrc)) break;
825 }
826 else
827 {
828 vrc = VERR_GENERAL_FAILURE;
829 /* write failure followed by error message */
830 if (errMsg.isEmpty())
831 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
832 vrc = aClient->write(SVCHlpMsg::Error);
833 if (RT_FAILURE(vrc)) break;
834 vrc = aClient->write(errMsg);
835 if (RT_FAILURE(vrc)) break;
836 }
837
838 break;
839 }
840 case SVCHlpMsg::EnableDynamicIpConfig:
841 {
842 LogFlowFunc(("EnableDynamicIpConfig:\n"));
843
844 Guid guid;
845 vrc = aClient->read(guid);
846 if (RT_FAILURE(vrc)) break;
847
848 Utf8Str errMsg;
849 hrc = VBoxNetCfgWinEnableDynamicIpConfig((const GUID *)guid.raw());
850
851 if (hrc == S_OK)
852 {
853 /* write success followed by GUID */
854 vrc = aClient->write(SVCHlpMsg::OK);
855 if (RT_FAILURE(vrc)) break;
856 }
857 else
858 {
859 vrc = VERR_GENERAL_FAILURE;
860 /* write failure followed by error message */
861 if (errMsg.isEmpty())
862 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
863 vrc = aClient->write(SVCHlpMsg::Error);
864 if (RT_FAILURE(vrc)) break;
865 vrc = aClient->write(errMsg);
866 if (RT_FAILURE(vrc)) break;
867 }
868
869 break;
870 }
871 case SVCHlpMsg::DhcpRediscover:
872 {
873 LogFlowFunc(("DhcpRediscover:\n"));
874
875 Guid guid;
876 vrc = aClient->read(guid);
877 if (RT_FAILURE(vrc)) break;
878
879 Utf8Str errMsg;
880 hrc = VBoxNetCfgWinDhcpRediscover((const GUID *)guid.raw());
881
882 if (hrc == S_OK)
883 {
884 /* write success followed by GUID */
885 vrc = aClient->write(SVCHlpMsg::OK);
886 if (RT_FAILURE(vrc)) break;
887 }
888 else
889 {
890 vrc = VERR_GENERAL_FAILURE;
891 /* write failure followed by error message */
892 if (errMsg.isEmpty())
893 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
894 vrc = aClient->write(SVCHlpMsg::Error);
895 if (RT_FAILURE(vrc)) break;
896 vrc = aClient->write(errMsg);
897 if (RT_FAILURE(vrc)) break;
898 }
899
900 break;
901 }
902 default:
903 AssertMsgFailedBreakStmt(
904 ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
905 VERR_GENERAL_FAILURE);
906 }
907
908 LogFlowFunc(("vrc=%Rrc\n", vrc));
909 LogFlowFuncLeave();
910 return vrc;
911}
912
913/** @todo REMOVE. OBSOLETE NOW. */
914/**
915 * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
916 * later OSes) and it has the UAC (User Account Control) feature enabled.
917 */
918static BOOL IsUACEnabled()
919{
920 LONG rc = 0;
921
922 OSVERSIONINFOEX info;
923 ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
924 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
925 rc = GetVersionEx((OSVERSIONINFO *) &info);
926 AssertReturn(rc != 0, FALSE);
927
928 LogFlowFunc(("dwMajorVersion=%d, dwMinorVersion=%d\n",
929 info.dwMajorVersion, info.dwMinorVersion));
930
931 /* we are interested only in Vista (and newer versions...). In all
932 * earlier versions UAC is not present. */
933 if (info.dwMajorVersion < 6)
934 return FALSE;
935
936 /* the default EnableLUA value is 1 (Enabled) */
937 DWORD dwEnableLUA = 1;
938
939 HKEY hKey;
940 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
941 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
942 0, KEY_QUERY_VALUE, &hKey);
943
944 Assert(rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
945 if (rc == ERROR_SUCCESS)
946 {
947
948 DWORD cbEnableLUA = sizeof(dwEnableLUA);
949 rc = RegQueryValueExA(hKey, "EnableLUA", NULL, NULL,
950 (LPBYTE) &dwEnableLUA, &cbEnableLUA);
951
952 RegCloseKey(hKey);
953
954 Assert(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
955 }
956
957 LogFlowFunc(("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
958
959 return dwEnableLUA == 1;
960}
961
962/* end */
963
964static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > * pPist,
965 INetCfgComponent * pncc, HostNetworkInterfaceType enmType,
966 int iDefaultInterface)
967{
968 LPWSTR lpszName;
969 GUID IfGuid;
970 HRESULT hr;
971 int rc = VERR_GENERAL_FAILURE;
972
973 hr = pncc->GetDisplayName(&lpszName);
974 Assert(hr == S_OK);
975 if (hr == S_OK)
976 {
977 Bstr name(lpszName);
978
979 hr = pncc->GetInstanceGuid(&IfGuid);
980 Assert(hr == S_OK);
981 if (hr == S_OK)
982 {
983 Guid guidIfCopy(IfGuid);
984 NETIFINFO Info;
985 RT_ZERO(Info);
986 Info.Uuid = *guidIfCopy.raw();
987 rc = collectNetIfInfo(name, guidIfCopy, &Info, iDefaultInterface);
988 if (RT_FAILURE(rc))
989 LogRelFunc(("collectNetIfInfo() -> %Rrc\n", rc));
990 LogFunc(("adding %ls\n", lpszName));
991 /* create a new object and add it to the list */
992 ComObjPtr<HostNetworkInterface> iface;
993 iface.createObject();
994 /* remove the curly bracket at the end */
995 rc = iface->init(name, enmType, &Info);
996 if (SUCCEEDED(rc))
997 {
998 if (Info.fIsDefault)
999 pPist->push_front(iface);
1000 else
1001 pPist->push_back(iface);
1002 }
1003 else
1004 {
1005 LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
1006 AssertComRC(rc);
1007 }
1008 }
1009 else
1010 LogRelFunc(("failed to get device instance GUID (0x%x)\n", hr));
1011 CoTaskMemFree(lpszName);
1012 }
1013 else
1014 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1015
1016 return rc;
1017}
1018
1019#endif /* VBOX_WITH_NETFLT */
1020
1021
1022static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkInterface> > &list)
1023{
1024#ifndef VBOX_WITH_NETFLT
1025 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
1026 return VERR_NOT_IMPLEMENTED;
1027#else /* # if defined VBOX_WITH_NETFLT */
1028 INetCfgComponent *pMpNcc;
1029 HRESULT hr;
1030 IEnumNetCfgComponent *pEnumComponent;
1031
1032 hr = pNc->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent);
1033 if (hr == S_OK)
1034 {
1035 while ((hr = pEnumComponent->Next(1, &pMpNcc, NULL)) == S_OK)
1036 {
1037 LPWSTR pwszName;
1038 ULONG uComponentStatus;
1039 hr = pMpNcc->GetDisplayName(&pwszName);
1040 if (hr == S_OK)
1041 LogFunc(("%ls\n", pwszName));
1042 else
1043 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1044 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1045 if (hr == S_OK)
1046 {
1047 if (uComponentStatus == 0)
1048 {
1049 LPWSTR pId;
1050 hr = pMpNcc->GetId(&pId);
1051 Assert(hr == S_OK);
1052 if (hr == S_OK)
1053 {
1054 LogFunc(("id = %ls\n", pId));
1055 if (!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1056 {
1057 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly, -1);
1058 }
1059 CoTaskMemFree(pId);
1060 }
1061 else
1062 LogRelFunc(("failed to get device id (0x%x)\n", hr));
1063 }
1064 }
1065 else
1066 LogRelFunc(("failed to get device status (0x%x)\n", hr));
1067 pMpNcc->Release();
1068 }
1069 Assert(hr == S_OK || hr == S_FALSE);
1070
1071 pEnumComponent->Release();
1072 }
1073 else
1074 LogRelFunc(("EnumComponents error (0x%x)\n", hr));
1075#endif /* # if defined VBOX_WITH_NETFLT */
1076 return VINF_SUCCESS;
1077}
1078
1079int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo)
1080{
1081#ifndef VBOX_WITH_NETFLT
1082 return VERR_NOT_IMPLEMENTED;
1083#else
1084 Bstr name;
1085 HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam());
1086 if (hr == S_OK)
1087 {
1088 Bstr IfGuid;
1089 hr = pIf->COMGETTER(Id)(IfGuid.asOutParam());
1090 Assert(hr == S_OK);
1091 if (hr == S_OK)
1092 {
1093 memset(pInfo, 0, sizeof(NETIFINFO));
1094 Guid guid(IfGuid);
1095 pInfo->Uuid = *(guid.raw());
1096
1097 return collectNetIfInfo(name, guid, pInfo, getDefaultInterfaceIndex());
1098 }
1099 }
1100 return VERR_GENERAL_FAILURE;
1101#endif
1102}
1103
1104int NetIfGetConfigByName(PNETIFINFO)
1105{
1106 return VERR_NOT_IMPLEMENTED;
1107}
1108
1109/**
1110 * Obtain the current state of the interface.
1111 *
1112 * @returns VBox status code.
1113 *
1114 * @param pcszIfName Interface name.
1115 * @param penmState Where to store the retrieved state.
1116 */
1117int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState)
1118{
1119 RT_NOREF(pcszIfName, penmState);
1120 return VERR_NOT_IMPLEMENTED;
1121}
1122
1123/**
1124 * Retrieve the physical link speed in megabits per second. If the interface is
1125 * not up or otherwise unavailable the zero speed is returned.
1126 *
1127 * @returns VBox status code.
1128 *
1129 * @param pcszIfName Interface name.
1130 * @param puMbits Where to store the link speed.
1131 */
1132int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits)
1133{
1134 RT_NOREF(pcszIfName, puMbits);
1135 return VERR_NOT_IMPLEMENTED;
1136}
1137
1138int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox,
1139 IHostNetworkInterface **aHostNetworkInterface,
1140 IProgress **aProgress,
1141 const char *pszName)
1142{
1143 RT_NOREF(pszName);
1144#ifndef VBOX_WITH_NETFLT
1145 return VERR_NOT_IMPLEMENTED;
1146#else
1147 /* create a progress object */
1148 ComObjPtr<Progress> progress;
1149 progress.createObject();
1150
1151 ComPtr<IHost> host;
1152 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1153 if (SUCCEEDED(rc))
1154 {
1155 rc = progress->init(pVirtualBox, host,
1156 Bstr(_T("Creating host only network interface")).raw(),
1157 FALSE /* aCancelable */);
1158 if (SUCCEEDED(rc))
1159 {
1160 if (FAILED(rc)) return rc;
1161 progress.queryInterfaceTo(aProgress);
1162
1163 /* create a new uninitialized host interface object */
1164 ComObjPtr<HostNetworkInterface> iface;
1165 iface.createObject();
1166 iface.queryInterfaceTo(aHostNetworkInterface);
1167
1168 /* create the networkInterfaceHelperClient() argument */
1169 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1170
1171 d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface;
1172// d->name = aName;
1173 d->iface = iface;
1174 d->vBox = pVirtualBox;
1175
1176 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1177 netIfNetworkInterfaceHelperClient,
1178 static_cast<void *>(d),
1179 progress);
1180 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1181
1182 }
1183 }
1184
1185 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1186#endif
1187}
1188
1189int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId,
1190 IProgress **aProgress)
1191{
1192#ifndef VBOX_WITH_NETFLT
1193 return VERR_NOT_IMPLEMENTED;
1194#else
1195 /* create a progress object */
1196 ComObjPtr<Progress> progress;
1197 progress.createObject();
1198 ComPtr<IHost> host;
1199 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1200 if (SUCCEEDED(rc))
1201 {
1202 rc = progress->init(pVirtualBox, host,
1203 Bstr(_T("Removing host network interface")).raw(),
1204 FALSE /* aCancelable */);
1205 if (SUCCEEDED(rc))
1206 {
1207 if (FAILED(rc)) return rc;
1208 progress.queryInterfaceTo(aProgress);
1209
1210 /* create the networkInterfaceHelperClient() argument */
1211 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1212
1213 d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface;
1214 d->guid = aId;
1215
1216 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1217 netIfNetworkInterfaceHelperClient,
1218 static_cast<void *>(d),
1219 progress);
1220 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1221
1222 }
1223 }
1224
1225 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1226#endif
1227}
1228
1229int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask)
1230{
1231 RT_NOREF(aOldIp);
1232#ifndef VBOX_WITH_NETFLT
1233 return VERR_NOT_IMPLEMENTED;
1234#else
1235 Bstr guid;
1236 HRESULT rc = pIf->COMGETTER(Id)(guid.asOutParam());
1237 if (SUCCEEDED(rc))
1238 {
1239// ComPtr<VirtualBox> vBox;
1240// rc = pIf->getVirtualBox(vBox.asOutParam());
1241// if (SUCCEEDED(rc))
1242 {
1243 /* create a progress object */
1244 ComObjPtr<Progress> progress;
1245 progress.createObject();
1246// ComPtr<IHost> host;
1247// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1248// if (SUCCEEDED(rc))
1249 {
1250 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1251 Bstr("Enabling Dynamic Ip Configuration").raw(),
1252 FALSE /* aCancelable */);
1253 if (SUCCEEDED(rc))
1254 {
1255 if (FAILED(rc)) return rc;
1256// progress.queryInterfaceTo(aProgress);
1257
1258 /* create the networkInterfaceHelperClient() argument */
1259 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1260
1261 d->msgCode = SVCHlpMsg::EnableStaticIpConfig;
1262 d->guid = Guid(guid);
1263 d->iface = pIf;
1264 d->u.StaticIP.IPAddress = ip;
1265 d->u.StaticIP.IPNetMask = mask;
1266
1267 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1268 netIfNetworkInterfaceHelperClient,
1269 static_cast<void *>(d),
1270 progress);
1271 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1272
1273 if (SUCCEEDED(rc))
1274 {
1275 progress->WaitForCompletion(-1);
1276 }
1277 }
1278 }
1279 }
1280 }
1281
1282 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1283#endif
1284}
1285
1286int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address,
1287 IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1288{
1289 RT_NOREF(aOldIPV6Address);
1290#ifndef VBOX_WITH_NETFLT
1291 return VERR_NOT_IMPLEMENTED;
1292#else
1293 Bstr guid;
1294 HRESULT rc = pIf->COMGETTER(Id)(guid.asOutParam());
1295 if (SUCCEEDED(rc))
1296 {
1297// ComPtr<VirtualBox> vBox;
1298// rc = pIf->getVirtualBox(vBox.asOutParam());
1299// if (SUCCEEDED(rc))
1300 {
1301 /* create a progress object */
1302 ComObjPtr<Progress> progress;
1303 progress.createObject();
1304// ComPtr<IHost> host;
1305// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1306// if (SUCCEEDED(rc))
1307 {
1308 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1309 Bstr("Enabling Dynamic Ip Configuration").raw(),
1310 FALSE /* aCancelable */);
1311 if (SUCCEEDED(rc))
1312 {
1313 if (FAILED(rc)) return rc;
1314// progress.queryInterfaceTo(aProgress);
1315
1316 /* create the networkInterfaceHelperClient() argument */
1317 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1318
1319 d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6;
1320 d->guid = guid;
1321 d->iface = pIf;
1322 d->u.StaticIPV6.IPV6Address = aIPV6Address;
1323 d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength;
1324
1325 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1326 netIfNetworkInterfaceHelperClient,
1327 static_cast<void *>(d),
1328 progress);
1329 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1330
1331 if (SUCCEEDED(rc))
1332 {
1333 progress->WaitForCompletion(-1);
1334 }
1335 }
1336 }
1337 }
1338 }
1339
1340 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1341#endif
1342}
1343
1344int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf)
1345{
1346#ifndef VBOX_WITH_NETFLT
1347 return VERR_NOT_IMPLEMENTED;
1348#else
1349 HRESULT rc;
1350 Bstr guid;
1351 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1352 if (SUCCEEDED(rc))
1353 {
1354// ComPtr<VirtualBox> vBox;
1355// rc = pIf->getVirtualBox(vBox.asOutParam());
1356// if (SUCCEEDED(rc))
1357 {
1358 /* create a progress object */
1359 ComObjPtr<Progress> progress;
1360 progress.createObject();
1361// ComPtr<IHost> host;
1362// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1363// if (SUCCEEDED(rc))
1364 {
1365 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1366 Bstr("Enabling Dynamic Ip Configuration").raw(),
1367 FALSE /* aCancelable */);
1368 if (SUCCEEDED(rc))
1369 {
1370 if (FAILED(rc)) return rc;
1371// progress.queryInterfaceTo(aProgress);
1372
1373 /* create the networkInterfaceHelperClient() argument */
1374 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1375
1376 d->msgCode = SVCHlpMsg::EnableDynamicIpConfig;
1377 d->guid = guid;
1378 d->iface = pIf;
1379
1380 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1381 netIfNetworkInterfaceHelperClient,
1382 static_cast<void *>(d),
1383 progress);
1384 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1385
1386 if (SUCCEEDED(rc))
1387 {
1388 progress->WaitForCompletion(-1);
1389 }
1390 }
1391 }
1392 }
1393 }
1394
1395 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1396#endif
1397}
1398
1399int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf)
1400{
1401#ifndef VBOX_WITH_NETFLT
1402 return VERR_NOT_IMPLEMENTED;
1403#else
1404 HRESULT rc;
1405 Bstr guid;
1406 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1407 if (SUCCEEDED(rc))
1408 {
1409// ComPtr<VirtualBox> vBox;
1410// rc = pIf->getVirtualBox(vBox.asOutParam());
1411// if (SUCCEEDED(rc))
1412 {
1413 /* create a progress object */
1414 ComObjPtr<Progress> progress;
1415 progress.createObject();
1416// ComPtr<IHost> host;
1417// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1418// if (SUCCEEDED(rc))
1419 {
1420 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1421 Bstr("Enabling Dynamic Ip Configuration").raw(),
1422 FALSE /* aCancelable */);
1423 if (SUCCEEDED(rc))
1424 {
1425 if (FAILED(rc)) return rc;
1426// progress.queryInterfaceTo(aProgress);
1427
1428 /* create the networkInterfaceHelperClient() argument */
1429 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1430
1431 d->msgCode = SVCHlpMsg::DhcpRediscover;
1432 d->guid = guid;
1433 d->iface = pIf;
1434
1435 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1436 netIfNetworkInterfaceHelperClient,
1437 static_cast<void *>(d),
1438 progress);
1439 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1440
1441 if (SUCCEEDED(rc))
1442 {
1443 progress->WaitForCompletion(-1);
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1450 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1451#endif
1452}
1453
1454
1455#define netIfLog LogFunc
1456
1457struct BoundAdapter
1458{
1459 LPWSTR pName;
1460 LPWSTR pHwId;
1461 RTUUID guid;
1462 PIP_ADAPTER_ADDRESSES pAdapter;
1463 BOOL fWireless;
1464};
1465
1466static int netIfGetUnboundHostOnlyAdapters(INetCfg *pNetCfg, std::list<BoundAdapter> &adapters)
1467{
1468 INetCfgComponent *pMiniport;
1469 HRESULT hr;
1470 IEnumNetCfgComponent *pEnumComponent;
1471
1472 if ((hr = pNetCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent)) != S_OK)
1473 LogRelFunc(("failed to enumerate network adapter components (0x%x)\n", hr));
1474 else
1475 {
1476 while ((hr = pEnumComponent->Next(1, &pMiniport, NULL)) == S_OK)
1477 {
1478 GUID guid;
1479 ULONG uComponentStatus;
1480 struct BoundAdapter adapter;
1481 memset(&adapter, 0, sizeof(adapter));
1482 if ((hr = pMiniport->GetDisplayName(&adapter.pName)) != S_OK)
1483 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1484 else if ((hr = pMiniport->GetDeviceStatus(&uComponentStatus)) != S_OK)
1485 netIfLog(("failed to get device status (0x%x)\n", hr));
1486 else if (uComponentStatus != 0)
1487 netIfLog(("wrong device status (0x%x)\n", uComponentStatus));
1488 else if ((hr = pMiniport->GetId(&adapter.pHwId)) != S_OK)
1489 LogRelFunc(("failed to get device id (0x%x)\n", hr));
1490 else if (_wcsnicmp(adapter.pHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1491 netIfLog(("not host-only id = %ls, ignored\n", adapter.pHwId));
1492 else if ((hr = pMiniport->GetInstanceGuid(&guid)) != S_OK)
1493 LogRelFunc(("failed to get instance id (0x%x)\n", hr));
1494 else
1495 {
1496 adapter.guid = *(Guid(guid).raw());
1497 netIfLog(("guid=%RTuuid, name=%ls id = %ls\n", &adapter.guid, adapter.pName, adapter.pHwId));
1498 adapters.push_back(adapter);
1499 adapter.pName = adapter.pHwId = NULL; /* do not free, will be done later */
1500 }
1501 if (adapter.pHwId)
1502 CoTaskMemFree(adapter.pHwId);
1503 if (adapter.pName)
1504 CoTaskMemFree(adapter.pName);
1505 pMiniport->Release();
1506 }
1507 Assert(hr == S_OK || hr == S_FALSE);
1508
1509 pEnumComponent->Release();
1510 }
1511 netIfLog(("return\n"));
1512 return VINF_SUCCESS;
1513}
1514
1515#define DEVNAME_PREFIX L"\\\\.\\"
1516
1517static BOOL netIfIsWireless(INetCfgComponent *pAdapter)
1518{
1519 bool fWireless = false;
1520
1521 /* Construct a device name. */
1522 LPWSTR pwszBindName = NULL;
1523 HRESULT hrc = pAdapter->GetBindName(&pwszBindName);
1524 if (SUCCEEDED(hrc) && pwszBindName)
1525 {
1526 WCHAR wszFileName[MAX_PATH];
1527 int vrc = RTUtf16Copy(wszFileName, MAX_PATH, DEVNAME_PREFIX);
1528 if (RT_SUCCESS(vrc))
1529 vrc = RTUtf16Cat(wszFileName, MAX_PATH, pwszBindName);
1530 if (RT_SUCCESS(vrc))
1531 {
1532 /* open the device */
1533 HANDLE hDevice = CreateFileW(wszFileName,
1534 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
1535 NULL,
1536 OPEN_EXISTING,
1537 FILE_ATTRIBUTE_NORMAL,
1538 NULL);
1539 if (hDevice != INVALID_HANDLE_VALUE)
1540 {
1541 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */
1542 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM;
1543 NDIS_PHYSICAL_MEDIUM PhMedium = NdisPhysicalMediumUnspecified;
1544 DWORD cbResultIgn = 0;
1545 if (DeviceIoControl(hDevice,
1546 IOCTL_NDIS_QUERY_GLOBAL_STATS,
1547 &Oid,
1548 sizeof(Oid),
1549 &PhMedium,
1550 sizeof(PhMedium),
1551 &cbResultIgn,
1552 NULL))
1553 {
1554 /* that was simple, now examine PhMedium */
1555 fWireless = PhMedium == NdisPhysicalMediumWirelessWan
1556 || PhMedium == NdisPhysicalMediumWirelessLan
1557 || PhMedium == NdisPhysicalMediumNative802_11
1558 || PhMedium == NdisPhysicalMediumBluetooth;
1559 }
1560 else
1561 {
1562 DWORD rcWin = GetLastError();
1563 LogRel(("netIfIsWireless: DeviceIoControl to '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1564 wszFileName, rcWin, rcWin));
1565 Assert(rcWin == ERROR_INVALID_PARAMETER || rcWin == ERROR_NOT_SUPPORTED || rcWin == ERROR_BAD_COMMAND);
1566 }
1567 CloseHandle(hDevice);
1568 }
1569 else
1570 {
1571 DWORD rcWin = GetLastError();
1572#if 0 /* bird: Triggers on each VBoxSVC startup so, disabled. Whoever want it, can enable using DEBUG_xxxx. */
1573 AssertLogRelMsgFailed(("netIfIsWireless: CreateFile on '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1574 wszFileName, rcWin, rcWin));
1575#else
1576 LogRel(("netIfIsWireless: CreateFile on '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1577 wszFileName, rcWin, rcWin));
1578#endif
1579 }
1580 }
1581 CoTaskMemFree(pwszBindName);
1582 }
1583 else
1584 LogRel(("netIfIsWireless: GetBindName failed hrc=%Rhrc\n", hrc));
1585
1586 return fWireless;
1587}
1588
1589static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
1590{
1591 INetCfg *pNetCfg = NULL;
1592 INetCfgComponent *pFilter;
1593 LPWSTR lpszApp;
1594 HRESULT hr;
1595
1596 netIfLog(("building the list of interfaces\n"));
1597 /* we are using the INetCfg API for getting the list of miniports */
1598 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, FALSE,
1599 VBOX_APP_NAME,
1600 10000,
1601 &lpszApp);
1602 Assert(hr == S_OK);
1603 if (hr != S_OK)
1604 {
1605 LogRelFunc(("failed to query INetCfg (0x%x)\n", hr));
1606 return hr;
1607 }
1608
1609 if ((hr = pNetCfg->FindComponent(L"oracle_VBoxNetLwf", &pFilter)) != S_OK
1610 /* fall back to NDIS5 miniport lookup */
1611 && (hr = pNetCfg->FindComponent(L"sun_VBoxNetFlt", &pFilter)))
1612 LogRelFunc(("could not find either 'oracle_VBoxNetLwf' or 'sun_VBoxNetFlt' components (0x%x)\n", hr));
1613 else
1614 {
1615 INetCfgComponentBindings *pFilterBindings;
1616 if ((pFilter->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pFilterBindings)) != S_OK)
1617 LogRelFunc(("failed to query INetCfgComponentBindings (0x%x)\n", hr));
1618 else
1619 {
1620 IEnumNetCfgBindingPath *pEnumBp;
1621 INetCfgBindingPath *pBp;
1622 if ((pFilterBindings->EnumBindingPaths(EBP_BELOW, &pEnumBp)) != S_OK)
1623 LogRelFunc(("failed to enumerate binding paths (0x%x)\n", hr));
1624 else
1625 {
1626 pEnumBp->Reset();
1627 while ((hr = pEnumBp->Next(1, &pBp, NULL)) == S_OK)
1628 {
1629 IEnumNetCfgBindingInterface *pEnumBi;
1630 INetCfgBindingInterface *pBi;
1631 if (pBp->IsEnabled() != S_OK)
1632 {
1633 /** @todo some id of disabled path could be useful. */
1634 netIfLog(("INetCfgBindingPath is disabled (0x%x)\n", hr));
1635 pBp->Release();
1636 continue;
1637 }
1638 if ((pBp->EnumBindingInterfaces(&pEnumBi)) != S_OK)
1639 LogRelFunc(("failed to enumerate binding interfaces (0x%x)\n", hr));
1640 else
1641 {
1642 hr = pEnumBi->Reset();
1643 while ((hr = pEnumBi->Next(1, &pBi, NULL)) == S_OK)
1644 {
1645 INetCfgComponent *pAdapter;
1646 if ((hr = pBi->GetLowerComponent(&pAdapter)) != S_OK)
1647 LogRelFunc(("failed to get lower component (0x%x)\n", hr));
1648 else
1649 {
1650 LPWSTR pwszName = NULL;
1651 if ((hr = pAdapter->GetDisplayName(&pwszName)) != S_OK)
1652 LogRelFunc(("failed to get display name (0x%x)\n", hr));
1653 else
1654 {
1655 ULONG uStatus;
1656 DWORD dwChars;
1657 if ((hr = pAdapter->GetDeviceStatus(&uStatus)) != S_OK)
1658 netIfLog(("%ls: failed to get device status (0x%x)\n",
1659 pwszName, hr));
1660 else if ((hr = pAdapter->GetCharacteristics(&dwChars)) != S_OK)
1661 netIfLog(("%ls: failed to get device characteristics (0x%x)\n",
1662 pwszName, hr));
1663 else if (uStatus != 0)
1664 netIfLog(("%ls: wrong status 0x%x\n",
1665 pwszName, uStatus));
1666 else if (dwChars & NCF_HIDDEN)
1667 netIfLog(("%ls: wrong characteristics 0x%x\n",
1668 pwszName, dwChars));
1669 else
1670 {
1671 GUID guid;
1672 LPWSTR pwszHwId = NULL;
1673 if ((hr = pAdapter->GetId(&pwszHwId)) != S_OK)
1674 LogRelFunc(("%ls: failed to get hardware id (0x%x)\n",
1675 pwszName, hr));
1676 else if (!_wcsnicmp(pwszHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1677 netIfLog(("host-only adapter %ls, ignored\n", pwszName));
1678 else if ((hr = pAdapter->GetInstanceGuid(&guid)) != S_OK)
1679 LogRelFunc(("%ls: failed to get instance GUID (0x%x)\n",
1680 pwszName, hr));
1681 else
1682 {
1683 struct BoundAdapter adapter;
1684 adapter.pName = pwszName;
1685 adapter.pHwId = pwszHwId;
1686 adapter.guid = *(Guid(guid).raw());
1687 adapter.pAdapter = NULL;
1688 adapter.fWireless = netIfIsWireless(pAdapter);
1689 netIfLog(("guid=%RTuuid, name=%ls, hwid=%ls, status=%x, chars=%x\n",
1690 &adapter.guid, pwszName, pwszHwId, uStatus, dwChars));
1691 boundAdapters.push_back(adapter);
1692 pwszName = pwszHwId = NULL; /* do not free, will be done later */
1693 }
1694 if (pwszHwId)
1695 CoTaskMemFree(pwszHwId);
1696 }
1697 if (pwszName)
1698 CoTaskMemFree(pwszName);
1699 }
1700
1701 pAdapter->Release();
1702 }
1703 pBi->Release();
1704 }
1705 pEnumBi->Release();
1706 }
1707 pBp->Release();
1708 }
1709 pEnumBp->Release();
1710 }
1711 pFilterBindings->Release();
1712 }
1713 pFilter->Release();
1714 }
1715 /* Host-only adapters are not necessarily bound, add them separately. */
1716 netIfGetUnboundHostOnlyAdapters(pNetCfg, boundAdapters);
1717 VBoxNetCfgWinReleaseINetCfg(pNetCfg, FALSE);
1718
1719 return S_OK;
1720}
1721
1722#if 0
1723static HRESULT netIfGetBoundAdaptersFallback(std::list<BoundAdapter> &boundAdapters)
1724{
1725 return CO_E_NOT_SUPPORTED;
1726}
1727#endif
1728
1729/**
1730 * Walk through the list of adpater addresses and extract the required
1731 * information. XP and older don't not have the OnLinkPrefixLength field.
1732 */
1733static void netIfFillInfoWithAddressesXp(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
1734{
1735 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1736 bool fIPFound = false;
1737 bool fIPv6Found = false;
1738 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
1739 {
1740 switch (pAddr->Address.lpSockaddr->sa_family)
1741 {
1742 case AF_INET:
1743 if (!fIPFound)
1744 {
1745 fIPFound = true;
1746 memcpy(&pInfo->IPAddress,
1747 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1748 sizeof(pInfo->IPAddress));
1749 }
1750 break;
1751 case AF_INET6:
1752 if (!fIPv6Found)
1753 {
1754 fIPv6Found = true;
1755 memcpy(&pInfo->IPv6Address,
1756 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
1757 sizeof(pInfo->IPv6Address));
1758 }
1759 break;
1760 }
1761 }
1762 PIP_ADAPTER_PREFIX pPrefix;
1763 ULONG uPrefixLenV4 = 0;
1764 ULONG uPrefixLenV6 = 0;
1765 for (pPrefix = pAdapter->FirstPrefix; pPrefix && !(uPrefixLenV4 && uPrefixLenV6); pPrefix = pPrefix->Next)
1766 {
1767 switch (pPrefix->Address.lpSockaddr->sa_family)
1768 {
1769 case AF_INET:
1770 if (!uPrefixLenV4)
1771 {
1772 ULONG ip = ((PSOCKADDR_IN)(pPrefix->Address.lpSockaddr))->sin_addr.s_addr;
1773 netIfLog(("prefix=%RTnaipv4 len=%u\n", ip, pPrefix->PrefixLength));
1774 if ( pPrefix->PrefixLength < sizeof(pInfo->IPNetMask) * 8
1775 && pPrefix->PrefixLength > 0
1776 && (ip & 0xF0) < 224)
1777 {
1778 uPrefixLenV4 = pPrefix->PrefixLength;
1779 RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
1780 }
1781 else
1782 netIfLog(("Unexpected IPv4 prefix length of %d\n",
1783 pPrefix->PrefixLength));
1784 }
1785 break;
1786 case AF_INET6:
1787 if (!uPrefixLenV6)
1788 {
1789 PBYTE ipv6 = ((PSOCKADDR_IN6)(pPrefix->Address.lpSockaddr))->sin6_addr.s6_addr;
1790 netIfLog(("prefix=%RTnaipv6 len=%u\n", ipv6, pPrefix->PrefixLength));
1791 if ( pPrefix->PrefixLength < sizeof(pInfo->IPv6NetMask) * 8
1792 && pPrefix->PrefixLength > 0
1793 && ipv6[0] != 0xFF)
1794 {
1795 uPrefixLenV6 = pPrefix->PrefixLength;
1796 RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
1797 }
1798 else
1799 netIfLog(("Unexpected IPv6 prefix length of %d\n", pPrefix->PrefixLength));
1800 }
1801 break;
1802 }
1803 }
1804 netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, uPrefixLenV4));
1805 netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, uPrefixLenV6));
1806}
1807
1808/**
1809 * Walk through the list of adpater addresses and extract the required
1810 * information. XP and older don't not have the OnLinkPrefixLength field.
1811 */
1812static void netIfFillInfoWithAddressesVista(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
1813{
1814 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1815
1816 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
1817 netIfLog(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
1818 else
1819 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
1820
1821 bool fIPFound = false;
1822 bool fIPv6Found = false;
1823 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
1824 {
1825 PIP_ADAPTER_UNICAST_ADDRESS_LH pAddrLh = (PIP_ADAPTER_UNICAST_ADDRESS_LH)pAddr;
1826 switch (pAddrLh->Address.lpSockaddr->sa_family)
1827 {
1828 case AF_INET:
1829 if (!fIPFound)
1830 {
1831 fIPFound = true;
1832 memcpy(&pInfo->IPAddress,
1833 &((struct sockaddr_in *)pAddrLh->Address.lpSockaddr)->sin_addr.s_addr,
1834 sizeof(pInfo->IPAddress));
1835 if (pAddrLh->OnLinkPrefixLength > 32)
1836 netIfLog(("Invalid IPv4 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
1837 else
1838 RTNetPrefixToMaskIPv4(pAddrLh->OnLinkPrefixLength, &pInfo->IPNetMask);
1839 }
1840 break;
1841 case AF_INET6:
1842 if (!fIPv6Found)
1843 {
1844 fIPv6Found = true;
1845 memcpy(&pInfo->IPv6Address,
1846 ((struct sockaddr_in6 *)pAddrLh->Address.lpSockaddr)->sin6_addr.s6_addr,
1847 sizeof(pInfo->IPv6Address));
1848 if (pAddrLh->OnLinkPrefixLength > 128)
1849 netIfLog(("Invalid IPv6 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
1850 else
1851 RTNetPrefixToMaskIPv6(pAddrLh->OnLinkPrefixLength, &pInfo->IPv6NetMask);
1852 }
1853 break;
1854 }
1855 }
1856
1857 if (fIPFound)
1858 {
1859 int iPrefixIPv4 = -1;
1860 RTNetMaskToPrefixIPv4(&pInfo->IPNetMask, &iPrefixIPv4);
1861 netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, iPrefixIPv4));
1862 }
1863 if (fIPv6Found)
1864 {
1865 int iPrefixIPv6 = -1;
1866 RTNetMaskToPrefixIPv6(&pInfo->IPv6NetMask, &iPrefixIPv6);
1867 netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, iPrefixIPv6));
1868 }
1869}
1870
1871#if (NTDDI_VERSION >= NTDDI_VISTA)
1872#define NETIF_GAA_FLAGS GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
1873#else /* (NTDDI_VERSION < NTDDI_VISTA) */
1874#define NETIF_GAA_FLAGS GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
1875#endif /* (NTDDI_VERSION < NTDDI_VISTA) */
1876
1877int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1878{
1879 HRESULT hr = S_OK;
1880 int iDefault = getDefaultInterfaceIndex();
1881 /* MSDN recommends to pre-allocate a 15KB buffer. */
1882 ULONG uBufLen = 15 * 1024;
1883 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1884 if (!pAddresses)
1885 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1886 DWORD dwRc = GetAdaptersAddresses(AF_UNSPEC, NETIF_GAA_FLAGS, NULL, pAddresses, &uBufLen);
1887 for (int tries = 0; tries < 3 && dwRc == ERROR_BUFFER_OVERFLOW; ++tries)
1888 {
1889 /* Get more memory and try again. */
1890 RTMemFree(pAddresses);
1891 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1892 if (!pAddresses)
1893 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1894 dwRc = GetAdaptersAddresses(AF_UNSPEC, NETIF_GAA_FLAGS, NULL, pAddresses, &uBufLen);
1895 }
1896 if (dwRc != NO_ERROR)
1897 {
1898 LogRelFunc(("GetAdaptersAddresses failed (0x%x)\n", dwRc));
1899 hr = HRESULT_FROM_WIN32(dwRc);
1900 }
1901 else
1902 {
1903 std::list<BoundAdapter> boundAdapters;
1904 HRESULT hr = netIfGetBoundAdapters(boundAdapters);
1905#if 0
1906 if (hr != S_OK)
1907 hr = netIfGetBoundAdaptersFallback(boundAdapters);
1908#endif
1909 if (hr != S_OK)
1910 LogRelFunc(("netIfGetBoundAdapters failed (0x%x)\n", hr));
1911 else
1912 {
1913 PIP_ADAPTER_ADDRESSES pAdapter;
1914
1915 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1916 {
1917 char *pszUuid = RTStrDup(pAdapter->AdapterName);
1918 if (!pszUuid)
1919 {
1920 LogRelFunc(("out of memory\n"));
1921 break;
1922 }
1923 size_t len = strlen(pszUuid) - 1;
1924 if (pszUuid[0] != '{' || pszUuid[len] != '}')
1925 LogRelFunc(("ignoring invalid GUID %s\n", pAdapter->AdapterName));
1926 else
1927 {
1928 std::list<BoundAdapter>::iterator it;
1929 pszUuid[len] = 0;
1930 for (it = boundAdapters.begin(); it != boundAdapters.end(); ++it)
1931 {
1932 if (!RTUuidCompareStr(&(*it).guid, pszUuid + 1))
1933 {
1934 (*it).pAdapter = pAdapter;
1935 break;
1936 }
1937 }
1938 }
1939 RTStrFree(pszUuid);
1940 }
1941 std::list<BoundAdapter>::iterator it;
1942 for (it = boundAdapters.begin(); it != boundAdapters.end(); ++it)
1943 {
1944 NETIFINFO info;
1945 memset(&info, 0, sizeof(info));
1946 info.Uuid = (*it).guid;
1947 info.enmMediumType = NETIF_T_ETHERNET;
1948 info.fWireless = (*it).fWireless;
1949 pAdapter = (*it).pAdapter;
1950 if (pAdapter)
1951 {
1952 info.enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
1953 info.fIsDefault = (pAdapter->IfIndex == (DWORD)iDefault);
1954 info.fDhcpEnabled = pAdapter->Flags & IP_ADAPTER_DHCP_ENABLED;
1955 OSVERSIONINFOEX OSInfoEx;
1956 RT_ZERO(OSInfoEx);
1957 OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1958 if ( GetVersionEx((LPOSVERSIONINFO)&OSInfoEx)
1959 && OSInfoEx.dwMajorVersion < 6)
1960 netIfFillInfoWithAddressesXp(&info, pAdapter);
1961 else
1962 netIfFillInfoWithAddressesVista(&info, pAdapter);
1963 }
1964 else
1965 info.enmStatus = NETIF_S_DOWN;
1966 /* create a new object and add it to the list */
1967 ComObjPtr<HostNetworkInterface> iface;
1968 iface.createObject();
1969 HostNetworkInterfaceType enmType =
1970 _wcsnicmp((*it).pHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2) ?
1971 HostNetworkInterfaceType_Bridged : HostNetworkInterfaceType_HostOnly;
1972 netIfLog(("Adding %ls as %s\n", (*it).pName,
1973 enmType == HostNetworkInterfaceType_Bridged ? "bridged" :
1974 enmType == HostNetworkInterfaceType_HostOnly ? "host-only" : "unknown"));
1975 int rc = iface->init((*it).pName, enmType, &info);
1976 if (FAILED(rc))
1977 LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
1978 else
1979 {
1980 if (info.fIsDefault)
1981 list.push_front(iface);
1982 else
1983 list.push_back(iface);
1984 }
1985 if ((*it).pHwId)
1986 CoTaskMemFree((*it).pHwId);
1987 if ((*it).pName)
1988 CoTaskMemFree((*it).pName);
1989 }
1990 }
1991 }
1992 RTMemFree(pAddresses);
1993
1994 return hr;
1995}
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