VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp@ 53082

Last change on this file since 53082 was 53082, checked in by vboxsync, 10 years ago

NetFlt/win: NDIS6: no halt on host suspend, hardware id changed to match the old NDIS5 id

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 104.0 KB
Line 
1/* $Id: VBoxNetCfg.cpp 53082 2014-10-17 06:49:23Z vboxsync $ */
2/** @file
3 * VBoxNetCfg.cpp - Network Configuration API.
4 */
5/*
6 * Copyright (C) 2011-2012 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16#include "VBox/VBoxNetCfg-win.h"
17#include "VBox/VBoxDrvCfg-win.h"
18
19#define _WIN32_DCOM
20
21#include <iphlpapi.h>
22
23#include <devguid.h>
24#include <stdio.h>
25#include <regstr.h>
26#include <shlobj.h>
27#include <cfgmgr32.h>
28#include <tchar.h>
29#include <objbase.h>
30
31#include <crtdbg.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <Wbemidl.h>
36#include <comdef.h>
37
38
39#ifndef Assert /** @todo r=bird: where would this be defined? */
40//# ifdef DEBUG
41//# define Assert(_expr) assert(_expr)
42//# else
43//# define Assert(_expr) do{ }while (0)
44//# endif
45# define Assert _ASSERT
46# define AssertMsg(expr, msg) do{}while (0)
47#endif
48static LOG_ROUTINE g_Logger = NULL;
49
50static VOID DoLogging(LPCSTR szString, ...);
51#define NonStandardLog DoLogging
52#define NonStandardLogFlow(x) DoLogging x
53
54#define DbgLog /** @todo r=bird: What does this do? */
55
56#define VBOX_NETCFG_LOCK_TIME_OUT 5000 /** @todo r=bird: What does this do? */
57
58
59static HRESULT vboxNetCfgWinINetCfgLock(IN INetCfg *pNetCfg,
60 IN LPCWSTR pszwClientDescription,
61 IN DWORD cmsTimeout,
62 OUT LPWSTR *ppszwClientDescription)
63{
64 INetCfgLock *pLock;
65 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
66 if (FAILED(hr))
67 {
68 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
69 return hr;
70 }
71
72 hr = pLock->AcquireWriteLock(cmsTimeout, pszwClientDescription, ppszwClientDescription);
73 if (hr == S_FALSE)
74 {
75 NonStandardLogFlow(("Write lock busy\n"));
76 }
77 else if (FAILED(hr))
78 {
79 NonStandardLogFlow(("AcquireWriteLock failed, hr (0x%x)\n", hr));
80 }
81
82 pLock->Release();
83 return hr;
84}
85
86static HRESULT vboxNetCfgWinINetCfgUnlock(IN INetCfg *pNetCfg)
87{
88 INetCfgLock *pLock;
89 HRESULT hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
90 if (FAILED(hr))
91 {
92 NonStandardLogFlow(("QueryInterface failed, hr (0x%x)\n", hr));
93 return hr;
94 }
95
96 hr = pLock->ReleaseWriteLock();
97 if (FAILED(hr))
98 NonStandardLogFlow(("ReleaseWriteLock failed, hr (0x%x)\n", hr));
99
100 pLock->Release();
101 return hr;
102}
103
104VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinQueryINetCfg(OUT INetCfg **ppNetCfg,
105 IN BOOL fGetWriteLock,
106 IN LPCWSTR pszwClientDescription,
107 IN DWORD cmsTimeout,
108 OUT LPWSTR *ppszwClientDescription)
109{
110 INetCfg *pNetCfg;
111 HRESULT hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNetCfg);
112 if (FAILED(hr))
113 {
114 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
115 return hr;
116 }
117
118 if (fGetWriteLock)
119 {
120 hr = vboxNetCfgWinINetCfgLock(pNetCfg, pszwClientDescription, cmsTimeout, ppszwClientDescription);
121 if (hr == S_FALSE)
122 {
123 NonStandardLogFlow(("Write lock is busy\n", hr));
124 hr = NETCFG_E_NO_WRITE_LOCK;
125 }
126 }
127
128 if (SUCCEEDED(hr))
129 {
130 hr = pNetCfg->Initialize(NULL);
131 if (SUCCEEDED(hr))
132 {
133 *ppNetCfg = pNetCfg;
134 return S_OK;
135 }
136 else
137 NonStandardLogFlow(("Initialize failed, hr (0x%x)\n", hr));
138 }
139
140 pNetCfg->Release();
141 return hr;
142}
143
144VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinReleaseINetCfg(IN INetCfg *pNetCfg, IN BOOL fHasWriteLock)
145{
146 if (!pNetCfg) /* If network config has been released already, just bail out. */
147 {
148 NonStandardLogFlow(("Warning: No network config given but write lock is set to TRUE\n"));
149 return S_OK;
150 }
151
152 HRESULT hr = pNetCfg->Uninitialize();
153 if (FAILED(hr))
154 {
155 NonStandardLogFlow(("Uninitialize failed, hr (0x%x)\n", hr));
156 /* Try to release the write lock below. */
157 }
158
159 if (fHasWriteLock)
160 {
161 HRESULT hr2 = vboxNetCfgWinINetCfgUnlock(pNetCfg);
162 if (FAILED(hr2))
163 NonStandardLogFlow(("vboxNetCfgWinINetCfgUnlock failed, hr (0x%x)\n", hr2));
164 if (SUCCEEDED(hr))
165 hr = hr2;
166 }
167
168 pNetCfg->Release();
169 return hr;
170}
171
172static HRESULT vboxNetCfgWinGetComponentByGuidEnum(IEnumNetCfgComponent *pEnumNcc,
173 IN const GUID *pGuid,
174 OUT INetCfgComponent **ppNcc)
175{
176 HRESULT hr = pEnumNcc->Reset();
177 if (FAILED(hr))
178 {
179 NonStandardLogFlow(("Reset failed, hr (0x%x)\n", hr));
180 return hr;
181 }
182
183 INetCfgComponent *pNcc;
184 while ((hr = pEnumNcc->Next(1, &pNcc, NULL)) == S_OK)
185 {
186 ULONG uComponentStatus;
187 hr = pNcc->GetDeviceStatus(&uComponentStatus);
188 if (SUCCEEDED(hr))
189 {
190 if (uComponentStatus == 0)
191 {
192 GUID NccGuid;
193 hr = pNcc->GetInstanceGuid(&NccGuid);
194
195 if (SUCCEEDED(hr))
196 {
197 if (NccGuid == *pGuid)
198 {
199 /* found the needed device */
200 *ppNcc = pNcc;
201 break;
202 }
203 }
204 else
205 NonStandardLogFlow(("GetInstanceGuid failed, hr (0x%x)\n", hr));
206 }
207 }
208
209 pNcc->Release();
210 }
211 return hr;
212}
213
214VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc,
215 IN const GUID *pguidClass,
216 IN const GUID * pComponentGuid,
217 OUT INetCfgComponent **ppncc)
218{
219 IEnumNetCfgComponent *pEnumNcc;
220 HRESULT hr = pNc->EnumComponents(pguidClass, &pEnumNcc);
221
222 if (SUCCEEDED(hr))
223 {
224 hr = vboxNetCfgWinGetComponentByGuidEnum(pEnumNcc, pComponentGuid, ppncc);
225 if (hr == S_FALSE)
226 {
227 NonStandardLogFlow(("Component not found\n"));
228 }
229 else if (FAILED(hr))
230 {
231 NonStandardLogFlow(("vboxNetCfgWinGetComponentByGuidEnum failed, hr (0x%x)\n", hr));
232 }
233 pEnumNcc->Release();
234 }
235 else
236 NonStandardLogFlow(("EnumComponents failed, hr (0x%x)\n", hr));
237 return hr;
238}
239
240static HRESULT vboxNetCfgWinQueryInstaller(IN INetCfg *pNetCfg, IN const GUID *pguidClass, INetCfgClassSetup **ppSetup)
241{
242 HRESULT hr = pNetCfg->QueryNetCfgClass(pguidClass, IID_INetCfgClassSetup, (void**)ppSetup);
243 if (FAILED(hr))
244 NonStandardLogFlow(("QueryNetCfgClass failed, hr (0x%x)\n", hr));
245 return hr;
246}
247
248VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
249 OUT INetCfgComponent **ppComponent)
250{
251 INetCfgClassSetup *pSetup;
252 HRESULT hr = vboxNetCfgWinQueryInstaller(pNetCfg, pguidClass, &pSetup);
253 if (FAILED(hr))
254 {
255 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
256 return hr;
257 }
258
259 OBO_TOKEN Token;
260 ZeroMemory(&Token, sizeof (Token));
261 Token.Type = OBO_USER;
262
263 hr = pSetup->Install(pszwComponentId, &Token,
264 0, /* IN DWORD dwSetupFlags */
265 0, /* IN DWORD dwUpgradeFromBuildNo */
266 NULL, /* IN LPCWSTR pszwAnswerFile */
267 NULL, /* IN LPCWSTR pszwAnswerSections */
268 ppComponent);
269 if (SUCCEEDED(hr))
270 {
271 /* ignore the apply failure */
272 HRESULT tmpHr = pNetCfg->Apply();
273 Assert(tmpHr == S_OK);
274 if (tmpHr != S_OK)
275 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", tmpHr));
276 }
277 else
278 NonStandardLogFlow(("Install failed, hr (0x%x)\n", hr));
279
280 pSetup->Release();
281 return hr;
282}
283
284static HRESULT vboxNetCfgWinInstallInfAndComponent(IN INetCfg *pNetCfg, IN LPCWSTR pszwComponentId, IN const GUID *pguidClass,
285 IN LPCWSTR const *apInfPaths, IN UINT cInfPaths,
286 OUT INetCfgComponent **ppComponent)
287{
288 HRESULT hr = S_OK;
289 UINT cFilesProcessed = 0;
290
291 NonStandardLogFlow(("Installing %u INF files ...\n", cInfPaths));
292
293 for (; cFilesProcessed < cInfPaths; cFilesProcessed++)
294 {
295 NonStandardLogFlow(("Installing INF file \"%ws\" ...\n", apInfPaths[cFilesProcessed]));
296 hr = VBoxDrvCfgInfInstall(apInfPaths[cFilesProcessed]);
297 if (FAILED(hr))
298 {
299 NonStandardLogFlow(("VBoxNetCfgWinInfInstall failed, hr (0x%x)\n", hr));
300 break;
301 }
302 }
303
304 if (SUCCEEDED(hr))
305 {
306 hr = VBoxNetCfgWinInstallComponent(pNetCfg, pszwComponentId, pguidClass, ppComponent);
307 if (FAILED(hr))
308 NonStandardLogFlow(("VBoxNetCfgWinInstallComponent failed, hr (0x%x)\n", hr));
309 }
310
311 if (FAILED(hr))
312 {
313 NonStandardLogFlow(("Installation failed, rolling back installation set ...\n"));
314
315 do
316 {
317 HRESULT hr2 = VBoxDrvCfgInfUninstall(apInfPaths[cFilesProcessed], 0);
318 if (FAILED(hr2))
319 NonStandardLogFlow(("VBoxDrvCfgInfUninstall failed, hr (0x%x)\n", hr2));
320 /* Keep going. */
321 if (!cFilesProcessed)
322 break;
323 } while (cFilesProcessed--);
324
325 NonStandardLogFlow(("Rollback complete\n"));
326 }
327
328 return hr;
329}
330
331VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUninstallComponent(IN INetCfg *pNetCfg, IN INetCfgComponent *pComponent)
332{
333 GUID GuidClass;
334 HRESULT hr = pComponent->GetClassGuid(&GuidClass);
335 if (FAILED(hr))
336 {
337 NonStandardLogFlow(("GetClassGuid failed, hr (0x%x)\n", hr));
338 return hr;
339 }
340
341 INetCfgClassSetup *pSetup = NULL;
342 hr = vboxNetCfgWinQueryInstaller(pNetCfg, &GuidClass, &pSetup);
343 if (FAILED(hr))
344 {
345 NonStandardLogFlow(("vboxNetCfgWinQueryInstaller failed, hr (0x%x)\n", hr));
346 return hr;
347 }
348
349 OBO_TOKEN Token;
350 ZeroMemory(&Token, sizeof(Token));
351 Token.Type = OBO_USER;
352
353 hr = pSetup->DeInstall(pComponent, &Token, NULL /* OUT LPWSTR *pmszwRefs */);
354 if (SUCCEEDED(hr))
355 {
356 hr = pNetCfg->Apply();
357 if (FAILED(hr))
358 NonStandardLogFlow(("Apply failed, hr (0x%x)\n", hr));
359 }
360 else
361 NonStandardLogFlow(("DeInstall failed, hr (0x%x)\n", hr));
362
363 if (pSetup)
364 pSetup->Release();
365 return hr;
366}
367
368typedef BOOL (*VBOXNETCFGWIN_NETCFGENUM_CALLBACK) (IN INetCfg *pNetCfg, IN INetCfgComponent *pNetCfgComponent, PVOID pContext);
369
370static HRESULT vboxNetCfgWinEnumNetCfgComponents(IN INetCfg *pNetCfg,
371 IN const GUID *pguidClass,
372 VBOXNETCFGWIN_NETCFGENUM_CALLBACK callback,
373 PVOID pContext)
374{
375 IEnumNetCfgComponent *pEnumComponent;
376 HRESULT hr = pNetCfg->EnumComponents(pguidClass, &pEnumComponent);
377 if (SUCCEEDED(hr))
378 {
379 INetCfgComponent *pNetCfgComponent;
380 hr = pEnumComponent->Reset();
381 do
382 {
383 hr = pEnumComponent->Next(1, &pNetCfgComponent, NULL);
384 if (hr == S_OK)
385 {
386// ULONG uComponentStatus;
387// hr = pNcc->GetDeviceStatus(&uComponentStatus);
388// if (SUCCEEDED(hr))
389 BOOL fResult = FALSE;
390 if (pNetCfgComponent)
391 {
392 if (pContext)
393 fResult = callback(pNetCfg, pNetCfgComponent, pContext);
394 pNetCfgComponent->Release();
395 }
396
397 if (!fResult)
398 break;
399 }
400 else
401 {
402 if (hr == S_FALSE)
403 {
404 hr = S_OK;
405 }
406 else
407 NonStandardLogFlow(("Next failed, hr (0x%x)\n", hr));
408 break;
409 }
410 } while (true);
411 pEnumComponent->Release();
412 }
413 return hr;
414}
415
416/*
417 * Forward declarations of functions used in vboxNetCfgWinRemoveAllNetDevicesOfIdCallback.
418 */
419VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf);
420VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection(LPWSTR pGuid, PCWSTR NewName);
421
422static BOOL vboxNetCfgWinRemoveAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
423{
424 SP_REMOVEDEVICE_PARAMS rmdParams;
425 memset(&rmdParams, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
426 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
427 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
428 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
429
430 if (SetupDiSetClassInstallParams(hDevInfo,pDev,
431 &rmdParams.ClassInstallHeader, sizeof(rmdParams)))
432 {
433 if (SetupDiSetSelectedDevice(hDevInfo, pDev))
434 {
435 /* Figure out NetCfgInstanceId. */
436 HKEY hKey = SetupDiOpenDevRegKey(hDevInfo,
437 pDev,
438 DICS_FLAG_GLOBAL,
439 0,
440 DIREG_DRV,
441 KEY_READ);
442 if (hKey == INVALID_HANDLE_VALUE)
443 {
444 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiOpenDevRegKey failed with error %ld\n",
445 GetLastError()));
446 }
447 else
448 {
449 WCHAR wszCfgGuidString[50] = { L'' };
450 DWORD cbSize = sizeof(wszCfgGuidString);
451 DWORD dwValueType;
452 DWORD ret = RegQueryValueExW(hKey, L"NetCfgInstanceId", NULL,
453 &dwValueType, (LPBYTE)wszCfgGuidString, &cbSize);
454 if (ret == ERROR_SUCCESS)
455 {
456 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Processing device ID \"%S\"\n",
457 wszCfgGuidString));
458
459 /* Figure out device name. */
460 WCHAR wszDevName[256], wszTempName[256];
461 ULONG cbName = sizeof(wszTempName);
462
463 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDev,
464 SPDRP_FRIENDLYNAME, /* IN DWORD Property,*/
465 NULL, /* OUT PDWORD PropertyRegDataType, OPTIONAL*/
466 (PBYTE)wszDevName, /* OUT PBYTE PropertyBuffer,*/
467 sizeof(wszDevName), /* IN DWORD PropertyBufferSize,*/
468 NULL /* OUT PDWORD RequiredSize OPTIONAL*/))
469 {
470 /*
471 * Rename the connection before removing the device. This will
472 * hopefully prevent an error when we will be attempting
473 * to rename a newly created connection (see @bugref{6740}).
474 */
475 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(wszDevName, wszTempName, &cbName);
476 wcscat_s(wszTempName, sizeof(wszTempName), L" removed");
477 if (SUCCEEDED(hr))
478 hr = VBoxNetCfgWinRenameConnection(wszCfgGuidString, wszTempName);
479 //NonStandardLogFlow(("VBoxNetCfgWinRenameConnection(%S,%S) => 0x%x\n", pWCfgGuidString, TempName, hr_tmp));
480 }
481 else
482 {
483 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Failed to get friendly name for device \"%S\"\n",
484 wszCfgGuidString));
485 }
486 }
487 else
488 {
489 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: Querying instance ID failed with %d\n",
490 ret));
491 }
492
493 RegCloseKey(hKey);
494 }
495
496 if (SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, pDev))
497 {
498 SP_DEVINSTALL_PARAMS devParams;
499 memset(&devParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
500 devParams.cbSize = sizeof(devParams);
501
502 if (SetupDiGetDeviceInstallParams(hDevInfo, pDev, &devParams))
503 {
504 if ( (devParams.Flags & DI_NEEDRESTART)
505 || (devParams.Flags & DI_NEEDREBOOT))
506 {
507 NonStandardLog(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: A reboot is required\n"));
508 }
509 }
510 else
511 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiGetDeviceInstallParams failed with %ld\n",
512 GetLastError()));
513 }
514 else
515 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiCallClassInstaller failed with %ld\n",
516 GetLastError()));
517 }
518 else
519 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetSelectedDevice failed with %ld\n",
520 GetLastError()));
521 }
522 else
523 NonStandardLogFlow(("vboxNetCfgWinRemoveAllNetDevicesOfIdCallback: SetupDiSetClassInstallParams failed with %ld\n",
524 GetLastError()));
525
526 /* Continue enumeration. */
527 return TRUE;
528}
529
530typedef struct VBOXNECTFGWINPROPCHANGE
531{
532 VBOXNECTFGWINPROPCHANGE_TYPE enmPcType;
533 HRESULT hr;
534} VBOXNECTFGWINPROPCHANGE ,*PVBOXNECTFGWINPROPCHANGE;
535
536static BOOL vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
537{
538 PVBOXNECTFGWINPROPCHANGE pPc = (PVBOXNECTFGWINPROPCHANGE)pContext;
539
540 SP_PROPCHANGE_PARAMS PcParams;
541 memset (&PcParams, 0, sizeof (PcParams));
542 PcParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
543 PcParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
544 PcParams.Scope = DICS_FLAG_GLOBAL;
545
546 switch(pPc->enmPcType)
547 {
548 case VBOXNECTFGWINPROPCHANGE_TYPE_DISABLE:
549 PcParams.StateChange = DICS_DISABLE;
550 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Change type (DICS_DISABLE): %d\n", pPc->enmPcType));
551 break;
552 case VBOXNECTFGWINPROPCHANGE_TYPE_ENABLE:
553 PcParams.StateChange = DICS_ENABLE;
554 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Change type (DICS_ENABLE): %d\n", pPc->enmPcType));
555 break;
556 default:
557 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: Unexpected prop change type: %d\n", pPc->enmPcType));
558 pPc->hr = E_INVALIDARG;
559 return FALSE;
560 }
561
562 if (SetupDiSetClassInstallParams(hDevInfo, pDev, &PcParams.ClassInstallHeader, sizeof(PcParams)))
563 {
564 if (SetupDiSetSelectedDevice(hDevInfo, pDev))
565 {
566 if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, pDev))
567 {
568 SP_DEVINSTALL_PARAMS devParams;
569 devParams.cbSize = sizeof(devParams);
570 if (SetupDiGetDeviceInstallParams(hDevInfo,pDev,&devParams))
571 {
572 if ( (devParams.Flags & DI_NEEDRESTART)
573 || (devParams.Flags & DI_NEEDREBOOT))
574 {
575 NonStandardLog(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: A reboot is required\n"));
576 }
577 }
578 else
579 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: SetupDiGetDeviceInstallParams failed with %ld\n",
580 GetLastError()));
581 }
582 else
583 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback: SetupDiCallClassInstaller failed with %ld\n",
584 GetLastError()));
585 }
586 else
587 NonStandardLogFlow(("SetupDiSetSelectedDevice failed with %ld\n", GetLastError()));
588 }
589 else
590 NonStandardLogFlow(("SetupDiSetClassInstallParams failed with %ld\n", GetLastError()));
591
592 /* Continue enumeration. */
593 return TRUE;
594}
595
596typedef BOOL (*VBOXNETCFGWIN_NETENUM_CALLBACK) (HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext);
597VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPCWSTR pwszPnPId,
598 VBOXNETCFGWIN_NETENUM_CALLBACK callback, PVOID pContext)
599{
600 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Searching for: %S\n", pwszPnPId));
601
602 HRESULT hr;
603 HDEVINFO hDevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET,
604 NULL, /* IN PCTSTR Enumerator, OPTIONAL */
605 NULL, /* IN HWND hwndParent, OPTIONAL */
606 DIGCF_PRESENT, /* IN DWORD Flags,*/
607 NULL, /* IN HDEVINFO DeviceInfoSet, OPTIONAL */
608 NULL, /* IN PCTSTR MachineName, OPTIONAL */
609 NULL /* IN PVOID Reserved */);
610 if (hDevInfo != INVALID_HANDLE_VALUE)
611 {
612 DWORD winEr;
613
614 DWORD dwDevId = 0;
615 size_t cPnPId = wcslen(pwszPnPId);
616
617 PBYTE pBuffer = NULL;
618
619 for (;;)
620 {
621 SP_DEVINFO_DATA Dev;
622 memset(&Dev, 0, sizeof(SP_DEVINFO_DATA));
623 Dev.cbSize = sizeof(SP_DEVINFO_DATA);
624
625 if (!SetupDiEnumDeviceInfo(hDevInfo, dwDevId, &Dev))
626 {
627 winEr = GetLastError();
628 if (winEr == ERROR_NO_MORE_ITEMS)
629 winEr = ERROR_SUCCESS;
630 break;
631 }
632
633 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Enumerating device %ld ... \n", dwDevId));
634 dwDevId++;
635
636 if (pBuffer)
637 free(pBuffer);
638 pBuffer = NULL;
639 DWORD cbBuffer = 0;
640 DWORD cbRequired = 0;
641
642 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &Dev,
643 SPDRP_HARDWAREID, /* IN DWORD Property */
644 NULL, /* OUT PDWORD PropertyRegDataType OPTIONAL */
645 pBuffer, /* OUT PBYTE PropertyBuffer */
646 cbBuffer, /* IN DWORD PropertyBufferSize */
647 &cbRequired /* OUT PDWORD RequiredSize OPTIONAL */))
648 {
649 winEr = GetLastError();
650 if (winEr != ERROR_INSUFFICIENT_BUFFER)
651 {
652 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (1) failed with %ld\n", winEr));
653 break;
654 }
655
656 pBuffer = (PBYTE)malloc(cbRequired);
657 if (!pBuffer)
658 {
659 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Out of memory allocating %ld bytes\n",
660 cbRequired));
661 winEr = ERROR_OUTOFMEMORY;
662 break;
663 }
664
665 cbBuffer = cbRequired;
666
667 if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo,&Dev,
668 SPDRP_HARDWAREID, /* IN DWORD Property */
669 NULL, /* OUT PDWORD PropertyRegDataType, OPTIONAL */
670 pBuffer, /* OUT PBYTE PropertyBuffer */
671 cbBuffer, /* IN DWORD PropertyBufferSize */
672 &cbRequired /* OUT PDWORD RequiredSize OPTIONAL */))
673 {
674 winEr = GetLastError();
675 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (2) failed with %ld\n",
676 winEr));
677 break;
678 }
679 }
680
681 PWSTR pCurId = (PWSTR)pBuffer;
682 size_t cCurId = wcslen(pCurId);
683
684 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Device %ld: %S\n", dwDevId, pCurId));
685
686 if (cCurId >= cPnPId)
687 {
688 NonStandardLogFlow(("!wcsnicmp(pCurId = (%S), pwszPnPId = (%S), cPnPId = (%d))", pCurId, pwszPnPId, cPnPId));
689
690 pCurId += cCurId - cPnPId;
691 if (!wcsnicmp(pCurId, pwszPnPId, cPnPId))
692 {
693 if (!callback(hDevInfo, &Dev, pContext))
694 break;
695 }
696 }
697 }
698
699 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Found %ld devices total\n", dwDevId));
700
701 if (pBuffer)
702 free(pBuffer);
703
704 hr = HRESULT_FROM_WIN32(winEr);
705
706 SetupDiDestroyDeviceInfoList(hDevInfo);
707 }
708 else
709 {
710 DWORD winEr = GetLastError();
711 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: SetupDiGetClassDevsExW failed with %ld\n", winEr));
712 hr = HRESULT_FROM_WIN32(winEr);
713 }
714
715 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices: Ended with hr (0x%x)\n", hr));
716 return hr;
717}
718
719VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(IN LPCWSTR lpszPnPId)
720{
721 return VBoxNetCfgWinEnumNetDevices(lpszPnPId, vboxNetCfgWinRemoveAllNetDevicesOfIdCallback, NULL);
722}
723
724VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinPropChangeAllNetDevicesOfId(IN LPCWSTR lpszPnPId, VBOXNECTFGWINPROPCHANGE_TYPE enmPcType)
725{
726 VBOXNECTFGWINPROPCHANGE Pc;
727 Pc.enmPcType = enmPcType;
728 Pc.hr = S_OK;
729 NonStandardLogFlow(("Calling VBoxNetCfgWinEnumNetDevices with lpszPnPId =(%S) and vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback", lpszPnPId));
730
731 HRESULT hr = VBoxNetCfgWinEnumNetDevices(lpszPnPId, vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback, &Pc);
732 if (!SUCCEEDED(hr))
733 {
734 NonStandardLogFlow(("VBoxNetCfgWinEnumNetDevices failed 0x%x\n", hr));
735 return hr;
736 }
737
738 if (!SUCCEEDED(Pc.hr))
739 {
740 NonStandardLogFlow(("vboxNetCfgWinPropChangeAllNetDevicesOfIdCallback failed 0x%x\n", Pc.hr));
741 return Pc.hr;
742 }
743
744 return S_OK;
745}
746
747/*
748 * logging
749 */
750static VOID DoLogging(LPCSTR szString, ...)
751{
752 LOG_ROUTINE pfnRoutine = (LOG_ROUTINE)(*((void * volatile *)&g_Logger));
753 if (pfnRoutine)
754 {
755 char szBuffer[4096] = {0};
756 va_list va;
757 va_start(va, szString);
758 _vsnprintf(szBuffer, RT_ELEMENTS(szBuffer), szString, va);
759 va_end(va);
760
761 pfnRoutine(szBuffer);
762 }
763}
764
765VBOXNETCFGWIN_DECL(VOID) VBoxNetCfgWinSetLogging(IN LOG_ROUTINE pfnLog)
766{
767 *((void * volatile *)&g_Logger) = pfnLog;
768}
769
770/*
771 * IP configuration API
772 */
773/* network settings config */
774/**
775 * Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
776 */
777template <class C>
778class ComStrongRef
779{
780protected:
781
782 static void addref (C *p) { p->AddRef(); }
783 static void release (C *p) { p->Release(); }
784};
785
786
787/**
788 * Base template for smart COM pointers. Not intended to be used directly.
789 */
790template <class C, template <class> class RefOps = ComStrongRef>
791class ComPtrBase : protected RefOps <C>
792{
793public:
794
795 /* special template to disable AddRef()/Release() */
796 template <class I>
797 class NoAddRefRelease : public I
798 {
799 private:
800#if !defined (VBOX_WITH_XPCOM)
801 STDMETHOD_(ULONG, AddRef)() = 0;
802 STDMETHOD_(ULONG, Release)() = 0;
803#else /* !defined (VBOX_WITH_XPCOM) */
804 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
805 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
806#endif /* !defined (VBOX_WITH_XPCOM) */
807 };
808
809protected:
810
811 ComPtrBase () : p (NULL) {}
812 ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
813 ComPtrBase (C *that_p) : p (that_p) { addref(); }
814
815 ~ComPtrBase() { release(); }
816
817 ComPtrBase &operator= (const ComPtrBase &that)
818 {
819 safe_assign (that.p);
820 return *this;
821 }
822
823 ComPtrBase &operator= (C *that_p)
824 {
825 safe_assign (that_p);
826 return *this;
827 }
828
829public:
830
831 void setNull()
832 {
833 release();
834 p = NULL;
835 }
836
837 bool isNull() const
838 {
839 return (p == NULL);
840 }
841
842 bool operator! () const { return isNull(); }
843
844 bool operator< (C* that_p) const { return p < that_p; }
845 bool operator== (C* that_p) const { return p == that_p; }
846
847 template <class I>
848 bool equalsTo (I *aThat) const
849 {
850 return ComPtrEquals (p, aThat);
851 }
852
853 template <class OC>
854 bool equalsTo (const ComPtrBase <OC> &oc) const
855 {
856 return equalsTo ((OC *) oc);
857 }
858
859 /** Intended to pass instances as in parameters to interface methods */
860 operator C* () const { return p; }
861
862 /**
863 * Dereferences the instance (redirects the -> operator to the managed
864 * pointer).
865 */
866 NoAddRefRelease <C> *operator-> () const
867 {
868 AssertMsg (p, ("Managed pointer must not be null\n"));
869 return (NoAddRefRelease <C> *) p;
870 }
871
872 template <class I>
873 HRESULT queryInterfaceTo (I **pp) const
874 {
875 if (pp)
876 {
877 if (p)
878 {
879 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
880 }
881 else
882 {
883 *pp = NULL;
884 return S_OK;
885 }
886 }
887
888 return E_INVALIDARG;
889 }
890
891 /** Intended to pass instances as out parameters to interface methods */
892 C **asOutParam()
893 {
894 setNull();
895 return &p;
896 }
897
898private:
899
900 void addref()
901 {
902 if (p)
903 RefOps <C>::addref (p);
904 }
905
906 void release()
907 {
908 if (p)
909 RefOps <C>::release (p);
910 }
911
912 void safe_assign (C *that_p)
913 {
914 /* be aware of self-assignment */
915 if (that_p)
916 RefOps <C>::addref (that_p);
917 release();
918 p = that_p;
919 }
920
921 C *p;
922};
923
924/**
925 * Smart COM pointer wrapper that automatically manages refcounting of
926 * interface pointers.
927 *
928 * @param I COM interface class
929 */
930template <class I, template <class> class RefOps = ComStrongRef>
931class ComPtr : public ComPtrBase <I, RefOps>
932{
933 typedef ComPtrBase <I, RefOps> Base;
934
935public:
936
937 ComPtr () : Base() {}
938 ComPtr (const ComPtr &that) : Base(that) {}
939 ComPtr &operator= (const ComPtr &that)
940 {
941 Base::operator= (that);
942 return *this;
943 }
944
945 template <class OI>
946 ComPtr (OI *that_p) : Base () { operator= (that_p); }
947
948 /* specialization for I */
949 ComPtr (I *that_p) : Base (that_p) {}
950
951 template <class OC>
952 ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
953
954 template <class OI>
955 ComPtr &operator= (OI *that_p)
956 {
957 if (that_p)
958 that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
959 else
960 Base::setNull();
961 return *this;
962 }
963
964 /* specialization for I */
965 ComPtr &operator=(I *that_p)
966 {
967 Base::operator= (that_p);
968 return *this;
969 }
970
971 template <class OC>
972 ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
973 {
974 return operator= ((OC *) oc);
975 }
976};
977
978static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const GUID * pGuid, IWbemClassObject **pAdapterConfig)
979{
980 HRESULT hr;
981 WCHAR wszQuery[256];
982 WCHAR wszGuid[50];
983
984 int length = StringFromGUID2(*pGuid, wszGuid, RT_ELEMENTS(wszGuid));
985 if (length)
986 {
987 swprintf(wszQuery, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"%s\"", wszGuid);
988 IEnumWbemClassObject* pEnumerator = NULL;
989 hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(wszQuery), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
990 NULL, &pEnumerator);
991 if (SUCCEEDED(hr))
992 {
993 if (pEnumerator)
994 {
995 IWbemClassObject *pclsObj;
996 ULONG uReturn = 0;
997 hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
998 NonStandardLogFlow(("netIfWinFindAdapterClassById: IEnumWbemClassObject::Next -> hr=0x%x pclsObj=%p uReturn=%u 42=%u\n",
999 hr, (void *)pclsObj, uReturn, 42));
1000 if (SUCCEEDED(hr))
1001 {
1002 if (uReturn && pclsObj != NULL)
1003 {
1004 *pAdapterConfig = pclsObj;
1005 pEnumerator->Release();
1006 NonStandardLogFlow(("netIfWinFindAdapterClassById: S_OK and %p\n", *pAdapterConfig));
1007 return S_OK;
1008 }
1009
1010 hr = E_FAIL;
1011 }
1012
1013 pEnumerator->Release();
1014 }
1015 else
1016 {
1017 NonStandardLogFlow(("ExecQuery returned no enumerator\n"));
1018 hr = E_FAIL;
1019 }
1020 }
1021 else
1022 NonStandardLogFlow(("ExecQuery failed (0x%x)\n", hr));
1023 }
1024 else
1025 {
1026 DWORD winEr = GetLastError();
1027 hr = HRESULT_FROM_WIN32( winEr );
1028 if (SUCCEEDED(hr))
1029 hr = E_FAIL;
1030 NonStandardLogFlow(("StringFromGUID2 failed winEr=%u, hr=0x%x\n", winEr, hr));
1031 }
1032
1033 NonStandardLogFlow(("netIfWinFindAdapterClassById: 0x%x and %p\n", hr, *pAdapterConfig));
1034 return hr;
1035}
1036
1037static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly)
1038{
1039 VARIANT vtServiceName;
1040 BOOL bIsHostOnly = FALSE;
1041 VariantInit(&vtServiceName);
1042
1043 HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0 /*lFlags*/, &vtServiceName, NULL /*pvtType*/, NULL /*plFlavor*/);
1044 if (SUCCEEDED(hr))
1045 {
1046 *pbIsHostOnly = bstr_t(vtServiceName.bstrVal) == bstr_t("VBoxNetAdp");
1047
1048 VariantClear(&vtServiceName);
1049 }
1050
1051 return hr;
1052}
1053
1054static HRESULT netIfWinGetIpSettings(IWbemClassObject * pAdapterConfig, ULONG *pIpv4, ULONG *pMaskv4)
1055{
1056 VARIANT vtIp;
1057 HRESULT hr;
1058 VariantInit(&vtIp);
1059
1060 *pIpv4 = 0;
1061 *pMaskv4 = 0;
1062
1063 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
1064 if (SUCCEEDED(hr))
1065 {
1066 if (vtIp.vt == (VT_ARRAY | VT_BSTR))
1067 {
1068 VARIANT vtMask;
1069 VariantInit(&vtMask);
1070 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
1071 if (SUCCEEDED(hr))
1072 {
1073 if (vtMask.vt == (VT_ARRAY | VT_BSTR))
1074 {
1075 SAFEARRAY * pIpArray = vtIp.parray;
1076 SAFEARRAY * pMaskArray = vtMask.parray;
1077 if (pIpArray && pMaskArray)
1078 {
1079 BSTR pCurIp;
1080 BSTR pCurMask;
1081 for (LONG i = 0;
1082 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
1083 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
1084 i++)
1085 {
1086 bstr_t ip(pCurIp);
1087
1088 ULONG Ipv4 = inet_addr((char*)(ip));
1089 if (Ipv4 != INADDR_NONE)
1090 {
1091 *pIpv4 = Ipv4;
1092 bstr_t mask(pCurMask);
1093 *pMaskv4 = inet_addr((char*)(mask));
1094 break;
1095 }
1096 }
1097 }
1098 }
1099 else
1100 {
1101 *pIpv4 = 0;
1102 *pMaskv4 = 0;
1103 }
1104
1105 VariantClear(&vtMask);
1106 }
1107 }
1108 else
1109 {
1110 *pIpv4 = 0;
1111 *pMaskv4 = 0;
1112 }
1113
1114 VariantClear(&vtIp);
1115 }
1116
1117 return hr;
1118}
1119
1120
1121static HRESULT netIfWinHasIpSettings(IWbemClassObject * pAdapterConfig, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, bool *pFound)
1122{
1123 VARIANT vtIp;
1124 HRESULT hr;
1125 VariantInit(&vtIp);
1126
1127 *pFound = false;
1128
1129 hr = pAdapterConfig->Get(L"IPAddress", 0, &vtIp, 0, 0);
1130 if (SUCCEEDED(hr))
1131 {
1132 VARIANT vtMask;
1133 VariantInit(&vtMask);
1134 hr = pAdapterConfig->Get(L"IPSubnet", 0, &vtMask, 0, 0);
1135 if (SUCCEEDED(hr))
1136 {
1137 SAFEARRAY * pIpArray = vtIp.parray;
1138 SAFEARRAY * pMaskArray = vtMask.parray;
1139 if (pIpArray && pMaskArray)
1140 {
1141 BSTR pIp, pMask;
1142 for (LONG k = 0;
1143 SafeArrayGetElement(pCheckIp, &k, (PVOID)&pIp) == S_OK
1144 && SafeArrayGetElement(pCheckMask, &k, (PVOID)&pMask) == S_OK;
1145 k++)
1146 {
1147 BSTR pCurIp;
1148 BSTR pCurMask;
1149 for (LONG i = 0;
1150 SafeArrayGetElement(pIpArray, &i, (PVOID)&pCurIp) == S_OK
1151 && SafeArrayGetElement(pMaskArray, &i, (PVOID)&pCurMask) == S_OK;
1152 i++)
1153 {
1154 if (!wcsicmp(pCurIp, pIp))
1155 {
1156 if (!wcsicmp(pCurMask, pMask))
1157 *pFound = true;
1158 break;
1159 }
1160 }
1161 }
1162 }
1163
1164
1165 VariantClear(&vtMask);
1166 }
1167
1168 VariantClear(&vtIp);
1169 }
1170
1171 return hr;
1172}
1173
1174static HRESULT netIfWinWaitIpSettings(IWbemServices *pSvc, const GUID * pGuid, SAFEARRAY * pCheckIp, SAFEARRAY * pCheckMask, ULONG sec2Wait, bool *pFound)
1175{
1176 /* on Vista we need to wait for the address to get applied */
1177 /* wait for the address to appear in the list */
1178 HRESULT hr = S_OK;
1179 ULONG i;
1180 *pFound = false;
1181 ComPtr <IWbemClassObject> pAdapterConfig;
1182 for (i = 0;
1183 (hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam())) == S_OK
1184 && (hr = netIfWinHasIpSettings(pAdapterConfig, pCheckIp, pCheckMask, pFound)) == S_OK
1185 && !(*pFound)
1186 && i < sec2Wait/6;
1187 i++)
1188 {
1189 Sleep(6000);
1190 }
1191
1192 return hr;
1193}
1194
1195static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc)
1196{
1197 IWbemLocator *pLoc = NULL;
1198 HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
1199 if (SUCCEEDED(hr))
1200 {
1201 IWbemServices *pSvc = NULL;
1202 hr = pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), /* [in] const BSTR strNetworkResource */
1203 NULL, /* [in] const BSTR strUser */
1204 NULL, /* [in] const BSTR strPassword */
1205 0, /* [in] const BSTR strLocale */
1206 NULL, /* [in] LONG lSecurityFlags */
1207 0, /* [in] const BSTR strAuthority */
1208 0, /* [in] IWbemContext* pCtx */
1209 &pSvc /* [out] IWbemServices** ppNamespace */);
1210 if (SUCCEEDED(hr))
1211 {
1212 hr = CoSetProxyBlanket(pSvc, /* IUnknown * pProxy */
1213 RPC_C_AUTHN_WINNT, /* DWORD dwAuthnSvc */
1214 RPC_C_AUTHZ_NONE, /* DWORD dwAuthzSvc */
1215 NULL, /* WCHAR * pServerPrincName */
1216 RPC_C_AUTHN_LEVEL_CALL, /* DWORD dwAuthnLevel */
1217 RPC_C_IMP_LEVEL_IMPERSONATE, /* DWORD dwImpLevel */
1218 NULL, /* RPC_AUTH_IDENTITY_HANDLE pAuthInfo */
1219 EOAC_NONE /* DWORD dwCapabilities */
1220 );
1221 if (SUCCEEDED(hr))
1222 {
1223 *ppSvc = pSvc;
1224 /* do not need it any more */
1225 pLoc->Release();
1226 return hr;
1227 }
1228 else
1229 NonStandardLogFlow(("CoSetProxyBlanket failed, hr (0x%x)\n", hr));
1230
1231 pSvc->Release();
1232 }
1233 else
1234 NonStandardLogFlow(("ConnectServer failed, hr (0x%x)\n", hr));
1235 pLoc->Release();
1236 }
1237 else
1238 NonStandardLogFlow(("CoCreateInstance failed, hr (0x%x)\n", hr));
1239 return hr;
1240}
1241
1242static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr)
1243{
1244 VARIANT index;
1245 HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0);
1246 if (SUCCEEDED(hr))
1247 {
1248 WCHAR strIndex[8];
1249 swprintf(strIndex, L"%u", index.uintVal);
1250 *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy();
1251 }
1252 else
1253 NonStandardLogFlow(("Get failed, hr (0x%x)\n", hr));
1254 return hr;
1255}
1256
1257static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath,
1258 BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs,
1259 IWbemClassObject** ppOutParams
1260 )
1261{
1262 HRESULT hr = S_OK;
1263 ComPtr<IWbemClassObject> pInParamsDefinition;
1264 ComPtr<IWbemClassObject> pClassInstance;
1265
1266 if (cArgs)
1267 {
1268 hr = pClass->GetMethod(MethodName, 0, pInParamsDefinition.asOutParam(), NULL);
1269 if (SUCCEEDED(hr))
1270 {
1271 hr = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam());
1272 if (SUCCEEDED(hr))
1273 {
1274 for (UINT i = 0; i < cArgs; i++)
1275 {
1276 hr = pClassInstance->Put(pArgNames[i], 0,
1277 pArgs[i], 0);
1278 if (FAILED(hr))
1279 break;
1280 }
1281 }
1282 }
1283 }
1284
1285 if (SUCCEEDED(hr))
1286 {
1287 IWbemClassObject* pOutParams = NULL;
1288 hr = pSvc->ExecMethod(ObjPath, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
1289 if (SUCCEEDED(hr))
1290 {
1291 *ppOutParams = pOutParams;
1292 }
1293 }
1294
1295 return hr;
1296}
1297
1298static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp)
1299{
1300 HRESULT hr;
1301 SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp);
1302 if (pIpArray)
1303 {
1304 for (UINT i = 0; i < cIp; i++)
1305 {
1306 char* addr = inet_ntoa(aIp[i]);
1307 BSTR val = bstr_t(addr).copy();
1308 long aIndex[1];
1309 aIndex[0] = i;
1310 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1311 if (FAILED(hr))
1312 {
1313 SysFreeString(val);
1314 SafeArrayDestroy(pIpArray);
1315 break;
1316 }
1317 }
1318
1319 if (SUCCEEDED(hr))
1320 {
1321 *ppArray = pIpArray;
1322 }
1323 }
1324 else
1325 hr = HRESULT_FROM_WIN32(GetLastError());
1326
1327 return hr;
1328}
1329
1330static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip)
1331{
1332 HRESULT hr;
1333 SAFEARRAY *pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1);
1334 if (pIpArray)
1335 {
1336 BSTR val = bstr_t(Ip, false).copy();
1337 long aIndex[1];
1338 aIndex[0] = 0;
1339 hr = SafeArrayPutElement(pIpArray, aIndex, val);
1340 if (FAILED(hr))
1341 {
1342 SysFreeString(val);
1343 SafeArrayDestroy(pIpArray);
1344 }
1345
1346 if (SUCCEEDED(hr))
1347 {
1348 *ppArray = pIpArray;
1349 }
1350 }
1351 else
1352 hr = HRESULT_FROM_WIN32(GetLastError());
1353
1354 return hr;
1355}
1356
1357
1358static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp)
1359{
1360 HRESULT hr;
1361 VariantInit(pIpAddresses);
1362 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1363 SAFEARRAY *pIpArray;
1364 hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp);
1365 if (SUCCEEDED(hr))
1366 {
1367 pIpAddresses->parray = pIpArray;
1368 }
1369 return hr;
1370}
1371
1372static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip)
1373{
1374 HRESULT hr;
1375 VariantInit(pIpAddresses);
1376 pIpAddresses->vt = VT_ARRAY | VT_BSTR;
1377 SAFEARRAY *pIpArray;
1378 hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip);
1379 if (SUCCEEDED(hr))
1380 {
1381 pIpAddresses->parray = pIpArray;
1382 }
1383 return hr;
1384}
1385
1386static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask)
1387{
1388 ComPtr<IWbemClassObject> pClass;
1389 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1390 HRESULT hr;
1391 if (ClassName)
1392 {
1393 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1394 if (SUCCEEDED(hr))
1395 {
1396 LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"};
1397 LPVARIANT args[] = {pIp, pMask};
1398 ComPtr<IWbemClassObject> pOutParams;
1399
1400 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam());
1401 if (SUCCEEDED(hr))
1402 {
1403 VARIANT varReturnValue;
1404 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1405 &varReturnValue, NULL, 0);
1406 Assert(SUCCEEDED(hr));
1407 if (SUCCEEDED(hr))
1408 {
1409// Assert(varReturnValue.vt == VT_UINT);
1410 int winEr = varReturnValue.uintVal;
1411 switch (winEr)
1412 {
1413 case 0:
1414 {
1415 hr = S_OK;
1416// bool bFound;
1417// HRESULT tmpHr = netIfWinWaitIpSettings(pSvc, pGuid, pIp->parray, pMask->parray, 180, &bFound);
1418 }
1419 break;
1420 default:
1421 hr = HRESULT_FROM_WIN32( winEr );
1422 break;
1423 }
1424 }
1425 }
1426 }
1427 SysFreeString(ClassName);
1428 }
1429 else
1430 hr = HRESULT_FROM_WIN32(GetLastError());
1431
1432 return hr;
1433}
1434
1435
1436static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp)
1437{
1438 VARIANT ipAddresses;
1439 HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp);
1440 if (SUCCEEDED(hr))
1441 {
1442 VARIANT ipMasks;
1443 hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp);
1444 if (SUCCEEDED(hr))
1445 {
1446 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1447 VariantClear(&ipMasks);
1448 }
1449 VariantClear(&ipAddresses);
1450 }
1451 return hr;
1452}
1453
1454static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, const GUID * pGuid, BSTR ObjPath, BSTR Ip, BSTR Mask)
1455{
1456 VARIANT ipAddresses;
1457 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip);
1458 if (SUCCEEDED(hr))
1459 {
1460 VARIANT ipMasks;
1461 hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask);
1462 if (SUCCEEDED(hr))
1463 {
1464 hr = netIfWinEnableStatic(pSvc, pGuid, ObjPath, &ipAddresses, &ipMasks);
1465 VariantClear(&ipMasks);
1466 }
1467 VariantClear(&ipAddresses);
1468 }
1469 return hr;
1470}
1471
1472/* win API allows to set gw metrics as well, we are not setting them */
1473static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw)
1474{
1475 ComPtr<IWbemClassObject> pClass;
1476 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1477 HRESULT hr;
1478 if (ClassName)
1479 {
1480 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1481 if (SUCCEEDED(hr))
1482 {
1483 LPWSTR argNames[] = {L"DefaultIPGateway"};
1484 LPVARIANT args[] = {pGw};
1485 ComPtr<IWbemClassObject> pOutParams;
1486
1487 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam());
1488 if (SUCCEEDED(hr))
1489 {
1490 VARIANT varReturnValue;
1491 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1492 Assert(SUCCEEDED(hr));
1493 if (SUCCEEDED(hr))
1494 {
1495// Assert(varReturnValue.vt == VT_UINT);
1496 int winEr = varReturnValue.uintVal;
1497 switch (winEr)
1498 {
1499 case 0:
1500 hr = S_OK;
1501 break;
1502 default:
1503 hr = HRESULT_FROM_WIN32( winEr );
1504 break;
1505 }
1506 }
1507 }
1508 }
1509 SysFreeString(ClassName);
1510 }
1511 else
1512 hr = HRESULT_FROM_WIN32(GetLastError());
1513
1514 return hr;
1515}
1516
1517/* win API allows to set gw metrics as well, we are not setting them */
1518static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw)
1519{
1520 VARIANT gwais;
1521 HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw);
1522 if (SUCCEEDED(hr))
1523 {
1524 netIfWinSetGateways(pSvc, ObjPath, &gwais);
1525 VariantClear(&gwais);
1526 }
1527 return hr;
1528}
1529
1530/* win API allows to set gw metrics as well, we are not setting them */
1531static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw)
1532{
1533 VARIANT vGw;
1534 HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw);
1535 if (SUCCEEDED(hr))
1536 {
1537 netIfWinSetGateways(pSvc, ObjPath, &vGw);
1538 VariantClear(&vGw);
1539 }
1540 return hr;
1541}
1542
1543static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath)
1544{
1545 ComPtr<IWbemClassObject> pClass;
1546 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1547 HRESULT hr;
1548 if (ClassName)
1549 {
1550 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1551 if (SUCCEEDED(hr))
1552 {
1553 ComPtr<IWbemClassObject> pOutParams;
1554
1555 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam());
1556 if (SUCCEEDED(hr))
1557 {
1558 VARIANT varReturnValue;
1559 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0,
1560 &varReturnValue, NULL, 0);
1561 Assert(SUCCEEDED(hr));
1562 if (SUCCEEDED(hr))
1563 {
1564// Assert(varReturnValue.vt == VT_UINT);
1565 int winEr = varReturnValue.uintVal;
1566 switch (winEr)
1567 {
1568 case 0:
1569 hr = S_OK;
1570 break;
1571 default:
1572 hr = HRESULT_FROM_WIN32( winEr );
1573 break;
1574 }
1575 }
1576 }
1577 }
1578 SysFreeString(ClassName);
1579 }
1580 else
1581 hr = HRESULT_FROM_WIN32(GetLastError());
1582
1583 return hr;
1584}
1585
1586static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath)
1587{
1588 ComPtr<IWbemClassObject> pClass;
1589 BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
1590 HRESULT hr;
1591 if (ClassName)
1592 {
1593 hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL);
1594 if (SUCCEEDED(hr))
1595 {
1596 ComPtr<IWbemClassObject> pOutParams;
1597
1598 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1599 if (SUCCEEDED(hr))
1600 {
1601 VARIANT varReturnValue;
1602 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1603 Assert(SUCCEEDED(hr));
1604 if (SUCCEEDED(hr))
1605 {
1606// Assert(varReturnValue.vt == VT_UINT);
1607 int winEr = varReturnValue.uintVal;
1608 if (winEr == 0)
1609 {
1610 hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam());
1611 if (SUCCEEDED(hr))
1612 {
1613 VARIANT varReturnValue;
1614 hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
1615 Assert(SUCCEEDED(hr));
1616 if (SUCCEEDED(hr))
1617 {
1618 // Assert(varReturnValue.vt == VT_UINT);
1619 int winEr = varReturnValue.uintVal;
1620 if (winEr == 0)
1621 hr = S_OK;
1622 else
1623 hr = HRESULT_FROM_WIN32( winEr );
1624 }
1625 }
1626 }
1627 else
1628 hr = HRESULT_FROM_WIN32( winEr );
1629 }
1630 }
1631 }
1632 SysFreeString(ClassName);
1633 }
1634 else
1635 hr = HRESULT_FROM_WIN32(GetLastError());
1636
1637 return hr;
1638}
1639
1640static HRESULT vboxNetCfgWinIsDhcpEnabled(IWbemClassObject * pAdapterConfig, BOOL *pEnabled)
1641{
1642 VARIANT vtEnabled;
1643 HRESULT hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1644 if (SUCCEEDED(hr))
1645 *pEnabled = vtEnabled.boolVal;
1646 return hr;
1647}
1648
1649VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(IN const GUID * pGuid, OUT PADAPTER_SETTINGS pSettings)
1650{
1651 HRESULT hr;
1652 ComPtr <IWbemServices> pSvc;
1653 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1654 if (SUCCEEDED(hr))
1655 {
1656 ComPtr<IWbemClassObject> pAdapterConfig;
1657 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1658 if (SUCCEEDED(hr))
1659 {
1660 hr = vboxNetCfgWinIsDhcpEnabled(pAdapterConfig, &pSettings->bDhcp);
1661 if (SUCCEEDED(hr))
1662 hr = netIfWinGetIpSettings(pAdapterConfig, &pSettings->ip, &pSettings->mask);
1663 }
1664 }
1665
1666 return hr;
1667}
1668
1669VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinIsDhcpEnabled(const GUID * pGuid, BOOL *pEnabled)
1670{
1671 HRESULT hr;
1672 ComPtr <IWbemServices> pSvc;
1673 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1674 if (SUCCEEDED(hr))
1675 {
1676 ComPtr<IWbemClassObject> pAdapterConfig;
1677 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1678 if (SUCCEEDED(hr))
1679 {
1680 VARIANT vtEnabled;
1681 hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0);
1682 if (SUCCEEDED(hr))
1683 *pEnabled = vtEnabled.boolVal;
1684 }
1685 }
1686
1687 return hr;
1688}
1689
1690VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(IN const GUID *pGuid, IN ULONG ip, IN ULONG mask)
1691{
1692 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: ip=0x%x mask=0x%x", ip, mask));
1693 ComPtr<IWbemServices> pSvc;
1694 HRESULT hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1695 if (SUCCEEDED(hr))
1696 {
1697 ComPtr<IWbemClassObject> pAdapterConfig;
1698 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1699 if (SUCCEEDED(hr))
1700 {
1701 BOOL bIsHostOnly;
1702 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1703 if (SUCCEEDED(hr))
1704 {
1705 if (bIsHostOnly)
1706 {
1707 in_addr aIp[1];
1708 in_addr aMask[1];
1709 aIp[0].S_un.S_addr = ip;
1710 aMask[0].S_un.S_addr = mask;
1711
1712 BSTR ObjPath;
1713 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1714 if (SUCCEEDED(hr))
1715 {
1716 hr = netIfWinEnableStaticV4(pSvc, pGuid, ObjPath, aIp, aMask, ip != 0 ? 1 : 0);
1717 if (SUCCEEDED(hr))
1718 {
1719#if 0
1720 in_addr aGw[1];
1721 aGw[0].S_un.S_addr = gw;
1722 hr = netIfWinSetGatewaysV4(pSvc, ObjPath, aGw, 1);
1723 if (SUCCEEDED(hr))
1724#endif
1725 {
1726 }
1727 }
1728 SysFreeString(ObjPath);
1729 }
1730 }
1731 else
1732 {
1733 hr = E_FAIL;
1734 }
1735 }
1736 }
1737 }
1738
1739 NonStandardLogFlow(("VBoxNetCfgWinEnableStaticIpConfig: returns 0x%x", hr));
1740 return hr;
1741}
1742
1743#if 0
1744static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway)
1745{
1746 HRESULT hr;
1747 ComPtr <IWbemServices> pSvc;
1748 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1749 if (SUCCEEDED(hr))
1750 {
1751 ComPtr<IWbemClassObject> pAdapterConfig;
1752 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1753 if (SUCCEEDED(hr))
1754 {
1755 BSTR ObjPath;
1756 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1757 if (SUCCEEDED(hr))
1758 {
1759 hr = netIfWinEnableStaticV4V6(pSvc, pAdapterConfig, ObjPath, aIPV6Address, aIPV6Mask);
1760 if (SUCCEEDED(hr))
1761 {
1762 if (aIPV6DefaultGateway)
1763 {
1764 hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway);
1765 }
1766 if (SUCCEEDED(hr))
1767 {
1768// hr = netIfWinUpdateConfig(pIf);
1769 }
1770 }
1771 SysFreeString(ObjPath);
1772 }
1773 }
1774 }
1775
1776 return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1777}
1778
1779static HRESULT netIfEnableStaticIpConfigV6(const GUID *pGuid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1780{
1781 RTNETADDRIPV6 Mask;
1782 int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask);
1783 if (RT_SUCCESS(rc))
1784 {
1785 Bstr maskStr = composeIPv6Address(&Mask);
1786 rc = netIfEnableStaticIpConfigV6(pGuid, aIPV6Address, maskStr, NULL);
1787 }
1788 return rc;
1789}
1790#endif
1791
1792VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(IN const GUID *pGuid)
1793{
1794 HRESULT hr;
1795 ComPtr <IWbemServices> pSvc;
1796 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1797 if (SUCCEEDED(hr))
1798 {
1799 ComPtr<IWbemClassObject> pAdapterConfig;
1800 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1801 if (SUCCEEDED(hr))
1802 {
1803 BOOL bIsHostOnly;
1804 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1805 if (SUCCEEDED(hr))
1806 {
1807 if (bIsHostOnly)
1808 {
1809 BSTR ObjPath;
1810 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1811 if (SUCCEEDED(hr))
1812 {
1813 hr = netIfWinEnableDHCP(pSvc, ObjPath);
1814 if (SUCCEEDED(hr))
1815 {
1816// hr = netIfWinUpdateConfig(pIf);
1817 }
1818 SysFreeString(ObjPath);
1819 }
1820 }
1821 else
1822 {
1823 hr = E_FAIL;
1824 }
1825 }
1826 }
1827 }
1828
1829
1830 return hr;
1831}
1832
1833VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(IN const GUID *pGuid)
1834{
1835 HRESULT hr;
1836 ComPtr <IWbemServices> pSvc;
1837 hr = netIfWinCreateIWbemServices(pSvc.asOutParam());
1838 if (SUCCEEDED(hr))
1839 {
1840 ComPtr<IWbemClassObject> pAdapterConfig;
1841 hr = netIfWinFindAdapterClassById(pSvc, pGuid, pAdapterConfig.asOutParam());
1842 if (SUCCEEDED(hr))
1843 {
1844 BOOL bIsHostOnly;
1845 hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly);
1846 if (SUCCEEDED(hr))
1847 {
1848 if (bIsHostOnly)
1849 {
1850 BSTR ObjPath;
1851 hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath);
1852 if (SUCCEEDED(hr))
1853 {
1854 hr = netIfWinDhcpRediscover(pSvc, ObjPath);
1855 if (SUCCEEDED(hr))
1856 {
1857 //hr = netIfWinUpdateConfig(pIf);
1858 }
1859 SysFreeString(ObjPath);
1860 }
1861 }
1862 else
1863 {
1864 hr = E_FAIL;
1865 }
1866 }
1867 }
1868 }
1869
1870
1871 return hr;
1872}
1873
1874typedef bool (*PFNVBOXNETCFG_IPSETTINGS_CALLBACK) (ULONG ip, ULONG mask, PVOID pContext);
1875
1876static void vboxNetCfgWinEnumIpConfig(PIP_ADAPTER_ADDRESSES pAddresses, PFNVBOXNETCFG_IPSETTINGS_CALLBACK pfnCallback, PVOID pContext)
1877{
1878 PIP_ADAPTER_ADDRESSES pAdapter;
1879 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1880 {
1881 PIP_ADAPTER_UNICAST_ADDRESS pAddr = pAdapter->FirstUnicastAddress;
1882 PIP_ADAPTER_PREFIX pPrefix = pAdapter->FirstPrefix;
1883
1884 if (pAddr && pPrefix)
1885 {
1886 do
1887 {
1888 bool fIPFound, fMaskFound;
1889 fIPFound = fMaskFound = false;
1890 ULONG ip, mask;
1891 for (; pAddr && !fIPFound; pAddr = pAddr->Next)
1892 {
1893 switch (pAddr->Address.lpSockaddr->sa_family)
1894 {
1895 case AF_INET:
1896 fIPFound = true;
1897 memcpy(&ip,
1898 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1899 sizeof(ip));
1900 break;
1901// case AF_INET6:
1902// break;
1903 }
1904 }
1905
1906 for (; pPrefix && !fMaskFound; pPrefix = pPrefix->Next)
1907 {
1908 switch (pPrefix->Address.lpSockaddr->sa_family)
1909 {
1910 case AF_INET:
1911 if (!pPrefix->PrefixLength || pPrefix->PrefixLength > 31) /* in case the ip helper API is queried while NetCfg write lock is held */
1912 break; /* the address values can contain illegal values */
1913 fMaskFound = true;
1914 mask = (~(((ULONG)~0) >> pPrefix->PrefixLength));
1915 mask = htonl(mask);
1916 break;
1917// case AF_INET6:
1918// break;
1919 }
1920 }
1921
1922 if (!fIPFound || !fMaskFound)
1923 break;
1924
1925 if (!pfnCallback(ip, mask, pContext))
1926 return;
1927 } while (true);
1928 }
1929 }
1930}
1931
1932typedef struct _IPPROBE_CONTEXT
1933{
1934 ULONG Prefix;
1935 bool bConflict;
1936}IPPROBE_CONTEXT, *PIPPROBE_CONTEXT;
1937
1938#define IPPROBE_INIT(_pContext, _addr) \
1939 ((_pContext)->bConflict = false, \
1940 (_pContext)->Prefix = _addr)
1941
1942#define IPPROBE_INIT_STR(_pContext, _straddr) \
1943 IPROBE_INIT(_pContext, inet_addr(_straddr))
1944
1945static bool vboxNetCfgWinIpProbeCallback (ULONG ip, ULONG mask, PVOID pContext)
1946{
1947 PIPPROBE_CONTEXT pProbe = (PIPPROBE_CONTEXT)pContext;
1948
1949 if ((ip & mask) == (pProbe->Prefix & mask))
1950 {
1951 pProbe->bConflict = true;
1952 return false;
1953 }
1954
1955 return true;
1956}
1957
1958VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(OUT PULONG pNetIp, OUT PULONG pNetMask)
1959{
1960 DWORD dwRc;
1961 HRESULT hr = S_OK;
1962 /*
1963 * Most of the hosts probably have less than 10 adapters,
1964 * so we'll mostly succeed from the first attempt.
1965 */
1966 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
1967 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
1968 if (!pAddresses)
1969 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1970 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1971 if (dwRc == ERROR_BUFFER_OVERFLOW)
1972 {
1973 /* Impressive! More than 10 adapters! Get more memory and try again. */
1974 free(pAddresses);
1975 pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(uBufLen);
1976 if (!pAddresses)
1977 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1978 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1979 }
1980 if (dwRc == NO_ERROR)
1981 {
1982 IPPROBE_CONTEXT Context;
1983 const ULONG ip192168 = inet_addr("192.168.0.0");
1984 srand(GetTickCount());
1985
1986 *pNetIp = 0;
1987 *pNetMask = 0;
1988
1989 for (int i = 0; i < 255; i++)
1990 {
1991 ULONG ipProbe = rand()*255/RAND_MAX;
1992 ipProbe = ip192168 | (ipProbe << 16);
1993 IPPROBE_INIT(&Context, ipProbe);
1994 vboxNetCfgWinEnumIpConfig(pAddresses, vboxNetCfgWinIpProbeCallback, &Context);
1995 if (!Context.bConflict)
1996 {
1997 *pNetIp = ipProbe;
1998 *pNetMask = inet_addr("255.255.255.0");
1999 break;
2000 }
2001 }
2002 if (*pNetIp == 0)
2003 dwRc = ERROR_DHCP_ADDRESS_CONFLICT;
2004 }
2005 else
2006 NonStandardLogFlow(("GetAdaptersAddresses err (%d)\n", dwRc));
2007
2008 if (pAddresses)
2009 free(pAddresses);
2010
2011 if (dwRc != NO_ERROR)
2012 {
2013 hr = HRESULT_FROM_WIN32(dwRc);
2014 }
2015
2016 return hr;
2017}
2018
2019/*
2020 * convenience functions to perform netflt/adp manipulations
2021 */
2022#define VBOXNETCFGWIN_NETFLT_ID L"sun_VBoxNetFlt"
2023#define VBOXNETCFGWIN_NETFLT_MP_ID L"sun_VBoxNetFltmp"
2024
2025static HRESULT vboxNetCfgWinNetFltUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2026{
2027 INetCfgComponent *pNcc = NULL;
2028 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETFLT_ID, &pNcc);
2029 if (hr == S_OK)
2030 {
2031 NonStandardLog("NetFlt is installed currently, uninstalling ...\n");
2032
2033 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
2034 NonStandardLogFlow(("NetFlt component uninstallation ended with hr (0x%x)\n", hr));
2035
2036 pNcc->Release();
2037 }
2038 else if (hr == S_FALSE)
2039 {
2040 NonStandardLog("NetFlt is not installed currently\n");
2041 }
2042 else
2043 {
2044 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
2045 }
2046
2047 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETFLT_ID, InfRmFlags);
2048 VBoxDrvCfgInfUninstallAllF(L"Net", VBOXNETCFGWIN_NETFLT_MP_ID, InfRmFlags);
2049
2050 return hr;
2051}
2052
2053VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc)
2054{
2055 return vboxNetCfgWinNetFltUninstall(pNc, 0);
2056}
2057
2058VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc,
2059 IN LPCWSTR const *apInfFullPaths, IN UINT cInfFullPaths)
2060{
2061 HRESULT hr = vboxNetCfgWinNetFltUninstall(pNc, SUOI_FORCEDELETE);
2062 if (SUCCEEDED(hr))
2063 {
2064 NonStandardLog("NetFlt will be installed ...\n");
2065 hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETFLT_ID,
2066 &GUID_DEVCLASS_NETSERVICE,
2067 apInfFullPaths,
2068 cInfFullPaths,
2069 NULL);
2070 }
2071 return hr;
2072}
2073
2074#define VBOXNETCFGWIN_NETADP_ID L"sun_VBoxNetAdp"
2075static HRESULT vboxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2076{
2077 HRESULT hr = S_OK;
2078 NonStandardLog("Finding NetAdp driver package and trying to uninstall it ...\n");
2079
2080 VBoxDrvCfgInfUninstallAllF(L"Net", VBOXNETCFGWIN_NETADP_ID, InfRmFlags);
2081 NonStandardLog("NetAdp is not installed currently\n");
2082 return hr;
2083}
2084
2085VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpUninstall(IN INetCfg *pNc)
2086{
2087 return vboxNetCfgWinNetAdpUninstall(pNc, SUOI_FORCEDELETE);
2088}
2089
2090/*
2091 * Use the same id as does the old implementation for NDIS 5
2092 * #define VBOXNETCFGWIN_NETLWF_ID L"oracle_VBoxNetLwf"
2093 */
2094#define VBOXNETCFGWIN_NETLWF_ID L"sun_VBoxNetFlt"
2095
2096static HRESULT vboxNetCfgWinNetLwfUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2097{
2098 INetCfgComponent * pNcc = NULL;
2099 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETLWF_ID, &pNcc);
2100 if (hr == S_OK)
2101 {
2102 NonStandardLog("NetLwf is installed currently, uninstalling ...\n");
2103
2104 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
2105
2106 pNcc->Release();
2107 }
2108 else if (hr == S_FALSE)
2109 {
2110 NonStandardLog("NetLwf is not installed currently\n");
2111 hr = S_OK;
2112 }
2113 else
2114 {
2115 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
2116 hr = S_OK;
2117 }
2118
2119 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETLWF_ID, InfRmFlags);
2120
2121 return hr;
2122}
2123
2124VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfUninstall(IN INetCfg *pNc)
2125{
2126 return vboxNetCfgWinNetLwfUninstall(pNc, 0);
2127}
2128
2129VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfInstall(IN INetCfg *pNc,
2130 IN LPCWSTR const pInfFullPath)
2131{
2132 HRESULT hr = vboxNetCfgWinNetLwfUninstall(pNc, SUOI_FORCEDELETE);
2133 if (SUCCEEDED(hr))
2134 {
2135 NonStandardLog("NetLwf will be installed ...\n");
2136 hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETLWF_ID,
2137 &GUID_DEVCLASS_NETSERVICE,
2138 &pInfFullPath,
2139 1,
2140 NULL);
2141 }
2142 return hr;
2143}
2144
2145#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
2146VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
2147{
2148 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
2149 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
2150 ULONG cbSufSize = 0;
2151
2152 if (pSuffix)
2153 {
2154 cbSize += (ULONG)wcslen(pSuffix) * 2;
2155 cbSize += 2; /* for space */
2156 }
2157
2158 if (*pcbBuf < cbSize)
2159 {
2160 *pcbBuf = cbSize;
2161 return E_FAIL;
2162 }
2163
2164 wcscpy(pBuf, VBOX_CONNECTION_NAME);
2165 if (pSuffix)
2166 {
2167 wcscat(pBuf, L" ");
2168 wcscat(pBuf, pSuffix);
2169 }
2170
2171 return S_OK;
2172}
2173
2174static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority(IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
2175{
2176 INetCfgComponentBindings *pNetCfgBindings;
2177 GUID *pGuid = (GUID*)pContext;
2178
2179 /* Get component's binding. */
2180 HRESULT hr = pNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pNetCfgBindings);
2181 if (SUCCEEDED(hr))
2182 {
2183 /* Get binding path enumerator reference. */
2184 IEnumNetCfgBindingPath *pEnumNetCfgBindPath;
2185 hr = pNetCfgBindings->EnumBindingPaths(EBP_BELOW, &pEnumNetCfgBindPath);
2186 if (SUCCEEDED(hr))
2187 {
2188 bool bFoundIface = false;
2189 hr = pEnumNetCfgBindPath->Reset();
2190 do
2191 {
2192 INetCfgBindingPath *pNetCfgBindPath;
2193 hr = pEnumNetCfgBindPath->Next(1, &pNetCfgBindPath, NULL);
2194 if (hr == S_OK)
2195 {
2196 IEnumNetCfgBindingInterface *pEnumNetCfgBindIface;
2197 hr = pNetCfgBindPath->EnumBindingInterfaces(&pEnumNetCfgBindIface);
2198 if (hr == S_OK)
2199 {
2200 pEnumNetCfgBindIface->Reset();
2201 do
2202 {
2203 INetCfgBindingInterface *pNetCfgBindIfce;
2204 hr = pEnumNetCfgBindIface->Next(1, &pNetCfgBindIfce, NULL);
2205 if (hr == S_OK)
2206 {
2207 INetCfgComponent *pNetCfgCompo;
2208 hr = pNetCfgBindIfce->GetLowerComponent(&pNetCfgCompo);
2209 if (hr == S_OK)
2210 {
2211 ULONG uComponentStatus;
2212 hr = pNetCfgCompo->GetDeviceStatus(&uComponentStatus);
2213 if (hr == S_OK)
2214 {
2215 GUID guid;
2216 hr = pNetCfgCompo->GetInstanceGuid(&guid);
2217 if ( hr == S_OK
2218 && guid == *pGuid)
2219 {
2220 hr = pNetCfgBindings->MoveAfter(pNetCfgBindPath, NULL);
2221 if (FAILED(hr))
2222 NonStandardLogFlow(("Unable to move interface, hr (0x%x)\n", hr));
2223 bFoundIface = true;
2224 }
2225 }
2226 pNetCfgCompo->Release();
2227 }
2228 else
2229 NonStandardLogFlow(("GetLowerComponent failed, hr (0x%x)\n", hr));
2230 pNetCfgBindIfce->Release();
2231 }
2232 else
2233 {
2234 if (hr == S_FALSE) /* No more binding interfaces? */
2235 hr = S_OK;
2236 else
2237 NonStandardLogFlow(("Next binding interface failed, hr (0x%x)\n", hr));
2238 break;
2239 }
2240 } while (!bFoundIface);
2241 pEnumNetCfgBindIface->Release();
2242 }
2243 else
2244 NonStandardLogFlow(("EnumBindingInterfaces failed, hr (0x%x)\n", hr));
2245 pNetCfgBindPath->Release();
2246 }
2247 else
2248 {
2249 if (hr == S_FALSE) /* No more binding paths? */
2250 hr = S_OK;
2251 else
2252 NonStandardLogFlow(("Next bind path failed, hr (0x%x)\n", hr));
2253 break;
2254 }
2255 } while (!bFoundIface);
2256 pEnumNetCfgBindPath->Release();
2257 }
2258 else
2259 NonStandardLogFlow(("EnumBindingPaths failed, hr (0x%x)\n", hr));
2260 pNetCfgBindings->Release();
2261 }
2262 else
2263 NonStandardLogFlow(("QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr));
2264 return TRUE;
2265}
2266
2267static UINT WINAPI vboxNetCfgWinPspFileCallback(
2268 PVOID Context,
2269 UINT Notification,
2270 UINT_PTR Param1,
2271 UINT_PTR Param2
2272 )
2273{
2274 switch (Notification)
2275 {
2276 case SPFILENOTIFY_TARGETNEWER:
2277 case SPFILENOTIFY_TARGETEXISTS:
2278 return TRUE;
2279 }
2280 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2281}
2282
2283/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
2284/*
2285 Copyright 2004 by the Massachusetts Institute of Technology
2286
2287 All rights reserved.
2288
2289 Permission to use, copy, modify, and distribute this software and its
2290 documentation for any purpose and without fee is hereby granted,
2291 provided that the above copyright notice appear in all copies and that
2292 both that copyright notice and this permission notice appear in
2293 supporting documentation, and that the name of the Massachusetts
2294 Institute of Technology (M.I.T.) not be used in advertising or publicity
2295 pertaining to distribution of the software without specific, written
2296 prior permission.
2297
2298 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2299 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2300 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2301 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2302 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2303 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2304 SOFTWARE.
2305*/
2306
2307
2308/**
2309 * Use the IShellFolder API to rename the connection.
2310 */
2311static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
2312{
2313 /* This is the GUID for the network connections folder. It is constant.
2314 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
2315 const GUID CLSID_NetworkConnections = {
2316 0x7007ACC7, 0x3202, 0x11D1, {
2317 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
2318 }
2319 };
2320
2321 LPITEMIDLIST pidl = NULL;
2322 IShellFolder *pShellFolder = NULL;
2323 HRESULT hr;
2324
2325 /* Build the display name in the form "::{GUID}". */
2326 if (wcslen(wGuid) >= MAX_PATH)
2327 return E_INVALIDARG;
2328 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
2329 swprintf(szAdapterGuid, L"::%ls", wGuid);
2330
2331 /* Create an instance of the network connections folder. */
2332 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
2333 CLSCTX_INPROC_SERVER, IID_IShellFolder,
2334 reinterpret_cast<LPVOID *>(&pShellFolder));
2335 /* Parse the display name. */
2336 if (SUCCEEDED (hr))
2337 {
2338 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
2339 &pidl, NULL);
2340 }
2341 if (SUCCEEDED (hr))
2342 {
2343 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
2344 &pidl);
2345 }
2346
2347 CoTaskMemFree (pidl);
2348
2349 if (pShellFolder)
2350 pShellFolder->Release();
2351
2352 return hr;
2353}
2354
2355/**
2356 * Loads a system DLL.
2357 *
2358 * @returns Module handle or NULL
2359 * @param pszName The DLL name.
2360 */
2361static HMODULE loadSystemDll(const char *pszName)
2362{
2363 char szPath[MAX_PATH];
2364 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
2365 size_t cbName = strlen(pszName) + 1;
2366 if (cchPath + 1 + cbName > sizeof(szPath))
2367 return NULL;
2368 szPath[cchPath] = '\\';
2369 memcpy(&szPath[cchPath + 1], pszName, cbName);
2370 return LoadLibraryA(szPath);
2371}
2372
2373VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
2374{
2375 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
2376 lpHrRenameConnection RenameConnectionFunc = NULL;
2377 HRESULT status;
2378
2379 /* First try the IShellFolder interface, which was unimplemented
2380 * for the network connections folder before XP. */
2381 status = rename_shellfolder (pGuid, NewName);
2382 if (status == E_NOTIMPL)
2383 {
2384/** @todo that code doesn't seem to work! */
2385 /* The IShellFolder interface is not implemented on this platform.
2386 * Try the (undocumented) HrRenameConnection API in the netshell
2387 * library. */
2388 CLSID clsid;
2389 HINSTANCE hNetShell;
2390 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
2391 if (FAILED(status))
2392 return E_FAIL;
2393 hNetShell = loadSystemDll("netshell.dll");
2394 if (hNetShell == NULL)
2395 return E_FAIL;
2396 RenameConnectionFunc =
2397 (lpHrRenameConnection) GetProcAddress (hNetShell,
2398 "HrRenameConnection");
2399 if (RenameConnectionFunc == NULL)
2400 {
2401 FreeLibrary (hNetShell);
2402 return E_FAIL;
2403 }
2404 status = RenameConnectionFunc (&clsid, NewName);
2405 FreeLibrary (hNetShell);
2406 }
2407 if (FAILED (status))
2408 return status;
2409
2410 return S_OK;
2411}
2412
2413#define DRIVERHWID _T("sun_VBoxNetAdp")
2414
2415#define SetErrBreak(strAndArgs) \
2416 if (1) { \
2417 hrc = E_FAIL; \
2418 NonStandardLog strAndArgs; \
2419 break; \
2420 } else do {} while (0)
2421
2422VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg)
2423{
2424 HRESULT hrc = S_OK;
2425
2426 do
2427 {
2428 TCHAR lszPnPInstanceId [512] = {0};
2429
2430 /* We have to find the device instance ID through a registry search */
2431
2432 HKEY hkeyNetwork = 0;
2433 HKEY hkeyConnection = 0;
2434
2435 do
2436 {
2437 WCHAR strRegLocation [256];
2438 WCHAR wszGuid[50];
2439
2440 int length = StringFromGUID2(*pGUID, wszGuid, RT_ELEMENTS(wszGuid));
2441 if (!length)
2442 SetErrBreak(("Failed to create a Guid string"));
2443
2444 swprintf (strRegLocation,
2445 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
2446 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
2447 wszGuid);
2448
2449 LONG status;
2450 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
2451 KEY_READ, &hkeyNetwork);
2452 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
2453 SetErrBreak (("Host interface network is not found in registry (%S) [1]",
2454 strRegLocation));
2455
2456 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
2457 KEY_READ, &hkeyConnection);
2458 if ((status != ERROR_SUCCESS) || !hkeyConnection)
2459 SetErrBreak (("Host interface network is not found in registry (%S) [2]",
2460 strRegLocation));
2461
2462 DWORD len = sizeof (lszPnPInstanceId);
2463 DWORD dwKeyType;
2464 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2465 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2466 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2467 SetErrBreak (("Host interface network is not found in registry (%S) [3]",
2468 strRegLocation));
2469 }
2470 while (0);
2471
2472 if (hkeyConnection)
2473 RegCloseKey (hkeyConnection);
2474 if (hkeyNetwork)
2475 RegCloseKey (hkeyNetwork);
2476
2477 if (FAILED (hrc))
2478 break;
2479
2480 /*
2481 * Now we are going to enumerate all network devices and
2482 * wait until we encounter the right device instance ID
2483 */
2484
2485 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2486
2487 do
2488 {
2489 BOOL ok;
2490 DWORD ret = 0;
2491 GUID netGuid;
2492 SP_DEVINFO_DATA DeviceInfoData;
2493 DWORD index = 0;
2494 BOOL found = FALSE;
2495 DWORD size = 0;
2496
2497 /* initialize the structure size */
2498 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2499
2500 /* copy the net class GUID */
2501 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2502
2503 /* return a device info set contains all installed devices of the Net class */
2504 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2505
2506 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2507 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2508
2509 /* enumerate the driver info list */
2510 while (TRUE)
2511 {
2512 TCHAR *deviceHwid;
2513
2514 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2515
2516 if (!ok)
2517 {
2518 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2519 break;
2520 else
2521 {
2522 index++;
2523 continue;
2524 }
2525 }
2526
2527 /* try to get the hardware ID registry property */
2528 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2529 &DeviceInfoData,
2530 SPDRP_HARDWAREID,
2531 NULL,
2532 NULL,
2533 0,
2534 &size);
2535 if (!ok)
2536 {
2537 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2538 {
2539 index++;
2540 continue;
2541 }
2542
2543 deviceHwid = (TCHAR *) malloc (size);
2544 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2545 &DeviceInfoData,
2546 SPDRP_HARDWAREID,
2547 NULL,
2548 (PBYTE)deviceHwid,
2549 size,
2550 NULL);
2551 if (!ok)
2552 {
2553 free (deviceHwid);
2554 deviceHwid = NULL;
2555 index++;
2556 continue;
2557 }
2558 }
2559 else
2560 {
2561 /* something is wrong. This shouldn't have worked with a NULL buffer */
2562 index++;
2563 continue;
2564 }
2565
2566 for (TCHAR *t = deviceHwid;
2567 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2568 t += _tcslen (t) + 1)
2569 {
2570 if (!_tcsicmp (DRIVERHWID, t))
2571 {
2572 /* get the device instance ID */
2573 TCHAR devId[MAX_DEVICE_ID_LEN];
2574 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2575 devId, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2576 {
2577 /* compare to what we determined before */
2578 if (wcscmp(devId, lszPnPInstanceId) == 0)
2579 {
2580 found = TRUE;
2581 break;
2582 }
2583 }
2584 }
2585 }
2586
2587 if (deviceHwid)
2588 {
2589 free (deviceHwid);
2590 deviceHwid = NULL;
2591 }
2592
2593 if (found)
2594 break;
2595
2596 index++;
2597 }
2598
2599 if (found == FALSE)
2600 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
2601 GetLastError()));
2602
2603 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2604 if (!ok)
2605 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2606 GetLastError()));
2607
2608 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2609 if (!ok)
2610 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2611 GetLastError()));
2612 }
2613 while (0);
2614
2615 /* clean up the device info set */
2616 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2617 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2618
2619 if (FAILED (hrc))
2620 break;
2621 }
2622 while (0);
2623
2624 return hrc;
2625}
2626
2627VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUpdateHostOnlyNetworkInterface(LPCWSTR pcsxwInf, BOOL *pbRebootRequired, LPCWSTR pcsxwId)
2628{
2629 return VBoxDrvCfgDrvUpdate(pcsxwId, pcsxwInf, pbRebootRequired);
2630}
2631
2632VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
2633 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
2634{
2635 HRESULT hrc = S_OK;
2636
2637 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2638 SP_DEVINFO_DATA DeviceInfoData;
2639 PVOID pQueueCallbackContext = NULL;
2640 DWORD ret = 0;
2641 BOOL found = FALSE;
2642 BOOL registered = FALSE;
2643 BOOL destroyList = FALSE;
2644 WCHAR pWCfgGuidString [50];
2645 WCHAR DevName[256];
2646
2647 do
2648 {
2649 GUID netGuid;
2650 SP_DRVINFO_DATA DriverInfoData;
2651 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2652 TCHAR className [MAX_PATH];
2653 DWORD index = 0;
2654 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2655 /* for our purposes, 2k buffer is more
2656 * than enough to obtain the hardware ID
2657 * of the VBoxNetAdp driver. */
2658 DWORD detailBuf [2048];
2659
2660 HKEY hkey = NULL;
2661 DWORD cbSize;
2662 DWORD dwValueType;
2663
2664 /* initialize the structure size */
2665 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2666 DriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
2667
2668 /* copy the net class GUID */
2669 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2670
2671 /* create an empty device info set associated with the net class GUID */
2672 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
2673 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2674 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
2675 GetLastError()));
2676
2677 /* get the class name from GUID */
2678 BOOL fResult = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2679 if (!fResult)
2680 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
2681 GetLastError()));
2682
2683 /* create a device info element and add the new device instance
2684 * key to registry */
2685 fResult = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2686 DICD_GENERATE_ID, &DeviceInfoData);
2687 if (!fResult)
2688 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
2689 GetLastError()));
2690
2691 /* select the newly created device info to be the currently
2692 selected member */
2693 fResult = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2694 if (!fResult)
2695 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2696 GetLastError()));
2697
2698 if (pInfPath)
2699 {
2700 /* get the device install parameters and disable filecopy */
2701 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2702 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2703 &DeviceInstallParams);
2704 if (fResult)
2705 {
2706 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2707 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2708 if (pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2709 {
2710 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2711
2712 if (bIsInfPathFile)
2713 {
2714 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2715 }
2716
2717 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2718 &DeviceInstallParams);
2719 if (!fResult)
2720 {
2721 DWORD winEr = GetLastError();
2722 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2723 break;
2724 }
2725 }
2726 else
2727 {
2728 NonStandardLogFlow(("SetupDiSetDeviceInstallParams faileed: INF path is too long\n"));
2729 break;
2730 }
2731 }
2732 else
2733 {
2734 DWORD winEr = GetLastError();
2735 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2736 }
2737 }
2738
2739 /* build a list of class drivers */
2740 fResult = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2741 SPDIT_CLASSDRIVER);
2742 if (!fResult)
2743 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
2744 GetLastError()));
2745
2746 destroyList = TRUE;
2747
2748 /* enumerate the driver info list */
2749 while (TRUE)
2750 {
2751 BOOL ret;
2752
2753 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2754 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2755
2756 /* if the function failed and GetLastError() returned
2757 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2758 * list. Otherwise there was something wrong with this
2759 * particular driver. */
2760 if (!ret)
2761 {
2762 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2763 break;
2764 else
2765 {
2766 index++;
2767 continue;
2768 }
2769 }
2770
2771 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2772 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2773
2774 /* if we successfully find the hardware ID and it turns out to
2775 * be the one for the loopback driver, then we are done. */
2776 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2777 &DeviceInfoData,
2778 &DriverInfoData,
2779 pDriverInfoDetail,
2780 sizeof (detailBuf),
2781 NULL))
2782 {
2783 TCHAR * t;
2784
2785 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2786 * whole list and see if there is a match somewhere. */
2787 t = pDriverInfoDetail->HardwareID;
2788 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2789 {
2790 if (!_tcsicmp(t, DRIVERHWID))
2791 break;
2792
2793 t += _tcslen(t) + 1;
2794 }
2795
2796 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2797 {
2798 found = TRUE;
2799 break;
2800 }
2801 }
2802
2803 index ++;
2804 }
2805
2806 if (!found)
2807 SetErrBreak(("Could not find Host Interface Networking driver! Please reinstall"));
2808
2809 /* set the loopback driver to be the currently selected */
2810 fResult = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2811 &DriverInfoData);
2812 if (!fResult)
2813 SetErrBreak(("SetupDiSetSelectedDriver failed (0x%08X)",
2814 GetLastError()));
2815
2816 /* register the phantom device to prepare for install */
2817 fResult = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2818 &DeviceInfoData);
2819 if (!fResult)
2820 {
2821 DWORD err = GetLastError();
2822 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
2823 err));
2824 }
2825
2826 /* registered, but remove if errors occur in the following code */
2827 registered = TRUE;
2828
2829 /* ask the installer if we can install the device */
2830 fResult = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2831 &DeviceInfoData);
2832 if (!fResult)
2833 {
2834 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2835 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2836 GetLastError()));
2837 /* that's fine */
2838 }
2839
2840 /* get the device install parameters and disable filecopy */
2841 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2842 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2843 &DeviceInstallParams);
2844 if (fResult)
2845 {
2846 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2847 if (pQueueCallbackContext)
2848 {
2849 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2850 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2851 fResult = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2852 &DeviceInstallParams);
2853 if (!fResult)
2854 {
2855 DWORD winEr = GetLastError();
2856 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2857 }
2858 Assert(fResult);
2859 }
2860 else
2861 {
2862 DWORD winEr = GetLastError();
2863 NonStandardLogFlow(("SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr));
2864 }
2865 }
2866 else
2867 {
2868 DWORD winEr = GetLastError();
2869 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2870 }
2871
2872 /* install the files first */
2873 fResult = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2874 &DeviceInfoData);
2875 if (!fResult)
2876 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2877 GetLastError()));
2878 /* get the device install parameters and disable filecopy */
2879 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2880 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2881 &DeviceInstallParams);
2882 if (fResult)
2883 {
2884 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2885 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2886 &DeviceInstallParams);
2887 if (!fResult)
2888 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
2889 GetLastError()));
2890 }
2891
2892 /*
2893 * Register any device-specific co-installers for this device,
2894 */
2895 fResult = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
2896 hDeviceInfo,
2897 &DeviceInfoData);
2898 if (!fResult)
2899 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2900 GetLastError()));
2901
2902 /*
2903 * install any installer-specified interfaces.
2904 * and then do the real install
2905 */
2906 fResult = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
2907 hDeviceInfo,
2908 &DeviceInfoData);
2909 if (!fResult)
2910 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2911 GetLastError()));
2912
2913 fResult = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
2914 hDeviceInfo,
2915 &DeviceInfoData);
2916 if (!fResult)
2917 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2918 GetLastError()));
2919
2920 /* Figure out NetCfgInstanceId */
2921 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
2922 &DeviceInfoData,
2923 DICS_FLAG_GLOBAL,
2924 0,
2925 DIREG_DRV,
2926 KEY_READ);
2927 if (hkey == INVALID_HANDLE_VALUE)
2928 SetErrBreak(("SetupDiOpenDevRegKey failed (0x%08X)", GetLastError()));
2929
2930 cbSize = sizeof(pWCfgGuidString);
2931 DWORD ret;
2932 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2933 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2934
2935 RegCloseKey (hkey);
2936
2937 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2938 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2939 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2940 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2941 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2942 NULL /*OUT PDWORD RequiredSize OPTIONAL*/))
2943 {
2944 int err = GetLastError();
2945 if (err != ERROR_INVALID_DATA)
2946 {
2947 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2948 err));
2949 }
2950
2951 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2952 SPDRP_DEVICEDESC, /* IN DWORD Property,*/
2953 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2954 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2955 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2956 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2957 ))
2958 {
2959 err = GetLastError();
2960 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2961 err));
2962 }
2963 }
2964 }
2965 while (0);
2966
2967 /*
2968 * cleanup
2969 */
2970 if (pQueueCallbackContext)
2971 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2972
2973 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2974 {
2975 /* an error has occurred, but the device is registered, we must remove it */
2976 if (ret != 0 && registered)
2977 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2978
2979 found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
2980
2981 /* destroy the driver info list */
2982 if (destroyList)
2983 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
2984 SPDIT_CLASSDRIVER);
2985 /* clean up the device info set */
2986 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2987 }
2988
2989 /* return the network connection GUID on success */
2990 if (SUCCEEDED(hrc))
2991 {
2992 WCHAR ConnectoinName[128];
2993 ULONG cbName = sizeof(ConnectoinName);
2994
2995 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(DevName, ConnectoinName, &cbName);
2996 if (SUCCEEDED(hr))
2997 hr = VBoxNetCfgWinRenameConnection(pWCfgGuidString, ConnectoinName);
2998
2999 if (lppszName)
3000 {
3001 *lppszName = SysAllocString((const OLECHAR *) DevName);
3002 if (!*lppszName)
3003 {
3004 NonStandardLogFlow(("SysAllocString failed\n"));
3005 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3006 }
3007 }
3008
3009 if (pGuid)
3010 {
3011 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID)pGuid);
3012 if (FAILED(hrc))
3013 NonStandardLogFlow(("CLSIDFromString failed, hrc (0x%x)\n", hrc));
3014 }
3015
3016 INetCfg *pNetCfg = NULL;
3017 LPWSTR lpszApp = NULL;
3018 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, TRUE, L"VirtualBox Host-Only Creation",
3019 30 * 1000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec. */
3020 /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
3021 &lpszApp);
3022 if (hr == S_OK)
3023 {
3024 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3025 &GUID_DEVCLASS_NETSERVICE,
3026 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3027 pGuid);
3028 if (SUCCEEDED(hr))
3029 {
3030 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3031 &GUID_DEVCLASS_NETTRANS,
3032 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3033 pGuid);
3034 if (SUCCEEDED(hr))
3035 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3036 &GUID_DEVCLASS_NETCLIENT,
3037 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3038 pGuid);
3039 }
3040
3041 if (SUCCEEDED(hr))
3042 {
3043 hr = pNetCfg->Apply();
3044 }
3045 else
3046 NonStandardLogFlow(("Enumeration failed, hr 0x%x\n", hr));
3047 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
3048 }
3049 else if (hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
3050 {
3051 NonStandardLogFlow(("Application %ws is holding the lock, failed\n", lpszApp));
3052 CoTaskMemFree(lpszApp);
3053 }
3054 else
3055 NonStandardLogFlow(("VBoxNetCfgWinQueryINetCfg failed, hr 0x%x\n", hr));
3056 }
3057 return hrc;
3058}
3059
3060#undef SetErrBreak
3061
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