VirtualBox

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

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

2d: basics for FBO (for linear stretching) suport, more impl for guest-mapped PBO, code cleaning, bug-fixes

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