VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/WinNetConfig.cpp@ 21361

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

export vboxnetflt for Windows to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 123.3 KB
Line 
1/* $Id: WinNetConfig.cpp 21343 2009-07-07 15:30:08Z vboxsync $ */
2/** @file
3 * VBoxNetCfgWin - Briefly describe this file, optionally with a longer description in a separate paragraph.
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 * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
23 *+---------------------------------------------------------------------------
24 *
25 * Microsoft Windows
26 * Copyright (C) Microsoft Corporation, 2001.
27 *
28 * Author: Alok Sinha 15-May-01
29 *
30 *----------------------------------------------------------------------------
31 */
32#include "VBox/WinNetConfig.h"
33
34#define _WIN32_DCOM
35
36
37#include <iphlpapi.h>
38
39#include <devguid.h>
40#include <stdio.h>
41#include <regstr.h>
42//#define INITGUID
43//#include <guiddef.h>
44//#include <devguid.h>
45//#include <objbase.h>
46//#include <setupapi.h>
47#include <shlobj.h>
48#include <cfgmgr32.h>
49#include <tchar.h>
50//#include <VBox/com/Guid.h>
51//#include <VBox/com/String.h>
52//#include <wtypes.h>
53#include <objbase.h>
54
55#include <crtdbg.h>
56#include <stdlib.h>
57
58#include <Wbemidl.h>
59#include <comdef.h>
60
61//#include <Winsock2.h>
62
63//using namespace com;
64
65#ifndef Assert
66//# ifdef DEBUG
67//# define Assert(_expr) assert(_expr)
68//# else
69//# define Assert(_expr) do{ }while(0)
70//# endif
71# define Assert _ASSERT
72# define AssertMsg(expr, msg) do{}while(0)
73#endif
74static LOG_ROUTINE g_Logger = NULL;
75
76static VOID DoLogging(LPCWSTR szString, ...);
77#define Log DoLogging
78
79#define DbgLog
80
81#define VBOX_NETCFG_LOCK_TIME_OUT 5000
82
83typedef bool (*ENUMERATION_CALLBACK) (LPWSTR pFileName, PVOID pContext);
84
85static HRESULT vboxNetCfgWinCollectInfs(LPCWSTR pPnPId)
86{
87 DWORD winEr = ERROR_SUCCESS;
88 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(
89 &GUID_DEVCLASS_NETSERVICE, /* IN LPGUID ClassGuid, OPTIONAL */
90 NULL /*IN HWND hwndParent OPTIONAL */
91 );
92 if(hDevInfo != INVALID_HANDLE_VALUE)
93 {
94 if(SetupDiBuildDriverInfoList(hDevInfo,
95 NULL, /*IN OUT PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
96 SPDIT_CLASSDRIVER /*IN DWORD DriverType*/
97 ))
98 {
99 SP_DRVINFO_DATA DrvInfo;
100 DrvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
101 char DetailBuf[16384];
102 PSP_DRVINFO_DETAIL_DATA pDrvDetail = (PSP_DRVINFO_DETAIL_DATA)DetailBuf;
103
104 for(DWORD i = 0;;i++)
105 {
106 if(SetupDiEnumDriverInfo(hDevInfo,
107 NULL, /* IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
108 SPDIT_CLASSDRIVER , /*IN DWORD DriverType,*/
109 i, /*IN DWORD MemberIndex,*/
110 &DrvInfo /*OUT PSP_DRVINFO_DATA DriverInfoData*/
111 ))
112 {
113 DWORD dwReq;
114 pDrvDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
115 if(SetupDiGetDriverInfoDetail(
116 hDevInfo, /*IN HDEVINFO DeviceInfoSet,*/
117 NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
118 &DrvInfo, /*IN PSP_DRVINFO_DATA DriverInfoData,*/
119 pDrvDetail, /*OUT PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData, OPTIONAL*/
120 sizeof(DetailBuf), /*IN DWORD DriverInfoDetailDataSize,*/
121 &dwReq /*OUT PDWORD RequiredSize OPTIONAL*/
122 ))
123 {
124 for(WCHAR * pHwId = pDrvDetail->HardwareID; pHwId && *pHwId && pHwId < (TCHAR*)(DetailBuf + sizeof(DetailBuf)/sizeof(DetailBuf[0])) ;pHwId += _tcslen(pHwId) + 1)
125 {
126 //TODO:
127 }
128 }
129 else
130 {
131 DWORD winEr = GetLastError();
132 Log(L"Err SetupDiGetDriverInfoDetail (%d), req = %d", winEr, dwReq);
133// Assert(0);
134 }
135
136 }
137 else
138 {
139 DWORD winEr = GetLastError();
140 if(winEr == ERROR_NO_MORE_ITEMS)
141 {
142 break;
143 }
144
145 Assert(0);
146 }
147 }
148
149 SetupDiDestroyDriverInfoList(hDevInfo,
150 NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
151 SPDIT_CLASSDRIVER/*IN DWORD DriverType*/
152 );
153 }
154 else
155 {
156 winEr = GetLastError();
157 Assert(0);
158 }
159
160 SetupDiDestroyDeviceInfoList(hDevInfo);
161 }
162 else
163 {
164 winEr = GetLastError();
165 Assert(0);
166 }
167
168 return HRESULT_FROM_WIN32(winEr);
169}
170
171//
172// Function: GetKeyValue
173//
174// Purpose: Retrieve the value of a key from the inf file.
175//
176// Arguments:
177// hInf [in] Inf file handle.
178// lpszSection [in] Section name.
179// lpszKey [in] Key name.
180// dwIndex [in] Key index.
181// lppszValue [out] Key value.
182//
183// Returns: S_OK on success, otherwise and error code.
184//
185// Notes:
186//
187
188static HRESULT vboxNetCfgWinGetKeyValue (HINF hInf,
189 LPCWSTR lpszSection,
190 LPCWSTR lpszKey,
191 DWORD dwIndex,
192 LPWSTR *lppszValue)
193{
194 INFCONTEXT infCtx;
195 DWORD dwSizeNeeded;
196 HRESULT hr;
197
198 *lppszValue = NULL;
199
200 if ( SetupFindFirstLineW(hInf,
201 lpszSection,
202 lpszKey,
203 &infCtx) == FALSE )
204 {
205 DWORD winEr = GetLastError();
206 DbgLog(L"vboxNetCfgWinGetKeyValue: SetupFindFirstLineW failed, winEr = (%d)\n", winEr);
207 //Assert(0);
208 return HRESULT_FROM_WIN32(winEr);
209 }
210
211 SetupGetStringFieldW( &infCtx,
212 dwIndex,
213 NULL,
214 0,
215 &dwSizeNeeded );
216
217 *lppszValue = (LPWSTR)CoTaskMemAlloc( sizeof(WCHAR) * dwSizeNeeded );
218
219 if ( !*lppszValue )
220 {
221 Log(L"vboxNetCfgWinGetKeyValue: CoTaskMemAlloc failed\n");
222 Assert(0);
223 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
224 }
225
226 if ( SetupGetStringFieldW(&infCtx,
227 dwIndex,
228 *lppszValue,
229 dwSizeNeeded,
230 NULL) == FALSE )
231 {
232 DWORD winEr = GetLastError();
233 DbgLog(L"vboxNetCfgWinGetKeyValue: SetupGetStringFieldW failed, winEr = (%d)\n", winEr);
234 hr = HRESULT_FROM_WIN32(winEr);
235 //Assert(0);
236 CoTaskMemFree( *lppszValue );
237 *lppszValue = NULL;
238 }
239 else
240 {
241 hr = S_OK;
242 }
243
244 return hr;
245}
246
247//
248// Function: GetPnpID
249//
250// Purpose: Retrieve PnpID from an inf file.
251//
252// Arguments:
253// lpszInfFile [in] Inf file to search.
254// lppszPnpID [out] PnpID found.
255//
256// Returns: TRUE on success.
257//
258// Notes:
259//
260
261static HRESULT vboxNetCfgWinGetPnpID (LPCWSTR lpszInfFile,
262 LPWSTR *lppszPnpID)
263{
264 HINF hInf;
265 LPWSTR lpszModelSection;
266 HRESULT hr;
267
268 *lppszPnpID = NULL;
269
270 hInf = SetupOpenInfFileW( lpszInfFile,
271 NULL,
272 INF_STYLE_WIN4,
273 NULL );
274
275 if ( hInf == INVALID_HANDLE_VALUE )
276 {
277 DWORD winEr = GetLastError();
278 DbgLog(L"vboxNetCfgWinGetPnpID: SetupOpenInfFileW failed, winEr = (%d), for file (%s)\n", winEr, lpszInfFile);
279 //Assert(0);
280 return HRESULT_FROM_WIN32(winEr);
281 }
282
283 //
284 // Read the Model section name from Manufacturer section.
285 //
286
287 hr = vboxNetCfgWinGetKeyValue( hInf,
288 L"Manufacturer",
289 NULL,
290 1,
291 &lpszModelSection );
292 //Assert(hr == S_OK);
293 if ( hr == S_OK )
294 {
295
296 //
297 // Read PnpID from the Model section.
298 //
299
300 hr = vboxNetCfgWinGetKeyValue( hInf,
301 lpszModelSection,
302 NULL,
303 2,
304 lppszPnpID );
305 //Assert(hr == S_OK);
306 if ( hr != S_OK )
307 {
308 DbgLog(L"vboxNetCfgWinGetPnpID: vboxNetCfgWinGetKeyValue lpszModelSection failed, hr = (0x%x), for file (%s)\n", hr, lpszInfFile);
309 }
310
311 CoTaskMemFree( lpszModelSection );
312 }
313 else
314 {
315 DbgLog(L"vboxNetCfgWinGetPnpID: vboxNetCfgWinGetKeyValue Manufacturer failed, hr = (0x%x), for file (%s)\n", hr, lpszInfFile);
316 }
317
318 SetupCloseInfFile( hInf );
319
320 return hr;
321}
322
323//VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUninstallInfs (LPCWSTR pPnPId)
324//{
325// std::list<std::wstring> InfList;
326// HRESULT hr = vboxNetCfgWinCollectInfs(pPnPId, &InfList);
327// if(hr == S_OK)
328// {
329// std::list <std::wstring>::iterator it;
330// for (it = InfList.begin(); it != InfList.end(); ++it)
331// {
332// Log(L"inf : %s\n", (*it).c_str());
333// }
334// }
335// return hr;
336//}
337
338static HRESULT vboxNetCfgWinEnumFiles(LPCWSTR pPattern, ENUMERATION_CALLBACK pCallback, PVOID pContext)
339{
340 WIN32_FIND_DATA Data;
341 memset(&Data, 0, sizeof(Data));
342 HRESULT hr = S_OK;
343
344 HANDLE hEnum = FindFirstFile(pPattern,&Data);
345 if(hEnum != INVALID_HANDLE_VALUE)
346 {
347
348 do
349 {
350 if(!pCallback(Data.cFileName, pContext))
351 {
352 break;
353 }
354
355 /* next iteration */
356 memset(&Data, 0, sizeof(Data));
357 BOOL bNext = FindNextFile(hEnum,&Data);
358 if(!bNext)
359 {
360 int winEr = GetLastError();
361 if(winEr != ERROR_NO_MORE_FILES)
362 {
363 Log(L"vboxNetCfgWinEnumFiles: FindNextFile err winEr (%d)\n", winEr);
364 Assert(0);
365 hr = HRESULT_FROM_WIN32(winEr);
366 }
367 break;
368 }
369 }while(true);
370 FindClose(hEnum);
371 }
372 else
373 {
374 int winEr = GetLastError();
375 if(winEr != ERROR_NO_MORE_FILES)
376 {
377 Log(L"vboxNetCfgWinEnumFiles: FindFirstFile err winEr (%d)\n", winEr);
378 Assert(0);
379 hr = HRESULT_FROM_WIN32(winEr);
380 }
381 }
382
383 return hr;
384}
385
386typedef struct _INF_INFO
387{
388 LPCWSTR pPnPId;
389}INF_INFO, *PINF_INFO;
390
391typedef struct _INFENUM_CONTEXT
392{
393 INF_INFO InfInfo;
394 DWORD Flags;
395 HRESULT hr;
396} INFENUM_CONTEXT, *PINFENUM_CONTEXT;
397
398static bool vboxNetCfgWinInfEnumerationCallback(LPCWSTR pFileName, PINFENUM_CONTEXT pContext)
399{
400// Log(L"vboxNetCfgWinInfEnumerationCallback: pFileName (%s)\n", pFileName);
401
402 LPWSTR lpszPnpID;
403 HRESULT hr = vboxNetCfgWinGetPnpID (pFileName,
404 &lpszPnpID);
405// Assert(hr == S_OK);
406 if(hr == S_OK)
407 {
408 if(!wcsicmp(pContext->InfInfo.pPnPId, lpszPnpID))
409 {
410 if(!SetupUninstallOEMInfW(pFileName,
411 pContext->Flags, /*DWORD Flags could be SUOI_FORCEDELETE */
412 NULL /*__in PVOID Reserved == NULL */
413 ))
414 {
415 DWORD dwError = GetLastError();
416
417 Log(L"vboxNetCfgWinInfEnumerationCallback: SetupUninstallOEMInf failed for file (%s), r (%d)\n", pFileName, dwError);
418 Assert(0);
419 hr = HRESULT_FROM_WIN32( dwError );
420 }
421 }
422 CoTaskMemFree(lpszPnpID);
423 }
424 else
425 {
426 DbgLog(L"vboxNetCfgWinInfEnumerationCallback: vboxNetCfgWinGetPnpID failed, hr = (0x%x)\n", hr);
427 }
428
429 return true;
430}
431
432
433static HRESULT VBoxNetCfgWinUninstallInfs(LPCWSTR pPnPId, DWORD Flags)
434{
435 WCHAR InfDirPath[MAX_PATH];
436 HRESULT hr = SHGetFolderPathW(NULL, /* HWND hwndOwner*/
437 CSIDL_WINDOWS, /* int nFolder*/
438 NULL, /*HANDLE hToken*/
439 SHGFP_TYPE_CURRENT, /*DWORD dwFlags*/
440 InfDirPath);
441 Assert(hr == S_OK);
442 if(hr == S_OK)
443 {
444 wcscat(InfDirPath, L"\\inf\\oem*.inf");
445
446 INFENUM_CONTEXT Context;
447 Context.InfInfo.pPnPId = pPnPId;
448 Context.Flags = Flags;
449 Context.hr = S_OK;
450 hr = vboxNetCfgWinEnumFiles(InfDirPath, (ENUMERATION_CALLBACK)vboxNetCfgWinInfEnumerationCallback, (PVOID)&Context);
451 Assert(hr == S_OK);
452 if(hr == S_OK)
453 {
454 hr = Context.hr;
455 }
456 else
457 {
458 Log(L"VBoxNetCfgWinUninstallInfs: vboxNetCfgWinEnumFiles failed, hr = (0x%x)\n", hr);
459 }
460//
461// HANDLE hInfDir = CreateFileW(InfDirPath,
462// FILE_READ_DATA, /* DWORD dwDesiredAccess*/
463// FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, /* DWORD dwShareMode */
464// NULL, /* LPSECURITY_ATTRIBUTES lpSecurityAttributes */
465// OPEN_EXISTING, /* DWORD dwCreationDisposition */
466// 0, /* DWORD dwFlagsAndAttributes */
467// NULL);
468// if(hInfDir != INVALID_HANDLE_VALUE)
469// {
470//
471// CloseHandle(hInfDir);
472// }
473// else
474// {
475// int winEr = GetLastError();
476// hr = HRESULT_FROM_WIN32(winEr);
477// }
478 }
479 else
480 {
481 Log(L"VBoxNetCfgWinUninstallInfs: SHGetFolderPathW failed, hr = (0x%x)\n", hr);
482 }
483
484 return hr;
485
486}
487
488
489
490/**
491 * Release reference
492 *
493 * @param punk Pointer to the interface to release reference to.
494 */
495VBOXNETCFGWIN_DECL(VOID)
496VBoxNetCfgWinReleaseRef(IN IUnknown* punk)
497{
498 if(punk)
499 {
500 punk->Release();
501 }
502
503 return;
504}
505
506/**
507 * Get a reference to INetCfg.
508 *
509 * @return HRESULT S_OK on success, otherwise an error code
510 * @param fGetWriteLock If TRUE, Write lock requested
511 * @param lpszAppName Application name requesting the reference.
512 * @param ppnc pointer the Reference to INetCfg to be stored to
513 * @param lpszLockedBy pointer the Application name who holds the write lock to be stored to, optional
514 */
515VBOXNETCFGWIN_DECL(HRESULT)
516VBoxNetCfgWinQueryINetCfgEx(IN BOOL fGetWriteLock,
517 IN LPCWSTR lpszAppName,
518 IN DWORD cmsTimeout,
519 OUT INetCfg **ppnc,
520 OUT LPWSTR *lpszLockedBy)
521{
522 INetCfg *pnc = NULL;
523 INetCfgLock *pncLock = NULL;
524 HRESULT hr = S_OK;
525
526 /*
527 * Initialize the output parameters.
528 */
529 *ppnc = NULL;
530
531 if ( lpszLockedBy )
532 {
533 *lpszLockedBy = NULL;
534 }
535// COM should be initialized before using the NetConfig API
536// /*
537// * Initialize COM
538// */
539// hr = CoInitialize( NULL );
540
541 if ( hr == S_OK )
542 {
543
544 /*
545 * Create the object implementing INetCfg.
546 */
547 hr = CoCreateInstance( CLSID_CNetCfg,
548 NULL, CLSCTX_INPROC_SERVER,
549 IID_INetCfg,
550 (void**)&pnc );
551 Assert(hr == S_OK);
552 if ( hr == S_OK )
553 {
554
555 if ( fGetWriteLock )
556 {
557
558 /*
559 * Get the locking reference
560 */
561 hr = pnc->QueryInterface( IID_INetCfgLock,
562 (LPVOID *)&pncLock );
563 Assert(hr == S_OK);
564 if ( hr == S_OK )
565 {
566
567 /*
568 * Attempt to lock the INetCfg for read/write
569 */
570 hr = pncLock->AcquireWriteLock( cmsTimeout,
571 lpszAppName,
572 lpszLockedBy);
573 if (hr == S_FALSE )
574 {
575 Log(L"VBoxNetCfgWinQueryINetCfg: WriteLock busy\n");
576 hr = NETCFG_E_NO_WRITE_LOCK;
577 }
578 else if (hr != S_OK)
579 {
580 Log(L"VBoxNetCfgWinQueryINetCfg: AcquireWriteLock failed, hr (0x%x)\n", hr);
581 }
582 }
583 else
584 {
585 Log(L"VBoxNetCfgWinQueryINetCfg: QueryInterface for IID_INetCfgLock failed, hr (0x%x)\n", hr);
586 }
587 }
588
589 if ( hr == S_OK )
590 {
591
592 /*
593 * Initialize the INetCfg object.
594 */
595 hr = pnc->Initialize( NULL );
596 Assert(hr == S_OK);
597 if ( hr == S_OK )
598 {
599 *ppnc = pnc;
600 pnc->AddRef();
601 }
602 else
603 {
604 Log(L"VBoxNetCfgWinQueryINetCfg: Initialize failed, hr (0x%x)\n", hr);
605
606 /*
607 * Initialize failed, if obtained lock, release it
608 */
609 if ( pncLock )
610 {
611 pncLock->ReleaseWriteLock();
612 }
613 }
614 }
615
616 VBoxNetCfgWinReleaseRef( pncLock );
617 VBoxNetCfgWinReleaseRef( pnc );
618 }
619 else
620 {
621 Log(L"VBoxNetCfgWinQueryINetCfg: CoCreateInstance for CLSID_CNetCfg failed, hr (0x%x)\n", hr);
622 }
623
624// COM should be initialized before using the NetConfig API
625// /*
626// * In case of error, uninitialize COM.
627// */
628// if ( hr != S_OK )
629// {
630// CoUninitialize();
631// }
632 }
633
634 return hr;
635}
636
637/**
638 * Get a reference to INetCfg.
639 *
640 * @return HRESULT S_OK on success, otherwise an error code
641 * @param fGetWriteLock If TRUE, Write lock requested
642 * @param lpszAppName Application name requesting the reference.
643 * @param ppnc pointer the Reference to INetCfg to be stored to
644 * @param lpszLockedBy pointer the Application name who holds the write lock to be stored to, optional
645 */
646VBOXNETCFGWIN_DECL(HRESULT)
647VBoxNetCfgWinQueryINetCfg(IN BOOL fGetWriteLock,
648 IN LPCWSTR lpszAppName,
649 OUT INetCfg **ppnc,
650 OUT LPWSTR *lpszLockedBy)
651{
652 return VBoxNetCfgWinQueryINetCfgEx(fGetWriteLock,
653 lpszAppName,
654 VBOX_NETCFG_LOCK_TIME_OUT,
655 ppnc,
656 lpszLockedBy);
657}
658/**
659 * Release a reference to INetCfg.
660 *
661 * @param pnc Reference to INetCfg to release.
662 * @param fHasWriteLock If TRUE, reference was held with write lock.
663 * @return S_OK on success, otherwise an error code.
664 */
665VBOXNETCFGWIN_DECL(HRESULT)
666VBoxNetCfgWinReleaseINetCfg(IN INetCfg *pnc,
667 IN BOOL fHasWriteLock)
668{
669 INetCfgLock *pncLock = NULL;
670 HRESULT hr = S_OK;
671
672 /*
673 * Uninitialize INetCfg
674 */
675 hr = pnc->Uninitialize();
676 Assert(hr == S_OK);
677 /*
678 * If write lock is present, unlock it
679 */
680 if ( hr == S_OK && fHasWriteLock )
681 {
682
683 /*
684 * Get the locking reference
685 */
686 hr = pnc->QueryInterface( IID_INetCfgLock,
687 (LPVOID *)&pncLock);
688 Assert(hr == S_OK);
689 if ( hr == S_OK )
690 {
691 hr = pncLock->ReleaseWriteLock();
692 VBoxNetCfgWinReleaseRef( pncLock );
693 }
694 }
695 else if(hr != S_OK)
696 {
697 Log(L"VBoxNetCfgWinReleaseINetCfg: Uninitialize failed, hr (0x%x)\n", hr);
698 }
699
700 VBoxNetCfgWinReleaseRef( pnc );
701
702// COM should be initialized before using the NetConfig API
703// /*
704// * Uninitialize COM.
705// */
706// CoUninitialize();
707
708 return hr;
709}
710
711/**
712 * Get network component enumerator reference.
713 *
714 * @param pnc Reference to INetCfg.
715 * @param pguidClass Class GUID of the network component.
716 * @param ppencc address the Enumerator reference to be stored to.
717 * @return S_OK on success, otherwise an error code.
718 */
719VBOXNETCFGWIN_DECL(HRESULT)
720VBoxNetCfgWinGetComponentEnum(INetCfg *pnc,
721 IN const GUID *pguidClass,
722 OUT IEnumNetCfgComponent **ppencc)
723{
724 INetCfgClass *pncclass;
725 HRESULT hr;
726
727 *ppencc = NULL;
728
729 /*
730 * Get the class reference.
731 */
732 hr = pnc->QueryNetCfgClass( pguidClass,
733 IID_INetCfgClass,
734 (PVOID *)&pncclass );
735 Assert(hr == S_OK);
736 if ( hr == S_OK )
737 {
738
739 /*
740 * Get the enumerator reference.
741 */
742 hr = pncclass->EnumComponents( ppencc );
743
744 /*
745 * We don't need the class reference any more.
746 */
747 VBoxNetCfgWinReleaseRef( pncclass );
748 }
749 else
750 {
751 Log(L"VBoxNetCfgWinGetComponentEnum: QueryNetCfgClass for IID_INetCfgClass failed, hr (0x%x)\n", hr);
752 }
753
754 return hr;
755}
756
757/**
758 * Enumerates the first network component.
759 *
760 * @param pencc Component enumerator reference.
761 * @param ppncc address the Network component reference to be stored to
762 * @return S_OK on success, otherwise an error code.
763 */
764/**
765 * Enumerate the next network component.
766 * The function behaves just like VBoxNetCfgWinGetFirstComponent if
767 * it is called right after VBoxNetCfgWinGetComponentEnum.
768 *
769 * @param pencc Component enumerator reference.
770 * @param ppncc address the Network component reference to be stored to.
771 * @return S_OK on success, otherwise an error code.
772 */
773VBOXNETCFGWIN_DECL(HRESULT)
774VBoxNetCfgWinGetNextComponent(IN IEnumNetCfgComponent *pencc,
775 OUT INetCfgComponent **ppncc)
776{
777 HRESULT hr;
778 ULONG ulCount;
779
780 *ppncc = NULL;
781
782 hr = pencc->Next( 1,
783 ppncc,
784 &ulCount );
785 Assert(hr == S_OK || hr == S_FALSE);
786 if(hr != S_OK && hr != S_FALSE)
787 {
788 Log(L"VBoxNetCfgWinGetNextComponent: Next failed, hr (0x%x)\n", hr);
789 }
790 return hr;
791}
792
793/**
794 * Install a network component(protocols, clients and services)
795 * given its INF file.
796 * @param pnc Reference to INetCfg.
797 * @param lpszComponentId PnpID of the network component.
798 * @param pguidClass Class GUID of the network component.
799 * @return S_OK on success, otherwise an error code.
800 */
801VBOXNETCFGWIN_DECL(HRESULT)
802VBoxNetCfgWinInstallComponent(IN INetCfg *pnc,
803 IN LPCWSTR szComponentId,
804 IN const GUID *pguidClass)
805{
806 INetCfgClassSetup *pncClassSetup = NULL;
807 INetCfgComponent *pncc = NULL;
808 OBO_TOKEN OboToken;
809 HRESULT hr = S_OK;
810
811 /*
812 * OBO_TOKEN specifies on whose behalf this
813 * component is being installed.
814 * Set it to OBO_USER so that szComponentId will be installed
815 * on behalf of the user.
816 */
817
818 ZeroMemory( &OboToken,
819 sizeof(OboToken) );
820 OboToken.Type = OBO_USER;
821
822 /*
823 * Get component's setup class reference.
824 */
825 hr = pnc->QueryNetCfgClass ( pguidClass,
826 IID_INetCfgClassSetup,
827 (void**)&pncClassSetup );
828 Assert(hr == S_OK);
829 if ( hr == S_OK )
830 {
831
832 hr = pncClassSetup->Install( szComponentId,
833 &OboToken,
834 0,
835 0, /* Upgrade from build number. */
836 NULL, /* Answerfile name */
837 NULL, /* Answerfile section name */
838 &pncc ); /* Reference after the component */
839 /* is installed. */
840 Assert(hr == S_OK);
841 if ( S_OK == hr )
842 {
843
844 /*
845 * we don't need to use pncc (INetCfgComponent), release it
846 */
847 VBoxNetCfgWinReleaseRef( pncc );
848 }
849 else
850 {
851 Log(L"VBoxNetCfgWinInstallComponent: Install failed, hr (0x%x)\n", hr);
852 }
853
854 VBoxNetCfgWinReleaseRef( pncClassSetup );
855 }
856 else
857 {
858 Log(L"VBoxNetCfgWinInstallComponent: QueryNetCfgClass for IID_INetCfgClassSetup failed, hr (0x%x)\n", hr);
859 }
860
861 return hr;
862}
863
864static HRESULT vboxNetCfgWinRemoveInf(IN LPCWSTR pInfFullPath, DWORD Flags)
865{
866 DWORD dwError;
867 HRESULT hr = S_OK;
868 WCHAR Drive[_MAX_DRIVE];
869 WCHAR Dir[_MAX_DIR];
870 WCHAR DirWithDrive[_MAX_DRIVE+_MAX_DIR];
871 WCHAR OemInfFullPath[MAX_PATH];
872 PWCHAR pOemInfName;
873
874 /*
875 * Get the path where the INF file is.
876 */
877 _wsplitpath( pInfFullPath, Drive, Dir, NULL, NULL );
878
879 wcscpy( DirWithDrive, Drive );
880 wcscat( DirWithDrive, Dir );
881
882 /*
883 * get the oem file name.
884 */
885 if (SetupCopyOEMInfW( pInfFullPath,
886 DirWithDrive, /* Other files are in the */
887 /* same dir. as primary INF */
888 SPOST_PATH, /* First param is path to INF */
889 SP_COPY_REPLACEONLY, /* we want to get the inf file name */
890 OemInfFullPath, /* Name of the INF after */
891 /* it's copied to %windir%\inf */
892 sizeof(OemInfFullPath) / sizeof(OemInfFullPath[0]), /* Max buf. size for the above */
893 NULL, /* Required size if non-null */
894 &pOemInfName ) ) /* Optionally get the filename */
895 {
896 Log(L"vboxNetCfgWinRemoveInf: found inf file (%s) for (%s)\n", OemInfFullPath, pInfFullPath);
897
898 if(!SetupUninstallOEMInfW(pOemInfName,
899 Flags, /*DWORD Flags could be SUOI_FORCEDELETE */
900 NULL /*__in PVOID Reserved == NULL */
901 ))
902 {
903 dwError = GetLastError();
904
905 Log(L"vboxNetCfgWinRemoveInf: SetupUninstallOEMInf failed for file (%s), r (%d)\n", pInfFullPath, dwError);
906 Log(L"vboxNetCfgWinRemoveInf: DirWithDrive (%s)\n", DirWithDrive);
907
908 Assert(0);
909 hr = HRESULT_FROM_WIN32( dwError );
910 }
911 }
912 else
913 {
914 dwError = GetLastError();
915
916 Log(L"vboxNetCfgWinRemoveInf: SetupCopyOEMInfW failed for file (%s), r (%d)\n", pInfFullPath, dwError);
917 Log(L"vboxNetCfgWinRemoveInf: DirWithDrive (%s)\n", DirWithDrive);
918
919
920 Assert(0);
921 hr = HRESULT_FROM_WIN32( dwError );
922 }
923 return hr;
924}
925
926static HRESULT vboxNetCfgWinCopyInf(IN LPCWSTR pInfFullPath)
927{
928 DWORD dwError;
929 HRESULT hr = S_OK;
930 WCHAR Drive[_MAX_DRIVE];
931 WCHAR Dir[_MAX_DIR];
932 WCHAR DirWithDrive[_MAX_DRIVE+_MAX_DIR];
933 WCHAR DirDestInf[_MAX_PATH] = { 0 };
934
935 /*
936 * Get the path where the INF file is.
937 */
938 _wsplitpath( pInfFullPath, Drive, Dir, NULL, NULL );
939
940 wcscpy( DirWithDrive, Drive );
941 wcscat( DirWithDrive, Dir );
942
943 /*
944 * Copy the INF file and other files referenced in the INF file.
945 */
946 if ( !SetupCopyOEMInfW( pInfFullPath,
947 DirWithDrive, /* Other files are in the */
948 /* same dir. as primary INF */
949 SPOST_PATH, /* First param is path to INF */
950 0, /* Default copy style */
951 DirDestInf, /* Name of the INF after */
952 /* it's copied to %windir%\inf */
953 sizeof(DirDestInf), /* Max buf. size for the above */
954 NULL, /* Required size if non-null */
955 NULL ) ) /* Optionally get the filename */
956 {
957 dwError = GetLastError();
958
959 Log(L"vboxNetCfgWinCopyInf: SetupCopyOEMInfW failed for file (%s), r (%d)\n", pInfFullPath, dwError);
960 Log(L"vboxNetCfgWinCopyInf: DirWithDrive (%s), DirDestInf(%s)\n", DirWithDrive, DirDestInf);
961
962 Assert(0);
963
964 hr = HRESULT_FROM_WIN32( dwError );
965 }
966
967 return hr;
968}
969
970/**
971 * Install a network component(protocols, clients and services)
972 * given its INF file.
973 *
974 * @param pnc Reference to INetCfg.
975 * @param lpszComponentId PnpID of the network component.
976 * @param pguidClass Class GUID of the network component.
977 * @param lpszInfFullPath INF file to install from.
978 * @return S_OK on success, otherwise an error code.
979 */
980VBOXNETCFGWIN_DECL(HRESULT)
981VBoxNetCfgWinInstallNetComponent(IN INetCfg *pnc,
982 IN LPCWSTR lpszComponentId,
983 IN const GUID *pguidClass,
984 IN LPCWSTR * apInfFullPaths,
985 IN UINT cInfFullPaths)
986{
987 HRESULT hr = S_OK;
988
989 /*
990 * If full path to INF has been specified, the INF
991 * needs to be copied using Setup API to ensure that any other files
992 * that the primary INF copies will be correctly found by Setup API
993 */
994 for(UINT i = 0; i < cInfFullPaths; i++)
995 {
996 hr = vboxNetCfgWinCopyInf(apInfFullPaths[i]);
997 Assert(hr == S_OK);
998 if(hr != S_OK)
999 {
1000 Log(L"VBoxNetCfgWinInstallNetComponent: vboxNetCfgWinCopyInf failed, hr (0x%x)\n", hr);
1001 if(i != 0)
1002 {
1003 /* remove infs already installed */
1004 for(UINT j = i-1; j != 0; j--)
1005 {
1006 vboxNetCfgWinRemoveInf(apInfFullPaths[j], 0);
1007 }
1008 }
1009
1010 break;
1011 }
1012 }
1013
1014 if (S_OK == hr)
1015 {
1016 /*
1017 * Install the network component.
1018 */
1019 hr = VBoxNetCfgWinInstallComponent( pnc,
1020 lpszComponentId,
1021 pguidClass );
1022 Assert(hr == S_OK);
1023 if ( hr == S_OK )
1024 {
1025 /*
1026 * On success, apply the changes
1027 */
1028 HRESULT tmpHr = pnc->Apply();
1029 Assert(tmpHr == S_OK);
1030 if(tmpHr != S_OK)
1031 {
1032 Log(L"VBoxNetCfgWinInstallNetComponent: Apply failed, hr (0x%x)\n", tmpHr);
1033 }
1034 }
1035 else
1036 {
1037 Log(L"VBoxNetCfgWinInstallNetComponent: VBoxNetCfgWinInstallComponent failed, hr (0x%x)\n", hr);
1038 }
1039 }
1040
1041 return hr;
1042}
1043
1044/**
1045 * Uninstall a network component.
1046 *
1047 * @param pnc Reference to INetCfg.
1048 * @param lpszInfId PnpID of the network component to uninstall
1049 * @param apInfFiles array of null-terminated strings containing the inf file names describing drivers to be removed from the system
1050 * @param cInfFiles the size of apInfFiles array
1051 * @return S_OK on success, otherwise an error code.
1052 */
1053VBOXNETCFGWIN_DECL(HRESULT)
1054VBoxNetCfgWinUninstallComponent(IN INetCfg *pnc,
1055 IN INetCfgComponent *pncc)
1056{
1057 INetCfgClass *pncClass;
1058 INetCfgClassSetup *pncClassSetup;
1059 GUID guidClass;
1060 OBO_TOKEN obo;
1061 HRESULT hr;
1062
1063 /*
1064 * Get the class GUID.
1065 */
1066 hr = pncc->GetClassGuid( &guidClass );
1067 Assert(hr == S_OK);
1068 if ( hr == S_OK )
1069 {
1070
1071 /*
1072 * Get a reference to component's class.
1073 */
1074 hr = pnc->QueryNetCfgClass( &guidClass,
1075 IID_INetCfgClass,
1076 (PVOID *)&pncClass );
1077 Assert(hr == S_OK);
1078 if ( hr == S_OK )
1079 {
1080
1081 /*
1082 * Get the setup interface.
1083 */
1084 hr = pncClass->QueryInterface( IID_INetCfgClassSetup,
1085 (LPVOID *)&pncClassSetup );
1086 Assert(hr == S_OK);
1087 if ( hr == S_OK )
1088 {
1089
1090 /*
1091 * Uninstall the component.
1092 */
1093 ZeroMemory( &obo,
1094 sizeof(OBO_TOKEN) );
1095
1096 obo.Type = OBO_USER;
1097
1098 hr = pncClassSetup->DeInstall( pncc,
1099 &obo,
1100 NULL );
1101 Assert(hr == S_OK);
1102 if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) )
1103 {
1104 HRESULT tmpHr = pnc->Apply();
1105 /* we ignore apply failures since they might occur on misconfigured systems*/
1106 Assert(tmpHr == S_OK);
1107 if ( (tmpHr != S_OK) )
1108 {
1109 Log(L"VBoxNetCfgWinUninstallComponent: Apply failed, hr (0x%x), ignoring\n", tmpHr);
1110 }
1111 }
1112 else
1113 {
1114 Log(L"VBoxNetCfgWinUninstallComponent: DeInstall failed, hr (0x%x)\n", hr);
1115 }
1116
1117 VBoxNetCfgWinReleaseRef( pncClassSetup );
1118 }
1119 else
1120 {
1121 Log(L"VBoxNetCfgWinUninstallComponent: QueryInterface for IID_INetCfgClassSetup failed, hr (0x%x)\n", hr);
1122 }
1123
1124 VBoxNetCfgWinReleaseRef( pncClass );
1125 }
1126 else
1127 {
1128 Log(L"VBoxNetCfgWinUninstallComponent: QueryNetCfgClass failed, hr (0x%x)\n", hr);
1129 }
1130 }
1131 else
1132 {
1133 Log(L"VBoxNetCfgWinUninstallComponent: GetClassGuid failed, hr (0x%x)\n", hr);
1134 }
1135
1136 return hr;
1137}
1138
1139#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
1140#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
1141
1142static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
1143{
1144 INetCfgComponent * pNcc = NULL;
1145 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
1146 if(hr == S_OK)
1147 {
1148 Log(L"NetFlt Is Installed currently\n");
1149
1150 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
1151
1152 VBoxNetCfgWinReleaseRef(pNcc);
1153 }
1154 else if(hr == S_FALSE)
1155 {
1156 Log(L"NetFlt Is Not Installed currently\n");
1157 hr = S_OK;
1158 }
1159 else
1160 {
1161 Log(L"vboxNetCfgWinNetFltUninstall: FindComponent for NetFlt failed, hr (0x%x)\n", hr);
1162 hr = S_OK;
1163 }
1164
1165 VBoxNetCfgWinUninstallInfs(VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
1166 VBoxNetCfgWinUninstallInfs(VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
1167
1168 return hr;
1169}
1170
1171VBOXNETCFGWIN_DECL(HRESULT)
1172VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
1173{
1174 return vboxNetCfgWinNetFltUninstall(pNc, 0);
1175}
1176
1177VBOXNETCFGWIN_DECL(HRESULT)
1178VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc, IN LPCWSTR * apInfFullPaths, IN UINT cInfFullPaths)
1179{
1180 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
1181
1182 hr = VBoxNetCfgWinInstallNetComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
1183 &GUID_DEVCLASS_NETSERVICE,
1184 apInfFullPaths,
1185 cInfFullPaths);
1186
1187 return hr;
1188}
1189
1190
1191/**
1192 * Get network component's binding path enumerator reference.
1193 *
1194 * @param pncc Network component reference.
1195 * @param dwBindingType EBP_ABOVE or EBP_BELOW.
1196 * @param ppencbp address the Enumerator reference to be stored to
1197 * @return S_OK on success, otherwise an error code.
1198 */
1199VBOXNETCFGWIN_DECL(HRESULT)
1200VBoxNetCfgWinGetBindingPathEnum(IN INetCfgComponent *pncc,
1201 IN DWORD dwBindingType,
1202 OUT IEnumNetCfgBindingPath **ppencbp)
1203{
1204 INetCfgComponentBindings *pnccb = NULL;
1205 HRESULT hr;
1206
1207 *ppencbp = NULL;
1208
1209 /* Get component's binding. */
1210 hr = pncc->QueryInterface( IID_INetCfgComponentBindings,
1211 (PVOID *)&pnccb );
1212 Assert(hr == S_OK);
1213 if ( hr == S_OK )
1214 {
1215
1216 /* Get binding path enumerator reference. */
1217 hr = pnccb->EnumBindingPaths( dwBindingType,
1218 ppencbp );
1219 if(hr != S_OK)
1220 {
1221 Log(L"VBoxNetCfgWinGetBindingPathEnum: EnumBindingPaths failed, hr (0x%x)\n", hr);
1222 }
1223
1224 VBoxNetCfgWinReleaseRef( pnccb );
1225 }
1226 else
1227 {
1228 Log(L"VBoxNetCfgWinGetBindingPathEnum: QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr);
1229 }
1230
1231 return hr;
1232}
1233
1234/**
1235 * Enumerates the first binding path.
1236 *
1237 * @param pencc Binding path enumerator reference.
1238 * @param ppncc address the Binding path reference to be stored to
1239 * @return S_OK on success, otherwise an error code.
1240 */
1241VBOXNETCFGWIN_DECL(HRESULT)
1242VBoxNetCfgWinGetFirstComponent(IN IEnumNetCfgComponent *pencc,
1243 OUT INetCfgComponent **ppncc)
1244{
1245 HRESULT hr;
1246 ULONG ulCount;
1247
1248 *ppncc = NULL;
1249
1250 pencc->Reset();
1251
1252 hr = pencc->Next( 1,
1253 ppncc,
1254 &ulCount );
1255 Assert(hr == S_OK || hr == S_FALSE);
1256 if(hr != S_OK && hr != S_FALSE)
1257 {
1258 Log(L"VBoxNetCfgWinGetFirstComponent: Next failed, hr (0x%x)\n", hr);
1259 }
1260 return hr;
1261}
1262
1263VBOXNETCFGWIN_DECL(HRESULT)
1264VBoxNetCfgWinGetFirstBindingPath(IN IEnumNetCfgBindingPath *pencbp,
1265 OUT INetCfgBindingPath **ppncbp)
1266{
1267 ULONG ulCount;
1268 HRESULT hr;
1269
1270 *ppncbp = NULL;
1271
1272 pencbp->Reset();
1273
1274 hr = pencbp->Next( 1,
1275 ppncbp,
1276 &ulCount );
1277 Assert(hr == S_OK || hr == S_FALSE);
1278 if(hr != S_OK && hr != S_FALSE)
1279 {
1280 Log(L"VBoxNetCfgWinGetFirstBindingPath: Next failed, hr (0x%x)\n", hr);
1281 }
1282
1283 return hr;
1284}
1285
1286/**
1287 * Get binding interface enumerator reference.
1288 *
1289 * @param pncbp Binding path reference.
1290 * @param ppencbp address the Enumerator reference to be stored to
1291 * @return S_OK on success, otherwise an error code
1292 */
1293VBOXNETCFGWIN_DECL(HRESULT)
1294VBoxNetCfgWinGetBindingInterfaceEnum(IN INetCfgBindingPath *pncbp,
1295 OUT IEnumNetCfgBindingInterface **ppencbi)
1296{
1297 HRESULT hr;
1298
1299 *ppencbi = NULL;
1300
1301 hr = pncbp->EnumBindingInterfaces( ppencbi );
1302 Assert(hr == S_OK);
1303 if(hr != S_OK)
1304 {
1305 Log(L"VBoxNetCfgWinGetBindingInterfaceEnum: EnumBindingInterfaces failed, hr (0x%x)\n", hr);
1306 }
1307
1308 return hr;
1309}
1310
1311/**
1312 * Enumerates the first binding interface.
1313 *
1314 * @param pencbi Binding interface enumerator reference.
1315 * @param ppncbi address the Binding interface reference to be stored to
1316 * @return S_OK on success, otherwise an error code
1317 */
1318VBOXNETCFGWIN_DECL(HRESULT)
1319VBoxNetCfgWinGetFirstBindingInterface(IN IEnumNetCfgBindingInterface *pencbi,
1320 OUT INetCfgBindingInterface **ppncbi)
1321{
1322 ULONG ulCount;
1323 HRESULT hr;
1324
1325 *ppncbi = NULL;
1326
1327 pencbi->Reset();
1328
1329 hr = pencbi->Next( 1,
1330 ppncbi,
1331 &ulCount );
1332 Assert(hr == S_OK || hr == S_FALSE);
1333 if(hr != S_OK && hr != S_FALSE)
1334 {
1335 Log(L"VBoxNetCfgWinGetFirstBindingInterface: Next failed, hr (0x%x)\n", hr);
1336 }
1337
1338 return hr;
1339}
1340
1341/*@
1342 * Enumerate the next binding interface.
1343 * The function behaves just like VBoxNetCfgWinGetFirstBindingInterface if
1344 * it is called right after VBoxNetCfgWinGetBindingInterfaceEnum.
1345 *
1346 * @param pencbi Binding interface enumerator reference.
1347 * @param ppncbi address the Binding interface reference t be stored to
1348 * @return S_OK on success, otherwise an error code
1349 */
1350VBOXNETCFGWIN_DECL(HRESULT)
1351VBoxNetCfgWinGetNextBindingInterface(IN IEnumNetCfgBindingInterface *pencbi,
1352 OUT INetCfgBindingInterface **ppncbi)
1353{
1354 ULONG ulCount;
1355 HRESULT hr;
1356
1357 *ppncbi = NULL;
1358
1359 hr = pencbi->Next( 1,
1360 ppncbi,
1361 &ulCount );
1362 Assert(hr == S_OK || hr == S_FALSE);
1363 if(hr != S_OK && hr != S_FALSE)
1364 {
1365 Log(L"VBoxNetCfgWinGetNextBindingInterface: Next failed, hr (0x%x)\n", hr);
1366 }
1367
1368 return hr;
1369}
1370
1371/**
1372 * Enumerate the next binding path.
1373 * The function behaves just like VBoxNetCfgWinGetFirstBindingPath if
1374 * it is called right after VBoxNetCfgWinGetBindingPathEnum.
1375 *
1376 * @param pencbp Binding path enumerator reference.
1377 * @param ppncbp Address the Binding path reference to be stored to
1378 * @return S_OK on sucess, otherwise an error code.
1379 */
1380VBOXNETCFGWIN_DECL(HRESULT)
1381VBoxNetCfgWinGetNextBindingPath(IN IEnumNetCfgBindingPath *pencbp,
1382 OUT INetCfgBindingPath **ppncbp)
1383{
1384 ULONG ulCount;
1385 HRESULT hr;
1386
1387 *ppncbp = NULL;
1388
1389 hr = pencbp->Next( 1,
1390 ppncbp,
1391 &ulCount );
1392 Assert(hr == S_OK || hr == S_FALSE);
1393 if(hr != S_OK && hr != S_FALSE)
1394 {
1395 Log(L"VBoxNetCfgWinGetNextBindingPath: Next failed, hr (0x%x)\n", hr);
1396 }
1397
1398 return hr;
1399}
1400
1401/*
1402 * helper function to get the component by its guid given enum interface
1403 */
1404static HRESULT vboxNetCfgWinGetComponentByGuidEnum(IEnumNetCfgComponent *pEnumNcc, IN const GUID * pGuid, OUT INetCfgComponent ** ppNcc)
1405{
1406 INetCfgComponent * pNcc;
1407 GUID NccGuid;
1408 HRESULT hr;
1409
1410 hr = VBoxNetCfgWinGetFirstComponent( pEnumNcc, &pNcc );
1411 Assert(hr == S_OK || hr == S_FALSE);
1412 while(hr == S_OK)
1413 {
1414 ULONG uComponentStatus;
1415 hr = pNcc->GetDeviceStatus(&uComponentStatus);
1416 if(hr == S_OK)
1417 {
1418 if(uComponentStatus == 0)
1419 {
1420 hr = pNcc->GetInstanceGuid(&NccGuid);
1421 Assert(hr == S_OK);
1422 if(hr == S_OK)
1423 {
1424 if(NccGuid == *pGuid)
1425 {
1426 /* found the needed device */
1427 *ppNcc = pNcc;
1428 break;
1429 }
1430 }
1431 else
1432 {
1433 Log(L"vboxNetCfgWinGetComponentByGuidEnum: GetInstanceGuid failed, hr (0x%x)\n", hr);
1434 }
1435 }
1436 }
1437
1438 VBoxNetCfgWinReleaseRef(pNcc);
1439
1440 hr = VBoxNetCfgWinGetNextComponent( pEnumNcc, &pNcc );
1441 }
1442
1443 return hr;
1444}
1445
1446/**
1447 * get the component by its guid
1448 */
1449VBOXNETCFGWIN_DECL(HRESULT)
1450VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc,
1451 IN const GUID *pguidClass,
1452 IN const GUID * pComponentGuid,
1453 OUT INetCfgComponent **ppncc)
1454{
1455 IEnumNetCfgComponent *pEnumNcc;
1456 HRESULT hr = VBoxNetCfgWinGetComponentEnum( pNc, pguidClass, &pEnumNcc );
1457 Assert(hr == S_OK);
1458 if(hr == S_OK)
1459 {
1460 hr = vboxNetCfgWinGetComponentByGuidEnum(pEnumNcc, pComponentGuid, ppncc);
1461 Assert(hr == S_OK || hr == S_FALSE);
1462 if(hr == S_FALSE)
1463 {
1464 Log(L"VBoxNetCfgWinGetComponentByGuid: component not found \n");
1465 }
1466 else if(hr != S_OK)
1467 {
1468 Log(L"VBoxNetCfgWinGetComponentByGuid: vboxNetCfgWinGetComponentByGuidEnum failed, hr (0x%x)\n", hr);
1469 }
1470 VBoxNetCfgWinReleaseRef(pEnumNcc);
1471 }
1472 else
1473 {
1474 Log(L"VBoxNetCfgWinGetComponentByGuid: VBoxNetCfgWinGetComponentEnum failed, hr (0x%x)\n", hr);
1475 }
1476 return hr;
1477}
1478
1479typedef BOOL (*VBOXNETCFGWIN_NETCFGENUM_CALLBACK) (IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext);
1480
1481static HRESULT vboxNetCfgWinEnumNetCfgComponents(IN INetCfg *pNc,
1482 IN const GUID *pguidClass,
1483 VBOXNETCFGWIN_NETCFGENUM_CALLBACK callback,
1484 PVOID pContext)
1485{
1486 IEnumNetCfgComponent *pEnumComponent;
1487 HRESULT hr = pNc->EnumComponents(pguidClass, &pEnumComponent);
1488 bool bBreak = false;
1489 Assert(hr == S_OK);
1490 if(hr == S_OK)
1491 {
1492 INetCfgComponent *pNcc;
1493 hr = pEnumComponent->Reset();
1494 Assert(hr == S_OK);
1495 do
1496 {
1497 hr = VBoxNetCfgWinGetNextComponent(pEnumComponent, &pNcc);
1498 Assert(hr == S_OK || hr == S_FALSE);
1499 if(hr == S_OK)
1500 {
1501 /* this is E_NOTIMPL for all components other than NET */
1502// ULONG uComponentStatus;
1503// hr = pNcc->GetDeviceStatus(&uComponentStatus);
1504// if(hr == S_OK)
1505 {
1506 if(!callback(pNc, pNcc, pContext))
1507 {
1508 bBreak = true;
1509 }
1510 }
1511 VBoxNetCfgWinReleaseRef(pNcc);
1512 }
1513 else
1514 {
1515 if(hr ==S_FALSE)
1516 {
1517 hr = S_OK;
1518 }
1519 else
1520 {
1521 Log(L"vboxNetCfgWinEnumNetCfgComponents: VBoxNetCfgWinGetNextComponent failed, hr (0x%x)\n", hr);
1522 }
1523 break;
1524 }
1525 } while(!bBreak);
1526
1527 VBoxNetCfgWinReleaseRef(pEnumComponent);
1528 }
1529 return hr;
1530}
1531
1532static VOID DoLogging(LPCWSTR szString, ...)
1533{
1534 LOG_ROUTINE pRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
1535 if(pRoutine)
1536 {
1537 WCHAR szBuffer[1024] = {0};
1538 va_list pArgList;
1539 va_start(pArgList, szString);
1540 _vsnwprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
1541 va_end(pArgList);
1542
1543 pRoutine(szBuffer);
1544 }
1545}
1546
1547VBOXNETCFGWIN_DECL(VOID) VBoxNetCfgWinSetLogging(LOG_ROUTINE Log)
1548{
1549 *((void * volatile *)&g_Logger) = Log;
1550}
1551
1552static BOOL vboxNetCfgWinRemoveAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
1553{
1554 DWORD winEr;
1555 HRESULT hr = S_OK;
1556 SP_REMOVEDEVICE_PARAMS rmdParams;
1557 SP_DEVINSTALL_PARAMS devParams;
1558 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
1559 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
1560 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
1561 rmdParams.HwProfile = 0;
1562 if(SetupDiSetClassInstallParams(hDevInfo,pDev,&rmdParams.ClassInstallHeader,sizeof(rmdParams)))
1563 {
1564 if(SetupDiCallClassInstaller(DIF_REMOVE,hDevInfo,pDev))
1565 {
1566 /*
1567 * see if device needs reboot
1568 */
1569 devParams.cbSize = sizeof(devParams);
1570 if(SetupDiGetDeviceInstallParams(hDevInfo,pDev,&devParams))
1571 {
1572 if(devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))
1573 {
1574 //
1575 // reboot required
1576 //
1577 hr = S_FALSE;
1578 }
1579 }
1580 else
1581 {
1582 //
1583 // appears to have succeeded
1584 //
1585 }
1586 }
1587 else
1588 {
1589 winEr = GetLastError();
1590 hr = HRESULT_FROM_WIN32(winEr);
1591 }
1592 }
1593 else
1594 {
1595 winEr = GetLastError();
1596 hr = HRESULT_FROM_WIN32(winEr);
1597 }
1598
1599 return TRUE;
1600}
1601
1602VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(LPWSTR pPnPId)
1603{
1604 return VBoxNetCfgWinEnumNetDevices(pPnPId, vboxNetCfgWinRemoveAllNetDevicesOfIdCallback, NULL);
1605}
1606
1607VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPWSTR pPnPId, VBOXNETCFGWIN_NETENUM_CALLBACK callback, PVOID pContext)
1608{
1609 DWORD winEr;
1610 HRESULT hr = S_OK;
1611
1612 HDEVINFO hDevInfo = SetupDiGetClassDevsExW(
1613 &GUID_DEVCLASS_NET,
1614 NULL, /* IN PCTSTR Enumerator, OPTIONAL*/
1615 NULL, /*IN HWND hwndParent, OPTIONAL*/
1616 DIGCF_PRESENT, /*IN DWORD Flags,*/
1617 NULL, /*IN HDEVINFO DeviceInfoSet, OPTIONAL*/
1618 NULL, /*IN PCTSTR MachineName, OPTIONAL*/
1619 NULL /*IN PVOID Reserved*/
1620 );
1621 if(hDevInfo != INVALID_HANDLE_VALUE)
1622 {
1623 DWORD iDev = 0;
1624 SP_DEVINFO_DATA Dev;
1625 PBYTE pBuffer = NULL;
1626 DWORD cbBuffer = 0;
1627 DWORD cbRequired = 0;
1628 BOOL bEnumCompleted;
1629 size_t cPnPId = wcslen(pPnPId);
1630
1631 Dev.cbSize = sizeof(Dev);
1632
1633 for(; bEnumCompleted = SetupDiEnumDeviceInfo(hDevInfo, iDev, &Dev); iDev++)
1634 {
1635 if(!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
1636 SPDRP_HARDWAREID, /* IN DWORD Property,*/
1637 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
1638 pBuffer, /*OUT PBYTE PropertyBuffer,*/
1639 cbBuffer, /* IN DWORD PropertyBufferSize,*/
1640 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
1641 ))
1642 {
1643 winEr = GetLastError();
1644 if(winEr != ERROR_INSUFFICIENT_BUFFER)
1645 {
1646 hr = HRESULT_FROM_WIN32(winEr);
1647 break;
1648 }
1649
1650 if(pBuffer)
1651 {
1652 free(pBuffer);
1653 }
1654
1655 pBuffer = (PBYTE)malloc(cbRequired);
1656 cbBuffer = cbRequired;
1657
1658 if(!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
1659 SPDRP_HARDWAREID, /* IN DWORD Property,*/
1660 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
1661 pBuffer, /*OUT PBYTE PropertyBuffer,*/
1662 cbBuffer, /* IN DWORD PropertyBufferSize,*/
1663 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
1664 ))
1665 {
1666 winEr = GetLastError();
1667 hr = HRESULT_FROM_WIN32(winEr);
1668 break;
1669 }
1670 }
1671
1672 PWCHAR pCurId = (PWCHAR)pBuffer;
1673 size_t cCurId = wcslen(pCurId);
1674 if(cCurId >= cPnPId)
1675 {
1676 pCurId += cCurId - cPnPId;
1677 if(!wcsnicmp(pCurId, pPnPId, cPnPId))
1678 {
1679 if(!callback(hDevInfo,&Dev,pContext))
1680 break;
1681 }
1682 }
1683
1684 }
1685
1686 if(pBuffer)
1687 free(pBuffer);
1688
1689 if(bEnumCompleted)
1690 {
1691 winEr = GetLastError();
1692 hr = winEr == ERROR_NO_MORE_ITEMS ? S_OK : HRESULT_FROM_WIN32(winEr);
1693 }
1694
1695 SetupDiDestroyDeviceInfoList(hDevInfo);
1696 }
1697 return hr;
1698}
1699
1700
1701
1702/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
1703/*
1704 Copyright 2004 by the Massachusetts Institute of Technology
1705
1706 All rights reserved.
1707
1708 Permission to use, copy, modify, and distribute this software and its
1709 documentation for any purpose and without fee is hereby granted,
1710 provided that the above copyright notice appear in all copies and that
1711 both that copyright notice and this permission notice appear in
1712 supporting documentation, and that the name of the Massachusetts
1713 Institute of Technology (M.I.T.) not be used in advertising or publicity
1714 pertaining to distribution of the software without specific, written
1715 prior permission.
1716
1717 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1718 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1719 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1720 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1721 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1722 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1723 SOFTWARE.
1724*/
1725
1726
1727#define NETSHELL_LIBRARY _T("netshell.dll")
1728
1729/**
1730 * Use the IShellFolder API to rename the connection.
1731 */
1732static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
1733{
1734 /* This is the GUID for the network connections folder. It is constant.
1735 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
1736 const GUID CLSID_NetworkConnections = {
1737 0x7007ACC7, 0x3202, 0x11D1, {
1738 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
1739 }
1740 };
1741
1742 LPITEMIDLIST pidl = NULL;
1743 IShellFolder *pShellFolder = NULL;
1744 HRESULT hr;
1745
1746 /* Build the display name in the form "::{GUID}". */
1747 if (wcslen (wGuid) >= MAX_PATH)
1748 return E_INVALIDARG;
1749 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
1750 swprintf (szAdapterGuid, L"::%ls", wGuid);
1751
1752 /* Create an instance of the network connections folder. */
1753 hr = CoCreateInstance (CLSID_NetworkConnections, NULL,
1754 CLSCTX_INPROC_SERVER, IID_IShellFolder,
1755 reinterpret_cast <LPVOID *> (&pShellFolder));
1756 /* Parse the display name. */
1757 if (SUCCEEDED (hr))
1758 {
1759 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
1760 &pidl, NULL);
1761 }
1762 if (SUCCEEDED (hr))
1763 {
1764 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
1765 &pidl);
1766 }
1767
1768 CoTaskMemFree (pidl);
1769
1770 if (pShellFolder)
1771 pShellFolder->Release();
1772
1773 return hr;
1774}
1775
1776VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
1777{
1778 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
1779 lpHrRenameConnection RenameConnectionFunc = NULL;
1780 HRESULT status;
1781// Guid guid(*pDevInstanceGuid);
1782// Bstr bstr(guid.toString());
1783// BSTR GuidString = bstr.mutableRaw();
1784// WCHAR GuidString[50];
1785//
1786// int length = StringFromGUID2(*pDevInstanceGuid, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
1787// if(!length)
1788// return E_FAIL;
1789
1790// strString[wcslen(strString) - 1] = L'\0';
1791//
1792// WCHAR * GuidString = strString + 1;
1793
1794 /* First try the IShellFolder interface, which was unimplemented
1795 * for the network connections folder before XP. */
1796 status = rename_shellfolder (pGuid, NewName);
1797 if (status == E_NOTIMPL)
1798 {
1799/** @todo that code doesn't seem to work! */
1800 /* The IShellFolder interface is not implemented on this platform.
1801 * Try the (undocumented) HrRenameConnection API in the netshell
1802 * library. */
1803 CLSID clsid;
1804 HINSTANCE hNetShell;
1805 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
1806 if (FAILED(status))
1807 return E_FAIL;
1808 hNetShell = LoadLibrary (NETSHELL_LIBRARY);
1809 if (hNetShell == NULL)
1810 return E_FAIL;
1811 RenameConnectionFunc =
1812 (lpHrRenameConnection) GetProcAddress (hNetShell,
1813 "HrRenameConnection");
1814 if (RenameConnectionFunc == NULL)
1815 {
1816 FreeLibrary (hNetShell);
1817 return E_FAIL;
1818 }
1819 status = RenameConnectionFunc (&clsid, NewName);
1820 FreeLibrary (hNetShell);
1821 }
1822 if (FAILED (status))
1823 return status;
1824
1825 return S_OK;
1826}
1827
1828#define DRIVERHWID _T("sun_VBoxNetAdp")
1829
1830#define SetErrBreak(strAndArgs) \
1831 if (1) { \
1832 hrc = E_FAIL; \
1833 Log strAndArgs; \
1834 Assert(0); \
1835 break; \
1836 } else do {} while (0)
1837
1838
1839VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface (const GUID *pGUID, BSTR *pErrMsg)
1840{
1841// LogFlowFuncEnter();
1842// LogFlowFunc (("Network connection GUID = {%RTuuid}\n", aGUID.raw()));
1843
1844// AssertReturn (aClient, VERR_INVALID_POINTER);
1845// AssertReturn (!aGUID.isEmpty(), VERR_INVALID_PARAMETER);
1846
1847 HRESULT hrc = S_OK;
1848
1849 do
1850 {
1851 TCHAR lszPnPInstanceId [512] = {0};
1852
1853 /* We have to find the device instance ID through a registry search */
1854
1855 HKEY hkeyNetwork = 0;
1856 HKEY hkeyConnection = 0;
1857
1858 do
1859 {
1860 WCHAR strRegLocation [256];
1861 WCHAR GuidString[50];
1862
1863 int length = StringFromGUID2(*pGUID, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
1864 if(!length)
1865 SetErrBreak((L"Failed to create a Guid string"));
1866
1867 swprintf (strRegLocation,
1868 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
1869 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
1870 GuidString);
1871
1872 LONG status;
1873 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
1874 KEY_READ, &hkeyNetwork);
1875 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
1876 SetErrBreak ((
1877 L"Host interface network is not found in registry (%s) [1]",
1878 strRegLocation));
1879
1880 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
1881 KEY_READ, &hkeyConnection);
1882 if ((status != ERROR_SUCCESS) || !hkeyConnection)
1883 SetErrBreak ((
1884 L"Host interface network is not found in registry (%s) [2]",
1885 strRegLocation));
1886
1887 DWORD len = sizeof (lszPnPInstanceId);
1888 DWORD dwKeyType;
1889 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
1890 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
1891 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
1892 SetErrBreak ((
1893 L"Host interface network is not found in registry (%s) [3]",
1894 strRegLocation));
1895 }
1896 while (0);
1897
1898 if (hkeyConnection)
1899 RegCloseKey (hkeyConnection);
1900 if (hkeyNetwork)
1901 RegCloseKey (hkeyNetwork);
1902
1903 if (FAILED (hrc))
1904 break;
1905
1906 /*
1907 * Now we are going to enumerate all network devices and
1908 * wait until we encounter the right device instance ID
1909 */
1910
1911 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1912
1913 do
1914 {
1915 BOOL ok;
1916 DWORD ret = 0;
1917 GUID netGuid;
1918 SP_DEVINFO_DATA DeviceInfoData;
1919 DWORD index = 0;
1920 BOOL found = FALSE;
1921 DWORD size = 0;
1922
1923 /* initialize the structure size */
1924 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
1925
1926 /* copy the net class GUID */
1927 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
1928
1929 /* return a device info set contains all installed devices of the Net class */
1930 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
1931
1932 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1933 SetErrBreak ((L"SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
1934
1935 /* enumerate the driver info list */
1936 while (TRUE)
1937 {
1938 TCHAR *deviceHwid;
1939
1940 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
1941
1942 if (!ok)
1943 {
1944 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1945 break;
1946 else
1947 {
1948 index++;
1949 continue;
1950 }
1951 }
1952
1953 /* try to get the hardware ID registry property */
1954 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1955 &DeviceInfoData,
1956 SPDRP_HARDWAREID,
1957 NULL,
1958 NULL,
1959 0,
1960 &size);
1961 if (!ok)
1962 {
1963 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1964 {
1965 index++;
1966 continue;
1967 }
1968
1969 deviceHwid = (TCHAR *) malloc (size);
1970 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1971 &DeviceInfoData,
1972 SPDRP_HARDWAREID,
1973 NULL,
1974 (PBYTE)deviceHwid,
1975 size,
1976 NULL);
1977 if (!ok)
1978 {
1979 free (deviceHwid);
1980 deviceHwid = NULL;
1981 index++;
1982 continue;
1983 }
1984 }
1985 else
1986 {
1987 /* something is wrong. This shouldn't have worked with a NULL buffer */
1988 index++;
1989 continue;
1990 }
1991
1992 for (TCHAR *t = deviceHwid;
1993 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
1994 t += _tcslen (t) + 1)
1995 {
1996 if (!_tcsicmp (DRIVERHWID, t))
1997 {
1998 /* get the device instance ID */
1999 TCHAR devID [MAX_DEVICE_ID_LEN];
2000 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2001 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2002 {
2003 /* compare to what we determined before */
2004 if (wcscmp(devID, lszPnPInstanceId) == 0)
2005 {
2006 found = TRUE;
2007 break;
2008 }
2009 }
2010 }
2011 }
2012
2013 if (deviceHwid)
2014 {
2015 free (deviceHwid);
2016 deviceHwid = NULL;
2017 }
2018
2019 if (found)
2020 break;
2021
2022 index++;
2023 }
2024
2025 if (found == FALSE)
2026 SetErrBreak ((L"Host Interface Network driver not found (0x%08X)",
2027 GetLastError()));
2028
2029 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2030 if (!ok)
2031 SetErrBreak ((L"SetupDiSetSelectedDevice failed (0x%08X)",
2032 GetLastError()));
2033
2034 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2035 if (!ok)
2036 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2037 GetLastError()));
2038 }
2039 while (0);
2040
2041 /* clean up the device info set */
2042 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2043 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2044
2045 if (FAILED (hrc))
2046 break;
2047 }
2048 while (0);
2049
2050// LogFlowFunc (("vrc=%Rrc\n", vrc));
2051// LogFlowFuncLeave();
2052 return hrc;
2053}
2054
2055static UINT WINAPI vboxNetCfgWinPspFileCallback(
2056 PVOID Context,
2057 UINT Notification,
2058 UINT_PTR Param1,
2059 UINT_PTR Param2
2060 )
2061{
2062 switch(Notification)
2063 {
2064 case SPFILENOTIFY_TARGETNEWER:
2065 case SPFILENOTIFY_TARGETEXISTS:
2066 return TRUE;
2067 }
2068 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2069}
2070
2071static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority (IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
2072{
2073 INetCfgComponentBindings *pNccb = NULL;
2074 IEnumNetCfgBindingPath *pEnumNccbp;
2075 GUID *pGuid = (GUID*)pContext;
2076 HRESULT hr;
2077 bool bFound = false;
2078
2079 /* Get component's binding. */
2080 hr = pNcc->QueryInterface( IID_INetCfgComponentBindings,
2081 (PVOID *)&pNccb );
2082 Assert(hr == S_OK);
2083 if ( hr == S_OK )
2084 {
2085 /* Get binding path enumerator reference. */
2086 hr = pNccb->EnumBindingPaths(EBP_BELOW, &pEnumNccbp);
2087 Assert(hr == S_OK);
2088 if(hr == S_OK)
2089 {
2090 INetCfgBindingPath *pNccbp;
2091 hr = pEnumNccbp->Reset();
2092 Assert(hr == S_OK);
2093 do
2094 {
2095 hr = VBoxNetCfgWinGetNextBindingPath(pEnumNccbp, &pNccbp);
2096 Assert(hr == S_OK || hr == S_FALSE);
2097 if(hr == S_OK)
2098 {
2099// if(pNccbp->IsEnabled() == S_OK)
2100 {
2101 IEnumNetCfgBindingInterface *pEnumNcbi;
2102 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pNccbp, &pEnumNcbi);
2103 Assert(hr == S_OK);
2104 if ( hr == S_OK )
2105 {
2106 INetCfgBindingInterface *pNcbi;
2107 hr = pEnumNcbi->Reset();
2108 Assert(hr == S_OK);
2109 do
2110 {
2111 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumNcbi, &pNcbi);
2112 Assert(hr == S_OK || hr == S_FALSE);
2113 if(hr == S_OK)
2114 {
2115 INetCfgComponent * pNccBoud;
2116 hr = pNcbi->GetLowerComponent(&pNccBoud);
2117 Assert(hr == S_OK);
2118 if(hr == S_OK)
2119 {
2120 ULONG uComponentStatus;
2121 hr = pNccBoud->GetDeviceStatus(&uComponentStatus);
2122 if(hr == S_OK)
2123 {
2124// if(uComponentStatus == 0)
2125 {
2126 GUID guid;
2127 hr = pNccBoud->GetInstanceGuid(&guid);
2128 if(guid == *pGuid)
2129 {
2130 hr = pNccb->MoveAfter(pNccbp, NULL);
2131 Assert(hr == S_OK);
2132 bFound = true;
2133 }
2134 }
2135 }
2136 VBoxNetCfgWinReleaseRef(pNccBoud);
2137 }
2138 VBoxNetCfgWinReleaseRef(pNcbi);
2139 }
2140 else
2141 {
2142 if(hr == S_FALSE)
2143 {
2144 hr = S_OK;
2145 }
2146 else
2147 {
2148 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingInterface failed, hr (0x%x)\n", hr);
2149 }
2150 break;
2151 }
2152 } while(!bFound);
2153 VBoxNetCfgWinReleaseRef(pEnumNcbi);
2154 }
2155 else
2156 {
2157 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetBindingInterfaceEnum failed, hr (0x%x)\n", hr);
2158 }
2159 }
2160
2161 VBoxNetCfgWinReleaseRef(pNccbp);
2162 }
2163 else
2164 {
2165 if(hr = S_FALSE)
2166 {
2167 hr = S_OK;
2168 }
2169 else
2170 {
2171 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingPath failed, hr (0x%x)\n", hr);
2172 }
2173 break;
2174 }
2175 } while(!bFound);
2176
2177 VBoxNetCfgWinReleaseRef(pEnumNccbp);
2178 }
2179 else
2180 {
2181 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: EnumBindingPaths failed, hr (0x%x)\n", hr);
2182 }
2183
2184 VBoxNetCfgWinReleaseRef( pNccb );
2185 }
2186 else
2187 {
2188 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr);
2189 }
2190
2191 return true;
2192}
2193
2194VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface (GUID *pGuid, BSTR *lppszName, BSTR *pErrMsg)
2195{
2196 HRESULT hrc = S_OK;
2197
2198 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2199 SP_DEVINFO_DATA DeviceInfoData;
2200 PVOID pQueueCallbackContext = NULL;
2201 DWORD ret = 0;
2202 BOOL found = FALSE;
2203 BOOL registered = FALSE;
2204 BOOL destroyList = FALSE;
2205 WCHAR pWCfgGuidString [50];
2206 WCHAR DevName[256];
2207
2208 do
2209 {
2210 BOOL ok;
2211 GUID netGuid;
2212 SP_DRVINFO_DATA DriverInfoData;
2213 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2214 TCHAR className [MAX_PATH];
2215 DWORD index = 0;
2216 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2217 /* for our purposes, 2k buffer is more
2218 * than enough to obtain the hardware ID
2219 * of the VBoxNetAdp driver. */
2220 DWORD detailBuf [2048];
2221
2222 HKEY hkey = NULL;
2223 DWORD cbSize;
2224 DWORD dwValueType;
2225
2226 /* initialize the structure size */
2227 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2228 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
2229
2230 /* copy the net class GUID */
2231 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2232
2233 /* create an empty device info set associated with the net class GUID */
2234 hDeviceInfo = SetupDiCreateDeviceInfoList (&netGuid, NULL);
2235 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2236 SetErrBreak ((L"SetupDiCreateDeviceInfoList failed (0x%08X)",
2237 GetLastError()));
2238
2239 /* get the class name from GUID */
2240 ok = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2241 if (!ok)
2242 SetErrBreak ((L"SetupDiClassNameFromGuid failed (0x%08X)",
2243 GetLastError()));
2244
2245 /* create a device info element and add the new device instance
2246 * key to registry */
2247 ok = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2248 DICD_GENERATE_ID, &DeviceInfoData);
2249 if (!ok)
2250 SetErrBreak ((L"SetupDiCreateDeviceInfo failed (0x%08X)",
2251 GetLastError()));
2252
2253 /* select the newly created device info to be the currently
2254 selected member */
2255 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2256 if (!ok)
2257 SetErrBreak ((L"SetupDiSetSelectedDevice failed (0x%08X)",
2258 GetLastError()));
2259
2260 /* build a list of class drivers */
2261 ok = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2262 SPDIT_CLASSDRIVER);
2263 if (!ok)
2264 SetErrBreak ((L"SetupDiBuildDriverInfoList failed (0x%08X)",
2265 GetLastError()));
2266
2267 destroyList = TRUE;
2268
2269 /* enumerate the driver info list */
2270 while (TRUE)
2271 {
2272 BOOL ret;
2273
2274 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2275 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2276
2277 /* if the function failed and GetLastError() returned
2278 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2279 * list. Othewise there was something wrong with this
2280 * particular driver. */
2281 if (!ret)
2282 {
2283 if(GetLastError() == ERROR_NO_MORE_ITEMS)
2284 break;
2285 else
2286 {
2287 index++;
2288 continue;
2289 }
2290 }
2291
2292 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2293 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2294
2295 /* if we successfully find the hardware ID and it turns out to
2296 * be the one for the loopback driver, then we are done. */
2297 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2298 &DeviceInfoData,
2299 &DriverInfoData,
2300 pDriverInfoDetail,
2301 sizeof (detailBuf),
2302 NULL))
2303 {
2304 TCHAR * t;
2305
2306 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2307 * whole list and see if there is a match somewhere. */
2308 t = pDriverInfoDetail->HardwareID;
2309 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2310 {
2311 if (!_tcsicmp(t, DRIVERHWID))
2312 break;
2313
2314 t += _tcslen(t) + 1;
2315 }
2316
2317 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2318 {
2319 found = TRUE;
2320 break;
2321 }
2322 }
2323
2324 index ++;
2325 }
2326
2327 if (!found)
2328 SetErrBreak ((L"Could not find Host Interface Networking driver! "
2329 L"Please reinstall"));
2330
2331 /* set the loopback driver to be the currently selected */
2332 ok = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2333 &DriverInfoData);
2334 if (!ok)
2335 SetErrBreak ((L"SetupDiSetSelectedDriver failed (0x%08X)",
2336 GetLastError()));
2337
2338 /* register the phantom device to prepare for install */
2339 ok = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2340 &DeviceInfoData);
2341 if (!ok)
2342 {
2343 DWORD err = GetLastError();
2344 SetErrBreak ((L"SetupDiCallClassInstaller failed (0x%08X)",
2345 err));
2346 }
2347
2348 /* registered, but remove if errors occur in the following code */
2349 registered = TRUE;
2350
2351 /* ask the installer if we can install the device */
2352 ok = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2353 &DeviceInfoData);
2354 if (!ok)
2355 {
2356 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2357 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2358 GetLastError()));
2359 /* that's fine */
2360 }
2361
2362 /* get the device install parameters and disable filecopy */
2363 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2364 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2365 &DeviceInstallParams);
2366 if (ok)
2367 {
2368 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2369 if(pQueueCallbackContext)
2370 {
2371 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2372 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2373 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2374 &DeviceInstallParams);
2375 if(!ok)
2376 {
2377 DWORD winEr = GetLastError();
2378 Assert(0);
2379 Log(L"SetupDiSetDeviceInstallParams: SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr);
2380 }
2381 Assert(ok);
2382 }
2383 else
2384 {
2385 DWORD winEr = GetLastError();
2386 Assert(0);
2387 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr);
2388 }
2389 }
2390 else
2391 {
2392 DWORD winEr = GetLastError();
2393 Assert(0);
2394 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr);
2395 }
2396
2397 /* install the files first */
2398 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2399 &DeviceInfoData);
2400 if (!ok)
2401 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2402 GetLastError()));
2403
2404 /* get the device install parameters and disable filecopy */
2405 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2406 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2407 &DeviceInstallParams);
2408 if (ok)
2409 {
2410 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2411 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2412 &DeviceInstallParams);
2413 if (!ok)
2414 SetErrBreak ((L"SetupDiSetDeviceInstallParams failed (0x%08X)",
2415 GetLastError()));
2416 }
2417
2418 /*
2419 * Register any device-specific co-installers for this device,
2420 */
2421
2422 ok = SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS,
2423 hDeviceInfo,
2424 &DeviceInfoData);
2425 if (!ok)
2426 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2427 GetLastError()));
2428
2429 /*
2430 * install any installer-specified interfaces.
2431 * and then do the real install
2432 */
2433 ok = SetupDiCallClassInstaller (DIF_INSTALLINTERFACES,
2434 hDeviceInfo,
2435 &DeviceInfoData);
2436 if (!ok)
2437 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2438 GetLastError()));
2439
2440 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICE,
2441 hDeviceInfo,
2442 &DeviceInfoData);
2443 if (!ok)
2444 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2445 GetLastError()));
2446
2447 /* Figure out NetCfgInstanceId */
2448 hkey = SetupDiOpenDevRegKey (hDeviceInfo,
2449 &DeviceInfoData,
2450 DICS_FLAG_GLOBAL,
2451 0,
2452 DIREG_DRV,
2453 KEY_READ);
2454 if (hkey == INVALID_HANDLE_VALUE)
2455 SetErrBreak ((L"SetupDiOpenDevRegKey failed (0x%08X)",
2456 GetLastError()));
2457
2458 cbSize = sizeof (pWCfgGuidString);
2459 DWORD ret;
2460 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2461 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2462
2463 RegCloseKey (hkey);
2464
2465 if(!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2466 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2467 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2468 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2469 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2470 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2471 ))
2472 {
2473 int err = GetLastError();
2474 if(err != ERROR_INVALID_DATA)
2475 {
2476 SetErrBreak ((L"SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2477 err));
2478 }
2479
2480 if(!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2481 SPDRP_DEVICEDESC , /* IN DWORD Property,*/
2482 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2483 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2484 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2485 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2486 ))
2487 {
2488 err = GetLastError();
2489 SetErrBreak ((L"SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2490 err));
2491 }
2492 }
2493 }
2494 while (0);
2495
2496 /*
2497 * cleanup
2498 */
2499 if(pQueueCallbackContext)
2500 {
2501 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2502 }
2503
2504 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2505 {
2506 /* an error has occurred, but the device is registered, we must remove it */
2507 if (ret != 0 && registered)
2508 SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2509
2510 found = SetupDiDeleteDeviceInfo (hDeviceInfo, &DeviceInfoData);
2511
2512 /* destroy the driver info list */
2513 if (destroyList)
2514 SetupDiDestroyDriverInfoList (hDeviceInfo, &DeviceInfoData,
2515 SPDIT_CLASSDRIVER);
2516 /* clean up the device info set */
2517 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2518 }
2519
2520 /* return the network connection GUID on success */
2521 if (SUCCEEDED(hrc))
2522 {
2523// Bstr str(DevName);
2524// str.detachTo(pName);
2525 WCHAR ConnectoinName[128];
2526 ULONG cbName = sizeof(ConnectoinName);
2527
2528 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName (DevName, ConnectoinName, &cbName);
2529 if(hr == S_OK)
2530 {
2531 hr = VBoxNetCfgWinRenameConnection (pWCfgGuidString, ConnectoinName);
2532 }
2533
2534 if(lppszName)
2535 {
2536 *lppszName = ::SysAllocString ((const OLECHAR *) DevName);
2537 if ( !*lppszName )
2538 {
2539 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SysAllocString failed\n");
2540 Assert(0);
2541 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2542 }
2543 }
2544
2545 if(pGuid)
2546 {
2547 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID) pGuid);
2548 if(hrc != S_OK)
2549 {
2550 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: CLSIDFromString failed, hrc (0x%x)\n", hrc);
2551 Assert(0);
2552 }
2553 }
2554
2555 INetCfg *pNc;
2556 LPWSTR lpszApp = NULL;
2557
2558
2559
2560 hr = VBoxNetCfgWinQueryINetCfgEx( TRUE,
2561 L"VirtualBox Host-Only Creation",
2562 30000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec, */
2563 &pNc, /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
2564 &lpszApp );
2565 Assert(hr == S_OK);
2566 if(hr == S_OK)
2567 {
2568 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2569 &GUID_DEVCLASS_NETSERVICE,
2570 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2571 pGuid);
2572 Assert(hr == S_OK);
2573
2574 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2575 &GUID_DEVCLASS_NETTRANS,
2576 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2577 pGuid);
2578 Assert(hr == S_OK);
2579
2580 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2581 &GUID_DEVCLASS_NETCLIENT,
2582 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2583 pGuid);
2584 Assert(hr == S_OK);
2585
2586 if(hr == S_OK)
2587 {
2588 hr = pNc->Apply();
2589 Assert(hr == S_OK);
2590 }
2591
2592 VBoxNetCfgWinReleaseINetCfg(pNc, TRUE);
2593 }
2594 else if(hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
2595 {
2596 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: app %s is holding the lock, failed\n", lpszApp);
2597 CoTaskMemFree(lpszApp);
2598 }
2599 else
2600 {
2601 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: VBoxNetCfgWinQueryINetCfgEx failed, hr 0x%x\n", hr);
2602 }
2603 }
2604
2605 return hrc;
2606}
2607
2608#undef SetErrBreak
2609
2610#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
2611VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName (PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
2612{
2613 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
2614 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
2615 ULONG cbSufSize = 0;
2616
2617 if(pSuffix)
2618 {
2619 cbSize += (ULONG)wcslen(pSuffix) * 2;
2620 cbSize += 2; /* for space */
2621 }
2622
2623 if(*pcbBuf < cbSize)
2624 {
2625 *pcbBuf = cbSize;
2626 return E_FAIL;
2627 }
2628
2629 wcscpy(pBuf, VBOX_CONNECTION_NAME);
2630 if(pSuffix)
2631 {
2632 wcscat(pBuf, L" ");
2633 wcscat(pBuf, pSuffix);
2634 }
2635
2636 return S_OK;
2637}
2638
2639/* network settings config */
2640/**
2641 * Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
2642 */
2643template <class C>
2644class ComStrongRef
2645{
2646protected:
2647
2648 static void addref (C *p) { p->AddRef(); }
2649 static void release (C *p) { p->Release(); }
2650};
2651
2652/**
2653 * Weak referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
2654 */
2655template <class C>
2656class ComWeakRef
2657{
2658protected:
2659
2660 static void addref (C * /* p */) {}
2661 static void release (C * /* p */) {}
2662};
2663
2664/**
2665 * Base template for smart COM pointers. Not intended to be used directly.
2666 */
2667template <class C, template <class> class RefOps = ComStrongRef>
2668class ComPtrBase : protected RefOps <C>
2669{
2670public:
2671
2672 /* special template to disable AddRef()/Release() */
2673 template <class I>
2674 class NoAddRefRelease : public I
2675 {
2676 private:
2677#if !defined (VBOX_WITH_XPCOM)
2678 STDMETHOD_(ULONG, AddRef)() = 0;
2679 STDMETHOD_(ULONG, Release)() = 0;
2680#else /* !defined (VBOX_WITH_XPCOM) */
2681 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
2682 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
2683#endif /* !defined (VBOX_WITH_XPCOM) */
2684 };
2685
2686protected:
2687
2688 ComPtrBase () : p (NULL) {}
2689 ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
2690 ComPtrBase (C *that_p) : p (that_p) { addref(); }
2691
2692 ~ComPtrBase() { release(); }
2693
2694 ComPtrBase &operator= (const ComPtrBase &that)
2695 {
2696 safe_assign (that.p);
2697 return *this;
2698 }
2699
2700 ComPtrBase &operator= (C *that_p)
2701 {
2702 safe_assign (that_p);
2703 return *this;
2704 }
2705
2706public:
2707
2708 void setNull()
2709 {
2710 release();
2711 p = NULL;
2712 }
2713
2714 bool isNull() const
2715 {
2716 return (p == NULL);
2717 }
2718
2719 bool operator! () const { return isNull(); }
2720
2721 bool operator< (C* that_p) const { return p < that_p; }
2722 bool operator== (C* that_p) const { return p == that_p; }
2723
2724 template <class I>
2725 bool equalsTo (I *aThat) const
2726 {
2727 return ComPtrEquals (p, aThat);
2728 }
2729
2730 template <class OC>
2731 bool equalsTo (const ComPtrBase <OC> &oc) const
2732 {
2733 return equalsTo ((OC *) oc);
2734 }
2735
2736 /** Intended to pass instances as in parameters to interface methods */
2737 operator C* () const { return p; }
2738
2739 /**
2740 * Dereferences the instance (redirects the -> operator to the managed
2741 * pointer).
2742 */
2743 NoAddRefRelease <C> *operator-> () const
2744 {
2745 AssertMsg (p, ("Managed pointer must not be null\n"));
2746 return (NoAddRefRelease <C> *) p;
2747 }
2748
2749 template <class I>
2750 HRESULT queryInterfaceTo (I **pp) const
2751 {
2752 if (pp)
2753 {
2754 if (p)
2755 {
2756 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
2757 }
2758 else
2759 {
2760 *pp = NULL;
2761 return S_OK;
2762 }
2763 }
2764
2765 return E_INVALIDARG;
2766 }
2767
2768 /** Intended to pass instances as out parameters to interface methods */
2769 C **asOutParam()
2770 {
2771 setNull();
2772 return &p;
2773 }
2774
2775private:
2776
2777 void addref()
2778 {
2779 if (p)
2780 RefOps <C>::addref (p);
2781 }
2782
2783 void release()
2784 {
2785 if (p)
2786 RefOps <C>::release (p);
2787 }
2788
2789 void safe_assign (C *that_p)
2790 {
2791 /* be aware of self-assignment */
2792 if (that_p)
2793 RefOps <C>::addref (that_p);
2794 release();
2795 p = that_p;
2796 }
2797
2798 C *p;
2799};
2800
2801/**
2802 * Smart COM pointer wrapper that automatically manages refcounting of
2803 * interface pointers.
2804 *
2805 * @param I COM interface class
2806 */
2807template <class I, template <class> class RefOps = ComStrongRef>
2808class ComPtr : public ComPtrBase <I, RefOps>
2809{
2810 typedef ComPtrBase <I, RefOps> Base;
2811
2812public:
2813
2814 ComPtr () : Base() {}
2815 ComPtr (const ComPtr &that) : Base (that) {}
2816 ComPtr &operator= (const ComPtr &that)
2817 {
2818 Base::operator= (that);
2819 return *this;
2820 }
2821
2822 template <class OI>
2823 ComPtr (OI *that_p) : Base () { operator= (that_p); }
2824
2825 /* specialization for I */
2826 ComPtr (I *that_p) : Base (that_p) {}
2827
2828 template <class OC>
2829 ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
2830
2831 template <class OI>
2832 ComPtr &operator= (OI *that_p)
2833 {
2834 if (that_p)
2835 that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
2836 else
2837 Base::setNull();
2838 return *this;
2839 }
2840
2841 /* specialization for I */
2842 ComPtr &operator=(I *that_p)
2843 {
2844 Base::operator= (that_p);
2845 return *this;
2846 }
2847
2848 template <class OC>
2849 ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
2850 {
2851 return operator= ((OC *) oc);
2852 }
2853};
2854
2855static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const GUID * pGuid, IWbemClassObject **pAdapterConfig)
2856{
2857 HRESULT hres;
2858 WCHAR aQueryString[256];
2859 WCHAR GuidString[50];
2860
2861 int length = StringFromGUID2(*pGuid, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
2862 if(length)
2863 {
2864 swprintf(aQueryString, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", GuidString);
2865 // Step 6: --------------------------------------------------
2866 // Use the IWbemServices pointer to make requests of WMI ----
2867
2868 IEnumWbemClassObject* pEnumerator = NULL;
2869 hres = pSvc->ExecQuery(
2870 bstr_t("WQL"),
2871 bstr_t(aQueryString),
2872 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
2873 NULL,
2874 &pEnumerator);
2875 if(SUCCEEDED(hres))
2876 {
2877 // Step 7: -------------------------------------------------
2878 // Get the data from the query in step 6 -------------------
2879
2880 IWbemClassObject *pclsObj;
2881 ULONG uReturn = 0;
2882
2883 if (pEnumerator)
2884 {
2885 HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
2886 &pclsObj, &uReturn);
2887
2888 if(SUCCEEDED(hres))
2889 {
2890 if(uReturn)
2891 {
2892 pEnumerator->Release();
2893 *pAdapterConfig = pclsObj;
2894 hres = S_OK;
2895 return hres;
2896 }
2897 else
2898 {
2899 hres = S_FALSE;
2900 }
2901 }
2902
2903 pEnumerator->Release();
2904 }
2905 }
2906 else
2907 {
2908 Log(L"Query for operating system name failed. Error code = 0x%x\n", hres);
2909 }
2910 }
2911 else
2912 {
2913 DWORD winEr = GetLastError();
2914 Log(L"Failed to create guid string from guid, winEr (%d)\n", winEr);
2915 hres = HRESULT_FROM_WIN32( winEr );
2916 }
2917
2918 return hres;
2919}
2920
2921static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
2922{
2923 VARIANT vtServiceName;
2924 BOOL bIsHostOnly = FALSE;
2925 VariantInit(&vtServiceName);
2926
2927 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0, &vtServiceName, 0, 0);
2928 if(SUCCEEDED(hr))
2929 {
2930 *pbIsHostOnly = (bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp"));
2931
2932 VariantClear(&vtServiceName);
2933 }
2934
2935 return hr;
2936}
2937
2938static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
2939{
2940 VARIANT vtIp;
2941 HRESULT hr;
2942 VariantInit(&vtIp);
2943
2944 *pIpv4 = 0;
2945 *pMaskv4 = 0;
2946
2947 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
2948 if(SUCCEEDED(hr))
2949 {
2950 if(vtIp.vt == (VT_ARRAY | VT_BSTR))
2951 {
2952 VARIANT vtMask;
2953 VariantInit(&vtMask);
2954 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
2955 if(SUCCEEDED(hr))
2956 {
2957 if(vtMask.vt == (VT_ARRAY | VT_BSTR))
2958 {
2959 SAFEARRAY * pIpArray = vtIp.parray;
2960 SAFEARRAY * pMaskArray = vtMask.parray;
2961 if(pIpArray && pMaskArray)
2962 {
2963 BSTR pCurIp;
2964 BSTR pCurMask;
2965 for(long index = 0;
2966 SafeArrayGetElement(pIpArray, &index, (PVOID)&pCurIp) == S_OK
2967 && SafeArrayGetElement(pMaskArray, &index, (PVOID)&pCurMask) == S_OK;
2968 index++)
2969 {
2970 _bstr_t ip(pCurIp);
2971
2972 ULONG Ipv4 = inet_addr((char*)(ip));
2973 if(Ipv4 != INADDR_NONE)
2974 {
2975 *pIpv4 = Ipv4;
2976 _bstr_t mask(pCurMask);
2977 *pMaskv4 = inet_addr((char*)(mask));
2978 break;
2979 }
2980 }
2981 }
2982 }
2983 else
2984 {
2985 *pIpv4 = 0;
2986 *pMaskv4 = 0;
2987 }
2988
2989 VariantClear(&vtMask);
2990 }
2991 }
2992 else
2993 {
2994 *pIpv4 = 0;
2995 *pMaskv4 = 0;
2996 }
2997
2998 VariantClear(&vtIp);
2999 }
3000
3001 return hr;
3002}
3003
3004
3005static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
3006{
3007 VARIANT vtIp;
3008 HRESULT hr;
3009 VariantInit(&vtIp);
3010
3011 *pFound = false;
3012
3013 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
3014 if(SUCCEEDED(hr))
3015 {
3016 VARIANT vtMask;
3017 VariantInit(&vtMask);
3018 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
3019 if(SUCCEEDED(hr))
3020 {
3021 SAFEARRAY * pIpArray = vtIp.parray;
3022 SAFEARRAY * pMaskArray = vtMask.parray;
3023 if(pIpArray && pMaskArray)
3024 {
3025 BSTR pIp, pMask;
3026 for(long k = 0;
3027 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
3028 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
3029 k++)
3030 {
3031 BSTR pCurIp;
3032 BSTR pCurMask;
3033 for(long index = 0;
3034 SafeArrayGetElement(pIpArray, &index, (PVOID)&pCurIp) == S_OK
3035 && SafeArrayGetElement(pMaskArray, &index, (PVOID)&pCurMask) == S_OK;
3036 index++)
3037 {
3038 if(!wcsicmp(pCurIp, pIp))
3039 {
3040 if(!wcsicmp(pCurMask, pMask))
3041 {
3042 *pFound = true;
3043 }
3044 break;
3045 }
3046 }
3047 }
3048 }
3049
3050
3051 VariantClear(&vtMask);
3052 }
3053
3054 VariantClear(&vtIp);
3055 }
3056
3057 return hr;
3058}
3059
3060static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
3061{
3062 /* on Vista we need to wait for the address to get applied */
3063 /* wait for the address to appear in the list */
3064 HRESULT hr = S_OK;
3065 ULONG i;
3066 *pFound = false;
3067 ComPtr <IWbemClassObject> pAdapterConfig;
3068 for(i = 0;
3069 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
3070 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
3071 && !(*pFound)
3072 && i < sec2Wait/6;
3073 i++)
3074 {
3075 Sleep(6000);
3076 }
3077
3078 return hr;
3079}
3080
3081static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
3082{
3083 HRESULT hres;
3084
3085 // Step 3: ---------------------------------------------------
3086 // Obtain the initial locator to WMI -------------------------
3087
3088 IWbemLocator *pLoc = NULL;
3089
3090 hres = CoCreateInstance(
3091 CLSID_WbemLocator,
3092 0,
3093 CLSCTX_INPROC_SERVER,
3094 IID_IWbemLocator, (LPVOID *) &pLoc);
3095 if(SUCCEEDED(hres))
3096 {
3097 // Step 4: -----------------------------------------------------
3098 // Connect to WMI through the IWbemLocator::ConnectServer method
3099
3100 IWbemServices *pSvc = NULL;
3101
3102 // Connect to the root\cimv2 namespace with
3103 // the current user and obtain pointer pSvc
3104 // to make IWbemServices calls.
3105 hres = pLoc->ConnectServer(
3106 _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
3107 NULL, // User name. NULL = current user
3108 NULL, // User password. NULL = current
3109 0, // Locale. NULL indicates current
3110 NULL, // Security flags.
3111 0, // Authority (e.g. Kerberos)
3112 0, // Context object
3113 &pSvc // pointer to IWbemServices proxy
3114 );
3115 if(SUCCEEDED(hres))
3116 {
3117 Log(L"Connected to ROOT\\CIMV2 WMI namespace\n");
3118
3119 // Step 5: --------------------------------------------------
3120 // Set security levels on the proxy -------------------------
3121
3122 hres = CoSetProxyBlanket(
3123 pSvc, // Indicates the proxy to set
3124 RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
3125 RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
3126 NULL, // Server principal name
3127 RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
3128 RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
3129 NULL, // client identity
3130 EOAC_NONE // proxy capabilities
3131 );
3132 if(SUCCEEDED(hres))
3133 {
3134 *ppSvc = pSvc;
3135 /* do not need it any more */
3136 pLoc->Release();
3137 return hres;
3138 }
3139 else
3140 {
3141 Log(L"Could not set proxy blanket. Error code = 0x%x\n", hres);
3142 }
3143
3144 pSvc->Release();
3145 }
3146 else
3147 {
3148 Log(L"Could not connect. Error code = 0x%x\n", hres);
3149 }
3150
3151 pLoc->Release();
3152 }
3153 else
3154 {
3155 Log(L"Failed to create IWbemLocator object. Err code = 0x%x\n", hres);
3156// CoUninitialize();
3157 }
3158
3159 return hres;
3160}
3161
3162static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
3163{
3164 VARIANT index;
3165
3166 // Get the value of the key property
3167 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
3168 if(SUCCEEDED(hr))
3169 {
3170 WCHAR strIndex[8];
3171 swprintf(strIndex, L"%u", index.uintVal);
3172 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
3173 }
3174 else
3175 {
3176 DWORD dwError = GetLastError();
3177 Assert(0);
3178 hr = HRESULT_FROM_WIN32( dwError );
3179 }
3180 return hr;
3181}
3182
3183static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
3184 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
3185 IWbemClassObject** ppOutParams
3186 )
3187{
3188 HRESULT hres = S_OK;
3189 // Step 6: --------------------------------------------------
3190 // Use the IWbemServices pointer to make requests of WMI ----
3191
3192 ComPtr<IWbemClassObject> pInParamsDefinition;
3193 ComPtr<IWbemClassObject> pClassInstance;
3194
3195 if(cArgs)
3196 {
3197 hres = pClass->GetMethod(MethodName, 0,
3198 pInParamsDefinition.asOutParam(), NULL);
3199 if(SUCCEEDED(hres))
3200 {
3201 hres = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
3202
3203 if(SUCCEEDED(hres))
3204 {
3205 for(UINT i = 0; i < cArgs; i++)
3206 {
3207 // Store the value for the in parameters
3208 hres = pClassInstance->Put(pArgNames[i], 0,
3209 pArgs[i], 0);
3210 if(FAILED(hres))
3211 {
3212 break;
3213 }
3214 }
3215 }
3216 }
3217 }
3218
3219 if(SUCCEEDED(hres))
3220 {
3221 IWbemClassObject* pOutParams = NULL;
3222 hres = pSvc->ExecMethod(ObjPath, MethodName, 0,
3223 NULL, pClassInstance, &pOutParams, NULL);
3224 if(SUCCEEDED(hres))
3225 {
3226 *ppOutParams = pOutParams;
3227 }
3228 }
3229
3230 return hres;
3231}
3232
3233static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
3234{
3235 HRESULT hr;
3236 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
3237 if(pIpArray)
3238 {
3239 for(UINT i = 0; i < cIp; i++)
3240 {
3241 char* addr = inet_ntoa(aIp[i]);
3242 BSTR val = bstr_t(addr).copy();
3243 long aIndex[1];
3244 aIndex[0] = i;
3245 hr = SafeArrayPutElement(pIpArray, aIndex, val);
3246 if(FAILED(hr))
3247 {
3248 SysFreeString(val);
3249 SafeArrayDestroy(pIpArray);
3250 break;
3251 }
3252 }
3253
3254 if(SUCCEEDED(hr))
3255 {
3256 *ppArray = pIpArray;
3257 }
3258 }
3259 else
3260 {
3261 DWORD dwError = GetLastError();
3262 Assert(0);
3263 hr = HRESULT_FROM_WIN32( dwError );
3264 }
3265
3266 return hr;
3267}
3268
3269static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
3270{
3271 HRESULT hr;
3272 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
3273 if(pIpArray)
3274 {
3275 BSTR val = bstr_t(Ip, false).copy();
3276 long aIndex[1];
3277 aIndex[0] = 0;
3278 hr = SafeArrayPutElement(pIpArray, aIndex, val);
3279 if(FAILED(hr))
3280 {
3281 SysFreeString(val);
3282 SafeArrayDestroy(pIpArray);
3283 }
3284
3285 if(SUCCEEDED(hr))
3286 {
3287 *ppArray = pIpArray;
3288 }
3289 }
3290 else
3291 {
3292 DWORD dwError = GetLastError();
3293 Assert(0);
3294 hr = HRESULT_FROM_WIN32( dwError );
3295 }
3296
3297 return hr;
3298}
3299
3300
3301static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
3302{
3303 HRESULT hr;
3304 VariantInit(pIpAddresses);
3305 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
3306 SAFEARRAY *pIpArray;
3307 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
3308 if(SUCCEEDED(hr))
3309 {
3310 pIpAddresses->parray = pIpArray;
3311 }
3312 return hr;
3313}
3314
3315static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
3316{
3317 HRESULT hr;
3318 VariantInit(pIpAddresses);
3319 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
3320 SAFEARRAY *pIpArray;
3321 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
3322 if(SUCCEEDED(hr))
3323 {
3324 pIpAddresses->parray = pIpArray;
3325 }
3326 return hr;
3327}
3328
3329static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
3330{
3331 ComPtr<IWbemClassObject> pClass;
3332 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3333 HRESULT hr;
3334 if(ClassName)
3335 {
3336 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3337 if(SUCCEEDED(hr))
3338 {
3339 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
3340 LPVARIANT args[] = {pIp, pMask};
3341 ComPtr<IWbemClassObject> pOutParams;
3342
3343 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3344 bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
3345 if(SUCCEEDED(hr))
3346 {
3347 VARIANT varReturnValue;
3348 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3349 &varReturnValue, NULL, 0);
3350 Assert(SUCCEEDED(hr));
3351 if(SUCCEEDED(hr))
3352 {
3353// Assert(varReturnValue.vt == VT_UINT);
3354 int winEr = varReturnValue.uintVal;
3355 switch(winEr)
3356 {
3357 case 0:
3358 {
3359 hr = S_OK;
3360// bool bFound;
3361// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
3362 }
3363 break;
3364 default:
3365 hr = HRESULT_FROM_WIN32( winEr );
3366 break;
3367 }
3368 }
3369 }
3370 }
3371 SysFreeString(ClassName);
3372 }
3373 else
3374 {
3375 DWORD dwError = GetLastError();
3376 Assert(0);
3377 hr = HRESULT_FROM_WIN32( dwError );
3378 }
3379
3380 return hr;
3381}
3382
3383
3384static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
3385{
3386 VARIANT ipAddresses;
3387 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
3388 if(SUCCEEDED(hr))
3389 {
3390 VARIANT ipMasks;
3391 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
3392 if(SUCCEEDED(hr))
3393 {
3394 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
3395 VariantClear(&ipMasks);
3396 }
3397 VariantClear(&ipAddresses);
3398 }
3399 return hr;
3400}
3401
3402static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
3403{
3404 VARIANT ipAddresses;
3405 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
3406 if(SUCCEEDED(hr))
3407 {
3408 VARIANT ipMasks;
3409 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
3410 if(SUCCEEDED(hr))
3411 {
3412 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
3413 VariantClear(&ipMasks);
3414 }
3415 VariantClear(&ipAddresses);
3416 }
3417 return hr;
3418}
3419
3420/* win API allows to set gw metrics as well, we are not setting them */
3421static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
3422{
3423 ComPtr<IWbemClassObject> pClass;
3424 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3425 HRESULT hr;
3426 if(ClassName)
3427 {
3428 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3429 if(SUCCEEDED(hr))
3430 {
3431 LPWSTR argNames[] = {L"DefaultIPGateway"};
3432 LPVARIANT args[] = {pGw};
3433 ComPtr<IWbemClassObject> pOutParams;
3434
3435 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3436 bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
3437 if(SUCCEEDED(hr))
3438 {
3439 VARIANT varReturnValue;
3440 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3441 &varReturnValue, NULL, 0);
3442 Assert(SUCCEEDED(hr));
3443 if(SUCCEEDED(hr))
3444 {
3445// Assert(varReturnValue.vt == VT_UINT);
3446 int winEr = varReturnValue.uintVal;
3447 switch(winEr)
3448 {
3449 case 0:
3450 hr = S_OK;
3451 break;
3452 default:
3453 hr = HRESULT_FROM_WIN32( winEr );
3454 break;
3455 }
3456 }
3457 } }
3458 SysFreeString(ClassName);
3459 }
3460 else
3461 {
3462 DWORD dwError = GetLastError();
3463 Assert(0);
3464 hr = HRESULT_FROM_WIN32( dwError );
3465 }
3466
3467 return hr;
3468}
3469
3470/* win API allows to set gw metrics as well, we are not setting them */
3471static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
3472{
3473 VARIANT gwais;
3474 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
3475 if(SUCCEEDED(hr))
3476 {
3477 netIfWinSetGateways(pSvc, ObjPath, &gwais);
3478 VariantClear(&gwais);
3479 }
3480 return hr;
3481}
3482
3483/* win API allows to set gw metrics as well, we are not setting them */
3484static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
3485{
3486 VARIANT vGw;
3487 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
3488 if(SUCCEEDED(hr))
3489 {
3490 netIfWinSetGateways(pSvc, ObjPath, &vGw);
3491 VariantClear(&vGw);
3492 }
3493 return hr;
3494}
3495
3496static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
3497{
3498 ComPtr<IWbemClassObject> pClass;
3499 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3500 HRESULT hr;
3501 if(ClassName)
3502 {
3503 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3504 if(SUCCEEDED(hr))
3505 {
3506 ComPtr<IWbemClassObject> pOutParams;
3507
3508 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3509 bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
3510 if(SUCCEEDED(hr))
3511 {
3512 VARIANT varReturnValue;
3513 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3514 &varReturnValue, NULL, 0);
3515 Assert(SUCCEEDED(hr));
3516 if(SUCCEEDED(hr))
3517 {
3518// Assert(varReturnValue.vt == VT_UINT);
3519 int winEr = varReturnValue.uintVal;
3520 switch(winEr)
3521 {
3522 case 0:
3523 hr = S_OK;
3524 break;
3525 default:
3526 hr = HRESULT_FROM_WIN32( winEr );
3527 break;
3528 }
3529 }
3530 }
3531 }
3532 SysFreeString(ClassName);
3533 }
3534 else
3535 {
3536 DWORD dwError = GetLastError();
3537 Assert(0);
3538 hr = HRESULT_FROM_WIN32( dwError );
3539 }
3540
3541 return hr;
3542}
3543
3544static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
3545{
3546 ComPtr<IWbemClassObject> pClass;
3547 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3548 HRESULT hr;
3549 if(ClassName)
3550 {
3551 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3552 if(SUCCEEDED(hr))
3553 {
3554 ComPtr<IWbemClassObject> pOutParams;
3555
3556 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3557 bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
3558 if(SUCCEEDED(hr))
3559 {
3560 VARIANT varReturnValue;
3561 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3562 &varReturnValue, NULL, 0);
3563 Assert(SUCCEEDED(hr));
3564 if(SUCCEEDED(hr))
3565 {
3566// Assert(varReturnValue.vt == VT_UINT);
3567 int winEr = varReturnValue.uintVal;
3568 if(winEr == 0)
3569 {
3570 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3571 bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
3572 if(SUCCEEDED(hr))
3573 {
3574 VARIANT varReturnValue;
3575 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3576 &varReturnValue, NULL, 0);
3577 Assert(SUCCEEDED(hr));
3578 if(SUCCEEDED(hr))
3579 {
3580 // Assert(varReturnValue.vt == VT_UINT);
3581 int winEr = varReturnValue.uintVal;
3582 if(winEr == 0)
3583 {
3584 hr = S_OK;
3585 }
3586 else
3587 {
3588 hr = HRESULT_FROM_WIN32( winEr );
3589 }
3590 }
3591 }
3592 }
3593 else
3594 {
3595 hr = HRESULT_FROM_WIN32( winEr );
3596 }
3597 }
3598 }
3599 }
3600 SysFreeString(ClassName);
3601 }
3602 else
3603 {
3604 DWORD dwError = GetLastError();
3605 Assert(0);
3606 hr = HRESULT_FROM_WIN32( dwError );
3607 }
3608
3609 return hr;
3610}
3611
3612static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
3613{
3614 VARIANT vtEnabled;
3615 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
3616 if(SUCCEEDED(hr))
3617 {
3618 *pEnabled = vtEnabled.boolVal;
3619 }
3620 return hr;
3621}
3622
3623VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(const GUID * pGuid, PADAPTER_SETTINGS pSettings)
3624{
3625 HRESULT hr;
3626 ComPtr <IWbemServices> pSvc;
3627 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3628 if(SUCCEEDED(hr))
3629 {
3630 ComPtr <IWbemClassObject> pAdapterConfig;
3631 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3632 if(hr == S_OK)
3633 {
3634 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
3635 if(SUCCEEDED(hr))
3636 {
3637 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
3638 }
3639 }
3640 }
3641
3642 return hr;
3643}
3644
3645VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
3646{
3647 HRESULT hr;
3648 ComPtr <IWbemServices> pSvc;
3649 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3650 if(SUCCEEDED(hr))
3651 {
3652 ComPtr <IWbemClassObject> pAdapterConfig;
3653 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3654 if(hr == S_OK)
3655 {
3656 VARIANT vtEnabled;
3657 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
3658 if(SUCCEEDED(hr))
3659 {
3660 *pEnabled = vtEnabled.boolVal;
3661 }
3662 }
3663 }
3664
3665 return hr;
3666}
3667
3668VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(const GUID *pGuid, ULONG ip, ULONG mask)
3669{
3670 HRESULT hr;
3671 ComPtr <IWbemServices> pSvc;
3672 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3673 if(SUCCEEDED(hr))
3674 {
3675 ComPtr <IWbemClassObject> pAdapterConfig;
3676 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3677 if(hr == S_OK)
3678 {
3679 BOOL bIsHostOnly;
3680 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3681 if(SUCCEEDED(hr))
3682 {
3683 if(bIsHostOnly)
3684 {
3685 in_addr aIp[1];
3686 in_addr aMask[1];
3687 aIp[0].S_un.S_addr = ip;
3688 aMask[0].S_un.S_addr = mask;
3689
3690 BSTR ObjPath;
3691 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3692 if(SUCCEEDED(hr))
3693 {
3694 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
3695 if(SUCCEEDED(hr))
3696 {
3697#if 0
3698 in_addr aGw[1];
3699 aGw[0].S_un.S_addr = gw;
3700 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
3701 if(SUCCEEDED(hr))
3702#endif
3703 {
3704 }
3705 }
3706 SysFreeString(ObjPath);
3707 }
3708 }
3709 else
3710 {
3711 hr = E_FAIL;
3712 }
3713 }
3714 }
3715 }
3716
3717 return hr;
3718}
3719
3720#if 0
3721static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
3722{
3723 HRESULT hr;
3724 ComPtr <IWbemServices> pSvc;
3725 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3726 if(SUCCEEDED(hr))
3727 {
3728 ComPtr <IWbemClassObject> pAdapterConfig;
3729 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3730 if(hr == S_OK)
3731 {
3732 BSTR ObjPath;
3733 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3734 if(SUCCEEDED(hr))
3735 {
3736 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
3737 if(SUCCEEDED(hr))
3738 {
3739 if(aIPV6DefaultGateway)
3740 {
3741 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
3742 }
3743 if(SUCCEEDED(hr))
3744 {
3745// hr = netIfWinUpdateConfig(pIf);
3746 }
3747 }
3748 SysFreeString(ObjPath);
3749 }
3750 }
3751 }
3752
3753 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
3754}
3755
3756static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
3757{
3758 RTNETADDRIPV6 Mask;
3759 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
3760 if(RT_SUCCESS(rc))
3761 {
3762 Bstr maskStr = composeIPv6Address(&Mask);
3763 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
3764 }
3765 return rc;
3766}
3767#endif
3768
3769VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(const GUID *pGuid)
3770{
3771 HRESULT hr;
3772 ComPtr <IWbemServices> pSvc;
3773 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3774 if(SUCCEEDED(hr))
3775 {
3776 ComPtr <IWbemClassObject> pAdapterConfig;
3777 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3778 if(hr == S_OK)
3779 {
3780 BOOL bIsHostOnly;
3781 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3782 if(SUCCEEDED(hr))
3783 {
3784 if(bIsHostOnly)
3785 {
3786 BSTR ObjPath;
3787 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3788 if(SUCCEEDED(hr))
3789 {
3790 hr = netIfWinEnableDHCP(pSvc, ObjPath);
3791 if(SUCCEEDED(hr))
3792 {
3793// hr = netIfWinUpdateConfig(pIf);
3794 }
3795 SysFreeString(ObjPath);
3796 }
3797 }
3798 else
3799 {
3800 hr = E_FAIL;
3801 }
3802 }
3803 }
3804 }
3805
3806
3807 return hr;
3808}
3809
3810VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(const GUID *pGuid)
3811{
3812 HRESULT hr;
3813 ComPtr <IWbemServices> pSvc;
3814 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3815 if(SUCCEEDED(hr))
3816 {
3817 ComPtr <IWbemClassObject> pAdapterConfig;
3818 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3819 if(hr == S_OK)
3820 {
3821 BOOL bIsHostOnly;
3822 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3823 if(SUCCEEDED(hr))
3824 {
3825 if(bIsHostOnly)
3826 {
3827 BSTR ObjPath;
3828 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3829 if(SUCCEEDED(hr))
3830 {
3831 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
3832 if(SUCCEEDED(hr))
3833 {
3834// hr = netIfWinUpdateConfig(pIf);
3835 }
3836 SysFreeString(ObjPath);
3837 }
3838 }
3839 else
3840 {
3841 hr = E_FAIL;
3842 }
3843 }
3844 }
3845 }
3846
3847
3848 return hr;
3849}
3850
3851typedef bool (*IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
3852
3853static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, IPSETTINGS_CALLBACK pCallback, PVOID pContext)
3854{
3855 PIP_ADAPTER_ADDRESSES pAdapter;
3856 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
3857 {
3858 PIP_ADAPTER_UNICAST_ADDRESS pAddr = pAdapter->FirstUnicastAddress;
3859 PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix;
3860
3861 if(pAddr && pPrefix)
3862 {
3863 do
3864 {
3865 bool fIPFound, fMaskFound;
3866 fIPFound = fMaskFound = false;
3867 ULONG ip, mask;
3868 for (; pAddr && !fIPFound; pAddr = pAddr->Next)
3869 {
3870 switch (pAddr->Address.lpSockaddr->sa_family)
3871 {
3872 case AF_INET:
3873 fIPFound = true;
3874 memcpy(&ip,
3875 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
3876 sizeof(ip));
3877 break;
3878// case AF_INET6:
3879// break;
3880 }
3881 }
3882
3883 for (; pPrefix && !fMaskFound; pPrefix = pPrefix->Next)
3884 {
3885 switch (pPrefix->Address.lpSockaddr->sa_family)
3886 {
3887 case AF_INET:
3888 if(!pPrefix->PrefixLength || pPrefix->PrefixLength > 31) /* in case the ip helper API is queried while NetCfg write lock is held */
3889 break; /* the address values can contain illegal values */
3890 fMaskFound = true;
3891 mask = (~(((ULONG)~0) >> pPrefix->PrefixLength));
3892 mask = htonl(mask);
3893 break;
3894// case AF_INET6:
3895// break;
3896 }
3897 }
3898
3899 if(!fIPFound || !fMaskFound)
3900 break;
3901
3902 if(!pCallback(ip, mask, pContext))
3903 return;
3904 }while(true);
3905 }
3906 }
3907}
3908
3909typedef struct _IPPROBE_CONTEXT
3910{
3911 ULONG Prefix;
3912 bool bConflict;
3913}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
3914
3915#define IPPROBE_INIT(_pContext, _addr) \
3916 ((_pContext)->bConflict = false, \
3917 (_pContext)->Prefix = _addr)
3918
3919#define IPPROBE_INIT_STR(_pContext, _straddr) \
3920 IPROBE_INIT(_pContext, inet_addr(_straddr))
3921
3922static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
3923{
3924 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
3925
3926 if((ip & mask) == (pProbe->Prefix & mask))
3927 {
3928 pProbe->bConflict = true;
3929 return false;
3930 }
3931
3932 return true;
3933}
3934
3935VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(PULONG pNetIp, PULONG pNetMask)
3936{
3937 DWORD dwRc;
3938 HRESULT hr = S_OK;
3939 /*
3940 * Most of the hosts probably have less than 10 adapters,
3941 * so we'll mostly succeed from the first attempt.
3942 */
3943 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
3944 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
3945 if (!pAddresses)
3946 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3947 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
3948 if (dwRc == ERROR_BUFFER_OVERFLOW)
3949 {
3950 /* Impressive! More than 10 adapters! Get more memory and try again. */
3951 free(pAddresses);
3952 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
3953 if (!pAddresses)
3954 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3955 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
3956 }
3957 if (dwRc == NO_ERROR)
3958 {
3959 IPPROBE_CONTEXT Context;
3960 const ULONG ip192168 = inet_addr("192.168.0.0");
3961 srand(GetTickCount());
3962
3963 *pNetIp = 0;
3964 *pNetMask = 0;
3965
3966 for(int i = 0; i < 255; i++)
3967 {
3968 ULONG ipProbe = rand()*255/RAND_MAX;
3969 ipProbe = ip192168 | (ipProbe << 16);
3970 IPPROBE_INIT(&Context, ipProbe);
3971 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
3972 if(!Context.bConflict)
3973 {
3974 *pNetIp = ipProbe;
3975 *pNetMask = inet_addr("255.255.255.0");
3976 break;
3977 }
3978 }
3979 if(*pNetIp == 0)
3980 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
3981 }
3982 else
3983 {
3984 Log(L"VBoxNetCfgWinGenHostOnlyNetworkNetworkIp: GetAdaptersAddresses err (%d)\n", dwRc);
3985 }
3986 free(pAddresses);
3987
3988 if(dwRc != NO_ERROR)
3989 {
3990 hr = HRESULT_FROM_WIN32(dwRc);
3991 }
3992
3993 return hr;
3994}
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