VirtualBox

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

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

netadp/win: actual inf deletion with NetAdpUninstall, (not yet added to win installer)

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