VirtualBox

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

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

NetIf/win fixes

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