VirtualBox

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

Last change on this file since 25232 was 24280, checked in by vboxsync, 15 years ago

installer/win: move [Un]InstallBranding & InstallPythonAPI actions out of ifdef NETFLT; netadp/win: better failure tracing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 128.6 KB
Line 
1/* $Id: WinNetConfig.cpp 24280 2009-11-03 08:06:50Z 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
1062/**
1063 * Install a network component(protocols, clients and services)
1064 * given its INF file.
1065 *
1066 * @param pnc Reference to INetCfg.
1067 * @param lpszComponentId PnpID of the network component.
1068 * @param pguidClass Class GUID of the network component.
1069 * @param lpszInfFullPath INF file to install from.
1070 * @return S_OK on success, otherwise an error code.
1071 */
1072VBOXNETCFGWIN_DECL(HRESULT)
1073VBoxNetCfgWinInstallNetComponent(IN INetCfg *pnc,
1074 IN LPCWSTR lpszComponentId,
1075 IN const GUID *pguidClass,
1076 IN LPCWSTR * apInfFullPaths,
1077 IN UINT cInfFullPaths)
1078{
1079 HRESULT hr = S_OK;
1080
1081 /*
1082 * If full path to INF has been specified, the INF
1083 * needs to be copied using Setup API to ensure that any other files
1084 * that the primary INF copies will be correctly found by Setup API
1085 */
1086 for(UINT i = 0; i < cInfFullPaths; i++)
1087 {
1088 hr = vboxNetCfgWinCopyInf(apInfFullPaths[i]);
1089 Assert(hr == S_OK);
1090 if(hr != S_OK)
1091 {
1092 Log(L"VBoxNetCfgWinInstallNetComponent: vboxNetCfgWinCopyInf failed, hr (0x%x)\n", hr);
1093 if(i != 0)
1094 {
1095 /* remove infs already installed */
1096 for(UINT j = i-1; j != 0; j--)
1097 {
1098 vboxNetCfgWinRemoveInf(apInfFullPaths[j], 0);
1099 }
1100 }
1101
1102 break;
1103 }
1104 }
1105
1106 if (S_OK == hr)
1107 {
1108 /*
1109 * Install the network component.
1110 */
1111 hr = VBoxNetCfgWinInstallComponent( pnc,
1112 lpszComponentId,
1113 pguidClass );
1114 Assert(hr == S_OK);
1115 if ( hr == S_OK )
1116 {
1117 /*
1118 * On success, apply the changes
1119 */
1120 HRESULT tmpHr = pnc->Apply();
1121 Assert(tmpHr == S_OK);
1122 if(tmpHr != S_OK)
1123 {
1124 Log(L"VBoxNetCfgWinInstallNetComponent: Apply failed, hr (0x%x)\n", tmpHr);
1125 }
1126 }
1127 else
1128 {
1129 Log(L"VBoxNetCfgWinInstallNetComponent: VBoxNetCfgWinInstallComponent failed, hr (0x%x)\n", hr);
1130 }
1131 }
1132
1133 return hr;
1134}
1135
1136/**
1137 * Uninstall a network component.
1138 *
1139 * @param pnc Reference to INetCfg.
1140 * @param lpszInfId PnpID of the network component to uninstall
1141 * @param apInfFiles array of null-terminated strings containing the inf file names describing drivers to be removed from the system
1142 * @param cInfFiles the size of apInfFiles array
1143 * @return S_OK on success, otherwise an error code.
1144 */
1145VBOXNETCFGWIN_DECL(HRESULT)
1146VBoxNetCfgWinUninstallComponent(IN INetCfg *pnc,
1147 IN INetCfgComponent *pncc)
1148{
1149 INetCfgClass *pncClass;
1150 INetCfgClassSetup *pncClassSetup;
1151 GUID guidClass;
1152 OBO_TOKEN obo;
1153 HRESULT hr;
1154
1155 /*
1156 * Get the class GUID.
1157 */
1158 hr = pncc->GetClassGuid( &guidClass );
1159 Assert(hr == S_OK);
1160 if ( hr == S_OK )
1161 {
1162
1163 /*
1164 * Get a reference to component's class.
1165 */
1166 hr = pnc->QueryNetCfgClass( &guidClass,
1167 IID_INetCfgClass,
1168 (PVOID *)&pncClass );
1169 Assert(hr == S_OK);
1170 if ( hr == S_OK )
1171 {
1172
1173 /*
1174 * Get the setup interface.
1175 */
1176 hr = pncClass->QueryInterface( IID_INetCfgClassSetup,
1177 (LPVOID *)&pncClassSetup );
1178 Assert(hr == S_OK);
1179 if ( hr == S_OK )
1180 {
1181
1182 /*
1183 * Uninstall the component.
1184 */
1185 ZeroMemory( &obo,
1186 sizeof(OBO_TOKEN) );
1187
1188 obo.Type = OBO_USER;
1189
1190 hr = pncClassSetup->DeInstall( pncc,
1191 &obo,
1192 NULL );
1193 Assert(hr == S_OK);
1194 if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) )
1195 {
1196 HRESULT tmpHr = pnc->Apply();
1197 /* we ignore apply failures since they might occur on misconfigured systems*/
1198 Assert(tmpHr == S_OK);
1199 if ( (tmpHr != S_OK) )
1200 {
1201 Log(L"VBoxNetCfgWinUninstallComponent: Apply failed, hr (0x%x), ignoring\n", tmpHr);
1202 }
1203 }
1204 else
1205 {
1206 Log(L"VBoxNetCfgWinUninstallComponent: DeInstall failed, hr (0x%x)\n", hr);
1207 }
1208
1209 VBoxNetCfgWinReleaseRef( pncClassSetup );
1210 }
1211 else
1212 {
1213 Log(L"VBoxNetCfgWinUninstallComponent: QueryInterface for IID_INetCfgClassSetup failed, hr (0x%x)\n", hr);
1214 }
1215
1216 VBoxNetCfgWinReleaseRef( pncClass );
1217 }
1218 else
1219 {
1220 Log(L"VBoxNetCfgWinUninstallComponent: QueryNetCfgClass failed, hr (0x%x)\n", hr);
1221 }
1222 }
1223 else
1224 {
1225 Log(L"VBoxNetCfgWinUninstallComponent: GetClassGuid failed, hr (0x%x)\n", hr);
1226 }
1227
1228 return hr;
1229}
1230
1231#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
1232#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
1233
1234static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
1235{
1236 INetCfgComponent * pNcc = NULL;
1237 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
1238 if(hr == S_OK)
1239 {
1240 Log(L"NetFlt Is Installed currently\n");
1241
1242 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
1243
1244 VBoxNetCfgWinReleaseRef(pNcc);
1245 }
1246 else if(hr == S_FALSE)
1247 {
1248 Log(L"NetFlt Is Not Installed currently\n");
1249 hr = S_OK;
1250 }
1251 else
1252 {
1253 Log(L"vboxNetCfgWinNetFltUninstall: FindComponent for NetFlt failed, hr (0x%x)\n", hr);
1254 hr = S_OK;
1255 }
1256
1257 VBoxNetCfgWinUninstallInfs(VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
1258 VBoxNetCfgWinUninstallInfs(VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
1259
1260 return hr;
1261}
1262
1263VBOXNETCFGWIN_DECL(HRESULT)
1264VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
1265{
1266 return vboxNetCfgWinNetFltUninstall(pNc, 0);
1267}
1268
1269VBOXNETCFGWIN_DECL(HRESULT)
1270VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc, IN LPCWSTR * apInfFullPaths, IN UINT cInfFullPaths)
1271{
1272 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
1273
1274 hr = VBoxNetCfgWinInstallNetComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
1275 &GUID_DEVCLASS_NETSERVICE,
1276 apInfFullPaths,
1277 cInfFullPaths);
1278
1279 return hr;
1280}
1281
1282
1283/**
1284 * Get network component's binding path enumerator reference.
1285 *
1286 * @param pncc Network component reference.
1287 * @param dwBindingType EBP_ABOVE or EBP_BELOW.
1288 * @param ppencbp address the Enumerator reference to be stored to
1289 * @return S_OK on success, otherwise an error code.
1290 */
1291VBOXNETCFGWIN_DECL(HRESULT)
1292VBoxNetCfgWinGetBindingPathEnum(IN INetCfgComponent *pncc,
1293 IN DWORD dwBindingType,
1294 OUT IEnumNetCfgBindingPath **ppencbp)
1295{
1296 INetCfgComponentBindings *pnccb = NULL;
1297 HRESULT hr;
1298
1299 *ppencbp = NULL;
1300
1301 /* Get component's binding. */
1302 hr = pncc->QueryInterface( IID_INetCfgComponentBindings,
1303 (PVOID *)&pnccb );
1304 Assert(hr == S_OK);
1305 if ( hr == S_OK )
1306 {
1307
1308 /* Get binding path enumerator reference. */
1309 hr = pnccb->EnumBindingPaths( dwBindingType,
1310 ppencbp );
1311 if(hr != S_OK)
1312 {
1313 Log(L"VBoxNetCfgWinGetBindingPathEnum: EnumBindingPaths failed, hr (0x%x)\n", hr);
1314 }
1315
1316 VBoxNetCfgWinReleaseRef( pnccb );
1317 }
1318 else
1319 {
1320 Log(L"VBoxNetCfgWinGetBindingPathEnum: QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr);
1321 }
1322
1323 return hr;
1324}
1325
1326/**
1327 * Enumerates the first binding path.
1328 *
1329 * @param pencc Binding path enumerator reference.
1330 * @param ppncc address the Binding path reference to be stored to
1331 * @return S_OK on success, otherwise an error code.
1332 */
1333VBOXNETCFGWIN_DECL(HRESULT)
1334VBoxNetCfgWinGetFirstComponent(IN IEnumNetCfgComponent *pencc,
1335 OUT INetCfgComponent **ppncc)
1336{
1337 HRESULT hr;
1338 ULONG ulCount;
1339
1340 *ppncc = NULL;
1341
1342 pencc->Reset();
1343
1344 hr = pencc->Next( 1,
1345 ppncc,
1346 &ulCount );
1347 Assert(hr == S_OK || hr == S_FALSE);
1348 if(hr != S_OK && hr != S_FALSE)
1349 {
1350 Log(L"VBoxNetCfgWinGetFirstComponent: Next failed, hr (0x%x)\n", hr);
1351 }
1352 return hr;
1353}
1354
1355VBOXNETCFGWIN_DECL(HRESULT)
1356VBoxNetCfgWinGetFirstBindingPath(IN IEnumNetCfgBindingPath *pencbp,
1357 OUT INetCfgBindingPath **ppncbp)
1358{
1359 ULONG ulCount;
1360 HRESULT hr;
1361
1362 *ppncbp = NULL;
1363
1364 pencbp->Reset();
1365
1366 hr = pencbp->Next( 1,
1367 ppncbp,
1368 &ulCount );
1369 Assert(hr == S_OK || hr == S_FALSE);
1370 if(hr != S_OK && hr != S_FALSE)
1371 {
1372 Log(L"VBoxNetCfgWinGetFirstBindingPath: Next failed, hr (0x%x)\n", hr);
1373 }
1374
1375 return hr;
1376}
1377
1378/**
1379 * Get binding interface enumerator reference.
1380 *
1381 * @param pncbp Binding path reference.
1382 * @param ppencbp address the Enumerator reference to be stored to
1383 * @return S_OK on success, otherwise an error code
1384 */
1385VBOXNETCFGWIN_DECL(HRESULT)
1386VBoxNetCfgWinGetBindingInterfaceEnum(IN INetCfgBindingPath *pncbp,
1387 OUT IEnumNetCfgBindingInterface **ppencbi)
1388{
1389 HRESULT hr;
1390
1391 *ppencbi = NULL;
1392
1393 hr = pncbp->EnumBindingInterfaces( ppencbi );
1394 Assert(hr == S_OK);
1395 if(hr != S_OK)
1396 {
1397 Log(L"VBoxNetCfgWinGetBindingInterfaceEnum: EnumBindingInterfaces failed, hr (0x%x)\n", hr);
1398 }
1399
1400 return hr;
1401}
1402
1403/**
1404 * Enumerates the first binding interface.
1405 *
1406 * @param pencbi Binding interface enumerator reference.
1407 * @param ppncbi address the Binding interface reference to be stored to
1408 * @return S_OK on success, otherwise an error code
1409 */
1410VBOXNETCFGWIN_DECL(HRESULT)
1411VBoxNetCfgWinGetFirstBindingInterface(IN IEnumNetCfgBindingInterface *pencbi,
1412 OUT INetCfgBindingInterface **ppncbi)
1413{
1414 ULONG ulCount;
1415 HRESULT hr;
1416
1417 *ppncbi = NULL;
1418
1419 pencbi->Reset();
1420
1421 hr = pencbi->Next( 1,
1422 ppncbi,
1423 &ulCount );
1424 Assert(hr == S_OK || hr == S_FALSE);
1425 if(hr != S_OK && hr != S_FALSE)
1426 {
1427 Log(L"VBoxNetCfgWinGetFirstBindingInterface: Next failed, hr (0x%x)\n", hr);
1428 }
1429
1430 return hr;
1431}
1432
1433/*@
1434 * Enumerate the next binding interface.
1435 * The function behaves just like VBoxNetCfgWinGetFirstBindingInterface if
1436 * it is called right after VBoxNetCfgWinGetBindingInterfaceEnum.
1437 *
1438 * @param pencbi Binding interface enumerator reference.
1439 * @param ppncbi address the Binding interface reference t be stored to
1440 * @return S_OK on success, otherwise an error code
1441 */
1442VBOXNETCFGWIN_DECL(HRESULT)
1443VBoxNetCfgWinGetNextBindingInterface(IN IEnumNetCfgBindingInterface *pencbi,
1444 OUT INetCfgBindingInterface **ppncbi)
1445{
1446 ULONG ulCount;
1447 HRESULT hr;
1448
1449 *ppncbi = NULL;
1450
1451 hr = pencbi->Next( 1,
1452 ppncbi,
1453 &ulCount );
1454 Assert(hr == S_OK || hr == S_FALSE);
1455 if(hr != S_OK && hr != S_FALSE)
1456 {
1457 Log(L"VBoxNetCfgWinGetNextBindingInterface: Next failed, hr (0x%x)\n", hr);
1458 }
1459
1460 return hr;
1461}
1462
1463/**
1464 * Enumerate the next binding path.
1465 * The function behaves just like VBoxNetCfgWinGetFirstBindingPath if
1466 * it is called right after VBoxNetCfgWinGetBindingPathEnum.
1467 *
1468 * @param pencbp Binding path enumerator reference.
1469 * @param ppncbp Address the Binding path reference to be stored to
1470 * @return S_OK on sucess, otherwise an error code.
1471 */
1472VBOXNETCFGWIN_DECL(HRESULT)
1473VBoxNetCfgWinGetNextBindingPath(IN IEnumNetCfgBindingPath *pencbp,
1474 OUT INetCfgBindingPath **ppncbp)
1475{
1476 ULONG ulCount;
1477 HRESULT hr;
1478
1479 *ppncbp = NULL;
1480
1481 hr = pencbp->Next( 1,
1482 ppncbp,
1483 &ulCount );
1484 Assert(hr == S_OK || hr == S_FALSE);
1485 if(hr != S_OK && hr != S_FALSE)
1486 {
1487 Log(L"VBoxNetCfgWinGetNextBindingPath: Next failed, hr (0x%x)\n", hr);
1488 }
1489
1490 return hr;
1491}
1492
1493/*
1494 * helper function to get the component by its guid given enum interface
1495 */
1496static HRESULT vboxNetCfgWinGetComponentByGuidEnum(IEnumNetCfgComponent *pEnumNcc, IN const GUID * pGuid, OUT INetCfgComponent ** ppNcc)
1497{
1498 INetCfgComponent * pNcc;
1499 GUID NccGuid;
1500 HRESULT hr;
1501
1502 hr = VBoxNetCfgWinGetFirstComponent( pEnumNcc, &pNcc );
1503 Assert(hr == S_OK || hr == S_FALSE);
1504 while(hr == S_OK)
1505 {
1506 ULONG uComponentStatus;
1507 hr = pNcc->GetDeviceStatus(&uComponentStatus);
1508 if(hr == S_OK)
1509 {
1510 if(uComponentStatus == 0)
1511 {
1512 hr = pNcc->GetInstanceGuid(&NccGuid);
1513 Assert(hr == S_OK);
1514 if(hr == S_OK)
1515 {
1516 if(NccGuid == *pGuid)
1517 {
1518 /* found the needed device */
1519 *ppNcc = pNcc;
1520 break;
1521 }
1522 }
1523 else
1524 {
1525 Log(L"vboxNetCfgWinGetComponentByGuidEnum: GetInstanceGuid failed, hr (0x%x)\n", hr);
1526 }
1527 }
1528 }
1529
1530 VBoxNetCfgWinReleaseRef(pNcc);
1531
1532 hr = VBoxNetCfgWinGetNextComponent( pEnumNcc, &pNcc );
1533 }
1534
1535 return hr;
1536}
1537
1538/**
1539 * get the component by its guid
1540 */
1541VBOXNETCFGWIN_DECL(HRESULT)
1542VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc,
1543 IN const GUID *pguidClass,
1544 IN const GUID * pComponentGuid,
1545 OUT INetCfgComponent **ppncc)
1546{
1547 IEnumNetCfgComponent *pEnumNcc;
1548 HRESULT hr = VBoxNetCfgWinGetComponentEnum( pNc, pguidClass, &pEnumNcc );
1549 Assert(hr == S_OK);
1550 if(hr == S_OK)
1551 {
1552 hr = vboxNetCfgWinGetComponentByGuidEnum(pEnumNcc, pComponentGuid, ppncc);
1553 Assert(hr == S_OK || hr == S_FALSE);
1554 if(hr == S_FALSE)
1555 {
1556 Log(L"VBoxNetCfgWinGetComponentByGuid: component not found \n");
1557 }
1558 else if(hr != S_OK)
1559 {
1560 Log(L"VBoxNetCfgWinGetComponentByGuid: vboxNetCfgWinGetComponentByGuidEnum failed, hr (0x%x)\n", hr);
1561 }
1562 VBoxNetCfgWinReleaseRef(pEnumNcc);
1563 }
1564 else
1565 {
1566 Log(L"VBoxNetCfgWinGetComponentByGuid: VBoxNetCfgWinGetComponentEnum failed, hr (0x%x)\n", hr);
1567 }
1568 return hr;
1569}
1570
1571typedef BOOL (*VBOXNETCFGWIN_NETCFGENUM_CALLBACK) (IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext);
1572
1573static HRESULT vboxNetCfgWinEnumNetCfgComponents(IN INetCfg *pNc,
1574 IN const GUID *pguidClass,
1575 VBOXNETCFGWIN_NETCFGENUM_CALLBACK callback,
1576 PVOID pContext)
1577{
1578 IEnumNetCfgComponent *pEnumComponent;
1579 HRESULT hr = pNc->EnumComponents(pguidClass, &pEnumComponent);
1580 bool bBreak = false;
1581 Assert(hr == S_OK);
1582 if(hr == S_OK)
1583 {
1584 INetCfgComponent *pNcc;
1585 hr = pEnumComponent->Reset();
1586 Assert(hr == S_OK);
1587 do
1588 {
1589 hr = VBoxNetCfgWinGetNextComponent(pEnumComponent, &pNcc);
1590 Assert(hr == S_OK || hr == S_FALSE);
1591 if(hr == S_OK)
1592 {
1593 /* this is E_NOTIMPL for all components other than NET */
1594// ULONG uComponentStatus;
1595// hr = pNcc->GetDeviceStatus(&uComponentStatus);
1596// if(hr == S_OK)
1597 {
1598 if(!callback(pNc, pNcc, pContext))
1599 {
1600 bBreak = true;
1601 }
1602 }
1603 VBoxNetCfgWinReleaseRef(pNcc);
1604 }
1605 else
1606 {
1607 if(hr ==S_FALSE)
1608 {
1609 hr = S_OK;
1610 }
1611 else
1612 {
1613 Log(L"vboxNetCfgWinEnumNetCfgComponents: VBoxNetCfgWinGetNextComponent failed, hr (0x%x)\n", hr);
1614 }
1615 break;
1616 }
1617 } while(!bBreak);
1618
1619 VBoxNetCfgWinReleaseRef(pEnumComponent);
1620 }
1621 return hr;
1622}
1623
1624static VOID DoLogging(LPCWSTR szString, ...)
1625{
1626 LOG_ROUTINE pRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
1627 if(pRoutine)
1628 {
1629 WCHAR szBuffer[1024] = {0};
1630 va_list pArgList;
1631 va_start(pArgList, szString);
1632 _vsnwprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
1633 va_end(pArgList);
1634
1635 pRoutine(szBuffer);
1636 }
1637}
1638
1639VBOXNETCFGWIN_DECL(VOID) VBoxNetCfgWinSetLogging(LOG_ROUTINE Log)
1640{
1641 *((void * volatile *)&g_Logger) = Log;
1642}
1643
1644static BOOL vboxNetCfgWinRemoveAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
1645{
1646 DWORD winEr;
1647 HRESULT hr = S_OK;
1648 SP_REMOVEDEVICE_PARAMS rmdParams;
1649 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
1650 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
1651 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
1652 rmdParams.HwProfile = 0;
1653 if(SetupDiSetClassInstallParams(hDevInfo,pDev,&rmdParams.ClassInstallHeader,sizeof(rmdParams)))
1654 {
1655 if(SetupDiSetSelectedDevice (hDevInfo, pDev))
1656 {
1657 if(SetupDiCallClassInstaller(DIF_REMOVE,hDevInfo,pDev))
1658 {
1659 SP_DEVINSTALL_PARAMS devParams;
1660 /*
1661 * see if device needs reboot
1662 */
1663 devParams.cbSize = sizeof(devParams);
1664 if(SetupDiGetDeviceInstallParams(hDevInfo,pDev,&devParams))
1665 {
1666 if(devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))
1667 {
1668 //
1669 // reboot required
1670 //
1671 hr = S_FALSE;
1672 Log(L"vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: !!!REBOOT REQUIRED!!!\n");
1673 }
1674 }
1675 else
1676 {
1677 //
1678 // appears to have succeeded
1679 //
1680 }
1681 }
1682 else
1683 {
1684 winEr = GetLastError();
1685 Log(L"vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiCallClassInstaller failed winErr(%d)\n", winEr);
1686 hr = HRESULT_FROM_WIN32(winEr);
1687 }
1688 }
1689 else
1690 {
1691 winEr = GetLastError();
1692 Log(L"vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetSelectedDevice failed winErr(%d)\n", winEr);
1693 hr = HRESULT_FROM_WIN32(winEr);
1694 }
1695 }
1696 else
1697 {
1698 winEr = GetLastError();
1699 Log(L"vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetClassInstallParams failed winErr(%d)\n", winEr);
1700 hr = HRESULT_FROM_WIN32(winEr);
1701 }
1702
1703 return TRUE;
1704}
1705
1706VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(LPWSTR pPnPId)
1707{
1708 return VBoxNetCfgWinEnumNetDevices(pPnPId, vboxNetCfgWinRemoveAllNetDevicesOfIdCallback, NULL);
1709}
1710
1711VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPWSTR pPnPId, VBOXNETCFGWIN_NETENUM_CALLBACK callback, PVOID pContext)
1712{
1713 DWORD winEr;
1714 HRESULT hr = S_OK;
1715
1716 HDEVINFO hDevInfo = SetupDiGetClassDevsExW(
1717 &GUID_DEVCLASS_NET,
1718 NULL, /* IN PCTSTR Enumerator, OPTIONAL*/
1719 NULL, /*IN HWND hwndParent, OPTIONAL*/
1720 DIGCF_PRESENT, /*IN DWORD Flags,*/
1721 NULL, /*IN HDEVINFO DeviceInfoSet, OPTIONAL*/
1722 NULL, /*IN PCTSTR MachineName, OPTIONAL*/
1723 NULL /*IN PVOID Reserved*/
1724 );
1725 if(hDevInfo != INVALID_HANDLE_VALUE)
1726 {
1727 DWORD iDev = 0;
1728 SP_DEVINFO_DATA Dev;
1729 PBYTE pBuffer = NULL;
1730 DWORD cbBuffer = 0;
1731 DWORD cbRequired = 0;
1732 BOOL bEnumCompleted;
1733 size_t cPnPId = wcslen(pPnPId);
1734
1735 Dev.cbSize = sizeof(Dev);
1736
1737 for(; bEnumCompleted = SetupDiEnumDeviceInfo(hDevInfo, iDev, &Dev); iDev++)
1738 {
1739 if(!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
1740 SPDRP_HARDWAREID, /* IN DWORD Property,*/
1741 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
1742 pBuffer, /*OUT PBYTE PropertyBuffer,*/
1743 cbBuffer, /* IN DWORD PropertyBufferSize,*/
1744 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
1745 ))
1746 {
1747 winEr = GetLastError();
1748 if(winEr != ERROR_INSUFFICIENT_BUFFER)
1749 {
1750 Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (1) failed winErr(%d)\n", winEr);
1751 hr = HRESULT_FROM_WIN32(winEr);
1752 break;
1753 }
1754
1755 if(pBuffer)
1756 {
1757 free(pBuffer);
1758 }
1759
1760 pBuffer = (PBYTE)malloc(cbRequired);
1761 cbBuffer = cbRequired;
1762
1763 if(!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
1764 SPDRP_HARDWAREID, /* IN DWORD Property,*/
1765 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
1766 pBuffer, /*OUT PBYTE PropertyBuffer,*/
1767 cbBuffer, /* IN DWORD PropertyBufferSize,*/
1768 &cbRequired /*OUT PDWORD RequiredSize OPTIONAL*/
1769 ))
1770 {
1771 winEr = GetLastError();
1772 Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (2) failed winErr(%d)\n", winEr);
1773 hr = HRESULT_FROM_WIN32(winEr);
1774 break;
1775 }
1776 }
1777
1778 PWCHAR pCurId = (PWCHAR)pBuffer;
1779 size_t cCurId = wcslen(pCurId);
1780 if(cCurId >= cPnPId)
1781 {
1782 pCurId += cCurId - cPnPId;
1783 if(!wcsnicmp(pCurId, pPnPId, cPnPId))
1784 {
1785
1786 if(!callback(hDevInfo,&Dev,pContext))
1787 break;
1788 }
1789 }
1790
1791 }
1792
1793 if(pBuffer)
1794 free(pBuffer);
1795
1796 if(bEnumCompleted)
1797 {
1798 winEr = GetLastError();
1799 hr = winEr == ERROR_NO_MORE_ITEMS ? S_OK : HRESULT_FROM_WIN32(winEr);
1800 }
1801
1802 SetupDiDestroyDeviceInfoList(hDevInfo);
1803 }
1804 else
1805 {
1806 DWORD winEr = GetLastError();
1807 Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetClassDevsExW failed winErr(%d)\n", winEr);
1808 hr = HRESULT_FROM_WIN32(winEr);
1809 }
1810
1811 return hr;
1812}
1813
1814
1815
1816/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
1817/*
1818 Copyright 2004 by the Massachusetts Institute of Technology
1819
1820 All rights reserved.
1821
1822 Permission to use, copy, modify, and distribute this software and its
1823 documentation for any purpose and without fee is hereby granted,
1824 provided that the above copyright notice appear in all copies and that
1825 both that copyright notice and this permission notice appear in
1826 supporting documentation, and that the name of the Massachusetts
1827 Institute of Technology (M.I.T.) not be used in advertising or publicity
1828 pertaining to distribution of the software without specific, written
1829 prior permission.
1830
1831 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1832 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1833 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1834 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1835 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1836 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1837 SOFTWARE.
1838*/
1839
1840
1841#define NETSHELL_LIBRARY _T("netshell.dll")
1842
1843/**
1844 * Use the IShellFolder API to rename the connection.
1845 */
1846static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
1847{
1848 /* This is the GUID for the network connections folder. It is constant.
1849 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
1850 const GUID CLSID_NetworkConnections = {
1851 0x7007ACC7, 0x3202, 0x11D1, {
1852 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
1853 }
1854 };
1855
1856 LPITEMIDLIST pidl = NULL;
1857 IShellFolder *pShellFolder = NULL;
1858 HRESULT hr;
1859
1860 /* Build the display name in the form "::{GUID}". */
1861 if (wcslen (wGuid) >= MAX_PATH)
1862 return E_INVALIDARG;
1863 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
1864 swprintf (szAdapterGuid, L"::%ls", wGuid);
1865
1866 /* Create an instance of the network connections folder. */
1867 hr = CoCreateInstance (CLSID_NetworkConnections, NULL,
1868 CLSCTX_INPROC_SERVER, IID_IShellFolder,
1869 reinterpret_cast <LPVOID *> (&pShellFolder));
1870 /* Parse the display name. */
1871 if (SUCCEEDED (hr))
1872 {
1873 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
1874 &pidl, NULL);
1875 }
1876 if (SUCCEEDED (hr))
1877 {
1878 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
1879 &pidl);
1880 }
1881
1882 CoTaskMemFree (pidl);
1883
1884 if (pShellFolder)
1885 pShellFolder->Release();
1886
1887 return hr;
1888}
1889
1890VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
1891{
1892 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
1893 lpHrRenameConnection RenameConnectionFunc = NULL;
1894 HRESULT status;
1895// Guid guid(*pDevInstanceGuid);
1896// Bstr bstr(guid.toString());
1897// BSTR GuidString = bstr.mutableRaw();
1898// WCHAR GuidString[50];
1899//
1900// int length = StringFromGUID2(*pDevInstanceGuid, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
1901// if(!length)
1902// return E_FAIL;
1903
1904// strString[wcslen(strString) - 1] = L'\0';
1905//
1906// WCHAR * GuidString = strString + 1;
1907
1908 /* First try the IShellFolder interface, which was unimplemented
1909 * for the network connections folder before XP. */
1910 status = rename_shellfolder (pGuid, NewName);
1911 if (status == E_NOTIMPL)
1912 {
1913/** @todo that code doesn't seem to work! */
1914 /* The IShellFolder interface is not implemented on this platform.
1915 * Try the (undocumented) HrRenameConnection API in the netshell
1916 * library. */
1917 CLSID clsid;
1918 HINSTANCE hNetShell;
1919 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
1920 if (FAILED(status))
1921 return E_FAIL;
1922 hNetShell = LoadLibrary (NETSHELL_LIBRARY);
1923 if (hNetShell == NULL)
1924 return E_FAIL;
1925 RenameConnectionFunc =
1926 (lpHrRenameConnection) GetProcAddress (hNetShell,
1927 "HrRenameConnection");
1928 if (RenameConnectionFunc == NULL)
1929 {
1930 FreeLibrary (hNetShell);
1931 return E_FAIL;
1932 }
1933 status = RenameConnectionFunc (&clsid, NewName);
1934 FreeLibrary (hNetShell);
1935 }
1936 if (FAILED (status))
1937 return status;
1938
1939 return S_OK;
1940}
1941
1942#define DRIVERHWID _T("sun_VBoxNetAdp")
1943
1944#define SetErrBreak(strAndArgs) \
1945 if (1) { \
1946 hrc = E_FAIL; \
1947 Log strAndArgs; \
1948 Assert(0); \
1949 break; \
1950 } else do {} while (0)
1951
1952
1953VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface (const GUID *pGUID, BSTR *pErrMsg)
1954{
1955// LogFlowFuncEnter();
1956// LogFlowFunc (("Network connection GUID = {%RTuuid}\n", aGUID.raw()));
1957
1958// AssertReturn (aClient, VERR_INVALID_POINTER);
1959// AssertReturn (!aGUID.isEmpty(), VERR_INVALID_PARAMETER);
1960
1961 HRESULT hrc = S_OK;
1962
1963 do
1964 {
1965 TCHAR lszPnPInstanceId [512] = {0};
1966
1967 /* We have to find the device instance ID through a registry search */
1968
1969 HKEY hkeyNetwork = 0;
1970 HKEY hkeyConnection = 0;
1971
1972 do
1973 {
1974 WCHAR strRegLocation [256];
1975 WCHAR GuidString[50];
1976
1977 int length = StringFromGUID2(*pGUID, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
1978 if(!length)
1979 SetErrBreak((L"Failed to create a Guid string"));
1980
1981 swprintf (strRegLocation,
1982 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
1983 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
1984 GuidString);
1985
1986 LONG status;
1987 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
1988 KEY_READ, &hkeyNetwork);
1989 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
1990 SetErrBreak ((
1991 L"Host interface network is not found in registry (%s) [1]",
1992 strRegLocation));
1993
1994 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
1995 KEY_READ, &hkeyConnection);
1996 if ((status != ERROR_SUCCESS) || !hkeyConnection)
1997 SetErrBreak ((
1998 L"Host interface network is not found in registry (%s) [2]",
1999 strRegLocation));
2000
2001 DWORD len = sizeof (lszPnPInstanceId);
2002 DWORD dwKeyType;
2003 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2004 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2005 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2006 SetErrBreak ((
2007 L"Host interface network is not found in registry (%s) [3]",
2008 strRegLocation));
2009 }
2010 while (0);
2011
2012 if (hkeyConnection)
2013 RegCloseKey (hkeyConnection);
2014 if (hkeyNetwork)
2015 RegCloseKey (hkeyNetwork);
2016
2017 if (FAILED (hrc))
2018 break;
2019
2020 /*
2021 * Now we are going to enumerate all network devices and
2022 * wait until we encounter the right device instance ID
2023 */
2024
2025 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2026
2027 do
2028 {
2029 BOOL ok;
2030 DWORD ret = 0;
2031 GUID netGuid;
2032 SP_DEVINFO_DATA DeviceInfoData;
2033 DWORD index = 0;
2034 BOOL found = FALSE;
2035 DWORD size = 0;
2036
2037 /* initialize the structure size */
2038 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2039
2040 /* copy the net class GUID */
2041 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2042
2043 /* return a device info set contains all installed devices of the Net class */
2044 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2045
2046 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2047 SetErrBreak ((L"SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2048
2049 /* enumerate the driver info list */
2050 while (TRUE)
2051 {
2052 TCHAR *deviceHwid;
2053
2054 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2055
2056 if (!ok)
2057 {
2058 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2059 break;
2060 else
2061 {
2062 index++;
2063 continue;
2064 }
2065 }
2066
2067 /* try to get the hardware ID registry property */
2068 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2069 &DeviceInfoData,
2070 SPDRP_HARDWAREID,
2071 NULL,
2072 NULL,
2073 0,
2074 &size);
2075 if (!ok)
2076 {
2077 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2078 {
2079 index++;
2080 continue;
2081 }
2082
2083 deviceHwid = (TCHAR *) malloc (size);
2084 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2085 &DeviceInfoData,
2086 SPDRP_HARDWAREID,
2087 NULL,
2088 (PBYTE)deviceHwid,
2089 size,
2090 NULL);
2091 if (!ok)
2092 {
2093 free (deviceHwid);
2094 deviceHwid = NULL;
2095 index++;
2096 continue;
2097 }
2098 }
2099 else
2100 {
2101 /* something is wrong. This shouldn't have worked with a NULL buffer */
2102 index++;
2103 continue;
2104 }
2105
2106 for (TCHAR *t = deviceHwid;
2107 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2108 t += _tcslen (t) + 1)
2109 {
2110 if (!_tcsicmp (DRIVERHWID, t))
2111 {
2112 /* get the device instance ID */
2113 TCHAR devID [MAX_DEVICE_ID_LEN];
2114 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2115 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2116 {
2117 /* compare to what we determined before */
2118 if (wcscmp(devID, lszPnPInstanceId) == 0)
2119 {
2120 found = TRUE;
2121 break;
2122 }
2123 }
2124 }
2125 }
2126
2127 if (deviceHwid)
2128 {
2129 free (deviceHwid);
2130 deviceHwid = NULL;
2131 }
2132
2133 if (found)
2134 break;
2135
2136 index++;
2137 }
2138
2139 if (found == FALSE)
2140 SetErrBreak ((L"Host Interface Network driver not found (0x%08X)",
2141 GetLastError()));
2142
2143 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2144 if (!ok)
2145 SetErrBreak ((L"SetupDiSetSelectedDevice failed (0x%08X)",
2146 GetLastError()));
2147
2148 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2149 if (!ok)
2150 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2151 GetLastError()));
2152 }
2153 while (0);
2154
2155 /* clean up the device info set */
2156 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2157 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2158
2159 if (FAILED (hrc))
2160 break;
2161 }
2162 while (0);
2163
2164// LogFlowFunc (("vrc=%Rrc\n", vrc));
2165// LogFlowFuncLeave();
2166 return hrc;
2167}
2168
2169static UINT WINAPI vboxNetCfgWinPspFileCallback(
2170 PVOID Context,
2171 UINT Notification,
2172 UINT_PTR Param1,
2173 UINT_PTR Param2
2174 )
2175{
2176 switch(Notification)
2177 {
2178 case SPFILENOTIFY_TARGETNEWER:
2179 case SPFILENOTIFY_TARGETEXISTS:
2180 return TRUE;
2181 }
2182 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2183}
2184
2185static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority (IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
2186{
2187 INetCfgComponentBindings *pNccb = NULL;
2188 IEnumNetCfgBindingPath *pEnumNccbp;
2189 GUID *pGuid = (GUID*)pContext;
2190 HRESULT hr;
2191 bool bFound = false;
2192
2193 /* Get component's binding. */
2194 hr = pNcc->QueryInterface( IID_INetCfgComponentBindings,
2195 (PVOID *)&pNccb );
2196 Assert(hr == S_OK);
2197 if ( hr == S_OK )
2198 {
2199 /* Get binding path enumerator reference. */
2200 hr = pNccb->EnumBindingPaths(EBP_BELOW, &pEnumNccbp);
2201 Assert(hr == S_OK);
2202 if(hr == S_OK)
2203 {
2204 INetCfgBindingPath *pNccbp;
2205 hr = pEnumNccbp->Reset();
2206 Assert(hr == S_OK);
2207 do
2208 {
2209 hr = VBoxNetCfgWinGetNextBindingPath(pEnumNccbp, &pNccbp);
2210 Assert(hr == S_OK || hr == S_FALSE);
2211 if(hr == S_OK)
2212 {
2213// if(pNccbp->IsEnabled() == S_OK)
2214 {
2215 IEnumNetCfgBindingInterface *pEnumNcbi;
2216 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pNccbp, &pEnumNcbi);
2217 Assert(hr == S_OK);
2218 if ( hr == S_OK )
2219 {
2220 INetCfgBindingInterface *pNcbi;
2221 hr = pEnumNcbi->Reset();
2222 Assert(hr == S_OK);
2223 do
2224 {
2225 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumNcbi, &pNcbi);
2226 Assert(hr == S_OK || hr == S_FALSE);
2227 if(hr == S_OK)
2228 {
2229 INetCfgComponent * pNccBoud;
2230 hr = pNcbi->GetLowerComponent(&pNccBoud);
2231 Assert(hr == S_OK);
2232 if(hr == S_OK)
2233 {
2234 ULONG uComponentStatus;
2235 hr = pNccBoud->GetDeviceStatus(&uComponentStatus);
2236 if(hr == S_OK)
2237 {
2238// if(uComponentStatus == 0)
2239 {
2240 GUID guid;
2241 hr = pNccBoud->GetInstanceGuid(&guid);
2242 if(guid == *pGuid)
2243 {
2244 hr = pNccb->MoveAfter(pNccbp, NULL);
2245 Assert(hr == S_OK);
2246 bFound = true;
2247 }
2248 }
2249 }
2250 VBoxNetCfgWinReleaseRef(pNccBoud);
2251 }
2252 VBoxNetCfgWinReleaseRef(pNcbi);
2253 }
2254 else
2255 {
2256 if(hr == S_FALSE)
2257 {
2258 hr = S_OK;
2259 }
2260 else
2261 {
2262 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingInterface failed, hr (0x%x)\n", hr);
2263 }
2264 break;
2265 }
2266 } while(!bFound);
2267 VBoxNetCfgWinReleaseRef(pEnumNcbi);
2268 }
2269 else
2270 {
2271 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetBindingInterfaceEnum failed, hr (0x%x)\n", hr);
2272 }
2273 }
2274
2275 VBoxNetCfgWinReleaseRef(pNccbp);
2276 }
2277 else
2278 {
2279 if(hr = S_FALSE)
2280 {
2281 hr = S_OK;
2282 }
2283 else
2284 {
2285 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingPath failed, hr (0x%x)\n", hr);
2286 }
2287 break;
2288 }
2289 } while(!bFound);
2290
2291 VBoxNetCfgWinReleaseRef(pEnumNccbp);
2292 }
2293 else
2294 {
2295 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: EnumBindingPaths failed, hr (0x%x)\n", hr);
2296 }
2297
2298 VBoxNetCfgWinReleaseRef( pNccb );
2299 }
2300 else
2301 {
2302 Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr);
2303 }
2304
2305 return true;
2306}
2307
2308VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface (LPCWSTR pInfPath, bool bIsInfPathFile, /* <- input params */
2309 GUID *pGuid, BSTR *lppszName, BSTR *pErrMsg) /* <- output params */
2310{
2311 HRESULT hrc = S_OK;
2312
2313 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2314 SP_DEVINFO_DATA DeviceInfoData;
2315 PVOID pQueueCallbackContext = NULL;
2316 DWORD ret = 0;
2317 BOOL found = FALSE;
2318 BOOL registered = FALSE;
2319 BOOL destroyList = FALSE;
2320 WCHAR pWCfgGuidString [50];
2321 WCHAR DevName[256];
2322
2323 do
2324 {
2325 BOOL ok;
2326 GUID netGuid;
2327 SP_DRVINFO_DATA DriverInfoData;
2328 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2329 TCHAR className [MAX_PATH];
2330 DWORD index = 0;
2331 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2332 /* for our purposes, 2k buffer is more
2333 * than enough to obtain the hardware ID
2334 * of the VBoxNetAdp driver. */
2335 DWORD detailBuf [2048];
2336
2337 HKEY hkey = NULL;
2338 DWORD cbSize;
2339 DWORD dwValueType;
2340
2341 /* initialize the structure size */
2342 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2343 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
2344
2345 /* copy the net class GUID */
2346 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2347
2348 /* create an empty device info set associated with the net class GUID */
2349 hDeviceInfo = SetupDiCreateDeviceInfoList (&netGuid, NULL);
2350 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2351 SetErrBreak ((L"SetupDiCreateDeviceInfoList failed (0x%08X)",
2352 GetLastError()));
2353
2354 /* get the class name from GUID */
2355 ok = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2356 if (!ok)
2357 SetErrBreak ((L"SetupDiClassNameFromGuid failed (0x%08X)",
2358 GetLastError()));
2359
2360 /* create a device info element and add the new device instance
2361 * key to registry */
2362 ok = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2363 DICD_GENERATE_ID, &DeviceInfoData);
2364 if (!ok)
2365 SetErrBreak ((L"SetupDiCreateDeviceInfo failed (0x%08X)",
2366 GetLastError()));
2367
2368 /* select the newly created device info to be the currently
2369 selected member */
2370 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2371 if (!ok)
2372 SetErrBreak ((L"SetupDiSetSelectedDevice failed (0x%08X)",
2373 GetLastError()));
2374
2375 if(pInfPath)
2376 {
2377 /* get the device install parameters and disable filecopy */
2378 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2379 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2380 &DeviceInstallParams);
2381 if (ok)
2382 {
2383 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2384 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2385 if(pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2386 {
2387 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2388
2389 if(bIsInfPathFile)
2390 {
2391 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2392 }
2393
2394 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2395 &DeviceInstallParams);
2396 if(!ok)
2397 {
2398 DWORD winEr = GetLastError();
2399 Log(L"SetupDiSetDeviceInstallParams: SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr);
2400 Assert(0);
2401 break;
2402 }
2403 }
2404 else
2405 {
2406 Log(L"SetupDiSetDeviceInstallParams: inf path is too long\n");
2407 Assert(0);
2408 break;
2409 }
2410 }
2411 else
2412 {
2413 DWORD winEr = GetLastError();
2414 Assert(0);
2415 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr);
2416 }
2417
2418 }
2419
2420 /* build a list of class drivers */
2421 ok = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2422 SPDIT_CLASSDRIVER);
2423 if (!ok)
2424 SetErrBreak ((L"SetupDiBuildDriverInfoList failed (0x%08X)",
2425 GetLastError()));
2426
2427 destroyList = TRUE;
2428
2429 /* enumerate the driver info list */
2430 while (TRUE)
2431 {
2432 BOOL ret;
2433
2434 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2435 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2436
2437 /* if the function failed and GetLastError() returned
2438 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2439 * list. Othewise there was something wrong with this
2440 * particular driver. */
2441 if (!ret)
2442 {
2443 if(GetLastError() == ERROR_NO_MORE_ITEMS)
2444 break;
2445 else
2446 {
2447 index++;
2448 continue;
2449 }
2450 }
2451
2452 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2453 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2454
2455 /* if we successfully find the hardware ID and it turns out to
2456 * be the one for the loopback driver, then we are done. */
2457 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2458 &DeviceInfoData,
2459 &DriverInfoData,
2460 pDriverInfoDetail,
2461 sizeof (detailBuf),
2462 NULL))
2463 {
2464 TCHAR * t;
2465
2466 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2467 * whole list and see if there is a match somewhere. */
2468 t = pDriverInfoDetail->HardwareID;
2469 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2470 {
2471 if (!_tcsicmp(t, DRIVERHWID))
2472 break;
2473
2474 t += _tcslen(t) + 1;
2475 }
2476
2477 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2478 {
2479 found = TRUE;
2480 break;
2481 }
2482 }
2483
2484 index ++;
2485 }
2486
2487 if (!found)
2488 SetErrBreak ((L"Could not find Host Interface Networking driver! "
2489 L"Please reinstall"));
2490
2491 /* set the loopback driver to be the currently selected */
2492 ok = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2493 &DriverInfoData);
2494 if (!ok)
2495 SetErrBreak ((L"SetupDiSetSelectedDriver failed (0x%08X)",
2496 GetLastError()));
2497
2498 /* register the phantom device to prepare for install */
2499 ok = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2500 &DeviceInfoData);
2501 if (!ok)
2502 {
2503 DWORD err = GetLastError();
2504 SetErrBreak ((L"SetupDiCallClassInstaller failed (0x%08X)",
2505 err));
2506 }
2507
2508 /* registered, but remove if errors occur in the following code */
2509 registered = TRUE;
2510
2511 /* ask the installer if we can install the device */
2512 ok = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2513 &DeviceInfoData);
2514 if (!ok)
2515 {
2516 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2517 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2518 GetLastError()));
2519 /* that's fine */
2520 }
2521
2522 /* get the device install parameters and disable filecopy */
2523 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2524 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2525 &DeviceInstallParams);
2526 if (ok)
2527 {
2528 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2529 if(pQueueCallbackContext)
2530 {
2531 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2532 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2533 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2534 &DeviceInstallParams);
2535 if(!ok)
2536 {
2537 DWORD winEr = GetLastError();
2538 Assert(0);
2539 Log(L"SetupDiSetDeviceInstallParams: SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr);
2540 }
2541 Assert(ok);
2542 }
2543 else
2544 {
2545 DWORD winEr = GetLastError();
2546 Assert(0);
2547 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr);
2548 }
2549 }
2550 else
2551 {
2552 DWORD winEr = GetLastError();
2553 Assert(0);
2554 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr);
2555 }
2556
2557 /* install the files first */
2558 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2559 &DeviceInfoData);
2560 if (!ok)
2561 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2562 GetLastError()));
2563
2564 /* get the device install parameters and disable filecopy */
2565 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2566 ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2567 &DeviceInstallParams);
2568 if (ok)
2569 {
2570 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2571 ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2572 &DeviceInstallParams);
2573 if (!ok)
2574 SetErrBreak ((L"SetupDiSetDeviceInstallParams failed (0x%08X)",
2575 GetLastError()));
2576 }
2577
2578 /*
2579 * Register any device-specific co-installers for this device,
2580 */
2581
2582 ok = SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS,
2583 hDeviceInfo,
2584 &DeviceInfoData);
2585 if (!ok)
2586 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2587 GetLastError()));
2588
2589 /*
2590 * install any installer-specified interfaces.
2591 * and then do the real install
2592 */
2593 ok = SetupDiCallClassInstaller (DIF_INSTALLINTERFACES,
2594 hDeviceInfo,
2595 &DeviceInfoData);
2596 if (!ok)
2597 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2598 GetLastError()));
2599
2600 ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICE,
2601 hDeviceInfo,
2602 &DeviceInfoData);
2603 if (!ok)
2604 SetErrBreak ((L"SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2605 GetLastError()));
2606
2607 /* Figure out NetCfgInstanceId */
2608 hkey = SetupDiOpenDevRegKey (hDeviceInfo,
2609 &DeviceInfoData,
2610 DICS_FLAG_GLOBAL,
2611 0,
2612 DIREG_DRV,
2613 KEY_READ);
2614 if (hkey == INVALID_HANDLE_VALUE)
2615 SetErrBreak ((L"SetupDiOpenDevRegKey failed (0x%08X)",
2616 GetLastError()));
2617
2618 cbSize = sizeof (pWCfgGuidString);
2619 DWORD ret;
2620 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2621 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2622
2623 RegCloseKey (hkey);
2624
2625 if(!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2626 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2627 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2628 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2629 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2630 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2631 ))
2632 {
2633 int err = GetLastError();
2634 if(err != ERROR_INVALID_DATA)
2635 {
2636 SetErrBreak ((L"SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2637 err));
2638 }
2639
2640 if(!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2641 SPDRP_DEVICEDESC , /* IN DWORD Property,*/
2642 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2643 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2644 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2645 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2646 ))
2647 {
2648 err = GetLastError();
2649 SetErrBreak ((L"SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2650 err));
2651 }
2652 }
2653 }
2654 while (0);
2655
2656 /*
2657 * cleanup
2658 */
2659 if(pQueueCallbackContext)
2660 {
2661 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2662 }
2663
2664 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2665 {
2666 /* an error has occurred, but the device is registered, we must remove it */
2667 if (ret != 0 && registered)
2668 SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2669
2670 found = SetupDiDeleteDeviceInfo (hDeviceInfo, &DeviceInfoData);
2671
2672 /* destroy the driver info list */
2673 if (destroyList)
2674 SetupDiDestroyDriverInfoList (hDeviceInfo, &DeviceInfoData,
2675 SPDIT_CLASSDRIVER);
2676 /* clean up the device info set */
2677 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2678 }
2679
2680 /* return the network connection GUID on success */
2681 if (SUCCEEDED(hrc))
2682 {
2683// Bstr str(DevName);
2684// str.detachTo(pName);
2685 WCHAR ConnectoinName[128];
2686 ULONG cbName = sizeof(ConnectoinName);
2687
2688 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName (DevName, ConnectoinName, &cbName);
2689 if(hr == S_OK)
2690 {
2691 hr = VBoxNetCfgWinRenameConnection (pWCfgGuidString, ConnectoinName);
2692 }
2693
2694 if(lppszName)
2695 {
2696 *lppszName = ::SysAllocString ((const OLECHAR *) DevName);
2697 if ( !*lppszName )
2698 {
2699 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: SysAllocString failed\n");
2700 Assert(0);
2701 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
2702 }
2703 }
2704
2705 if(pGuid)
2706 {
2707 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID) pGuid);
2708 if(hrc != S_OK)
2709 {
2710 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: CLSIDFromString failed, hrc (0x%x)\n", hrc);
2711 Assert(0);
2712 }
2713 }
2714
2715 INetCfg *pNc;
2716 LPWSTR lpszApp = NULL;
2717
2718
2719
2720 hr = VBoxNetCfgWinQueryINetCfgEx( TRUE,
2721 L"VirtualBox Host-Only Creation",
2722 30000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec, */
2723 &pNc, /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
2724 &lpszApp );
2725 Assert(hr == S_OK);
2726 if(hr == S_OK)
2727 {
2728 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2729 &GUID_DEVCLASS_NETSERVICE,
2730 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2731 pGuid);
2732 Assert(hr == S_OK);
2733
2734 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2735 &GUID_DEVCLASS_NETTRANS,
2736 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2737 pGuid);
2738 Assert(hr == S_OK);
2739
2740 hr = vboxNetCfgWinEnumNetCfgComponents(pNc,
2741 &GUID_DEVCLASS_NETCLIENT,
2742 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
2743 pGuid);
2744 Assert(hr == S_OK);
2745
2746 if(hr == S_OK)
2747 {
2748 hr = pNc->Apply();
2749 Assert(hr == S_OK);
2750 }
2751
2752 VBoxNetCfgWinReleaseINetCfg(pNc, TRUE);
2753 }
2754 else if(hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
2755 {
2756 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: app %s is holding the lock, failed\n", lpszApp);
2757 CoTaskMemFree(lpszApp);
2758 }
2759 else
2760 {
2761 Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: VBoxNetCfgWinQueryINetCfgEx failed, hr 0x%x\n", hr);
2762 }
2763 }
2764
2765 return hrc;
2766}
2767
2768#undef SetErrBreak
2769
2770#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
2771VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName (PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
2772{
2773 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
2774 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
2775 ULONG cbSufSize = 0;
2776
2777 if(pSuffix)
2778 {
2779 cbSize += (ULONG)wcslen(pSuffix) * 2;
2780 cbSize += 2; /* for space */
2781 }
2782
2783 if(*pcbBuf < cbSize)
2784 {
2785 *pcbBuf = cbSize;
2786 return E_FAIL;
2787 }
2788
2789 wcscpy(pBuf, VBOX_CONNECTION_NAME);
2790 if(pSuffix)
2791 {
2792 wcscat(pBuf, L" ");
2793 wcscat(pBuf, pSuffix);
2794 }
2795
2796 return S_OK;
2797}
2798
2799/* network settings config */
2800/**
2801 * Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
2802 */
2803template <class C>
2804class ComStrongRef
2805{
2806protected:
2807
2808 static void addref (C *p) { p->AddRef(); }
2809 static void release (C *p) { p->Release(); }
2810};
2811
2812/**
2813 * Weak referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
2814 */
2815template <class C>
2816class ComWeakRef
2817{
2818protected:
2819
2820 static void addref (C * /* p */) {}
2821 static void release (C * /* p */) {}
2822};
2823
2824/**
2825 * Base template for smart COM pointers. Not intended to be used directly.
2826 */
2827template <class C, template <class> class RefOps = ComStrongRef>
2828class ComPtrBase : protected RefOps <C>
2829{
2830public:
2831
2832 /* special template to disable AddRef()/Release() */
2833 template <class I>
2834 class NoAddRefRelease : public I
2835 {
2836 private:
2837#if !defined (VBOX_WITH_XPCOM)
2838 STDMETHOD_(ULONG, AddRef)() = 0;
2839 STDMETHOD_(ULONG, Release)() = 0;
2840#else /* !defined (VBOX_WITH_XPCOM) */
2841 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
2842 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
2843#endif /* !defined (VBOX_WITH_XPCOM) */
2844 };
2845
2846protected:
2847
2848 ComPtrBase () : p (NULL) {}
2849 ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
2850 ComPtrBase (C *that_p) : p (that_p) { addref(); }
2851
2852 ~ComPtrBase() { release(); }
2853
2854 ComPtrBase &operator= (const ComPtrBase &that)
2855 {
2856 safe_assign (that.p);
2857 return *this;
2858 }
2859
2860 ComPtrBase &operator= (C *that_p)
2861 {
2862 safe_assign (that_p);
2863 return *this;
2864 }
2865
2866public:
2867
2868 void setNull()
2869 {
2870 release();
2871 p = NULL;
2872 }
2873
2874 bool isNull() const
2875 {
2876 return (p == NULL);
2877 }
2878
2879 bool operator! () const { return isNull(); }
2880
2881 bool operator< (C* that_p) const { return p < that_p; }
2882 bool operator== (C* that_p) const { return p == that_p; }
2883
2884 template <class I>
2885 bool equalsTo (I *aThat) const
2886 {
2887 return ComPtrEquals (p, aThat);
2888 }
2889
2890 template <class OC>
2891 bool equalsTo (const ComPtrBase <OC> &oc) const
2892 {
2893 return equalsTo ((OC *) oc);
2894 }
2895
2896 /** Intended to pass instances as in parameters to interface methods */
2897 operator C* () const { return p; }
2898
2899 /**
2900 * Dereferences the instance (redirects the -> operator to the managed
2901 * pointer).
2902 */
2903 NoAddRefRelease <C> *operator-> () const
2904 {
2905 AssertMsg (p, ("Managed pointer must not be null\n"));
2906 return (NoAddRefRelease <C> *) p;
2907 }
2908
2909 template <class I>
2910 HRESULT queryInterfaceTo (I **pp) const
2911 {
2912 if (pp)
2913 {
2914 if (p)
2915 {
2916 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
2917 }
2918 else
2919 {
2920 *pp = NULL;
2921 return S_OK;
2922 }
2923 }
2924
2925 return E_INVALIDARG;
2926 }
2927
2928 /** Intended to pass instances as out parameters to interface methods */
2929 C **asOutParam()
2930 {
2931 setNull();
2932 return &p;
2933 }
2934
2935private:
2936
2937 void addref()
2938 {
2939 if (p)
2940 RefOps <C>::addref (p);
2941 }
2942
2943 void release()
2944 {
2945 if (p)
2946 RefOps <C>::release (p);
2947 }
2948
2949 void safe_assign (C *that_p)
2950 {
2951 /* be aware of self-assignment */
2952 if (that_p)
2953 RefOps <C>::addref (that_p);
2954 release();
2955 p = that_p;
2956 }
2957
2958 C *p;
2959};
2960
2961/**
2962 * Smart COM pointer wrapper that automatically manages refcounting of
2963 * interface pointers.
2964 *
2965 * @param I COM interface class
2966 */
2967template <class I, template <class> class RefOps = ComStrongRef>
2968class ComPtr : public ComPtrBase <I, RefOps>
2969{
2970 typedef ComPtrBase <I, RefOps> Base;
2971
2972public:
2973
2974 ComPtr () : Base() {}
2975 ComPtr (const ComPtr &that) : Base (that) {}
2976 ComPtr &operator= (const ComPtr &that)
2977 {
2978 Base::operator= (that);
2979 return *this;
2980 }
2981
2982 template <class OI>
2983 ComPtr (OI *that_p) : Base () { operator= (that_p); }
2984
2985 /* specialization for I */
2986 ComPtr (I *that_p) : Base (that_p) {}
2987
2988 template <class OC>
2989 ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
2990
2991 template <class OI>
2992 ComPtr &operator= (OI *that_p)
2993 {
2994 if (that_p)
2995 that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
2996 else
2997 Base::setNull();
2998 return *this;
2999 }
3000
3001 /* specialization for I */
3002 ComPtr &operator=(I *that_p)
3003 {
3004 Base::operator= (that_p);
3005 return *this;
3006 }
3007
3008 template <class OC>
3009 ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
3010 {
3011 return operator= ((OC *) oc);
3012 }
3013};
3014
3015static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const GUID * pGuid, IWbemClassObject **pAdapterConfig)
3016{
3017 HRESULT hres;
3018 WCHAR aQueryString[256];
3019 WCHAR GuidString[50];
3020
3021 int length = StringFromGUID2(*pGuid, GuidString, sizeof(GuidString)/sizeof(GuidString[0]));
3022 if(length)
3023 {
3024 swprintf(aQueryString, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", GuidString);
3025 // Step 6: --------------------------------------------------
3026 // Use the IWbemServices pointer to make requests of WMI ----
3027
3028 IEnumWbemClassObject* pEnumerator = NULL;
3029 hres = pSvc->ExecQuery(
3030 bstr_t("WQL"),
3031 bstr_t(aQueryString),
3032 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
3033 NULL,
3034 &pEnumerator);
3035 if(SUCCEEDED(hres))
3036 {
3037 // Step 7: -------------------------------------------------
3038 // Get the data from the query in step 6 -------------------
3039
3040 IWbemClassObject *pclsObj;
3041 ULONG uReturn = 0;
3042
3043 if (pEnumerator)
3044 {
3045 HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
3046 &pclsObj, &uReturn);
3047
3048 if(SUCCEEDED(hres))
3049 {
3050 if(uReturn)
3051 {
3052 pEnumerator->Release();
3053 *pAdapterConfig = pclsObj;
3054 hres = S_OK;
3055 return hres;
3056 }
3057 else
3058 {
3059 hres = S_FALSE;
3060 }
3061 }
3062
3063 pEnumerator->Release();
3064 }
3065 }
3066 else
3067 {
3068 Log(L"Query for operating system name failed. Error code = 0x%x\n", hres);
3069 }
3070 }
3071 else
3072 {
3073 DWORD winEr = GetLastError();
3074 Log(L"Failed to create guid string from guid, winEr (%d)\n", winEr);
3075 hres = HRESULT_FROM_WIN32( winEr );
3076 }
3077
3078 return hres;
3079}
3080
3081static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
3082{
3083 VARIANT vtServiceName;
3084 BOOL bIsHostOnly = FALSE;
3085 VariantInit(&vtServiceName);
3086
3087 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0, &vtServiceName, 0, 0);
3088 if(SUCCEEDED(hr))
3089 {
3090 *pbIsHostOnly = (bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp"));
3091
3092 VariantClear(&vtServiceName);
3093 }
3094
3095 return hr;
3096}
3097
3098static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
3099{
3100 VARIANT vtIp;
3101 HRESULT hr;
3102 VariantInit(&vtIp);
3103
3104 *pIpv4 = 0;
3105 *pMaskv4 = 0;
3106
3107 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
3108 if(SUCCEEDED(hr))
3109 {
3110 if(vtIp.vt == (VT_ARRAY | VT_BSTR))
3111 {
3112 VARIANT vtMask;
3113 VariantInit(&vtMask);
3114 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
3115 if(SUCCEEDED(hr))
3116 {
3117 if(vtMask.vt == (VT_ARRAY | VT_BSTR))
3118 {
3119 SAFEARRAY * pIpArray = vtIp.parray;
3120 SAFEARRAY * pMaskArray = vtMask.parray;
3121 if(pIpArray && pMaskArray)
3122 {
3123 BSTR pCurIp;
3124 BSTR pCurMask;
3125 for(long index = 0;
3126 SafeArrayGetElement(pIpArray, &index, (PVOID)&pCurIp) == S_OK
3127 && SafeArrayGetElement(pMaskArray, &index, (PVOID)&pCurMask) == S_OK;
3128 index++)
3129 {
3130 _bstr_t ip(pCurIp);
3131
3132 ULONG Ipv4 = inet_addr((char*)(ip));
3133 if(Ipv4 != INADDR_NONE)
3134 {
3135 *pIpv4 = Ipv4;
3136 _bstr_t mask(pCurMask);
3137 *pMaskv4 = inet_addr((char*)(mask));
3138 break;
3139 }
3140 }
3141 }
3142 }
3143 else
3144 {
3145 *pIpv4 = 0;
3146 *pMaskv4 = 0;
3147 }
3148
3149 VariantClear(&vtMask);
3150 }
3151 }
3152 else
3153 {
3154 *pIpv4 = 0;
3155 *pMaskv4 = 0;
3156 }
3157
3158 VariantClear(&vtIp);
3159 }
3160
3161 return hr;
3162}
3163
3164
3165static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
3166{
3167 VARIANT vtIp;
3168 HRESULT hr;
3169 VariantInit(&vtIp);
3170
3171 *pFound = false;
3172
3173 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
3174 if(SUCCEEDED(hr))
3175 {
3176 VARIANT vtMask;
3177 VariantInit(&vtMask);
3178 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
3179 if(SUCCEEDED(hr))
3180 {
3181 SAFEARRAY * pIpArray = vtIp.parray;
3182 SAFEARRAY * pMaskArray = vtMask.parray;
3183 if(pIpArray && pMaskArray)
3184 {
3185 BSTR pIp, pMask;
3186 for(long k = 0;
3187 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
3188 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
3189 k++)
3190 {
3191 BSTR pCurIp;
3192 BSTR pCurMask;
3193 for(long index = 0;
3194 SafeArrayGetElement(pIpArray, &index, (PVOID)&pCurIp) == S_OK
3195 && SafeArrayGetElement(pMaskArray, &index, (PVOID)&pCurMask) == S_OK;
3196 index++)
3197 {
3198 if(!wcsicmp(pCurIp, pIp))
3199 {
3200 if(!wcsicmp(pCurMask, pMask))
3201 {
3202 *pFound = true;
3203 }
3204 break;
3205 }
3206 }
3207 }
3208 }
3209
3210
3211 VariantClear(&vtMask);
3212 }
3213
3214 VariantClear(&vtIp);
3215 }
3216
3217 return hr;
3218}
3219
3220static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
3221{
3222 /* on Vista we need to wait for the address to get applied */
3223 /* wait for the address to appear in the list */
3224 HRESULT hr = S_OK;
3225 ULONG i;
3226 *pFound = false;
3227 ComPtr <IWbemClassObject> pAdapterConfig;
3228 for(i = 0;
3229 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
3230 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
3231 && !(*pFound)
3232 && i < sec2Wait/6;
3233 i++)
3234 {
3235 Sleep(6000);
3236 }
3237
3238 return hr;
3239}
3240
3241static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
3242{
3243 HRESULT hres;
3244
3245 // Step 3: ---------------------------------------------------
3246 // Obtain the initial locator to WMI -------------------------
3247
3248 IWbemLocator *pLoc = NULL;
3249
3250 hres = CoCreateInstance(
3251 CLSID_WbemLocator,
3252 0,
3253 CLSCTX_INPROC_SERVER,
3254 IID_IWbemLocator, (LPVOID *) &pLoc);
3255 if(SUCCEEDED(hres))
3256 {
3257 // Step 4: -----------------------------------------------------
3258 // Connect to WMI through the IWbemLocator::ConnectServer method
3259
3260 IWbemServices *pSvc = NULL;
3261
3262 // Connect to the root\cimv2 namespace with
3263 // the current user and obtain pointer pSvc
3264 // to make IWbemServices calls.
3265 hres = pLoc->ConnectServer(
3266 _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
3267 NULL, // User name. NULL = current user
3268 NULL, // User password. NULL = current
3269 0, // Locale. NULL indicates current
3270 NULL, // Security flags.
3271 0, // Authority (e.g. Kerberos)
3272 0, // Context object
3273 &pSvc // pointer to IWbemServices proxy
3274 );
3275 if(SUCCEEDED(hres))
3276 {
3277 Log(L"Connected to ROOT\\CIMV2 WMI namespace\n");
3278
3279 // Step 5: --------------------------------------------------
3280 // Set security levels on the proxy -------------------------
3281
3282 hres = CoSetProxyBlanket(
3283 pSvc, // Indicates the proxy to set
3284 RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
3285 RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
3286 NULL, // Server principal name
3287 RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
3288 RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
3289 NULL, // client identity
3290 EOAC_NONE // proxy capabilities
3291 );
3292 if(SUCCEEDED(hres))
3293 {
3294 *ppSvc = pSvc;
3295 /* do not need it any more */
3296 pLoc->Release();
3297 return hres;
3298 }
3299 else
3300 {
3301 Log(L"Could not set proxy blanket. Error code = 0x%x\n", hres);
3302 }
3303
3304 pSvc->Release();
3305 }
3306 else
3307 {
3308 Log(L"Could not connect. Error code = 0x%x\n", hres);
3309 }
3310
3311 pLoc->Release();
3312 }
3313 else
3314 {
3315 Log(L"Failed to create IWbemLocator object. Err code = 0x%x\n", hres);
3316// CoUninitialize();
3317 }
3318
3319 return hres;
3320}
3321
3322static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
3323{
3324 VARIANT index;
3325
3326 // Get the value of the key property
3327 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
3328 if(SUCCEEDED(hr))
3329 {
3330 WCHAR strIndex[8];
3331 swprintf(strIndex, L"%u", index.uintVal);
3332 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
3333 }
3334 else
3335 {
3336 DWORD dwError = GetLastError();
3337 Assert(0);
3338 hr = HRESULT_FROM_WIN32( dwError );
3339 }
3340 return hr;
3341}
3342
3343static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
3344 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
3345 IWbemClassObject** ppOutParams
3346 )
3347{
3348 HRESULT hres = S_OK;
3349 // Step 6: --------------------------------------------------
3350 // Use the IWbemServices pointer to make requests of WMI ----
3351
3352 ComPtr<IWbemClassObject> pInParamsDefinition;
3353 ComPtr<IWbemClassObject> pClassInstance;
3354
3355 if(cArgs)
3356 {
3357 hres = pClass->GetMethod(MethodName, 0,
3358 pInParamsDefinition.asOutParam(), NULL);
3359 if(SUCCEEDED(hres))
3360 {
3361 hres = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
3362
3363 if(SUCCEEDED(hres))
3364 {
3365 for(UINT i = 0; i < cArgs; i++)
3366 {
3367 // Store the value for the in parameters
3368 hres = pClassInstance->Put(pArgNames[i], 0,
3369 pArgs[i], 0);
3370 if(FAILED(hres))
3371 {
3372 break;
3373 }
3374 }
3375 }
3376 }
3377 }
3378
3379 if(SUCCEEDED(hres))
3380 {
3381 IWbemClassObject* pOutParams = NULL;
3382 hres = pSvc->ExecMethod(ObjPath, MethodName, 0,
3383 NULL, pClassInstance, &pOutParams, NULL);
3384 if(SUCCEEDED(hres))
3385 {
3386 *ppOutParams = pOutParams;
3387 }
3388 }
3389
3390 return hres;
3391}
3392
3393static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
3394{
3395 HRESULT hr;
3396 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
3397 if(pIpArray)
3398 {
3399 for(UINT i = 0; i < cIp; i++)
3400 {
3401 char* addr = inet_ntoa(aIp[i]);
3402 BSTR val = bstr_t(addr).copy();
3403 long aIndex[1];
3404 aIndex[0] = i;
3405 hr = SafeArrayPutElement(pIpArray, aIndex, val);
3406 if(FAILED(hr))
3407 {
3408 SysFreeString(val);
3409 SafeArrayDestroy(pIpArray);
3410 break;
3411 }
3412 }
3413
3414 if(SUCCEEDED(hr))
3415 {
3416 *ppArray = pIpArray;
3417 }
3418 }
3419 else
3420 {
3421 DWORD dwError = GetLastError();
3422 Assert(0);
3423 hr = HRESULT_FROM_WIN32( dwError );
3424 }
3425
3426 return hr;
3427}
3428
3429static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
3430{
3431 HRESULT hr;
3432 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
3433 if(pIpArray)
3434 {
3435 BSTR val = bstr_t(Ip, false).copy();
3436 long aIndex[1];
3437 aIndex[0] = 0;
3438 hr = SafeArrayPutElement(pIpArray, aIndex, val);
3439 if(FAILED(hr))
3440 {
3441 SysFreeString(val);
3442 SafeArrayDestroy(pIpArray);
3443 }
3444
3445 if(SUCCEEDED(hr))
3446 {
3447 *ppArray = pIpArray;
3448 }
3449 }
3450 else
3451 {
3452 DWORD dwError = GetLastError();
3453 Assert(0);
3454 hr = HRESULT_FROM_WIN32( dwError );
3455 }
3456
3457 return hr;
3458}
3459
3460
3461static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
3462{
3463 HRESULT hr;
3464 VariantInit(pIpAddresses);
3465 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
3466 SAFEARRAY *pIpArray;
3467 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
3468 if(SUCCEEDED(hr))
3469 {
3470 pIpAddresses->parray = pIpArray;
3471 }
3472 return hr;
3473}
3474
3475static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
3476{
3477 HRESULT hr;
3478 VariantInit(pIpAddresses);
3479 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
3480 SAFEARRAY *pIpArray;
3481 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
3482 if(SUCCEEDED(hr))
3483 {
3484 pIpAddresses->parray = pIpArray;
3485 }
3486 return hr;
3487}
3488
3489static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
3490{
3491 ComPtr<IWbemClassObject> pClass;
3492 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3493 HRESULT hr;
3494 if(ClassName)
3495 {
3496 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3497 if(SUCCEEDED(hr))
3498 {
3499 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
3500 LPVARIANT args[] = {pIp, pMask};
3501 ComPtr<IWbemClassObject> pOutParams;
3502
3503 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3504 bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
3505 if(SUCCEEDED(hr))
3506 {
3507 VARIANT varReturnValue;
3508 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3509 &varReturnValue, NULL, 0);
3510 Assert(SUCCEEDED(hr));
3511 if(SUCCEEDED(hr))
3512 {
3513// Assert(varReturnValue.vt == VT_UINT);
3514 int winEr = varReturnValue.uintVal;
3515 switch(winEr)
3516 {
3517 case 0:
3518 {
3519 hr = S_OK;
3520// bool bFound;
3521// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
3522 }
3523 break;
3524 default:
3525 hr = HRESULT_FROM_WIN32( winEr );
3526 break;
3527 }
3528 }
3529 }
3530 }
3531 SysFreeString(ClassName);
3532 }
3533 else
3534 {
3535 DWORD dwError = GetLastError();
3536 Assert(0);
3537 hr = HRESULT_FROM_WIN32( dwError );
3538 }
3539
3540 return hr;
3541}
3542
3543
3544static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
3545{
3546 VARIANT ipAddresses;
3547 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
3548 if(SUCCEEDED(hr))
3549 {
3550 VARIANT ipMasks;
3551 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
3552 if(SUCCEEDED(hr))
3553 {
3554 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
3555 VariantClear(&ipMasks);
3556 }
3557 VariantClear(&ipAddresses);
3558 }
3559 return hr;
3560}
3561
3562static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
3563{
3564 VARIANT ipAddresses;
3565 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
3566 if(SUCCEEDED(hr))
3567 {
3568 VARIANT ipMasks;
3569 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
3570 if(SUCCEEDED(hr))
3571 {
3572 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
3573 VariantClear(&ipMasks);
3574 }
3575 VariantClear(&ipAddresses);
3576 }
3577 return hr;
3578}
3579
3580/* win API allows to set gw metrics as well, we are not setting them */
3581static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
3582{
3583 ComPtr<IWbemClassObject> pClass;
3584 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3585 HRESULT hr;
3586 if(ClassName)
3587 {
3588 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3589 if(SUCCEEDED(hr))
3590 {
3591 LPWSTR argNames[] = {L"DefaultIPGateway"};
3592 LPVARIANT args[] = {pGw};
3593 ComPtr<IWbemClassObject> pOutParams;
3594
3595 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3596 bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
3597 if(SUCCEEDED(hr))
3598 {
3599 VARIANT varReturnValue;
3600 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3601 &varReturnValue, NULL, 0);
3602 Assert(SUCCEEDED(hr));
3603 if(SUCCEEDED(hr))
3604 {
3605// Assert(varReturnValue.vt == VT_UINT);
3606 int winEr = varReturnValue.uintVal;
3607 switch(winEr)
3608 {
3609 case 0:
3610 hr = S_OK;
3611 break;
3612 default:
3613 hr = HRESULT_FROM_WIN32( winEr );
3614 break;
3615 }
3616 }
3617 } }
3618 SysFreeString(ClassName);
3619 }
3620 else
3621 {
3622 DWORD dwError = GetLastError();
3623 Assert(0);
3624 hr = HRESULT_FROM_WIN32( dwError );
3625 }
3626
3627 return hr;
3628}
3629
3630/* win API allows to set gw metrics as well, we are not setting them */
3631static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
3632{
3633 VARIANT gwais;
3634 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
3635 if(SUCCEEDED(hr))
3636 {
3637 netIfWinSetGateways(pSvc, ObjPath, &gwais);
3638 VariantClear(&gwais);
3639 }
3640 return hr;
3641}
3642
3643/* win API allows to set gw metrics as well, we are not setting them */
3644static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
3645{
3646 VARIANT vGw;
3647 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
3648 if(SUCCEEDED(hr))
3649 {
3650 netIfWinSetGateways(pSvc, ObjPath, &vGw);
3651 VariantClear(&vGw);
3652 }
3653 return hr;
3654}
3655
3656static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
3657{
3658 ComPtr<IWbemClassObject> pClass;
3659 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3660 HRESULT hr;
3661 if(ClassName)
3662 {
3663 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3664 if(SUCCEEDED(hr))
3665 {
3666 ComPtr<IWbemClassObject> pOutParams;
3667
3668 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3669 bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
3670 if(SUCCEEDED(hr))
3671 {
3672 VARIANT varReturnValue;
3673 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3674 &varReturnValue, NULL, 0);
3675 Assert(SUCCEEDED(hr));
3676 if(SUCCEEDED(hr))
3677 {
3678// Assert(varReturnValue.vt == VT_UINT);
3679 int winEr = varReturnValue.uintVal;
3680 switch(winEr)
3681 {
3682 case 0:
3683 hr = S_OK;
3684 break;
3685 default:
3686 hr = HRESULT_FROM_WIN32( winEr );
3687 break;
3688 }
3689 }
3690 }
3691 }
3692 SysFreeString(ClassName);
3693 }
3694 else
3695 {
3696 DWORD dwError = GetLastError();
3697 Assert(0);
3698 hr = HRESULT_FROM_WIN32( dwError );
3699 }
3700
3701 return hr;
3702}
3703
3704static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
3705{
3706 ComPtr<IWbemClassObject> pClass;
3707 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
3708 HRESULT hr;
3709 if(ClassName)
3710 {
3711 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
3712 if(SUCCEEDED(hr))
3713 {
3714 ComPtr<IWbemClassObject> pOutParams;
3715
3716 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3717 bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
3718 if(SUCCEEDED(hr))
3719 {
3720 VARIANT varReturnValue;
3721 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3722 &varReturnValue, NULL, 0);
3723 Assert(SUCCEEDED(hr));
3724 if(SUCCEEDED(hr))
3725 {
3726// Assert(varReturnValue.vt == VT_UINT);
3727 int winEr = varReturnValue.uintVal;
3728 if(winEr == 0)
3729 {
3730 hr = netIfExecMethod(pSvc, pClass, ObjPath,
3731 bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
3732 if(SUCCEEDED(hr))
3733 {
3734 VARIANT varReturnValue;
3735 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
3736 &varReturnValue, NULL, 0);
3737 Assert(SUCCEEDED(hr));
3738 if(SUCCEEDED(hr))
3739 {
3740 // Assert(varReturnValue.vt == VT_UINT);
3741 int winEr = varReturnValue.uintVal;
3742 if(winEr == 0)
3743 {
3744 hr = S_OK;
3745 }
3746 else
3747 {
3748 hr = HRESULT_FROM_WIN32( winEr );
3749 }
3750 }
3751 }
3752 }
3753 else
3754 {
3755 hr = HRESULT_FROM_WIN32( winEr );
3756 }
3757 }
3758 }
3759 }
3760 SysFreeString(ClassName);
3761 }
3762 else
3763 {
3764 DWORD dwError = GetLastError();
3765 Assert(0);
3766 hr = HRESULT_FROM_WIN32( dwError );
3767 }
3768
3769 return hr;
3770}
3771
3772static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
3773{
3774 VARIANT vtEnabled;
3775 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
3776 if(SUCCEEDED(hr))
3777 {
3778 *pEnabled = vtEnabled.boolVal;
3779 }
3780 return hr;
3781}
3782
3783VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(const GUID * pGuid, PADAPTER_SETTINGS pSettings)
3784{
3785 HRESULT hr;
3786 ComPtr <IWbemServices> pSvc;
3787 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3788 if(SUCCEEDED(hr))
3789 {
3790 ComPtr <IWbemClassObject> pAdapterConfig;
3791 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3792 if(hr == S_OK)
3793 {
3794 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
3795 if(SUCCEEDED(hr))
3796 {
3797 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
3798 }
3799 }
3800 }
3801
3802 return hr;
3803}
3804
3805VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
3806{
3807 HRESULT hr;
3808 ComPtr <IWbemServices> pSvc;
3809 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3810 if(SUCCEEDED(hr))
3811 {
3812 ComPtr <IWbemClassObject> pAdapterConfig;
3813 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3814 if(hr == S_OK)
3815 {
3816 VARIANT vtEnabled;
3817 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
3818 if(SUCCEEDED(hr))
3819 {
3820 *pEnabled = vtEnabled.boolVal;
3821 }
3822 }
3823 }
3824
3825 return hr;
3826}
3827
3828VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(const GUID *pGuid, ULONG ip, ULONG mask)
3829{
3830 HRESULT hr;
3831 ComPtr <IWbemServices> pSvc;
3832 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3833 if(SUCCEEDED(hr))
3834 {
3835 ComPtr <IWbemClassObject> pAdapterConfig;
3836 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3837 if(hr == S_OK)
3838 {
3839 BOOL bIsHostOnly;
3840 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3841 if(SUCCEEDED(hr))
3842 {
3843 if(bIsHostOnly)
3844 {
3845 in_addr aIp[1];
3846 in_addr aMask[1];
3847 aIp[0].S_un.S_addr = ip;
3848 aMask[0].S_un.S_addr = mask;
3849
3850 BSTR ObjPath;
3851 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3852 if(SUCCEEDED(hr))
3853 {
3854 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
3855 if(SUCCEEDED(hr))
3856 {
3857#if 0
3858 in_addr aGw[1];
3859 aGw[0].S_un.S_addr = gw;
3860 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
3861 if(SUCCEEDED(hr))
3862#endif
3863 {
3864 }
3865 }
3866 SysFreeString(ObjPath);
3867 }
3868 }
3869 else
3870 {
3871 hr = E_FAIL;
3872 }
3873 }
3874 }
3875 }
3876
3877 return hr;
3878}
3879
3880#if 0
3881static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
3882{
3883 HRESULT hr;
3884 ComPtr <IWbemServices> pSvc;
3885 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3886 if(SUCCEEDED(hr))
3887 {
3888 ComPtr <IWbemClassObject> pAdapterConfig;
3889 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3890 if(hr == S_OK)
3891 {
3892 BSTR ObjPath;
3893 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3894 if(SUCCEEDED(hr))
3895 {
3896 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
3897 if(SUCCEEDED(hr))
3898 {
3899 if(aIPV6DefaultGateway)
3900 {
3901 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
3902 }
3903 if(SUCCEEDED(hr))
3904 {
3905// hr = netIfWinUpdateConfig(pIf);
3906 }
3907 }
3908 SysFreeString(ObjPath);
3909 }
3910 }
3911 }
3912
3913 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
3914}
3915
3916static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
3917{
3918 RTNETADDRIPV6 Mask;
3919 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
3920 if(RT_SUCCESS(rc))
3921 {
3922 Bstr maskStr = composeIPv6Address(&Mask);
3923 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
3924 }
3925 return rc;
3926}
3927#endif
3928
3929VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(const GUID *pGuid)
3930{
3931 HRESULT hr;
3932 ComPtr <IWbemServices> pSvc;
3933 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3934 if(SUCCEEDED(hr))
3935 {
3936 ComPtr <IWbemClassObject> pAdapterConfig;
3937 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3938 if(hr == S_OK)
3939 {
3940 BOOL bIsHostOnly;
3941 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3942 if(SUCCEEDED(hr))
3943 {
3944 if(bIsHostOnly)
3945 {
3946 BSTR ObjPath;
3947 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3948 if(SUCCEEDED(hr))
3949 {
3950 hr = netIfWinEnableDHCP(pSvc, ObjPath);
3951 if(SUCCEEDED(hr))
3952 {
3953// hr = netIfWinUpdateConfig(pIf);
3954 }
3955 SysFreeString(ObjPath);
3956 }
3957 }
3958 else
3959 {
3960 hr = E_FAIL;
3961 }
3962 }
3963 }
3964 }
3965
3966
3967 return hr;
3968}
3969
3970VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(const GUID *pGuid)
3971{
3972 HRESULT hr;
3973 ComPtr <IWbemServices> pSvc;
3974 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
3975 if(SUCCEEDED(hr))
3976 {
3977 ComPtr <IWbemClassObject> pAdapterConfig;
3978 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
3979 if(hr == S_OK)
3980 {
3981 BOOL bIsHostOnly;
3982 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
3983 if(SUCCEEDED(hr))
3984 {
3985 if(bIsHostOnly)
3986 {
3987 BSTR ObjPath;
3988 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
3989 if(SUCCEEDED(hr))
3990 {
3991 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
3992 if(SUCCEEDED(hr))
3993 {
3994// hr = netIfWinUpdateConfig(pIf);
3995 }
3996 SysFreeString(ObjPath);
3997 }
3998 }
3999 else
4000 {
4001 hr = E_FAIL;
4002 }
4003 }
4004 }
4005 }
4006
4007
4008 return hr;
4009}
4010
4011typedef bool (*IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
4012
4013static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, IPSETTINGS_CALLBACK pCallback, PVOID pContext)
4014{
4015 PIP_ADAPTER_ADDRESSES pAdapter;
4016 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
4017 {
4018 PIP_ADAPTER_UNICAST_ADDRESS pAddr = pAdapter->FirstUnicastAddress;
4019 PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix;
4020
4021 if(pAddr && pPrefix)
4022 {
4023 do
4024 {
4025 bool fIPFound, fMaskFound;
4026 fIPFound = fMaskFound = false;
4027 ULONG ip, mask;
4028 for (; pAddr && !fIPFound; pAddr = pAddr->Next)
4029 {
4030 switch (pAddr->Address.lpSockaddr->sa_family)
4031 {
4032 case AF_INET:
4033 fIPFound = true;
4034 memcpy(&ip,
4035 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
4036 sizeof(ip));
4037 break;
4038// case AF_INET6:
4039// break;
4040 }
4041 }
4042
4043 for (; pPrefix && !fMaskFound; pPrefix = pPrefix->Next)
4044 {
4045 switch (pPrefix->Address.lpSockaddr->sa_family)
4046 {
4047 case AF_INET:
4048 if(!pPrefix->PrefixLength || pPrefix->PrefixLength > 31) /* in case the ip helper API is queried while NetCfg write lock is held */
4049 break; /* the address values can contain illegal values */
4050 fMaskFound = true;
4051 mask = (~(((ULONG)~0) >> pPrefix->PrefixLength));
4052 mask = htonl(mask);
4053 break;
4054// case AF_INET6:
4055// break;
4056 }
4057 }
4058
4059 if(!fIPFound || !fMaskFound)
4060 break;
4061
4062 if(!pCallback(ip, mask, pContext))
4063 return;
4064 }while(true);
4065 }
4066 }
4067}
4068
4069typedef struct _IPPROBE_CONTEXT
4070{
4071 ULONG Prefix;
4072 bool bConflict;
4073}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
4074
4075#define IPPROBE_INIT(_pContext, _addr) \
4076 ((_pContext)->bConflict = false, \
4077 (_pContext)->Prefix = _addr)
4078
4079#define IPPROBE_INIT_STR(_pContext, _straddr) \
4080 IPROBE_INIT(_pContext, inet_addr(_straddr))
4081
4082static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
4083{
4084 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
4085
4086 if((ip & mask) == (pProbe->Prefix & mask))
4087 {
4088 pProbe->bConflict = true;
4089 return false;
4090 }
4091
4092 return true;
4093}
4094
4095VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(PULONG pNetIp, PULONG pNetMask)
4096{
4097 DWORD dwRc;
4098 HRESULT hr = S_OK;
4099 /*
4100 * Most of the hosts probably have less than 10 adapters,
4101 * so we'll mostly succeed from the first attempt.
4102 */
4103 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
4104 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
4105 if (!pAddresses)
4106 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
4107 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
4108 if (dwRc == ERROR_BUFFER_OVERFLOW)
4109 {
4110 /* Impressive! More than 10 adapters! Get more memory and try again. */
4111 free(pAddresses);
4112 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
4113 if (!pAddresses)
4114 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
4115 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
4116 }
4117 if (dwRc == NO_ERROR)
4118 {
4119 IPPROBE_CONTEXT Context;
4120 const ULONG ip192168 = inet_addr("192.168.0.0");
4121 srand(GetTickCount());
4122
4123 *pNetIp = 0;
4124 *pNetMask = 0;
4125
4126 for(int i = 0; i < 255; i++)
4127 {
4128 ULONG ipProbe = rand()*255/RAND_MAX;
4129 ipProbe = ip192168 | (ipProbe << 16);
4130 IPPROBE_INIT(&Context, ipProbe);
4131 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
4132 if(!Context.bConflict)
4133 {
4134 *pNetIp = ipProbe;
4135 *pNetMask = inet_addr("255.255.255.0");
4136 break;
4137 }
4138 }
4139 if(*pNetIp == 0)
4140 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
4141 }
4142 else
4143 {
4144 Log(L"VBoxNetCfgWinGenHostOnlyNetworkNetworkIp: GetAdaptersAddresses err (%d)\n", dwRc);
4145 }
4146 free(pAddresses);
4147
4148 if(dwRc != NO_ERROR)
4149 {
4150 hr = HRESULT_FROM_WIN32(dwRc);
4151 }
4152
4153 return hr;
4154}
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