VirtualBox

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

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

NettIf/win: ipconfig fixes

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette