VirtualBox

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

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

Main/Network: fall-back address mask extraction mode for compatibility with Windows XP (bugref:7973)

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