VirtualBox

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

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

Main/Network: query adapter hw id and name via Setup API (#7993)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 68.7 KB
Line 
1/* $Id: NetIf-win.cpp 57950 2015-09-29 18:15:48Z 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 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), name.asOutParam(),
679 bstrErr.asOutParam());
680
681 if (hrc == S_OK)
682 {
683 ULONG ip, mask;
684 hrc = VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(&ip, &mask);
685 if (hrc == S_OK)
686 {
687 /* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip,
688 * i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */
689 ip = ip | (1 << 24);
690 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID*)guid.raw(), ip, mask);
691 }
692
693 /* write success followed by GUID */
694 vrc = aClient->write(SVCHlpMsg::CreateHostOnlyNetworkInterface_OK);
695 if (RT_FAILURE(vrc)) break;
696 vrc = aClient->write(Utf8Str(name));
697 if (RT_FAILURE(vrc)) break;
698 vrc = aClient->write(guid);
699 if (RT_FAILURE(vrc)) break;
700 }
701 else
702 {
703 vrc = VERR_GENERAL_FAILURE;
704 errMsg = Utf8Str(bstrErr);
705 /* write failure followed by error message */
706 if (errMsg.isEmpty())
707 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
708 vrc = aClient->write(SVCHlpMsg::Error);
709 if (RT_FAILURE(vrc)) break;
710 vrc = aClient->write(errMsg);
711 if (RT_FAILURE(vrc)) break;
712 }
713
714 break;
715 }
716 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
717 {
718 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
719
720 Guid guid;
721 Bstr bstrErr;
722
723 vrc = aClient->read(guid);
724 if (RT_FAILURE(vrc)) break;
725
726 Utf8Str errMsg;
727 hrc = VBoxNetCfgWinRemoveHostOnlyNetworkInterface((const GUID*)guid.raw(), bstrErr.asOutParam());
728
729 if (hrc == S_OK)
730 {
731 /* write parameter-less success */
732 vrc = aClient->write(SVCHlpMsg::OK);
733 if (RT_FAILURE(vrc)) break;
734 }
735 else
736 {
737 vrc = VERR_GENERAL_FAILURE;
738 errMsg = Utf8Str(bstrErr);
739 /* write failure followed by error message */
740 if (errMsg.isEmpty())
741 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
742 vrc = aClient->write(SVCHlpMsg::Error);
743 if (RT_FAILURE(vrc)) break;
744 vrc = aClient->write(errMsg);
745 if (RT_FAILURE(vrc)) break;
746 }
747
748 break;
749 }
750 case SVCHlpMsg::EnableStaticIpConfigV6:
751 {
752 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
753
754 Guid guid;
755 Utf8Str ipV6;
756 ULONG maskLengthV6;
757 vrc = aClient->read(guid);
758 if (RT_FAILURE(vrc)) break;
759 vrc = aClient->read(ipV6);
760 if (RT_FAILURE(vrc)) break;
761 vrc = aClient->read(maskLengthV6);
762 if (RT_FAILURE(vrc)) break;
763
764 Utf8Str errMsg;
765 vrc = VERR_NOT_IMPLEMENTED;
766
767 if (RT_SUCCESS(vrc))
768 {
769 /* write success followed by GUID */
770 vrc = aClient->write(SVCHlpMsg::OK);
771 if (RT_FAILURE(vrc)) break;
772 }
773 else
774 {
775 /* write failure followed by error message */
776 if (errMsg.isEmpty())
777 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
778 vrc = aClient->write(SVCHlpMsg::Error);
779 if (RT_FAILURE(vrc)) break;
780 vrc = aClient->write(errMsg);
781 if (RT_FAILURE(vrc)) break;
782 }
783
784 break;
785 }
786 case SVCHlpMsg::EnableStaticIpConfig:
787 {
788 LogFlowFunc(("EnableStaticIpConfig:\n"));
789
790 Guid guid;
791 ULONG ip, mask;
792 vrc = aClient->read(guid);
793 if (RT_FAILURE(vrc)) break;
794 vrc = aClient->read(ip);
795 if (RT_FAILURE(vrc)) break;
796 vrc = aClient->read(mask);
797 if (RT_FAILURE(vrc)) break;
798
799 Utf8Str errMsg;
800 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID *)guid.raw(), ip, mask);
801
802 if (hrc == S_OK)
803 {
804 /* write success followed by GUID */
805 vrc = aClient->write(SVCHlpMsg::OK);
806 if (RT_FAILURE(vrc)) break;
807 }
808 else
809 {
810 vrc = VERR_GENERAL_FAILURE;
811 /* write failure followed by error message */
812 if (errMsg.isEmpty())
813 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
814 vrc = aClient->write(SVCHlpMsg::Error);
815 if (RT_FAILURE(vrc)) break;
816 vrc = aClient->write(errMsg);
817 if (RT_FAILURE(vrc)) break;
818 }
819
820 break;
821 }
822 case SVCHlpMsg::EnableDynamicIpConfig:
823 {
824 LogFlowFunc(("EnableDynamicIpConfig:\n"));
825
826 Guid guid;
827 vrc = aClient->read(guid);
828 if (RT_FAILURE(vrc)) break;
829
830 Utf8Str errMsg;
831 hrc = VBoxNetCfgWinEnableDynamicIpConfig((const GUID *)guid.raw());
832
833 if (hrc == S_OK)
834 {
835 /* write success followed by GUID */
836 vrc = aClient->write(SVCHlpMsg::OK);
837 if (RT_FAILURE(vrc)) break;
838 }
839 else
840 {
841 vrc = VERR_GENERAL_FAILURE;
842 /* write failure followed by error message */
843 if (errMsg.isEmpty())
844 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
845 vrc = aClient->write(SVCHlpMsg::Error);
846 if (RT_FAILURE(vrc)) break;
847 vrc = aClient->write(errMsg);
848 if (RT_FAILURE(vrc)) break;
849 }
850
851 break;
852 }
853 case SVCHlpMsg::DhcpRediscover:
854 {
855 LogFlowFunc(("DhcpRediscover:\n"));
856
857 Guid guid;
858 vrc = aClient->read(guid);
859 if (RT_FAILURE(vrc)) break;
860
861 Utf8Str errMsg;
862 hrc = VBoxNetCfgWinDhcpRediscover((const GUID *)guid.raw());
863
864 if (hrc == S_OK)
865 {
866 /* write success followed by GUID */
867 vrc = aClient->write(SVCHlpMsg::OK);
868 if (RT_FAILURE(vrc)) break;
869 }
870 else
871 {
872 vrc = VERR_GENERAL_FAILURE;
873 /* write failure followed by error message */
874 if (errMsg.isEmpty())
875 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
876 vrc = aClient->write(SVCHlpMsg::Error);
877 if (RT_FAILURE(vrc)) break;
878 vrc = aClient->write(errMsg);
879 if (RT_FAILURE(vrc)) break;
880 }
881
882 break;
883 }
884 default:
885 AssertMsgFailedBreakStmt(
886 ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
887 VERR_GENERAL_FAILURE);
888 }
889
890 LogFlowFunc(("vrc=%Rrc\n", vrc));
891 LogFlowFuncLeave();
892 return vrc;
893}
894
895/** @todo REMOVE. OBSOLETE NOW. */
896/**
897 * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
898 * later OSes) and it has the UAC (User Account Control) feature enabled.
899 */
900static BOOL IsUACEnabled()
901{
902 LONG rc = 0;
903
904 OSVERSIONINFOEX info;
905 ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
906 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
907 rc = GetVersionEx((OSVERSIONINFO *) &info);
908 AssertReturn(rc != 0, FALSE);
909
910 LogFlowFunc(("dwMajorVersion=%d, dwMinorVersion=%d\n",
911 info.dwMajorVersion, info.dwMinorVersion));
912
913 /* we are interested only in Vista (and newer versions...). In all
914 * earlier versions UAC is not present. */
915 if (info.dwMajorVersion < 6)
916 return FALSE;
917
918 /* the default EnableLUA value is 1 (Enabled) */
919 DWORD dwEnableLUA = 1;
920
921 HKEY hKey;
922 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
923 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
924 0, KEY_QUERY_VALUE, &hKey);
925
926 Assert(rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
927 if (rc == ERROR_SUCCESS)
928 {
929
930 DWORD cbEnableLUA = sizeof(dwEnableLUA);
931 rc = RegQueryValueExA(hKey, "EnableLUA", NULL, NULL,
932 (LPBYTE) &dwEnableLUA, &cbEnableLUA);
933
934 RegCloseKey(hKey);
935
936 Assert(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
937 }
938
939 LogFlowFunc(("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
940
941 return dwEnableLUA == 1;
942}
943
944/* end */
945
946static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > * pPist,
947 INetCfgComponent * pncc, HostNetworkInterfaceType enmType,
948 int iDefaultInterface)
949{
950 LPWSTR lpszName;
951 GUID IfGuid;
952 HRESULT hr;
953 int rc = VERR_GENERAL_FAILURE;
954
955 hr = pncc->GetDisplayName(&lpszName);
956 Assert(hr == S_OK);
957 if (hr == S_OK)
958 {
959 Bstr name(lpszName);
960
961 hr = pncc->GetInstanceGuid(&IfGuid);
962 Assert(hr == S_OK);
963 if (hr == S_OK)
964 {
965 NETIFINFO Info;
966 RT_ZERO(Info);
967 Info.Uuid = *(Guid(IfGuid).raw());
968 rc = collectNetIfInfo(name, Guid(IfGuid), &Info, iDefaultInterface);
969 if (RT_FAILURE(rc))
970 {
971 LogRel(("vboxNetWinAddComponent: collectNetIfInfo() -> %Rrc\n", rc));
972 }
973 Log(("vboxNetWinAddComponent: adding %ls\n", lpszName));
974 /* create a new object and add it to the list */
975 ComObjPtr<HostNetworkInterface> iface;
976 iface.createObject();
977 /* remove the curly bracket at the end */
978 rc = iface->init(name, enmType, &Info);
979 if (SUCCEEDED(rc))
980 {
981 if (Info.bIsDefault)
982 pPist->push_front(iface);
983 else
984 pPist->push_back(iface);
985 }
986 else
987 {
988 LogRel(("vboxNetWinAddComponent: HostNetworkInterface::init() -> %Rrc\n", rc));
989 Assert(0);
990 }
991 }
992 else
993 LogRel(("vboxNetWinAddComponent: failed to get device instance GUID (0x%x)\n", hr));
994 CoTaskMemFree(lpszName);
995 }
996 else
997 LogRel(("vboxNetWinAddComponent: failed to get device display name (0x%x)\n", hr));
998
999 return rc;
1000}
1001
1002#endif /* VBOX_WITH_NETFLT */
1003
1004
1005static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkInterface> > &list)
1006{
1007#ifndef VBOX_WITH_NETFLT
1008 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
1009 return VERR_NOT_IMPLEMENTED;
1010#else /* # if defined VBOX_WITH_NETFLT */
1011 INetCfgComponent *pMpNcc;
1012 HRESULT hr;
1013 IEnumNetCfgComponent *pEnumComponent;
1014
1015 hr = pNc->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent);
1016 if (hr == S_OK)
1017 {
1018 while ((hr = pEnumComponent->Next(1, &pMpNcc, NULL)) == S_OK)
1019 {
1020 LPWSTR pwszName;
1021 ULONG uComponentStatus;
1022 hr = pMpNcc->GetDisplayName(&pwszName);
1023 if (hr == S_OK)
1024 Log(("netIfListHostAdapters: %ls\n", pwszName));
1025 else
1026 LogRel(("netIfListHostAdapters: failed to get device display name (0x%x)\n", hr));
1027 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1028 if (hr == S_OK)
1029 {
1030 if (uComponentStatus == 0)
1031 {
1032 LPWSTR pId;
1033 hr = pMpNcc->GetId(&pId);
1034 Assert(hr == S_OK);
1035 if (hr == S_OK)
1036 {
1037 Log(("netIfListHostAdapters: id = %ls\n", pId));
1038 if (!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1039 {
1040 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly, -1);
1041 }
1042 CoTaskMemFree(pId);
1043 }
1044 else
1045 LogRel(("netIfListHostAdapters: failed to get device id (0x%x)\n", hr));
1046 }
1047 }
1048 else
1049 LogRel(("netIfListHostAdapters: failed to get device status (0x%x)\n", hr));
1050 pMpNcc->Release();
1051 }
1052 Assert(hr == S_OK || hr == S_FALSE);
1053
1054 pEnumComponent->Release();
1055 }
1056 else
1057 LogRel(("netIfListHostAdapters: EnumComponents error (0x%x)\n", hr));
1058#endif /* # if defined VBOX_WITH_NETFLT */
1059 return VINF_SUCCESS;
1060}
1061
1062int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo)
1063{
1064#ifndef VBOX_WITH_NETFLT
1065 return VERR_NOT_IMPLEMENTED;
1066#else
1067 Bstr name;
1068 HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam());
1069 if (hr == S_OK)
1070 {
1071 Bstr IfGuid;
1072 hr = pIf->COMGETTER(Id)(IfGuid.asOutParam());
1073 Assert(hr == S_OK);
1074 if (hr == S_OK)
1075 {
1076 memset(pInfo, 0, sizeof(NETIFINFO));
1077 Guid guid(IfGuid);
1078 pInfo->Uuid = *(guid.raw());
1079
1080 return collectNetIfInfo(name, guid, pInfo, getDefaultInterfaceIndex());
1081 }
1082 }
1083 return VERR_GENERAL_FAILURE;
1084#endif
1085}
1086
1087int NetIfGetConfigByName(PNETIFINFO)
1088{
1089 return VERR_NOT_IMPLEMENTED;
1090}
1091
1092/**
1093 * Obtain the current state of the interface.
1094 *
1095 * @returns VBox status code.
1096 *
1097 * @param pcszIfName Interface name.
1098 * @param penmState Where to store the retrieved state.
1099 */
1100int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState)
1101{
1102 return VERR_NOT_IMPLEMENTED;
1103}
1104
1105/**
1106 * Retrieve the physical link speed in megabits per second. If the interface is
1107 * not up or otherwise unavailable the zero speed is returned.
1108 *
1109 * @returns VBox status code.
1110 *
1111 * @param pcszIfName Interface name.
1112 * @param puMbits Where to store the link speed.
1113 */
1114int NetIfGetLinkSpeed(const char * /*pcszIfName*/, uint32_t * /*puMbits*/)
1115{
1116 return VERR_NOT_IMPLEMENTED;
1117}
1118
1119int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox,
1120 IHostNetworkInterface **aHostNetworkInterface,
1121 IProgress **aProgress,
1122 const char *pcszName)
1123{
1124#ifndef VBOX_WITH_NETFLT
1125 return VERR_NOT_IMPLEMENTED;
1126#else
1127 /* create a progress object */
1128 ComObjPtr<Progress> progress;
1129 progress.createObject();
1130
1131 ComPtr<IHost> host;
1132 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1133 if (SUCCEEDED(rc))
1134 {
1135 rc = progress->init(pVirtualBox, host,
1136 Bstr(_T("Creating host only network interface")).raw(),
1137 FALSE /* aCancelable */);
1138 if (SUCCEEDED(rc))
1139 {
1140 if (FAILED(rc)) return rc;
1141 progress.queryInterfaceTo(aProgress);
1142
1143 /* create a new uninitialized host interface object */
1144 ComObjPtr<HostNetworkInterface> iface;
1145 iface.createObject();
1146 iface.queryInterfaceTo(aHostNetworkInterface);
1147
1148 /* create the networkInterfaceHelperClient() argument */
1149 std::auto_ptr<NetworkInterfaceHelperClientData>
1150 d(new NetworkInterfaceHelperClientData());
1151 AssertReturn(d.get(), E_OUTOFMEMORY);
1152
1153 d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface;
1154// d->name = aName;
1155 d->iface = iface;
1156 d->vBox = pVirtualBox;
1157
1158 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1159 netIfNetworkInterfaceHelperClient,
1160 static_cast<void *>(d.get()),
1161 progress);
1162 if (SUCCEEDED(rc))
1163 {
1164 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1165 d.release();
1166 }
1167 }
1168 }
1169
1170 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1171#endif
1172}
1173
1174int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId,
1175 IProgress **aProgress)
1176{
1177#ifndef VBOX_WITH_NETFLT
1178 return VERR_NOT_IMPLEMENTED;
1179#else
1180 /* create a progress object */
1181 ComObjPtr<Progress> progress;
1182 progress.createObject();
1183 ComPtr<IHost> host;
1184 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1185 if (SUCCEEDED(rc))
1186 {
1187 rc = progress->init(pVirtualBox, host,
1188 Bstr(_T("Removing host network interface")).raw(),
1189 FALSE /* aCancelable */);
1190 if (SUCCEEDED(rc))
1191 {
1192 if (FAILED(rc)) return rc;
1193 progress.queryInterfaceTo(aProgress);
1194
1195 /* create the networkInterfaceHelperClient() argument */
1196 std::auto_ptr<NetworkInterfaceHelperClientData>
1197 d(new NetworkInterfaceHelperClientData());
1198 AssertReturn(d.get(), E_OUTOFMEMORY);
1199
1200 d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface;
1201 d->guid = aId;
1202
1203 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1204 netIfNetworkInterfaceHelperClient,
1205 static_cast<void *>(d.get()),
1206 progress);
1207
1208 if (SUCCEEDED(rc))
1209 {
1210 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1211 d.release();
1212 }
1213 }
1214 }
1215
1216 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1217#endif
1218}
1219
1220int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask)
1221{
1222#ifndef VBOX_WITH_NETFLT
1223 return VERR_NOT_IMPLEMENTED;
1224#else
1225 HRESULT rc;
1226 Bstr guid;
1227 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1228 if (SUCCEEDED(rc))
1229 {
1230// ComPtr<VirtualBox> vBox;
1231// rc = pIf->getVirtualBox(vBox.asOutParam());
1232// if (SUCCEEDED(rc))
1233 {
1234 /* create a progress object */
1235 ComObjPtr<Progress> progress;
1236 progress.createObject();
1237// ComPtr<IHost> host;
1238// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1239// if (SUCCEEDED(rc))
1240 {
1241 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1242 Bstr("Enabling Dynamic Ip Configuration").raw(),
1243 FALSE /* aCancelable */);
1244 if (SUCCEEDED(rc))
1245 {
1246 if (FAILED(rc)) return rc;
1247// progress.queryInterfaceTo(aProgress);
1248
1249 /* create the networkInterfaceHelperClient() argument */
1250 std::auto_ptr<NetworkInterfaceHelperClientData>
1251 d(new NetworkInterfaceHelperClientData());
1252 AssertReturn(d.get(), E_OUTOFMEMORY);
1253
1254 d->msgCode = SVCHlpMsg::EnableStaticIpConfig;
1255 d->guid = Guid(guid);
1256 d->iface = pIf;
1257 d->u.StaticIP.IPAddress = ip;
1258 d->u.StaticIP.IPNetMask = mask;
1259
1260 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1261 netIfNetworkInterfaceHelperClient,
1262 static_cast<void *>(d.get()),
1263 progress);
1264
1265 if (SUCCEEDED(rc))
1266 {
1267 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1268 d.release();
1269
1270 progress->WaitForCompletion(-1);
1271 }
1272 }
1273 }
1274 }
1275 }
1276
1277 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1278#endif
1279}
1280
1281int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address,
1282 IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1283{
1284#ifndef VBOX_WITH_NETFLT
1285 return VERR_NOT_IMPLEMENTED;
1286#else
1287 HRESULT rc;
1288 Bstr guid;
1289 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1290 if (SUCCEEDED(rc))
1291 {
1292// ComPtr<VirtualBox> vBox;
1293// rc = pIf->getVirtualBox(vBox.asOutParam());
1294// if (SUCCEEDED(rc))
1295 {
1296 /* create a progress object */
1297 ComObjPtr<Progress> progress;
1298 progress.createObject();
1299// ComPtr<IHost> host;
1300// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1301// if (SUCCEEDED(rc))
1302 {
1303 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1304 Bstr("Enabling Dynamic Ip Configuration").raw(),
1305 FALSE /* aCancelable */);
1306 if (SUCCEEDED(rc))
1307 {
1308 if (FAILED(rc)) return rc;
1309// progress.queryInterfaceTo(aProgress);
1310
1311 /* create the networkInterfaceHelperClient() argument */
1312 std::auto_ptr<NetworkInterfaceHelperClientData>
1313 d(new NetworkInterfaceHelperClientData());
1314 AssertReturn(d.get(), E_OUTOFMEMORY);
1315
1316 d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6;
1317 d->guid = guid;
1318 d->iface = pIf;
1319 d->u.StaticIPV6.IPV6Address = aIPV6Address;
1320 d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength;
1321
1322 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1323 netIfNetworkInterfaceHelperClient,
1324 static_cast<void *>(d.get()),
1325 progress);
1326
1327 if (SUCCEEDED(rc))
1328 {
1329 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1330 d.release();
1331
1332 progress->WaitForCompletion(-1);
1333 }
1334 }
1335 }
1336 }
1337 }
1338
1339 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1340#endif
1341}
1342
1343int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf)
1344{
1345#ifndef VBOX_WITH_NETFLT
1346 return VERR_NOT_IMPLEMENTED;
1347#else
1348 HRESULT rc;
1349 Bstr guid;
1350 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1351 if (SUCCEEDED(rc))
1352 {
1353// ComPtr<VirtualBox> vBox;
1354// rc = pIf->getVirtualBox(vBox.asOutParam());
1355// if (SUCCEEDED(rc))
1356 {
1357 /* create a progress object */
1358 ComObjPtr<Progress> progress;
1359 progress.createObject();
1360// ComPtr<IHost> host;
1361// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1362// if (SUCCEEDED(rc))
1363 {
1364 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1365 Bstr("Enabling Dynamic Ip Configuration").raw(),
1366 FALSE /* aCancelable */);
1367 if (SUCCEEDED(rc))
1368 {
1369 if (FAILED(rc)) return rc;
1370// progress.queryInterfaceTo(aProgress);
1371
1372 /* create the networkInterfaceHelperClient() argument */
1373 std::auto_ptr<NetworkInterfaceHelperClientData>
1374 d(new NetworkInterfaceHelperClientData());
1375 AssertReturn(d.get(), E_OUTOFMEMORY);
1376
1377 d->msgCode = SVCHlpMsg::EnableDynamicIpConfig;
1378 d->guid = guid;
1379 d->iface = pIf;
1380
1381 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1382 netIfNetworkInterfaceHelperClient,
1383 static_cast<void *>(d.get()),
1384 progress);
1385
1386 if (SUCCEEDED(rc))
1387 {
1388 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1389 d.release();
1390
1391 progress->WaitForCompletion(-1);
1392 }
1393 }
1394 }
1395 }
1396 }
1397
1398 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1399#endif
1400}
1401
1402int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf)
1403{
1404#ifndef VBOX_WITH_NETFLT
1405 return VERR_NOT_IMPLEMENTED;
1406#else
1407 HRESULT rc;
1408 Bstr guid;
1409 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1410 if (SUCCEEDED(rc))
1411 {
1412// ComPtr<VirtualBox> vBox;
1413// rc = pIf->getVirtualBox(vBox.asOutParam());
1414// if (SUCCEEDED(rc))
1415 {
1416 /* create a progress object */
1417 ComObjPtr<Progress> progress;
1418 progress.createObject();
1419// ComPtr<IHost> host;
1420// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1421// if (SUCCEEDED(rc))
1422 {
1423 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1424 Bstr("Enabling Dynamic Ip Configuration").raw(),
1425 FALSE /* aCancelable */);
1426 if (SUCCEEDED(rc))
1427 {
1428 if (FAILED(rc)) return rc;
1429// progress.queryInterfaceTo(aProgress);
1430
1431 /* create the networkInterfaceHelperClient() argument */
1432 std::auto_ptr<NetworkInterfaceHelperClientData>
1433 d(new NetworkInterfaceHelperClientData());
1434 AssertReturn(d.get(), E_OUTOFMEMORY);
1435
1436 d->msgCode = SVCHlpMsg::DhcpRediscover;
1437 d->guid = guid;
1438 d->iface = pIf;
1439
1440 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1441 netIfNetworkInterfaceHelperClient,
1442 static_cast<void *>(d.get()),
1443 progress);
1444
1445 if (SUCCEEDED(rc))
1446 {
1447 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1448 d.release();
1449
1450 progress->WaitForCompletion(-1);
1451 }
1452 }
1453 }
1454 }
1455 }
1456
1457 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1458#endif
1459}
1460
1461#ifndef NETIF_WITHOUT_NETCFG
1462int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1463{
1464#ifndef VBOX_WITH_NETFLT
1465 return VERR_NOT_IMPLEMENTED;
1466#else /* # if defined VBOX_WITH_NETFLT */
1467 INetCfg *pNc = NULL;
1468 INetCfgComponent *pMpNcc;
1469 INetCfgComponent *pTcpIpNcc;
1470 LPWSTR lpszApp;
1471 HRESULT hr;
1472 IEnumNetCfgBindingPath *pEnumBp;
1473 INetCfgBindingPath *pBp;
1474 IEnumNetCfgBindingInterface *pEnumBi;
1475 INetCfgBindingInterface *pBi;
1476 int iDefault = getDefaultInterfaceIndex();
1477
1478 Log(("NetIfList: building the list of interfaces\n"));
1479 /* we are using the INetCfg API for getting the list of miniports */
1480 hr = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE,
1481 VBOX_APP_NAME,
1482 10000,
1483 &lpszApp);
1484 Assert(hr == S_OK);
1485 if (hr != S_OK)
1486 {
1487 if (pNc)
1488 pNc->Release();
1489 pNc = NULL;
1490 LogRel(("NetIfList: failed to acquire INetCfg interface (0x%x), trying CoCreateInstance...\n", hr));
1491 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNc);
1492 if (SUCCEEDED(hr))
1493 {
1494 hr = pNc->Initialize(NULL);
1495 if (FAILED(hr))
1496 {
1497 LogRel(("NetIfList: INetCfg::Initialize failed with 0x%x\n", hr));
1498 if (pNc)
1499 pNc->Release();
1500 pNc = NULL;
1501 }
1502 }
1503 else
1504 LogRel(("NetIfList: CoCreateInstance failed with 0x%x\n", hr));
1505 }
1506
1507 if (hr == S_OK)
1508 {
1509# ifdef VBOX_NETFLT_ONDEMAND_BIND
1510 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
1511 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
1512# else
1513 /* for the filter-based approach we get all miniports our filter (oracle_VBoxNetLwf)is bound to */
1514 hr = pNc->FindComponent(L"oracle_VBoxNetLwf", &pTcpIpNcc);
1515 if (hr != S_OK)
1516 {
1517 LogRel(("NetIfList: could not find VBoxNetLwf component (error 0x%x), trying VBoxNetFlt instead\n", hr));
1518 /* fall back to NDIS5 miniport lookup (sun_VBoxNetFlt) */
1519 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
1520 }
1521# ifndef VBOX_WITH_HARDENING
1522 if (hr != S_OK)
1523 {
1524 /* TODO: try to install the netflt from here */
1525 }
1526# endif
1527
1528# endif
1529
1530 if (hr == S_OK)
1531 {
1532 INetCfgComponentBindings *pBindings;
1533 hr = pTcpIpNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pBindings);
1534 Assert(hr == S_OK);
1535 if (hr == S_OK)
1536 {
1537 hr = pBindings->EnumBindingPaths(EBP_BELOW, &pEnumBp);
1538 Assert(hr == S_OK);
1539 if (hr == S_OK)
1540 {
1541 hr = pEnumBp->Reset();
1542 Assert(hr == S_OK);
1543 if (hr == S_OK)
1544 {
1545 while ((hr = pEnumBp->Next(1, &pBp, NULL)) == S_OK)
1546 {
1547 Log(("NetIfList: fetched INetCfgBindingPath interface\n"));
1548 /* S_OK == enabled, S_FALSE == disabled */
1549 if (pBp->IsEnabled() == S_OK)
1550 {
1551 hr = pBp->EnumBindingInterfaces(&pEnumBi);
1552 Assert(hr == S_OK);
1553 if (hr == S_OK)
1554 {
1555 hr = pEnumBi->Reset();
1556 Assert(hr == S_OK);
1557 if (hr == S_OK)
1558 {
1559 while ((hr = pEnumBi->Next(1, &pBi, NULL)) == S_OK)
1560 {
1561 Log(("NetIfList: fetched INetCfgBindingInterface interface\n"));
1562 hr = pBi->GetLowerComponent(&pMpNcc);
1563 Assert(hr == S_OK);
1564 if (hr == S_OK)
1565 {
1566 LPWSTR pwszName;
1567 ULONG uComponentStatus;
1568 hr = pMpNcc->GetDisplayName(&pwszName);
1569 if (hr == S_OK)
1570 Log(("NetIfList: got %ls\n", pwszName));
1571 else
1572 LogRel(("NetIfList: failed to get device display name (0x%x)\n", hr));
1573 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1574 if (hr == S_OK)
1575 {
1576 if (uComponentStatus == 0)
1577 {
1578 LPWSTR pId;
1579 hr = pMpNcc->GetId(&pId);
1580 Assert(hr == S_OK);
1581 if (hr == S_OK)
1582 {
1583 Log(("NetIfList: fetched network adapter id: %.80ls\n", pId));
1584 /*
1585 * Host-only interfaces are ignored here and included into the list
1586 * later in netIfListHostAdapters()
1587 */
1588 if (_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1589 {
1590 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_Bridged,
1591 iDefault);
1592 }
1593 CoTaskMemFree(pId);
1594 }
1595 else
1596 LogRel(("NetIfList: failed to get device id (0x%x)\n", hr));
1597 }
1598 else
1599 LogRel(("NetIfList: wrong device status (0x%x)\n", uComponentStatus));
1600 }
1601 else
1602 LogRel(("NetIfList: failed to get device status (0x%x)\n", hr));
1603 pMpNcc->Release();
1604 }
1605 else
1606 LogRel(("NetIfList: failed to get lower component (0x%x)\n", hr));
1607 pBi->Release();
1608 }
1609 Assert(hr == S_OK || hr == S_FALSE);
1610 }
1611 else
1612 LogRel(("NetIfList: IEnumNetCfgBindingInterface::Reset failed (0x%x)\n", hr));
1613 pEnumBi->Release();
1614 }
1615 else
1616 LogRel(("NetIfList: failed to enumerate binding interfaces (0x%x)\n", hr));
1617 }
1618 else
1619 LogRel(("NetIfList: INetCfgBindingPath is disabled\n"));
1620 pBp->Release();
1621 }
1622 Assert(hr == S_OK || hr == S_FALSE);
1623 }
1624 else
1625 LogRel(("NetIfList: IEnumNetCfgBindingPath::Reset failed (0x%x)\n", hr));
1626 pEnumBp->Release();
1627 }
1628 else
1629 LogRel(("NetIfList: EnumBindingPaths failed (0x%x)\n", hr));
1630 pBindings->Release();
1631 }
1632 else
1633 LogRel(("NetIfList: failed to acquire INetCfgComponentBindings interface\n"));
1634 pTcpIpNcc->Release();
1635 }
1636 else
1637 {
1638 LogRel(("failed to get the oracle_VBoxNetLwf(sun_VBoxNetFlt) component, error (0x%x)\n", hr));
1639 }
1640
1641 /* Add host-only adapters to the list */
1642 netIfListHostAdapters(pNc, list);
1643
1644 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
1645 }
1646
1647 return VINF_SUCCESS;
1648#endif /* # if defined VBOX_WITH_NETFLT */
1649}
1650
1651#else /* !NETIF_WITHOUT_NETCFG */
1652
1653static void getTypeAndName(PIP_ADAPTER_ADDRESSES pAdapter, HostNetworkInterfaceType *enmType, PWCHAR pwszName, int cbName)
1654{
1655 /* In case we fail to get the right values we initialize them with best-effort defaults. */
1656 *enmType = wcsncmp(pAdapter->Description, L"VirtualBox", 10) == 0
1657 ? HostNetworkInterfaceType_HostOnly
1658 : HostNetworkInterfaceType_Bridged;
1659 wcscpy_s(pwszName, cbName / sizeof(*pwszName), pAdapter->Description);
1660
1661 char szKeyName[256];
1662 sprintf_s(szKeyName, sizeof(szKeyName),
1663 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
1664 pAdapter->AdapterName);
1665 HKEY hkeyConnection;
1666 LONG status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hkeyConnection);
1667 if (status != ERROR_SUCCESS)
1668 {
1669 LogRel(("NetIf: Failed to find connection key in registry for %ls at %s\n",
1670 pAdapter->Description, szKeyName));
1671 }
1672 else
1673 {
1674 WCHAR wszId[256];
1675 DWORD dwLen = sizeof(wszId);
1676 status = RegQueryValueExW(hkeyConnection, L"PnPInstanceID", NULL, NULL, (LPBYTE)wszId, &dwLen);
1677 if (status != ERROR_SUCCESS)
1678 {
1679 LogRel(("NetIf: Failed to get PnPInstanceID from registry for %ls\n", pAdapter->Description));
1680 }
1681 else
1682 {
1683 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET, NULL);
1684 if (hDevInfo != INVALID_HANDLE_VALUE)
1685 {
1686 SP_DEVINFO_DATA DevInfoData;
1687
1688 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1689 if (SetupDiOpenDeviceInfo(hDevInfo, wszId, NULL, 0, &DevInfoData))
1690 {
1691 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
1692 SPDRP_HARDWAREID, NULL,
1693 (PBYTE)wszId, sizeof(wszId), NULL))
1694 {
1695 /*
1696 * We do not care for multiple strings that may have been
1697 * returned since our host-only adapter has a single id.
1698 */
1699 if (_wcsnicmp(wszId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1700 *enmType = HostNetworkInterfaceType_Bridged;
1701 else
1702 *enmType = HostNetworkInterfaceType_HostOnly;
1703 }
1704 SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
1705 SPDRP_FRIENDLYNAME, NULL,
1706 (PBYTE)pwszName, cbName, NULL);
1707 }
1708 SetupDiDestroyDeviceInfoList(hDevInfo);
1709 }
1710 LogRel(("PnP ID: %ls\n", wszId));
1711 }
1712 RegCloseKey(hkeyConnection);
1713 }
1714}
1715
1716int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1717{
1718 DWORD dwRc;
1719 int rc = VINF_SUCCESS;
1720 int iDefault = getDefaultInterfaceIndex();
1721 /*
1722 * Most of the hosts probably have less than 10 adapters,
1723 * so we'll mostly succeed from the first attempt.
1724 */
1725 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
1726 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1727 if (!pAddresses)
1728 return VERR_NO_MEMORY;
1729 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1730 if (dwRc == ERROR_BUFFER_OVERFLOW)
1731 {
1732 /* Impressive! More than 10 adapters! Get more memory and try again. */
1733 RTMemFree(pAddresses);
1734 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1735 if (!pAddresses)
1736 return VERR_NO_MEMORY;
1737 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1738 }
1739 if (dwRc == NO_ERROR)
1740 {
1741 PIP_ADAPTER_ADDRESSES pAdapter;
1742 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1743 {
1744 Log(("Enumerating %s\n", pAdapter->AdapterName));
1745 /* Vista+ systems introduced separate type for wireless adapters */
1746 if (pAdapter->IfType != IF_TYPE_ETHERNET_CSMACD && pAdapter->IfType != IF_TYPE_IEEE80211)
1747 {
1748 LogRel(("Skipped non-Ethernet '%ls'\n", pAdapter->FriendlyName));
1749 continue;
1750 }
1751
1752 NETIFINFO Info;
1753 RT_ZERO(Info);
1754
1755 if (pAdapter->AdapterName[0] == '{')
1756 {
1757 bool fIPv4Found, fIPv6Found;
1758 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1759 fIPv4Found = fIPv6Found = false;
1760 for (pAddr = pAdapter->FirstUnicastAddress;
1761 pAddr && !(fIPv4Found && fIPv6Found);
1762 pAddr = pAddr->Next)
1763 {
1764 switch (pAddr->Address.lpSockaddr->sa_family)
1765 {
1766 case AF_INET:
1767 if (!fIPv4Found)
1768 {
1769 fIPv4Found = true;
1770 memcpy(&Info.IPAddress,
1771 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1772 sizeof(Info.IPAddress));
1773 }
1774 break;
1775 case AF_INET6:
1776 if (!fIPv6Found)
1777 {
1778 fIPv6Found = true;
1779 memcpy(&Info.IPv6Address,
1780 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
1781 sizeof(Info.IPv6Address));
1782 }
1783 break;
1784 }
1785 }
1786 PIP_ADAPTER_PREFIX pPrefix;
1787 fIPv4Found = fIPv6Found = false;
1788 for (pPrefix = pAdapter->FirstPrefix;
1789 pPrefix && !(fIPv4Found && fIPv6Found);
1790 pPrefix = pPrefix->Next)
1791 {
1792 switch (pPrefix->Address.lpSockaddr->sa_family)
1793 {
1794 case AF_INET:
1795 if (!fIPv4Found)
1796 {
1797 if (pPrefix->PrefixLength <= sizeof(Info.IPNetMask) * 8)
1798 {
1799 fIPv4Found = true;
1800 ASMBitSetRange(&Info.IPNetMask, 0, pPrefix->PrefixLength);
1801 }
1802 else
1803 LogRel(("NetIfList: Unexpected IPv4 prefix length of %d\n",
1804 pPrefix->PrefixLength));
1805 }
1806 break;
1807 case AF_INET6:
1808 if (!fIPv6Found)
1809 {
1810 if (pPrefix->PrefixLength <= sizeof(Info.IPv6NetMask) * 8)
1811 {
1812 fIPv6Found = true;
1813 ASMBitSetRange(&Info.IPv6NetMask, 0, pPrefix->PrefixLength);
1814 }
1815 else
1816 LogRel(("NetIfList: Unexpected IPv6 prefix length of %d\n",
1817 pPrefix->PrefixLength));
1818 }
1819 break;
1820 }
1821 }
1822 if (sizeof(Info.MACAddress) != pAdapter->PhysicalAddressLength)
1823 LogRel(("NetIfList: Unexpected physical address length: %u\n",
1824 pAdapter->PhysicalAddressLength));
1825 else
1826 memcpy(Info.MACAddress.au8, pAdapter->PhysicalAddress, sizeof(Info.MACAddress));
1827 Info.enmMediumType = NETIF_T_ETHERNET;
1828 Info.enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
1829 Info.bDhcpEnabled = !!(pAdapter->Flags & IP_ADAPTER_DHCP_ENABLED);
1830 Info.bIsDefault = (pAdapter->IfIndex == iDefault);
1831
1832 HostNetworkInterfaceType enmType;
1833 WCHAR wszName[256];
1834 /* Try to get name and type via Setup API */
1835 getTypeAndName(pAdapter, &enmType, wszName, sizeof(wszName));
1836
1837 char *pszUuid = pAdapter->AdapterName + 1;
1838 size_t len = strlen(pszUuid) - 1;
1839 if (pszUuid[len] != '}')
1840 {
1841 LogRel(("%s is not a valid UUID!\n", pAdapter->AdapterName));
1842 continue;
1843 }
1844 pszUuid[len] = 0;
1845 rc = RTUuidFromStr(&Info.Uuid, pszUuid);
1846 if (RT_FAILURE(rc))
1847 {
1848 LogRel(("NetIfList: Failed to convert %s to UUID (%Rrc)\n", pszUuid, rc));
1849 continue;
1850 }
1851 LogRel(("Adding %ls as %s\n", pAdapter->Description,
1852 enmType == HostNetworkInterfaceType_Bridged ? "bridged" :
1853 enmType == HostNetworkInterfaceType_HostOnly ? "host-only" : "unknown"));
1854 /* create a new object and add it to the list */
1855 ComObjPtr<HostNetworkInterface> iface;
1856 iface.createObject();
1857 /* remove the curly bracket at the end */
1858 rc = iface->init(wszName, enmType, &Info);
1859 if (SUCCEEDED(rc))
1860 {
1861 if (Info.bIsDefault)
1862 list.push_front(iface);
1863 else
1864 list.push_back(iface);
1865 }
1866 else
1867 {
1868 LogRel(("NetIfList: HostNetworkInterface::init() -> %Rrc\n", rc));
1869 Assert(0);
1870 }
1871 }
1872 }
1873 }
1874
1875 RTMemFree(pAddresses);
1876
1877 return VINF_SUCCESS;
1878}
1879#endif /* !NETIF_WITHOUT_NETCFG */
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