VirtualBox

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

Last change on this file since 28668 was 26512, checked in by vboxsync, 15 years ago

HostDrivers: tabs -> spaces.

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

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