VirtualBox

source: vbox/trunk/src/VBox/Main/win/NetIfList-win.cpp@ 17713

Last change on this file since 17713 was 17713, checked in by vboxsync, 16 years ago

NetIf/win: dhcp enabled property implementation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 86.0 KB
Line 
1/* $Id: NetIfList-win.cpp 17713 2009-03-11 17:30:58Z vboxsync $ */
2/** @file
3 * Main - NetIfList, Windows implementation.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_MAIN
28
29#include <iprt/asm.h>
30#include <iprt/err.h>
31#include <list>
32
33#define _WIN32_DCOM
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#include <windows.h>
37
38#ifdef VBOX_WITH_NETFLT
39#include "VBox/WinNetConfig.h"
40#include "devguid.h"
41#endif
42
43#include <iphlpapi.h>
44
45#include "Logging.h"
46#include "HostNetworkInterfaceImpl.h"
47#include "ProgressImpl.h"
48#include "VirtualBoxImpl.h"
49#include "netif.h"
50
51#ifdef VBOX_WITH_NETFLT
52#include <Wbemidl.h>
53#include <comdef.h>
54
55#include "svchlp.h"
56
57#include <shellapi.h>
58#define INITGUID
59#include <guiddef.h>
60#include <devguid.h>
61#include <objbase.h>
62#include <setupapi.h>
63#include <shlobj.h>
64#include <cfgmgr32.h>
65
66#define VBOX_APP_NAME L"VirtualBox"
67
68static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
69{
70 HRESULT hres;
71
72 // Step 3: ---------------------------------------------------
73 // Obtain the initial locator to WMI -------------------------
74
75 IWbemLocator *pLoc = NULL;
76
77 hres = CoCreateInstance(
78 CLSID_WbemLocator,
79 0,
80 CLSCTX_INPROC_SERVER,
81 IID_IWbemLocator, (LPVOID *) &pLoc);
82 if(SUCCEEDED(hres))
83 {
84 // Step 4: -----------------------------------------------------
85 // Connect to WMI through the IWbemLocator::ConnectServer method
86
87 IWbemServices *pSvc = NULL;
88
89 // Connect to the root\cimv2 namespace with
90 // the current user and obtain pointer pSvc
91 // to make IWbemServices calls.
92 hres = pLoc->ConnectServer(
93 _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
94 NULL, // User name. NULL = current user
95 NULL, // User password. NULL = current
96 0, // Locale. NULL indicates current
97 NULL, // Security flags.
98 0, // Authority (e.g. Kerberos)
99 0, // Context object
100 &pSvc // pointer to IWbemServices proxy
101 );
102 if(SUCCEEDED(hres))
103 {
104 LogRel(("Connected to ROOT\\CIMV2 WMI namespace\n"));
105
106 // Step 5: --------------------------------------------------
107 // Set security levels on the proxy -------------------------
108
109 hres = CoSetProxyBlanket(
110 pSvc, // Indicates the proxy to set
111 RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
112 RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
113 NULL, // Server principal name
114 RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
115 RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
116 NULL, // client identity
117 EOAC_NONE // proxy capabilities
118 );
119 if(SUCCEEDED(hres))
120 {
121 *ppSvc = pSvc;
122 /* do not need it any more */
123 pLoc->Release();
124 return hres;
125 }
126 else
127 {
128 LogRel(("Could not set proxy blanket. Error code = 0x%x\n", hres));
129 }
130
131 pSvc->Release();
132 }
133 else
134 {
135 LogRel(("Could not connect. Error code = 0x%x\n", hres));
136 }
137
138 pLoc->Release();
139 }
140 else
141 {
142 LogRel(("Failed to create IWbemLocator object. Err code = 0x%x\n", hres));
143// CoUninitialize();
144 }
145
146 return hres;
147}
148
149static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const Guid &guid, IWbemClassObject **pAdapterConfig)
150{
151 HRESULT hres;
152 WCHAR aQueryString[256];
153// char uuidStr[RTUUID_STR_LENGTH];
154// int rc = RTUuidToStr(guid.toString().raw(), uuidStr, sizeof(uuidStr));
155 {
156 swprintf(aQueryString, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"{%S}\"", guid.toString().raw());
157 // Step 6: --------------------------------------------------
158 // Use the IWbemServices pointer to make requests of WMI ----
159
160 IEnumWbemClassObject* pEnumerator = NULL;
161 hres = pSvc->ExecQuery(
162 bstr_t("WQL"),
163 bstr_t(aQueryString),
164 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
165 NULL,
166 &pEnumerator);
167 if(SUCCEEDED(hres))
168 {
169 // Step 7: -------------------------------------------------
170 // Get the data from the query in step 6 -------------------
171
172 IWbemClassObject *pclsObj;
173 ULONG uReturn = 0;
174
175 while (pEnumerator)
176 {
177 HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
178 &pclsObj, &uReturn);
179
180 if(SUCCEEDED(hres))
181 {
182 if(uReturn)
183 {
184 pEnumerator->Release();
185 *pAdapterConfig = pclsObj;
186 hres = S_OK;
187 return hres;
188 }
189 else
190 {
191 hres = S_FALSE;
192 }
193 }
194
195 }
196 pEnumerator->Release();
197 }
198 else
199 {
200 Log(("Query for operating system name failed. Error code = 0x%x\n", hres));
201 }
202 }
203
204 return hres;
205}
206
207static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
208{
209 VARIANT index;
210
211 // Get the value of the key property
212 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
213 if(SUCCEEDED(hr))
214 {
215 WCHAR strIndex[8];
216 swprintf(strIndex, L"%u", index.uintVal);
217 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
218 }
219 else
220 {
221 DWORD dwError = GetLastError();
222 Assert(0);
223 hr = HRESULT_FROM_WIN32( dwError );
224 }
225 return hr;
226}
227
228static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
229 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
230 IWbemClassObject** ppOutParams
231 )
232{
233 HRESULT hres = S_OK;
234 // Step 6: --------------------------------------------------
235 // Use the IWbemServices pointer to make requests of WMI ----
236
237 ComPtr<IWbemClassObject> pInParamsDefinition;
238 ComPtr<IWbemClassObject> pClassInstance;
239
240 if(cArgs)
241 {
242 hres = pClass->GetMethod(MethodName, 0,
243 pInParamsDefinition.asOutParam(), NULL);
244 if(SUCCEEDED(hres))
245 {
246 hres = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
247
248 if(SUCCEEDED(hres))
249 {
250 for(UINT i = 0; i < cArgs; i++)
251 {
252 // Store the value for the in parameters
253 hres = pClassInstance->Put(pArgNames[i], 0,
254 pArgs[i], 0);
255 if(FAILED(hres))
256 {
257 break;
258 }
259 }
260 }
261 }
262 }
263
264 if(SUCCEEDED(hres))
265 {
266 IWbemClassObject* pOutParams = NULL;
267 hres = pSvc->ExecMethod(ObjPath, MethodName, 0,
268 NULL, pClassInstance, &pOutParams, NULL);
269 if(SUCCEEDED(hres))
270 {
271 *ppOutParams = pOutParams;
272 }
273 }
274
275 return hres;
276}
277
278static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
279{
280 HRESULT hr;
281 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
282 if(pIpArray)
283 {
284 for(UINT i = 0; i < cIp; i++)
285 {
286 char* addr = inet_ntoa(aIp[i]);
287 BSTR val = bstr_t(addr).copy();
288 long aIndex[1];
289 aIndex[0] = i;
290 hr = SafeArrayPutElement(pIpArray, aIndex, val);
291 if(FAILED(hr))
292 {
293 SysFreeString(val);
294 SafeArrayDestroy(pIpArray);
295 break;
296 }
297 }
298
299 if(SUCCEEDED(hr))
300 {
301 *ppArray = pIpArray;
302 }
303 }
304 else
305 {
306 DWORD dwError = GetLastError();
307 Assert(0);
308 hr = HRESULT_FROM_WIN32( dwError );
309 }
310
311 return hr;
312}
313
314static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
315{
316 HRESULT hr;
317 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
318 if(pIpArray)
319 {
320 BSTR val = bstr_t(Ip, false).copy();
321 long aIndex[1];
322 aIndex[0] = 0;
323 hr = SafeArrayPutElement(pIpArray, aIndex, val);
324 if(FAILED(hr))
325 {
326 SysFreeString(val);
327 SafeArrayDestroy(pIpArray);
328 }
329
330 if(SUCCEEDED(hr))
331 {
332 *ppArray = pIpArray;
333 }
334 }
335 else
336 {
337 DWORD dwError = GetLastError();
338 Assert(0);
339 hr = HRESULT_FROM_WIN32( dwError );
340 }
341
342 return hr;
343}
344
345
346static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
347{
348 HRESULT hr;
349 VariantInit(pIpAddresses);
350 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
351 SAFEARRAY *pIpArray;
352 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
353 if(SUCCEEDED(hr))
354 {
355 pIpAddresses->parray = pIpArray;
356 }
357 return hr;
358}
359
360static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
361{
362 HRESULT hr;
363 VariantInit(pIpAddresses);
364 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
365 SAFEARRAY *pIpArray;
366 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
367 if(SUCCEEDED(hr))
368 {
369 pIpAddresses->parray = pIpArray;
370 }
371 return hr;
372}
373
374static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
375{
376 ComPtr<IWbemClassObject> pClass;
377 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
378 HRESULT hr;
379 if(ClassName)
380 {
381 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
382 if(SUCCEEDED(hr))
383 {
384 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
385 LPVARIANT args[] = {pIp, pMask};
386 ComPtr<IWbemClassObject> pOutParams;
387
388 hr = netIfExecMethod(pSvc, pClass, ObjPath,
389 bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
390 if(SUCCEEDED(hr))
391 {
392 VARIANT varReturnValue;
393 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
394 &varReturnValue, NULL, 0);
395 Assert(SUCCEEDED(hr));
396 if(SUCCEEDED(hr))
397 {
398// Assert(varReturnValue.vt == VT_UINT);
399 int winEr = varReturnValue.uintVal;
400 switch(winEr)
401 {
402 case 0:
403 hr = S_OK;
404 break;
405 default:
406 hr = HRESULT_FROM_WIN32( winEr );
407 break;
408 }
409 }
410 }
411 }
412 SysFreeString(ClassName);
413 }
414 else
415 {
416 DWORD dwError = GetLastError();
417 Assert(0);
418 hr = HRESULT_FROM_WIN32( dwError );
419 }
420
421 return hr;
422}
423
424
425static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
426{
427 VARIANT ipAddresses;
428 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
429 if(SUCCEEDED(hr))
430 {
431 VARIANT ipMasks;
432 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
433 if(SUCCEEDED(hr))
434 {
435 netIfWinEnableStatic(pSvc, ObjPath, &ipAddresses, &ipMasks);
436 VariantClear(&ipMasks);
437 }
438 VariantClear(&ipAddresses);
439 }
440 return hr;
441}
442
443static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Ip, BSTR Mask)
444{
445 VARIANT ipAddresses;
446 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
447 if(SUCCEEDED(hr))
448 {
449 VARIANT ipMasks;
450 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
451 if(SUCCEEDED(hr))
452 {
453 netIfWinEnableStatic(pSvc, ObjPath, &ipAddresses, &ipMasks);
454 VariantClear(&ipMasks);
455 }
456 VariantClear(&ipAddresses);
457 }
458 return hr;
459}
460
461/* win API allows to set gw metrics as well, we are not setting them */
462static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
463{
464 ComPtr<IWbemClassObject> pClass;
465 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
466 HRESULT hr;
467 if(ClassName)
468 {
469 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
470 if(SUCCEEDED(hr))
471 {
472 LPWSTR argNames[] = {L"DefaultIPGateway"};
473 LPVARIANT args[] = {pGw};
474 ComPtr<IWbemClassObject> pOutParams;
475
476 hr = netIfExecMethod(pSvc, pClass, ObjPath,
477 bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
478 if(SUCCEEDED(hr))
479 {
480 VARIANT varReturnValue;
481 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
482 &varReturnValue, NULL, 0);
483 Assert(SUCCEEDED(hr));
484 if(SUCCEEDED(hr))
485 {
486// Assert(varReturnValue.vt == VT_UINT);
487 int winEr = varReturnValue.uintVal;
488 switch(winEr)
489 {
490 case 0:
491 hr = S_OK;
492 break;
493 default:
494 hr = HRESULT_FROM_WIN32( winEr );
495 break;
496 }
497 }
498 } }
499 SysFreeString(ClassName);
500 }
501 else
502 {
503 DWORD dwError = GetLastError();
504 Assert(0);
505 hr = HRESULT_FROM_WIN32( dwError );
506 }
507
508 return hr;
509}
510
511/* win API allows to set gw metrics as well, we are not setting them */
512static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
513{
514 VARIANT gwais;
515 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
516 if(SUCCEEDED(hr))
517 {
518 netIfWinSetGateways(pSvc, ObjPath, &gwais);
519 VariantClear(&gwais);
520 }
521 return hr;
522}
523
524/* win API allows to set gw metrics as well, we are not setting them */
525static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
526{
527 VARIANT vGw;
528 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
529 if(SUCCEEDED(hr))
530 {
531 netIfWinSetGateways(pSvc, ObjPath, &vGw);
532 VariantClear(&vGw);
533 }
534 return hr;
535}
536
537static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
538{
539 ComPtr<IWbemClassObject> pClass;
540 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
541 HRESULT hr;
542 if(ClassName)
543 {
544 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
545 if(SUCCEEDED(hr))
546 {
547 ComPtr<IWbemClassObject> pOutParams;
548
549 hr = netIfExecMethod(pSvc, pClass, ObjPath,
550 bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
551 if(SUCCEEDED(hr))
552 {
553 VARIANT varReturnValue;
554 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
555 &varReturnValue, NULL, 0);
556 Assert(SUCCEEDED(hr));
557 if(SUCCEEDED(hr))
558 {
559// Assert(varReturnValue.vt == VT_UINT);
560 int winEr = varReturnValue.uintVal;
561 switch(winEr)
562 {
563 case 0:
564 hr = S_OK;
565 break;
566 default:
567 hr = HRESULT_FROM_WIN32( winEr );
568 break;
569 }
570 }
571 }
572 }
573 SysFreeString(ClassName);
574 }
575 else
576 {
577 DWORD dwError = GetLastError();
578 Assert(0);
579 hr = HRESULT_FROM_WIN32( dwError );
580 }
581
582 return hr;
583}
584
585static int netIfWinIsDhcpEnabled(const Guid &guid, BOOL *pEnabled)
586{
587 HRESULT hr;
588 ComPtr <IWbemServices> pSvc;
589 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
590 if(SUCCEEDED(hr))
591 {
592 ComPtr <IWbemClassObject> pAdapterConfig;
593 hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam());
594 if(SUCCEEDED(hr))
595 {
596 VARIANT vtEnabled;
597 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
598 if(SUCCEEDED(hr))
599 {
600 *pEnabled = vtEnabled.boolVal;
601 }
602 }
603 }
604
605 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
606}
607
608static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo)
609{
610 DWORD dwRc;
611 int rc = VINF_SUCCESS;
612 /*
613 * Most of the hosts probably have less than 10 adapters,
614 * so we'll mostly succeed from the first attempt.
615 */
616 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
617 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
618 if (!pAddresses)
619 return VERR_NO_MEMORY;
620 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
621 if (dwRc == ERROR_BUFFER_OVERFLOW)
622 {
623 /* Impressive! More than 10 adapters! Get more memory and try again. */
624 RTMemFree(pAddresses);
625 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
626 if (!pAddresses)
627 return VERR_NO_MEMORY;
628 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
629 }
630 if (dwRc == NO_ERROR)
631 {
632 PIP_ADAPTER_ADDRESSES pAdapter;
633 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
634 {
635 char *pszUuid = RTStrDup(pAdapter->AdapterName);
636 size_t len = strlen(pszUuid) - 1;
637 if (pszUuid[0] == '{' && pszUuid[len] == '}')
638 {
639 pszUuid[len] = 0;
640 if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1))
641 {
642 bool fIPFound, fIPv6Found;
643 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
644 fIPFound = fIPv6Found = false;
645 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
646 {
647 switch (pAddr->Address.lpSockaddr->sa_family)
648 {
649 case AF_INET:
650 if (!fIPFound)
651 {
652 fIPFound = true;
653 memcpy(&pInfo->IPAddress,
654 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
655 sizeof(pInfo->IPAddress));
656 }
657 break;
658 case AF_INET6:
659 if (!fIPv6Found)
660 {
661 fIPv6Found = true;
662 memcpy(&pInfo->IPv6Address,
663 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
664 sizeof(pInfo->IPv6Address));
665 }
666 break;
667 }
668 }
669 PIP_ADAPTER_PREFIX pPrefix;
670 fIPFound = fIPv6Found = false;
671 for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
672 {
673 switch (pPrefix->Address.lpSockaddr->sa_family)
674 {
675 case AF_INET:
676 if (!fIPFound)
677 {
678 fIPFound = true;
679 ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength);
680 }
681 break;
682 case AF_INET6:
683 if (!fIPv6Found)
684 {
685 fIPv6Found = true;
686 ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength);
687 }
688 break;
689 }
690 }
691 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
692 Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
693 else
694 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
695 pInfo->enmMediumType = NETIF_T_ETHERNET;
696 pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
697 RTStrFree(pszUuid);
698 break;
699 }
700 }
701 RTStrFree(pszUuid);
702 }
703
704 BOOL bEnabled;
705 rc = netIfWinIsDhcpEnabled(guid, &bEnabled);
706 Assert(RT_SUCCESS(rc));
707 if(RT_SUCCESS(rc))
708 {
709 pInfo->bDhcpEnabled = bEnabled;
710 }
711 }
712 RTMemFree(pAddresses);
713
714 return VINF_SUCCESS;
715}
716
717static int netIfEnableStaticIpConfig(const Guid &guid, ULONG ip, ULONG mask)
718{
719 HRESULT hr;
720 ComPtr <IWbemServices> pSvc;
721 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
722 if(SUCCEEDED(hr))
723 {
724 ComPtr <IWbemClassObject> pAdapterConfig;
725 hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam());
726 if(SUCCEEDED(hr))
727 {
728 in_addr aIp[1];
729 in_addr aMask[1];
730 aIp[0].S_un.S_addr = ip;
731 aMask[0].S_un.S_addr = mask;
732
733 BSTR ObjPath;
734 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
735 if(SUCCEEDED(hr))
736 {
737 hr = netIfWinEnableStaticV4(pSvc, ObjPath, aIp, aMask, 1);
738 if(SUCCEEDED(hr))
739 {
740#if 0
741 in_addr aGw[1];
742 aGw[0].S_un.S_addr = gw;
743 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
744 if(SUCCEEDED(hr))
745#endif
746 {
747// hr = netIfWinUpdateConfig(pIf);
748 }
749 }
750 SysFreeString(ObjPath);
751 }
752 }
753 }
754
755 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
756}
757
758static int netIfEnableStaticIpConfigV6(const Guid & guid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
759{
760 HRESULT hr;
761 ComPtr <IWbemServices> pSvc;
762 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
763 if(SUCCEEDED(hr))
764 {
765 ComPtr <IWbemClassObject> pAdapterConfig;
766 hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam());
767 if(SUCCEEDED(hr))
768 {
769 BSTR ObjPath;
770 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
771 if(SUCCEEDED(hr))
772 {
773 hr = netIfWinEnableStaticV4V6(pSvc, ObjPath, aIPV6Address, aIPV6Mask);
774 if(SUCCEEDED(hr))
775 {
776 if(aIPV6DefaultGateway)
777 {
778 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
779 }
780 if(SUCCEEDED(hr))
781 {
782// hr = netIfWinUpdateConfig(pIf);
783 }
784 }
785 SysFreeString(ObjPath);
786 }
787 }
788 }
789
790 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
791}
792
793static int netIfEnableStaticIpConfigV6(const Guid &guid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
794{
795 RTNETADDRIPV6 Mask;
796 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
797 if(RT_SUCCESS(rc))
798 {
799 Bstr maskStr = composeIPv6Address(&Mask);
800 rc = netIfEnableStaticIpConfigV6(guid, aIPV6Address, maskStr, NULL);
801 }
802 return rc;
803}
804
805static HRESULT netIfEnableDynamicIpConfig(const Guid &guid)
806{
807 HRESULT hr;
808 ComPtr <IWbemServices> pSvc;
809 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
810 if(SUCCEEDED(hr))
811 {
812 ComPtr <IWbemClassObject> pAdapterConfig;
813 hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam());
814 if(SUCCEEDED(hr))
815 {
816 BSTR ObjPath;
817 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
818 if(SUCCEEDED(hr))
819 {
820 hr = netIfWinEnableDHCP(pSvc, ObjPath);
821 if(SUCCEEDED(hr))
822 {
823// hr = netIfWinUpdateConfig(pIf);
824 }
825 SysFreeString(ObjPath);
826 }
827 }
828 }
829
830
831 return hr;
832}
833
834/* svc helper func */
835
836struct StaticIpConfig
837{
838 ULONG IPAddress;
839 ULONG IPNetMask;
840};
841
842struct StaticIpV6Config
843{
844 BSTR IPV6Address;
845 ULONG IPV6NetMaskLength;
846};
847
848struct NetworkInterfaceHelperClientData
849{
850 SVCHlpMsg::Code msgCode;
851 /* for SVCHlpMsg::CreateHostOnlyNetworkInterface */
852 Bstr name;
853 ComObjPtr <HostNetworkInterface> iface;
854 /* for SVCHlpMsg::RemoveHostOnlyNetworkInterface */
855 Guid guid;
856
857 union
858 {
859 StaticIpConfig StaticIP;
860 StaticIpV6Config StaticIPV6;
861 } u;
862
863
864};
865
866static HRESULT netIfNetworkInterfaceHelperClient (SVCHlpClient *aClient,
867 Progress *aProgress,
868 void *aUser, int *aVrc)
869{
870 LogFlowFuncEnter();
871 LogFlowFunc (("aClient={%p}, aProgress={%p}, aUser={%p}\n",
872 aClient, aProgress, aUser));
873
874 AssertReturn ((aClient == NULL && aProgress == NULL && aVrc == NULL) ||
875 (aClient != NULL && aProgress != NULL && aVrc != NULL),
876 E_POINTER);
877 AssertReturn (aUser, E_POINTER);
878
879 std::auto_ptr <NetworkInterfaceHelperClientData>
880 d (static_cast <NetworkInterfaceHelperClientData *> (aUser));
881
882 if (aClient == NULL)
883 {
884 /* "cleanup only" mode, just return (it will free aUser) */
885 return S_OK;
886 }
887
888 HRESULT rc = S_OK;
889 int vrc = VINF_SUCCESS;
890
891 switch (d->msgCode)
892 {
893 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
894 {
895 LogFlowFunc (("CreateHostOnlyNetworkInterface:\n"));
896 LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw()));
897
898 /* write message and parameters */
899 vrc = aClient->write (d->msgCode);
900 if (RT_FAILURE (vrc)) break;
901// vrc = aClient->write (Utf8Str (d->name));
902// if (RT_FAILURE (vrc)) break;
903
904 /* wait for a reply */
905 bool endLoop = false;
906 while (!endLoop)
907 {
908 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
909
910 vrc = aClient->read (reply);
911 if (RT_FAILURE (vrc)) break;
912
913 switch (reply)
914 {
915 case SVCHlpMsg::CreateHostOnlyNetworkInterface_OK:
916 {
917 /* read the GUID */
918 Guid guid;
919 Utf8Str name;
920 vrc = aClient->read (name);
921 if (RT_FAILURE (vrc)) break;
922 vrc = aClient->read (guid);
923 if (RT_FAILURE (vrc)) break;
924
925 LogFlowFunc (("Network connection GUID = {%RTuuid}\n", guid.raw()));
926
927 /* initialize the object returned to the caller by
928 * CreateHostOnlyNetworkInterface() */
929 rc = d->iface->init (Bstr(name), guid, HostNetworkInterfaceType_HostOnly);
930 endLoop = true;
931 break;
932 }
933 case SVCHlpMsg::Error:
934 {
935 /* read the error message */
936 Utf8Str errMsg;
937 vrc = aClient->read (errMsg);
938 if (RT_FAILURE (vrc)) break;
939
940 rc = E_FAIL;//TODO: setError (E_FAIL, errMsg);
941 endLoop = true;
942 break;
943 }
944 default:
945 {
946 endLoop = true;
947 rc = E_FAIL;//TODO: ComAssertMsgFailedBreak ((
948 //"Invalid message code %d (%08lX)\n",
949 //reply, reply),
950 //rc = E_FAIL);
951 }
952 }
953 }
954
955 break;
956 }
957 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
958 {
959 LogFlowFunc (("RemoveHostOnlyNetworkInterface:\n"));
960 LogFlowFunc (("Network connection GUID = {%RTuuid}\n", d->guid.raw()));
961
962 /* write message and parameters */
963 vrc = aClient->write (d->msgCode);
964 if (RT_FAILURE (vrc)) break;
965 vrc = aClient->write (d->guid);
966 if (RT_FAILURE (vrc)) break;
967
968 /* wait for a reply */
969 bool endLoop = false;
970 while (!endLoop)
971 {
972 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
973
974 vrc = aClient->read (reply);
975 if (RT_FAILURE (vrc)) break;
976
977 switch (reply)
978 {
979 case SVCHlpMsg::OK:
980 {
981 /* no parameters */
982 rc = S_OK;
983 endLoop = true;
984 break;
985 }
986 case SVCHlpMsg::Error:
987 {
988 /* read the error message */
989 Utf8Str errMsg;
990 vrc = aClient->read (errMsg);
991 if (RT_FAILURE (vrc)) break;
992
993 rc = E_FAIL; // TODO: setError (E_FAIL, errMsg);
994 endLoop = true;
995 break;
996 }
997 default:
998 {
999 endLoop = true;
1000 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak ((
1001 //"Invalid message code %d (%08lX)\n",
1002 //reply, reply),
1003 //rc = E_FAIL);
1004 }
1005 }
1006 }
1007
1008 break;
1009 }
1010 case SVCHlpMsg::EnableDynamicIpConfig: /* see usage in code */
1011 {
1012 LogFlowFunc (("EnableDynamicIpConfig:\n"));
1013 LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw()));
1014
1015 /* write message and parameters */
1016 vrc = aClient->write (d->msgCode);
1017 if (RT_FAILURE (vrc)) break;
1018 vrc = aClient->write (d->guid);
1019 if (RT_FAILURE (vrc)) break;
1020
1021 /* wait for a reply */
1022 bool endLoop = false;
1023 while (!endLoop)
1024 {
1025 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
1026
1027 vrc = aClient->read (reply);
1028 if (RT_FAILURE (vrc)) break;
1029
1030 switch (reply)
1031 {
1032 case SVCHlpMsg::OK:
1033 {
1034 /* no parameters */
1035 rc = d->iface->updateConfig();
1036 endLoop = true;
1037 break;
1038 }
1039 case SVCHlpMsg::Error:
1040 {
1041 /* read the error message */
1042 Utf8Str errMsg;
1043 vrc = aClient->read (errMsg);
1044 if (RT_FAILURE (vrc)) break;
1045
1046 rc = E_FAIL; // TODO: setError (E_FAIL, errMsg);
1047 endLoop = true;
1048 break;
1049 }
1050 default:
1051 {
1052 endLoop = true;
1053 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak ((
1054 //"Invalid message code %d (%08lX)\n",
1055 //reply, reply),
1056 //rc = E_FAIL);
1057 }
1058 }
1059 }
1060
1061 break;
1062 }
1063 case SVCHlpMsg::EnableStaticIpConfig: /* see usage in code */
1064 {
1065 LogFlowFunc (("EnableStaticIpConfig:\n"));
1066 LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw()));
1067
1068 /* write message and parameters */
1069 vrc = aClient->write (d->msgCode);
1070 if (RT_FAILURE (vrc)) break;
1071 vrc = aClient->write (d->guid);
1072 if (RT_FAILURE (vrc)) break;
1073 vrc = aClient->write (d->u.StaticIP.IPAddress);
1074 if (RT_FAILURE (vrc)) break;
1075 vrc = aClient->write (d->u.StaticIP.IPNetMask);
1076 if (RT_FAILURE (vrc)) break;
1077
1078 /* wait for a reply */
1079 bool endLoop = false;
1080 while (!endLoop)
1081 {
1082 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
1083
1084 vrc = aClient->read (reply);
1085 if (RT_FAILURE (vrc)) break;
1086
1087 switch (reply)
1088 {
1089 case SVCHlpMsg::OK:
1090 {
1091 /* no parameters */
1092 rc = d->iface->updateConfig();
1093 endLoop = true;
1094 break;
1095 }
1096 case SVCHlpMsg::Error:
1097 {
1098 /* read the error message */
1099 Utf8Str errMsg;
1100 vrc = aClient->read (errMsg);
1101 if (RT_FAILURE (vrc)) break;
1102
1103 rc = E_FAIL; // TODO: setError (E_FAIL, errMsg);
1104 endLoop = true;
1105 break;
1106 }
1107 default:
1108 {
1109 endLoop = true;
1110 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak ((
1111 //"Invalid message code %d (%08lX)\n",
1112 //reply, reply),
1113 //rc = E_FAIL);
1114 }
1115 }
1116 }
1117
1118 break;
1119 }
1120 case SVCHlpMsg::EnableStaticIpConfigV6: /* see usage in code */
1121 {
1122 LogFlowFunc (("EnableStaticIpConfigV6:\n"));
1123 LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw()));
1124
1125 /* write message and parameters */
1126 vrc = aClient->write (d->msgCode);
1127 if (RT_FAILURE (vrc)) break;
1128 vrc = aClient->write (d->guid);
1129 if (RT_FAILURE (vrc)) break;
1130 vrc = aClient->write (Utf8Str(d->u.StaticIPV6.IPV6Address));
1131 if (RT_FAILURE (vrc)) break;
1132 vrc = aClient->write (d->u.StaticIPV6.IPV6NetMaskLength);
1133 if (RT_FAILURE (vrc)) break;
1134
1135 /* wait for a reply */
1136 bool endLoop = false;
1137 while (!endLoop)
1138 {
1139 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
1140
1141 vrc = aClient->read (reply);
1142 if (RT_FAILURE (vrc)) break;
1143
1144 switch (reply)
1145 {
1146 case SVCHlpMsg::OK:
1147 {
1148 /* no parameters */
1149 rc = d->iface->updateConfig();
1150 endLoop = true;
1151 break;
1152 }
1153 case SVCHlpMsg::Error:
1154 {
1155 /* read the error message */
1156 Utf8Str errMsg;
1157 vrc = aClient->read (errMsg);
1158 if (RT_FAILURE (vrc)) break;
1159
1160 rc = E_FAIL; // TODO: setError (E_FAIL, errMsg);
1161 endLoop = true;
1162 break;
1163 }
1164 default:
1165 {
1166 endLoop = true;
1167 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak ((
1168 //"Invalid message code %d (%08lX)\n",
1169 //reply, reply),
1170 //rc = E_FAIL);
1171 }
1172 }
1173 }
1174
1175 break;
1176 }
1177 default:
1178 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak ((
1179// "Invalid message code %d (%08lX)\n",
1180// d->msgCode, d->msgCode),
1181// rc = E_FAIL);
1182 }
1183
1184 if (aVrc)
1185 *aVrc = vrc;
1186
1187 LogFlowFunc (("rc=0x%08X, vrc=%Rrc\n", rc, vrc));
1188 LogFlowFuncLeave();
1189 return rc;
1190}
1191
1192
1193/* The original source of the VBoxTAP adapter creation/destruction code has the following copyright */
1194/*
1195 Copyright 2004 by the Massachusetts Institute of Technology
1196
1197 All rights reserved.
1198
1199 Permission to use, copy, modify, and distribute this software and its
1200 documentation for any purpose and without fee is hereby granted,
1201 provided that the above copyright notice appear in all copies and that
1202 both that copyright notice and this permission notice appear in
1203 supporting documentation, and that the name of the Massachusetts
1204 Institute of Technology (M.I.T.) not be used in advertising or publicity
1205 pertaining to distribution of the software without specific, written
1206 prior permission.
1207
1208 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1209 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1210 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1211 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1212 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1213 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1214 SOFTWARE.
1215*/
1216
1217
1218#define NETSHELL_LIBRARY _T("netshell.dll")
1219
1220/**
1221 * Use the IShellFolder API to rename the connection.
1222 */
1223static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
1224{
1225 /* This is the GUID for the network connections folder. It is constant.
1226 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
1227 const GUID CLSID_NetworkConnections = {
1228 0x7007ACC7, 0x3202, 0x11D1, {
1229 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
1230 }
1231 };
1232
1233 LPITEMIDLIST pidl = NULL;
1234 IShellFolder *pShellFolder = NULL;
1235 HRESULT hr;
1236
1237 /* Build the display name in the form "::{GUID}". */
1238 if (wcslen (wGuid) >= MAX_PATH)
1239 return E_INVALIDARG;
1240 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
1241 swprintf (szAdapterGuid, L"::%ls", wGuid);
1242
1243 /* Create an instance of the network connections folder. */
1244 hr = CoCreateInstance (CLSID_NetworkConnections, NULL,
1245 CLSCTX_INPROC_SERVER, IID_IShellFolder,
1246 reinterpret_cast <LPVOID *> (&pShellFolder));
1247 /* Parse the display name. */
1248 if (SUCCEEDED (hr))
1249 {
1250 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
1251 &pidl, NULL);
1252 }
1253 if (SUCCEEDED (hr))
1254 {
1255 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
1256 &pidl);
1257 }
1258
1259 CoTaskMemFree (pidl);
1260
1261 if (pShellFolder)
1262 pShellFolder->Release();
1263
1264 return hr;
1265}
1266
1267extern "C" HRESULT RenameConnection (PCWSTR GuidString, PCWSTR NewName)
1268{
1269 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
1270 lpHrRenameConnection RenameConnectionFunc = NULL;
1271 HRESULT status;
1272
1273 /* First try the IShellFolder interface, which was unimplemented
1274 * for the network connections folder before XP. */
1275 status = rename_shellfolder (GuidString, NewName);
1276 if (status == E_NOTIMPL)
1277 {
1278/** @todo that code doesn't seem to work! */
1279 /* The IShellFolder interface is not implemented on this platform.
1280 * Try the (undocumented) HrRenameConnection API in the netshell
1281 * library. */
1282 CLSID clsid;
1283 HINSTANCE hNetShell;
1284 status = CLSIDFromString ((LPOLESTR) GuidString, &clsid);
1285 if (FAILED(status))
1286 return E_FAIL;
1287 hNetShell = LoadLibrary (NETSHELL_LIBRARY);
1288 if (hNetShell == NULL)
1289 return E_FAIL;
1290 RenameConnectionFunc =
1291 (lpHrRenameConnection) GetProcAddress (hNetShell,
1292 "HrRenameConnection");
1293 if (RenameConnectionFunc == NULL)
1294 {
1295 FreeLibrary (hNetShell);
1296 return E_FAIL;
1297 }
1298 status = RenameConnectionFunc (&clsid, NewName);
1299 FreeLibrary (hNetShell);
1300 }
1301 if (FAILED (status))
1302 return status;
1303
1304 return S_OK;
1305}
1306
1307#define DRIVERHWID _T("sun_VBoxNetAdp")
1308
1309#define SetErrBreak(strAndArgs) \
1310 if (1) { \
1311 aErrMsg = Utf8StrFmt strAndArgs; vrc = VERR_GENERAL_FAILURE; break; \
1312 } else do {} while (0)
1313
1314/* static */
1315static int createNetworkInterface (SVCHlpClient *aClient,
1316 BSTR * pName,
1317 Guid &aGUID, Utf8Str &aErrMsg)
1318{
1319 LogFlowFuncEnter();
1320// LogFlowFunc (("Network connection name = '%s'\n", aName.raw()));
1321
1322 AssertReturn (aClient, VERR_INVALID_POINTER);
1323// AssertReturn (!aName.isNull(), VERR_INVALID_PARAMETER);
1324
1325 int vrc = VINF_SUCCESS;
1326
1327 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1328 SP_DEVINFO_DATA DeviceInfoData;
1329 DWORD ret = 0;
1330 BOOL found = FALSE;
1331 BOOL registered = FALSE;
1332 BOOL destroyList = FALSE;
1333 TCHAR pCfgGuidString [50];
1334
1335 do
1336 {
1337 BOOL ok;
1338 GUID netGuid;
1339 SP_DRVINFO_DATA DriverInfoData;
1340 SP_DEVINSTALL_PARAMS DeviceInstallParams;
1341 TCHAR className [MAX_PATH];
1342 DWORD index = 0;
1343 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
1344 /* for our purposes, 2k buffer is more
1345 * than enough to obtain the hardware ID
1346 * of the VBoxTAP driver. */
1347 DWORD detailBuf [2048];
1348
1349 HKEY hkey = NULL;
1350 DWORD cbSize;
1351 DWORD dwValueType;
1352
1353 /* initialize the structure size */
1354 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1355 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
1356
1357 /* copy the net class GUID */
1358 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
1359
1360 /* create an empty device info set associated with the net class GUID */
1361 hDeviceInfo = SetupDiCreateDeviceInfoList (&netGuid, NULL);
1362 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1363 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
1364 GetLastError()));
1365
1366 /* get the class name from GUID */
1367 ok = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
1368 if (!ok)
1369 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
1370 GetLastError()));
1371
1372 /* create a device info element and add the new device instance
1373 * key to registry */
1374 ok = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
1375 DICD_GENERATE_ID, &DeviceInfoData);
1376 if (!ok)
1377 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
1378 GetLastError()));
1379
1380 /* select the newly created device info to be the currently
1381 selected member */
1382 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
1383 if (!ok)
1384 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
1385 GetLastError()));
1386
1387 /* build a list of class drivers */
1388 ok = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
1389 SPDIT_CLASSDRIVER);
1390 if (!ok)
1391 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
1392 GetLastError()));
1393
1394 destroyList = TRUE;
1395
1396 /* enumerate the driver info list */
1397 while (TRUE)
1398 {
1399 BOOL ret;
1400
1401 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
1402 SPDIT_CLASSDRIVER, index, &DriverInfoData);
1403
1404 /* if the function failed and GetLastError() returned
1405 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
1406 * list. Othewise there was something wrong with this
1407 * particular driver. */
1408 if (!ret)
1409 {
1410 if(GetLastError() == ERROR_NO_MORE_ITEMS)
1411 break;
1412 else
1413 {
1414 index++;
1415 continue;
1416 }
1417 }
1418
1419 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
1420 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
1421
1422 /* if we successfully find the hardware ID and it turns out to
1423 * be the one for the loopback driver, then we are done. */
1424 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
1425 &DeviceInfoData,
1426 &DriverInfoData,
1427 pDriverInfoDetail,
1428 sizeof (detailBuf),
1429 NULL))
1430 {
1431 TCHAR * t;
1432
1433 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
1434 * whole list and see if there is a match somewhere. */
1435 t = pDriverInfoDetail->HardwareID;
1436 while (t && *t && t < (TCHAR *) &detailBuf [sizeof(detailBuf) / sizeof (detailBuf[0])])
1437 {
1438 if (!_tcsicmp(t, DRIVERHWID))
1439 break;
1440
1441 t += _tcslen(t) + 1;
1442 }
1443
1444 if (t && *t && t < (TCHAR *) &detailBuf [sizeof(detailBuf) / sizeof (detailBuf[0])])
1445 {
1446 found = TRUE;
1447 break;
1448 }
1449 }
1450
1451 index ++;
1452 }
1453
1454 if (!found)
1455 SetErrBreak (("Could not find Host Interface Networking driver! "
1456 "Please reinstall"));
1457
1458 /* set the loopback driver to be the currently selected */
1459 ok = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
1460 &DriverInfoData);
1461 if (!ok)
1462 SetErrBreak (("SetupDiSetSelectedDriver failed (0x%08X)",
1463 GetLastError()));
1464
1465 /* register the phantom device to prepare for install */
1466 ok = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
1467 &DeviceInfoData);
1468 if (!ok)
1469 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
1470 GetLastError()));
1471
1472 /* registered, but remove if errors occur in the following code */
1473 registered = TRUE;
1474
1475 /* ask the installer if we can install the device */
1476 ok = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
1477 &DeviceInfoData);
1478 if (!ok)
1479 {
1480 if (GetLastError() != ERROR_DI_DO_DEFAULT)
1481 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
1482 GetLastError()));
1483 /* that's fine */
1484 }
1485
1486 /* install the files first */
1487 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
1488 &DeviceInfoData);
1489 if (!ok)
1490 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
1491 GetLastError()));
1492
1493 /* get the device install parameters and disable filecopy */
1494 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
1495 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
1496 &DeviceInstallParams);
1497 if (ok)
1498 {
1499 DeviceInstallParams.Flags |= DI_NOFILECOPY;
1500 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
1501 &DeviceInstallParams);
1502 if (!ok)
1503 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
1504 GetLastError()));
1505 }
1506
1507 /*
1508 * Register any device-specific co-installers for this device,
1509 */
1510
1511 ok = SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS,
1512 hDeviceInfo,
1513 &DeviceInfoData);
1514 if (!ok)
1515 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
1516 GetLastError()));
1517
1518 /*
1519 * install any installer-specified interfaces.
1520 * and then do the real install
1521 */
1522 ok = SetupDiCallClassInstaller (DIF_INSTALLINTERFACES,
1523 hDeviceInfo,
1524 &DeviceInfoData);
1525 if (!ok)
1526 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
1527 GetLastError()));
1528
1529 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICE,
1530 hDeviceInfo,
1531 &DeviceInfoData);
1532 if (!ok)
1533 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
1534 GetLastError()));
1535
1536 /* Figure out NetCfgInstanceId */
1537 hkey = SetupDiOpenDevRegKey (hDeviceInfo,
1538 &DeviceInfoData,
1539 DICS_FLAG_GLOBAL,
1540 0,
1541 DIREG_DRV,
1542 KEY_READ);
1543 if (hkey == INVALID_HANDLE_VALUE)
1544 SetErrBreak (("SetupDiOpenDevRegKey failed (0x%08X)",
1545 GetLastError()));
1546
1547 cbSize = sizeof (pCfgGuidString);
1548 DWORD ret;
1549 ret = RegQueryValueEx (hkey, _T("NetCfgInstanceId"), NULL,
1550 &dwValueType, (LPBYTE) pCfgGuidString, &cbSize);
1551 RegCloseKey (hkey);
1552 }
1553 while (0);
1554
1555 /*
1556 * cleanup
1557 */
1558
1559 if (hDeviceInfo != INVALID_HANDLE_VALUE)
1560 {
1561 /* an error has occured, but the device is registered, we must remove it */
1562 if (ret != 0 && registered)
1563 SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
1564
1565 found = SetupDiDeleteDeviceInfo (hDeviceInfo, &DeviceInfoData);
1566
1567 /* destroy the driver info list */
1568 if (destroyList)
1569 SetupDiDestroyDriverInfoList (hDeviceInfo, &DeviceInfoData,
1570 SPDIT_CLASSDRIVER);
1571 /* clean up the device info set */
1572 SetupDiDestroyDeviceInfoList (hDeviceInfo);
1573 }
1574
1575 /* return the network connection GUID on success */
1576 if (RT_SUCCESS (vrc))
1577 {
1578 /* remove the curly bracket at the end */
1579 pCfgGuidString [_tcslen (pCfgGuidString) - 1] = '\0';
1580 LogFlowFunc (("Network connection GUID string = {%ls}\n", pCfgGuidString + 1));
1581
1582 aGUID = Guid (Utf8Str (pCfgGuidString + 1));
1583 LogFlowFunc (("Network connection GUID = {%RTuuid}\n", aGUID.raw()));
1584 Assert (!aGUID.isEmpty());
1585
1586 INetCfg *pNc;
1587 INetCfgComponent *pMpNcc;
1588 LPWSTR lpszApp;
1589
1590 HRESULT hr = VBoxNetCfgWinQueryINetCfg( FALSE,
1591 VBOX_APP_NAME,
1592 &pNc,
1593 &lpszApp );
1594 if(hr == S_OK)
1595 {
1596 hr = VBoxNetCfgWinGetComponentByGuid(pNc,
1597 &GUID_DEVCLASS_NET,
1598 aGUID.asOutParam(),
1599 &pMpNcc);
1600 if(hr == S_OK)
1601 {
1602 LPWSTR name;
1603 hr = pMpNcc->GetDisplayName(&name);
1604 if(hr == S_OK)
1605 {
1606 Bstr str(name);
1607 str.detachTo(pName);
1608
1609 CoTaskMemFree (name);
1610 }
1611
1612 VBoxNetCfgWinReleaseRef(pMpNcc);
1613 }
1614 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
1615 }
1616
1617 if(hr != S_OK)
1618 {
1619 vrc = VERR_GENERAL_FAILURE;
1620 }
1621
1622 }
1623
1624 LogFlowFunc (("vrc=%Rrc\n", vrc));
1625 LogFlowFuncLeave();
1626 return vrc;
1627}
1628
1629/* static */
1630static int removeNetworkInterface (SVCHlpClient *aClient,
1631 const Guid &aGUID,
1632 Utf8Str &aErrMsg)
1633{
1634 LogFlowFuncEnter();
1635 LogFlowFunc (("Network connection GUID = {%RTuuid}\n", aGUID.raw()));
1636
1637 AssertReturn (aClient, VERR_INVALID_POINTER);
1638 AssertReturn (!aGUID.isEmpty(), VERR_INVALID_PARAMETER);
1639
1640 int vrc = VINF_SUCCESS;
1641
1642 do
1643 {
1644 TCHAR lszPnPInstanceId [512] = {0};
1645
1646 /* We have to find the device instance ID through a registry search */
1647
1648 HKEY hkeyNetwork = 0;
1649 HKEY hkeyConnection = 0;
1650
1651 do
1652 {
1653 char strRegLocation [256];
1654 sprintf (strRegLocation,
1655 "SYSTEM\\CurrentControlSet\\Control\\Network\\"
1656 "{4D36E972-E325-11CE-BFC1-08002BE10318}\\{%s}",
1657 aGUID.toString().raw());
1658 LONG status;
1659 status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, strRegLocation, 0,
1660 KEY_READ, &hkeyNetwork);
1661 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
1662 SetErrBreak ((
1663 "Host interface network is not found in registry (%s) [1]",
1664 strRegLocation));
1665
1666 status = RegOpenKeyExA (hkeyNetwork, "Connection", 0,
1667 KEY_READ, &hkeyConnection);
1668 if ((status != ERROR_SUCCESS) || !hkeyConnection)
1669 SetErrBreak ((
1670 "Host interface network is not found in registry (%s) [2]",
1671 strRegLocation));
1672
1673 DWORD len = sizeof (lszPnPInstanceId);
1674 DWORD dwKeyType;
1675 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
1676 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
1677 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
1678 SetErrBreak ((
1679 "Host interface network is not found in registry (%s) [3]",
1680 strRegLocation));
1681 }
1682 while (0);
1683
1684 if (hkeyConnection)
1685 RegCloseKey (hkeyConnection);
1686 if (hkeyNetwork)
1687 RegCloseKey (hkeyNetwork);
1688
1689 if (RT_FAILURE (vrc))
1690 break;
1691
1692 /*
1693 * Now we are going to enumerate all network devices and
1694 * wait until we encounter the right device instance ID
1695 */
1696
1697 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1698
1699 do
1700 {
1701 BOOL ok;
1702 DWORD ret = 0;
1703 GUID netGuid;
1704 SP_DEVINFO_DATA DeviceInfoData;
1705 DWORD index = 0;
1706 BOOL found = FALSE;
1707 DWORD size = 0;
1708
1709 /* initialize the structure size */
1710 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
1711
1712 /* copy the net class GUID */
1713 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
1714
1715 /* return a device info set contains all installed devices of the Net class */
1716 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
1717
1718 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1719 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
1720
1721 /* enumerate the driver info list */
1722 while (TRUE)
1723 {
1724 TCHAR *deviceHwid;
1725
1726 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
1727
1728 if (!ok)
1729 {
1730 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1731 break;
1732 else
1733 {
1734 index++;
1735 continue;
1736 }
1737 }
1738
1739 /* try to get the hardware ID registry property */
1740 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1741 &DeviceInfoData,
1742 SPDRP_HARDWAREID,
1743 NULL,
1744 NULL,
1745 0,
1746 &size);
1747 if (!ok)
1748 {
1749 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1750 {
1751 index++;
1752 continue;
1753 }
1754
1755 deviceHwid = (TCHAR *) malloc (size);
1756 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1757 &DeviceInfoData,
1758 SPDRP_HARDWAREID,
1759 NULL,
1760 (PBYTE)deviceHwid,
1761 size,
1762 NULL);
1763 if (!ok)
1764 {
1765 free (deviceHwid);
1766 deviceHwid = NULL;
1767 index++;
1768 continue;
1769 }
1770 }
1771 else
1772 {
1773 /* something is wrong. This shouldn't have worked with a NULL buffer */
1774 index++;
1775 continue;
1776 }
1777
1778 for (TCHAR *t = deviceHwid;
1779 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
1780 t += _tcslen (t) + 1)
1781 {
1782 if (!_tcsicmp (DRIVERHWID, t))
1783 {
1784 /* get the device instance ID */
1785 TCHAR devID [MAX_DEVICE_ID_LEN];
1786 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
1787 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
1788 {
1789 /* compare to what we determined before */
1790 if (wcscmp(devID, lszPnPInstanceId) == 0)
1791 {
1792 found = TRUE;
1793 break;
1794 }
1795 }
1796 }
1797 }
1798
1799 if (deviceHwid)
1800 {
1801 free (deviceHwid);
1802 deviceHwid = NULL;
1803 }
1804
1805 if (found)
1806 break;
1807
1808 index++;
1809 }
1810
1811 if (found == FALSE)
1812 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
1813 GetLastError()));
1814
1815 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
1816 if (!ok)
1817 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
1818 GetLastError()));
1819
1820 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
1821 if (!ok)
1822 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
1823 GetLastError()));
1824 }
1825 while (0);
1826
1827 /* clean up the device info set */
1828 if (hDeviceInfo != INVALID_HANDLE_VALUE)
1829 SetupDiDestroyDeviceInfoList (hDeviceInfo);
1830
1831 if (RT_FAILURE (vrc))
1832 break;
1833 }
1834 while (0);
1835
1836 LogFlowFunc (("vrc=%Rrc\n", vrc));
1837 LogFlowFuncLeave();
1838 return vrc;
1839}
1840
1841#undef SetErrBreak
1842
1843int netIfNetworkInterfaceHelperServer (SVCHlpClient *aClient,
1844 SVCHlpMsg::Code aMsgCode)
1845{
1846 LogFlowFuncEnter();
1847 LogFlowFunc (("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode));
1848
1849 AssertReturn (aClient, VERR_INVALID_POINTER);
1850
1851 int vrc = VINF_SUCCESS;
1852
1853 switch (aMsgCode)
1854 {
1855 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
1856 {
1857 LogFlowFunc (("CreateHostOnlyNetworkInterface:\n"));
1858
1859// Utf8Str name;
1860// vrc = aClient->read (name);
1861// if (RT_FAILURE (vrc)) break;
1862
1863 Guid guid;
1864 Utf8Str errMsg;
1865 Bstr name;
1866 vrc = createNetworkInterface (aClient, name.asOutParam(), guid, errMsg);
1867
1868 if (RT_SUCCESS (vrc))
1869 {
1870 /* write success followed by GUID */
1871 vrc = aClient->write (SVCHlpMsg::CreateHostOnlyNetworkInterface_OK);
1872 if (RT_FAILURE (vrc)) break;
1873 vrc = aClient->write (Utf8Str (name));
1874 if (RT_FAILURE (vrc)) break;
1875 vrc = aClient->write (guid);
1876 if (RT_FAILURE (vrc)) break;
1877 }
1878 else
1879 {
1880 /* write failure followed by error message */
1881 if (errMsg.isEmpty())
1882 errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc);
1883 vrc = aClient->write (SVCHlpMsg::Error);
1884 if (RT_FAILURE (vrc)) break;
1885 vrc = aClient->write (errMsg);
1886 if (RT_FAILURE (vrc)) break;
1887 }
1888
1889 break;
1890 }
1891 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
1892 {
1893 LogFlowFunc (("RemoveHostOnlyNetworkInterface:\n"));
1894
1895 Guid guid;
1896 vrc = aClient->read (guid);
1897 if (RT_FAILURE (vrc)) break;
1898
1899 Utf8Str errMsg;
1900 vrc = removeNetworkInterface (aClient, guid, errMsg);
1901
1902 if (RT_SUCCESS (vrc))
1903 {
1904 /* write parameter-less success */
1905 vrc = aClient->write (SVCHlpMsg::OK);
1906 if (RT_FAILURE (vrc)) break;
1907 }
1908 else
1909 {
1910 /* write failure followed by error message */
1911 if (errMsg.isEmpty())
1912 errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc);
1913 vrc = aClient->write (SVCHlpMsg::Error);
1914 if (RT_FAILURE (vrc)) break;
1915 vrc = aClient->write (errMsg);
1916 if (RT_FAILURE (vrc)) break;
1917 }
1918
1919 break;
1920 }
1921 case SVCHlpMsg::EnableStaticIpConfigV6:
1922 {
1923 LogFlowFunc (("EnableStaticIpConfigV6:\n"));
1924
1925 Guid guid;
1926 Utf8Str ipV6;
1927 ULONG maskLengthV6;
1928 vrc = aClient->read (guid);
1929 if (RT_FAILURE (vrc)) break;
1930 vrc = aClient->read (ipV6);
1931 if (RT_FAILURE (vrc)) break;
1932 vrc = aClient->read (maskLengthV6);
1933 if (RT_FAILURE (vrc)) break;
1934
1935 Utf8Str errMsg;
1936 vrc = netIfEnableStaticIpConfigV6 (guid, Bstr(ipV6), maskLengthV6);
1937
1938 if (RT_SUCCESS (vrc))
1939 {
1940 /* write success followed by GUID */
1941 vrc = aClient->write (SVCHlpMsg::OK);
1942 if (RT_FAILURE (vrc)) break;
1943 }
1944 else
1945 {
1946 /* write failure followed by error message */
1947 if (errMsg.isEmpty())
1948 errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc);
1949 vrc = aClient->write (SVCHlpMsg::Error);
1950 if (RT_FAILURE (vrc)) break;
1951 vrc = aClient->write (errMsg);
1952 if (RT_FAILURE (vrc)) break;
1953 }
1954
1955 break;
1956 }
1957 case SVCHlpMsg::EnableStaticIpConfig:
1958 {
1959 LogFlowFunc (("EnableStaticIpConfig:\n"));
1960
1961 Guid guid;
1962 ULONG ip, mask;
1963 vrc = aClient->read (guid);
1964 if (RT_FAILURE (vrc)) break;
1965 vrc = aClient->read (ip);
1966 if (RT_FAILURE (vrc)) break;
1967 vrc = aClient->read (mask);
1968 if (RT_FAILURE (vrc)) break;
1969
1970 Utf8Str errMsg;
1971 vrc = netIfEnableStaticIpConfig (guid, ip, mask);
1972
1973 if (RT_SUCCESS (vrc))
1974 {
1975 /* write success followed by GUID */
1976 vrc = aClient->write (SVCHlpMsg::OK);
1977 if (RT_FAILURE (vrc)) break;
1978 }
1979 else
1980 {
1981 /* write failure followed by error message */
1982 if (errMsg.isEmpty())
1983 errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc);
1984 vrc = aClient->write (SVCHlpMsg::Error);
1985 if (RT_FAILURE (vrc)) break;
1986 vrc = aClient->write (errMsg);
1987 if (RT_FAILURE (vrc)) break;
1988 }
1989
1990 break;
1991 }
1992 case SVCHlpMsg::EnableDynamicIpConfig:
1993 {
1994 LogFlowFunc (("EnableDynamicIpConfig:\n"));
1995
1996 Guid guid;
1997 vrc = aClient->read (guid);
1998 if (RT_FAILURE (vrc)) break;
1999
2000 Utf8Str errMsg;
2001 vrc = netIfEnableDynamicIpConfig (guid);
2002
2003 if (RT_SUCCESS (vrc))
2004 {
2005 /* write success followed by GUID */
2006 vrc = aClient->write (SVCHlpMsg::OK);
2007 if (RT_FAILURE (vrc)) break;
2008 }
2009 else
2010 {
2011 /* write failure followed by error message */
2012 if (errMsg.isEmpty())
2013 errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc);
2014 vrc = aClient->write (SVCHlpMsg::Error);
2015 if (RT_FAILURE (vrc)) break;
2016 vrc = aClient->write (errMsg);
2017 if (RT_FAILURE (vrc)) break;
2018 }
2019
2020 break;
2021 }
2022 default:
2023 AssertMsgFailedBreakStmt (
2024 ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
2025 VERR_GENERAL_FAILURE);
2026 }
2027
2028 LogFlowFunc (("vrc=%Rrc\n", vrc));
2029 LogFlowFuncLeave();
2030 return vrc;
2031}
2032
2033/** @todo REMOVE. OBSOLETE NOW. */
2034/**
2035 * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
2036 * later OSes) and it has the UAC (User Account Control) feature enabled.
2037 */
2038static BOOL IsUACEnabled()
2039{
2040 LONG rc = 0;
2041
2042 OSVERSIONINFOEX info;
2043 ZeroMemory (&info, sizeof (OSVERSIONINFOEX));
2044 info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
2045 rc = GetVersionEx ((OSVERSIONINFO *) &info);
2046 AssertReturn (rc != 0, FALSE);
2047
2048 LogFlowFunc (("dwMajorVersion=%d, dwMinorVersion=%d\n",
2049 info.dwMajorVersion, info.dwMinorVersion));
2050
2051 /* we are interested only in Vista (and newer versions...). In all
2052 * earlier versions UAC is not present. */
2053 if (info.dwMajorVersion < 6)
2054 return FALSE;
2055
2056 /* the default EnableLUA value is 1 (Enabled) */
2057 DWORD dwEnableLUA = 1;
2058
2059 HKEY hKey;
2060 rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
2061 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
2062 0, KEY_QUERY_VALUE, &hKey);
2063
2064 Assert (rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
2065 if (rc == ERROR_SUCCESS)
2066 {
2067
2068 DWORD cbEnableLUA = sizeof (dwEnableLUA);
2069 rc = RegQueryValueExA (hKey, "EnableLUA", NULL, NULL,
2070 (LPBYTE) &dwEnableLUA, &cbEnableLUA);
2071
2072 RegCloseKey (hKey);
2073
2074 Assert (rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
2075 }
2076
2077 LogFlowFunc (("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
2078
2079 return dwEnableLUA == 1;
2080}
2081
2082/* end */
2083
2084static int vboxNetWinAddComponent(std::list <ComObjPtr <HostNetworkInterface> > * pPist, INetCfgComponent * pncc, HostNetworkInterfaceType enmType)
2085{
2086 LPWSTR lpszName;
2087 GUID IfGuid;
2088 HRESULT hr;
2089 int rc = VERR_GENERAL_FAILURE;
2090
2091 hr = pncc->GetDisplayName( &lpszName );
2092 Assert(hr == S_OK);
2093 if(hr == S_OK)
2094 {
2095 size_t cUnicodeName = wcslen(lpszName) + 1;
2096 size_t uniLen = (cUnicodeName * 2 + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
2097 Bstr name (uniLen + 1 /* extra zero */);
2098 wcscpy((wchar_t *) name.mutableRaw(), lpszName);
2099
2100 hr = pncc->GetInstanceGuid(&IfGuid);
2101 Assert(hr == S_OK);
2102 if (hr == S_OK)
2103 {
2104 NETIFINFO Info;
2105 memset(&Info, 0, sizeof(Info));
2106 Info.Uuid = *(Guid(IfGuid).raw());
2107 rc = collectNetIfInfo(name, Guid(IfGuid), &Info);
2108 if (RT_FAILURE(rc))
2109 {
2110 Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc));
2111 }
2112 /* create a new object and add it to the list */
2113 ComObjPtr <HostNetworkInterface> iface;
2114 iface.createObject();
2115 /* remove the curly bracket at the end */
2116 if (SUCCEEDED (iface->init (name, enmType, &Info)))
2117 {
2118 pPist->push_back (iface);
2119 rc = VINF_SUCCESS;
2120 }
2121 else
2122 {
2123 Assert(0);
2124 }
2125 }
2126 CoTaskMemFree(lpszName);
2127 }
2128
2129 return rc;
2130}
2131
2132#endif /* #ifndef VBOX_WITH_NETFLT */
2133
2134
2135static int netIfListHostAdapters(std::list <ComObjPtr <HostNetworkInterface> > &list)
2136{
2137#ifndef VBOX_WITH_NETFLT
2138 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
2139 return VERR_NOT_IMPLEMENTED;
2140#else /* # if defined VBOX_WITH_NETFLT */
2141 INetCfg *pNc;
2142 INetCfgComponent *pMpNcc;
2143 LPWSTR lpszApp = NULL;
2144 HRESULT hr;
2145 IEnumNetCfgComponent *pEnumComponent;
2146
2147 /* we are using the INetCfg API for getting the list of miniports */
2148 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
2149 VBOX_APP_NAME,
2150 &pNc,
2151 &lpszApp );
2152 Assert(hr == S_OK);
2153 if(hr == S_OK)
2154 {
2155 hr = VBoxNetCfgWinGetComponentEnum(pNc, &GUID_DEVCLASS_NET, &pEnumComponent);
2156 if(hr == S_OK)
2157 {
2158 while((hr = VBoxNetCfgWinGetNextComponent(pEnumComponent, &pMpNcc)) == S_OK)
2159 {
2160 ULONG uComponentStatus;
2161 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
2162//#ifndef DEBUG_bird
2163// Assert(hr == S_OK);
2164//#endif
2165 if(hr == S_OK)
2166 {
2167 if(uComponentStatus == 0)
2168 {
2169 LPWSTR pId;
2170 hr = pMpNcc->GetId(&pId);
2171 Assert(hr == S_OK);
2172 if(hr == S_OK)
2173 {
2174 if(!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
2175 {
2176 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly);
2177 }
2178 CoTaskMemFree(pId);
2179 }
2180 }
2181 }
2182 VBoxNetCfgWinReleaseRef(pMpNcc);
2183 }
2184 Assert(hr == S_OK || hr == S_FALSE);
2185
2186 VBoxNetCfgWinReleaseRef(pEnumComponent);
2187 }
2188 else
2189 {
2190 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
2191 }
2192
2193 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
2194 }
2195 else if(lpszApp)
2196 {
2197 CoTaskMemFree(lpszApp);
2198 }
2199#endif /* # if defined VBOX_WITH_NETFLT */
2200 return VINF_SUCCESS;
2201}
2202
2203int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo)
2204{
2205#ifndef VBOX_WITH_NETFLT
2206 return VERR_NOT_IMPLEMENTED;
2207#else
2208 Bstr name;
2209 HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam());
2210 if(hr == S_OK)
2211 {
2212 GUID IfGuid;
2213 hr = pIf->COMGETTER(Id)(&IfGuid);
2214 Assert(hr == S_OK);
2215 if (hr == S_OK)
2216 {
2217 return collectNetIfInfo(name, Guid(IfGuid), pInfo);
2218 }
2219 }
2220 return VERR_GENERAL_FAILURE;
2221#endif
2222}
2223
2224int NetIfCreateHostOnlyNetworkInterface (VirtualBox *pVBox,
2225 IHostNetworkInterface **aHostNetworkInterface,
2226 IProgress **aProgress)
2227{
2228 /* create a progress object */
2229 ComObjPtr <Progress> progress;
2230 progress.createObject();
2231
2232 ComPtr<IHost> host;
2233 HRESULT rc = pVBox->COMGETTER(Host)(host.asOutParam());
2234 if(SUCCEEDED(rc))
2235 {
2236 rc = progress->init (pVBox, host,
2237 Bstr (_T ("Creating host only network interface")),
2238 FALSE /* aCancelable */);
2239 if(SUCCEEDED(rc))
2240 {
2241 CheckComRCReturnRC (rc);
2242 progress.queryInterfaceTo (aProgress);
2243
2244 /* create a new uninitialized host interface object */
2245 ComObjPtr <HostNetworkInterface> iface;
2246 iface.createObject();
2247 iface.queryInterfaceTo (aHostNetworkInterface);
2248
2249 /* create the networkInterfaceHelperClient() argument */
2250 std::auto_ptr <NetworkInterfaceHelperClientData>
2251 d (new NetworkInterfaceHelperClientData());
2252 AssertReturn (d.get(), E_OUTOFMEMORY);
2253
2254 d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface;
2255// d->name = aName;
2256 d->iface = iface;
2257
2258 rc = pVBox->startSVCHelperClient (
2259 IsUACEnabled() == TRUE /* aPrivileged */,
2260 netIfNetworkInterfaceHelperClient,
2261 static_cast <void *> (d.get()),
2262 progress);
2263
2264 if (SUCCEEDED (rc))
2265 {
2266 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
2267 d.release();
2268 }
2269 }
2270 }
2271
2272 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
2273}
2274
2275int NetIfRemoveHostOnlyNetworkInterface (VirtualBox *pVBox, IN_GUID aId,
2276 IHostNetworkInterface **aHostNetworkInterface,
2277 IProgress **aProgress)
2278{
2279 /* create a progress object */
2280 ComObjPtr <Progress> progress;
2281 progress.createObject();
2282 ComPtr<IHost> host;
2283 HRESULT rc = pVBox->COMGETTER(Host)(host.asOutParam());
2284 if(SUCCEEDED(rc))
2285 {
2286 rc = progress->init (pVBox, host,
2287 Bstr (_T ("Removing host network interface")),
2288 FALSE /* aCancelable */);
2289 if(SUCCEEDED(rc))
2290 {
2291 CheckComRCReturnRC (rc);
2292 progress.queryInterfaceTo (aProgress);
2293
2294 /* create the networkInterfaceHelperClient() argument */
2295 std::auto_ptr <NetworkInterfaceHelperClientData>
2296 d (new NetworkInterfaceHelperClientData());
2297 AssertReturn (d.get(), E_OUTOFMEMORY);
2298
2299 d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface;
2300 d->guid = aId;
2301
2302 rc = pVBox->startSVCHelperClient (
2303 IsUACEnabled() == TRUE /* aPrivileged */,
2304 netIfNetworkInterfaceHelperClient,
2305 static_cast <void *> (d.get()),
2306 progress);
2307
2308 if (SUCCEEDED (rc))
2309 {
2310 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
2311 d.release();
2312 }
2313 }
2314 }
2315
2316 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
2317}
2318
2319int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG ip, ULONG mask)
2320{
2321 HRESULT rc;
2322 GUID guid;
2323 rc = pIf->COMGETTER(Id) (&guid);
2324 if(SUCCEEDED(rc))
2325 {
2326// ComPtr<VirtualBox> vBox;
2327// rc = pIf->getVirtualBox (vBox.asOutParam());
2328// if(SUCCEEDED(rc))
2329 {
2330 /* create a progress object */
2331 ComObjPtr <Progress> progress;
2332 progress.createObject();
2333// ComPtr<IHost> host;
2334// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
2335// if(SUCCEEDED(rc))
2336 {
2337 rc = progress->init (vBox, (IHostNetworkInterface*)pIf,
2338 Bstr ("Enabling Dynamic Ip Configuration"),
2339 FALSE /* aCancelable */);
2340 if(SUCCEEDED(rc))
2341 {
2342 CheckComRCReturnRC (rc);
2343// progress.queryInterfaceTo (aProgress);
2344
2345 /* create the networkInterfaceHelperClient() argument */
2346 std::auto_ptr <NetworkInterfaceHelperClientData>
2347 d (new NetworkInterfaceHelperClientData());
2348 AssertReturn (d.get(), E_OUTOFMEMORY);
2349
2350 d->msgCode = SVCHlpMsg::EnableStaticIpConfig;
2351 d->guid = guid;
2352 d->iface = pIf;
2353 d->u.StaticIP.IPAddress = ip;
2354 d->u.StaticIP.IPNetMask = mask;
2355
2356 rc = vBox->startSVCHelperClient (
2357 IsUACEnabled() == TRUE /* aPrivileged */,
2358 netIfNetworkInterfaceHelperClient,
2359 static_cast <void *> (d.get()),
2360 progress);
2361
2362 if (SUCCEEDED (rc))
2363 {
2364 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
2365 d.release();
2366
2367 progress->WaitForCompletion(-1);
2368 }
2369 }
2370 }
2371 }
2372 }
2373
2374 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
2375}
2376
2377int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
2378{
2379 HRESULT rc;
2380 GUID guid;
2381 rc = pIf->COMGETTER(Id) (&guid);
2382 if(SUCCEEDED(rc))
2383 {
2384// ComPtr<VirtualBox> vBox;
2385// rc = pIf->getVirtualBox (vBox.asOutParam());
2386// if(SUCCEEDED(rc))
2387 {
2388 /* create a progress object */
2389 ComObjPtr <Progress> progress;
2390 progress.createObject();
2391// ComPtr<IHost> host;
2392// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
2393// if(SUCCEEDED(rc))
2394 {
2395 rc = progress->init (vBox, (IHostNetworkInterface*)pIf,
2396 Bstr ("Enabling Dynamic Ip Configuration"),
2397 FALSE /* aCancelable */);
2398 if(SUCCEEDED(rc))
2399 {
2400 CheckComRCReturnRC (rc);
2401// progress.queryInterfaceTo (aProgress);
2402
2403 /* create the networkInterfaceHelperClient() argument */
2404 std::auto_ptr <NetworkInterfaceHelperClientData>
2405 d (new NetworkInterfaceHelperClientData());
2406 AssertReturn (d.get(), E_OUTOFMEMORY);
2407
2408 d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6;
2409 d->guid = guid;
2410 d->iface = pIf;
2411 d->u.StaticIPV6.IPV6Address = aIPV6Address;
2412 d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength;
2413
2414 rc = vBox->startSVCHelperClient (
2415 IsUACEnabled() == TRUE /* aPrivileged */,
2416 netIfNetworkInterfaceHelperClient,
2417 static_cast <void *> (d.get()),
2418 progress);
2419
2420 if (SUCCEEDED (rc))
2421 {
2422 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
2423 d.release();
2424
2425 progress->WaitForCompletion(-1);
2426 }
2427 }
2428 }
2429 }
2430 }
2431
2432 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
2433}
2434
2435int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf)
2436{
2437 HRESULT rc;
2438 GUID guid;
2439 rc = pIf->COMGETTER(Id) (&guid);
2440 if(SUCCEEDED(rc))
2441 {
2442// ComPtr<VirtualBox> vBox;
2443// rc = pIf->getVirtualBox (vBox.asOutParam());
2444// if(SUCCEEDED(rc))
2445 {
2446 /* create a progress object */
2447 ComObjPtr <Progress> progress;
2448 progress.createObject();
2449// ComPtr<IHost> host;
2450// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
2451// if(SUCCEEDED(rc))
2452 {
2453 rc = progress->init (vBox, (IHostNetworkInterface*)pIf,
2454 Bstr ("Enabling Dynamic Ip Configuration"),
2455 FALSE /* aCancelable */);
2456 if(SUCCEEDED(rc))
2457 {
2458 CheckComRCReturnRC (rc);
2459// progress.queryInterfaceTo (aProgress);
2460
2461 /* create the networkInterfaceHelperClient() argument */
2462 std::auto_ptr <NetworkInterfaceHelperClientData>
2463 d (new NetworkInterfaceHelperClientData());
2464 AssertReturn (d.get(), E_OUTOFMEMORY);
2465
2466 d->msgCode = SVCHlpMsg::EnableDynamicIpConfig;
2467 d->guid = guid;
2468 d->iface = pIf;
2469
2470 rc = vBox->startSVCHelperClient (
2471 IsUACEnabled() == TRUE /* aPrivileged */,
2472 netIfNetworkInterfaceHelperClient,
2473 static_cast <void *> (d.get()),
2474 progress);
2475
2476 if (SUCCEEDED (rc))
2477 {
2478 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
2479 d.release();
2480
2481 progress->WaitForCompletion(-1);
2482 }
2483 }
2484 }
2485 }
2486 }
2487
2488 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
2489}
2490
2491int NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
2492{
2493#ifndef VBOX_WITH_NETFLT
2494 return VERR_NOT_IMPLEMENTED;
2495#else /* # if defined VBOX_WITH_NETFLT */
2496 INetCfg *pNc;
2497 INetCfgComponent *pMpNcc;
2498 INetCfgComponent *pTcpIpNcc;
2499 LPWSTR lpszApp;
2500 HRESULT hr;
2501 IEnumNetCfgBindingPath *pEnumBp;
2502 INetCfgBindingPath *pBp;
2503 IEnumNetCfgBindingInterface *pEnumBi;
2504 INetCfgBindingInterface *pBi;
2505
2506 /* we are using the INetCfg API for getting the list of miniports */
2507 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
2508 VBOX_APP_NAME,
2509 &pNc,
2510 &lpszApp );
2511 Assert(hr == S_OK);
2512 if(hr == S_OK)
2513 {
2514# ifdef VBOX_NETFLT_ONDEMAND_BIND
2515 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
2516 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
2517# else
2518 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
2519 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
2520# ifndef VBOX_WITH_HARDENING
2521 if(hr != S_OK)
2522 {
2523 /* TODO: try to install the netflt from here */
2524 }
2525# endif
2526
2527# endif
2528
2529 if(hr == S_OK)
2530 {
2531 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
2532 Assert(hr == S_OK);
2533 if ( hr == S_OK )
2534 {
2535 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
2536 Assert(hr == S_OK || hr == S_FALSE);
2537 while( hr == S_OK )
2538 {
2539 /* S_OK == enabled, S_FALSE == disabled */
2540 if(pBp->IsEnabled() == S_OK)
2541 {
2542 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
2543 Assert(hr == S_OK);
2544 if ( hr == S_OK )
2545 {
2546 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
2547 Assert(hr == S_OK);
2548 while(hr == S_OK)
2549 {
2550 hr = pBi->GetLowerComponent( &pMpNcc );
2551 Assert(hr == S_OK);
2552 if(hr == S_OK)
2553 {
2554 ULONG uComponentStatus;
2555 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
2556//#ifndef DEBUG_bird
2557// Assert(hr == S_OK);
2558//#endif
2559 if(hr == S_OK)
2560 {
2561 if(uComponentStatus == 0)
2562 {
2563 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_Bridged);
2564 }
2565 }
2566 VBoxNetCfgWinReleaseRef( pMpNcc );
2567 }
2568 VBoxNetCfgWinReleaseRef(pBi);
2569
2570 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
2571 }
2572 VBoxNetCfgWinReleaseRef(pEnumBi);
2573 }
2574 }
2575 VBoxNetCfgWinReleaseRef(pBp);
2576
2577 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
2578 }
2579 VBoxNetCfgWinReleaseRef(pEnumBp);
2580 }
2581 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
2582 }
2583 else
2584 {
2585 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
2586 }
2587
2588 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
2589 }
2590
2591 netIfListHostAdapters(list);
2592
2593 return VINF_SUCCESS;
2594#endif /* # if defined VBOX_WITH_NETFLT */
2595}
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