VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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