VirtualBox

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

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

HostDrivers: Updated (C) year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 103.9 KB
Line 
1/* $Id: VBoxNetCfg.cpp 56293 2015-06-09 14:23:56Z vboxsync $ */
2/** @file
3 * VBoxNetCfg.cpp - Network Configuration API.
4 */
5/*
6 * Copyright (C) 2011-2015 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, LPCWSTR pwszId, 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", pwszId, InfRmFlags);
2081 NonStandardLog("NetAdp is not installed currently\n");
2082 return hr;
2083}
2084
2085VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, IN LPCWSTR pwszId)
2086{
2087 return vboxNetCfgWinNetAdpUninstall(pNc, pwszId, SUOI_FORCEDELETE);
2088}
2089
2090#define VBOXNETCFGWIN_NETLWF_ID L"oracle_VBoxNetLwf"
2091
2092static HRESULT vboxNetCfgWinNetLwfUninstall(IN INetCfg *pNc, DWORD InfRmFlags)
2093{
2094 INetCfgComponent * pNcc = NULL;
2095 HRESULT hr = pNc->FindComponent(VBOXNETCFGWIN_NETLWF_ID, &pNcc);
2096 if (hr == S_OK)
2097 {
2098 NonStandardLog("NetLwf is installed currently, uninstalling ...\n");
2099
2100 hr = VBoxNetCfgWinUninstallComponent(pNc, pNcc);
2101
2102 pNcc->Release();
2103 }
2104 else if (hr == S_FALSE)
2105 {
2106 NonStandardLog("NetLwf is not installed currently\n");
2107 hr = S_OK;
2108 }
2109 else
2110 {
2111 NonStandardLogFlow(("FindComponent failed, hr (0x%x)\n", hr));
2112 hr = S_OK;
2113 }
2114
2115 VBoxDrvCfgInfUninstallAllF(L"NetService", VBOXNETCFGWIN_NETLWF_ID, InfRmFlags);
2116
2117 return hr;
2118}
2119
2120VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfUninstall(IN INetCfg *pNc)
2121{
2122 return vboxNetCfgWinNetLwfUninstall(pNc, 0);
2123}
2124
2125VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfInstall(IN INetCfg *pNc,
2126 IN LPCWSTR const pInfFullPath)
2127{
2128 HRESULT hr = vboxNetCfgWinNetLwfUninstall(pNc, SUOI_FORCEDELETE);
2129 if (SUCCEEDED(hr))
2130 {
2131 NonStandardLog("NetLwf will be installed ...\n");
2132 hr = vboxNetCfgWinInstallInfAndComponent(pNc, VBOXNETCFGWIN_NETLWF_ID,
2133 &GUID_DEVCLASS_NETSERVICE,
2134 &pInfFullPath,
2135 1,
2136 NULL);
2137 }
2138 return hr;
2139}
2140
2141#define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network"
2142VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf)
2143{
2144 const WCHAR * pSuffix = wcsrchr( DevName, L'#' );
2145 ULONG cbSize = sizeof(VBOX_CONNECTION_NAME);
2146 ULONG cbSufSize = 0;
2147
2148 if (pSuffix)
2149 {
2150 cbSize += (ULONG)wcslen(pSuffix) * 2;
2151 cbSize += 2; /* for space */
2152 }
2153
2154 if (*pcbBuf < cbSize)
2155 {
2156 *pcbBuf = cbSize;
2157 return E_FAIL;
2158 }
2159
2160 wcscpy(pBuf, VBOX_CONNECTION_NAME);
2161 if (pSuffix)
2162 {
2163 wcscat(pBuf, L" ");
2164 wcscat(pBuf, pSuffix);
2165 }
2166
2167 return S_OK;
2168}
2169
2170static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority(IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext)
2171{
2172 INetCfgComponentBindings *pNetCfgBindings;
2173 GUID *pGuid = (GUID*)pContext;
2174
2175 /* Get component's binding. */
2176 HRESULT hr = pNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pNetCfgBindings);
2177 if (SUCCEEDED(hr))
2178 {
2179 /* Get binding path enumerator reference. */
2180 IEnumNetCfgBindingPath *pEnumNetCfgBindPath;
2181 hr = pNetCfgBindings->EnumBindingPaths(EBP_BELOW, &pEnumNetCfgBindPath);
2182 if (SUCCEEDED(hr))
2183 {
2184 bool bFoundIface = false;
2185 hr = pEnumNetCfgBindPath->Reset();
2186 do
2187 {
2188 INetCfgBindingPath *pNetCfgBindPath;
2189 hr = pEnumNetCfgBindPath->Next(1, &pNetCfgBindPath, NULL);
2190 if (hr == S_OK)
2191 {
2192 IEnumNetCfgBindingInterface *pEnumNetCfgBindIface;
2193 hr = pNetCfgBindPath->EnumBindingInterfaces(&pEnumNetCfgBindIface);
2194 if (hr == S_OK)
2195 {
2196 pEnumNetCfgBindIface->Reset();
2197 do
2198 {
2199 INetCfgBindingInterface *pNetCfgBindIfce;
2200 hr = pEnumNetCfgBindIface->Next(1, &pNetCfgBindIfce, NULL);
2201 if (hr == S_OK)
2202 {
2203 INetCfgComponent *pNetCfgCompo;
2204 hr = pNetCfgBindIfce->GetLowerComponent(&pNetCfgCompo);
2205 if (hr == S_OK)
2206 {
2207 ULONG uComponentStatus;
2208 hr = pNetCfgCompo->GetDeviceStatus(&uComponentStatus);
2209 if (hr == S_OK)
2210 {
2211 GUID guid;
2212 hr = pNetCfgCompo->GetInstanceGuid(&guid);
2213 if ( hr == S_OK
2214 && guid == *pGuid)
2215 {
2216 hr = pNetCfgBindings->MoveAfter(pNetCfgBindPath, NULL);
2217 if (FAILED(hr))
2218 NonStandardLogFlow(("Unable to move interface, hr (0x%x)\n", hr));
2219 bFoundIface = true;
2220 }
2221 }
2222 pNetCfgCompo->Release();
2223 }
2224 else
2225 NonStandardLogFlow(("GetLowerComponent failed, hr (0x%x)\n", hr));
2226 pNetCfgBindIfce->Release();
2227 }
2228 else
2229 {
2230 if (hr == S_FALSE) /* No more binding interfaces? */
2231 hr = S_OK;
2232 else
2233 NonStandardLogFlow(("Next binding interface failed, hr (0x%x)\n", hr));
2234 break;
2235 }
2236 } while (!bFoundIface);
2237 pEnumNetCfgBindIface->Release();
2238 }
2239 else
2240 NonStandardLogFlow(("EnumBindingInterfaces failed, hr (0x%x)\n", hr));
2241 pNetCfgBindPath->Release();
2242 }
2243 else
2244 {
2245 if (hr == S_FALSE) /* No more binding paths? */
2246 hr = S_OK;
2247 else
2248 NonStandardLogFlow(("Next bind path failed, hr (0x%x)\n", hr));
2249 break;
2250 }
2251 } while (!bFoundIface);
2252 pEnumNetCfgBindPath->Release();
2253 }
2254 else
2255 NonStandardLogFlow(("EnumBindingPaths failed, hr (0x%x)\n", hr));
2256 pNetCfgBindings->Release();
2257 }
2258 else
2259 NonStandardLogFlow(("QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr));
2260 return TRUE;
2261}
2262
2263static UINT WINAPI vboxNetCfgWinPspFileCallback(
2264 PVOID Context,
2265 UINT Notification,
2266 UINT_PTR Param1,
2267 UINT_PTR Param2
2268 )
2269{
2270 switch (Notification)
2271 {
2272 case SPFILENOTIFY_TARGETNEWER:
2273 case SPFILENOTIFY_TARGETEXISTS:
2274 return TRUE;
2275 }
2276 return SetupDefaultQueueCallback(Context, Notification, Param1, Param2);
2277}
2278
2279/* The original source of the VBoxNetAdp adapter creation/destruction code has the following copyright */
2280/*
2281 Copyright 2004 by the Massachusetts Institute of Technology
2282
2283 All rights reserved.
2284
2285 Permission to use, copy, modify, and distribute this software and its
2286 documentation for any purpose and without fee is hereby granted,
2287 provided that the above copyright notice appear in all copies and that
2288 both that copyright notice and this permission notice appear in
2289 supporting documentation, and that the name of the Massachusetts
2290 Institute of Technology (M.I.T.) not be used in advertising or publicity
2291 pertaining to distribution of the software without specific, written
2292 prior permission.
2293
2294 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2295 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2296 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2297 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2298 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2299 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2300 SOFTWARE.
2301*/
2302
2303
2304/**
2305 * Use the IShellFolder API to rename the connection.
2306 */
2307static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
2308{
2309 /* This is the GUID for the network connections folder. It is constant.
2310 * {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
2311 const GUID CLSID_NetworkConnections = {
2312 0x7007ACC7, 0x3202, 0x11D1, {
2313 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
2314 }
2315 };
2316
2317 LPITEMIDLIST pidl = NULL;
2318 IShellFolder *pShellFolder = NULL;
2319 HRESULT hr;
2320
2321 /* Build the display name in the form "::{GUID}". */
2322 if (wcslen(wGuid) >= MAX_PATH)
2323 return E_INVALIDARG;
2324 WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
2325 swprintf(szAdapterGuid, L"::%ls", wGuid);
2326
2327 /* Create an instance of the network connections folder. */
2328 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
2329 CLSCTX_INPROC_SERVER, IID_IShellFolder,
2330 reinterpret_cast<LPVOID *>(&pShellFolder));
2331 /* Parse the display name. */
2332 if (SUCCEEDED (hr))
2333 {
2334 hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
2335 &pidl, NULL);
2336 }
2337 if (SUCCEEDED (hr))
2338 {
2339 hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
2340 &pidl);
2341 }
2342
2343 CoTaskMemFree (pidl);
2344
2345 if (pShellFolder)
2346 pShellFolder->Release();
2347
2348 return hr;
2349}
2350
2351/**
2352 * Loads a system DLL.
2353 *
2354 * @returns Module handle or NULL
2355 * @param pszName The DLL name.
2356 */
2357static HMODULE loadSystemDll(const char *pszName)
2358{
2359 char szPath[MAX_PATH];
2360 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
2361 size_t cbName = strlen(pszName) + 1;
2362 if (cchPath + 1 + cbName > sizeof(szPath))
2363 return NULL;
2364 szPath[cchPath] = '\\';
2365 memcpy(&szPath[cchPath + 1], pszName, cbName);
2366 return LoadLibraryA(szPath);
2367}
2368
2369VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection (LPWSTR pGuid, PCWSTR NewName)
2370{
2371 typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
2372 lpHrRenameConnection RenameConnectionFunc = NULL;
2373 HRESULT status;
2374
2375 /* First try the IShellFolder interface, which was unimplemented
2376 * for the network connections folder before XP. */
2377 status = rename_shellfolder (pGuid, NewName);
2378 if (status == E_NOTIMPL)
2379 {
2380/** @todo that code doesn't seem to work! */
2381 /* The IShellFolder interface is not implemented on this platform.
2382 * Try the (undocumented) HrRenameConnection API in the netshell
2383 * library. */
2384 CLSID clsid;
2385 HINSTANCE hNetShell;
2386 status = CLSIDFromString ((LPOLESTR) pGuid, &clsid);
2387 if (FAILED(status))
2388 return E_FAIL;
2389 hNetShell = loadSystemDll("netshell.dll");
2390 if (hNetShell == NULL)
2391 return E_FAIL;
2392 RenameConnectionFunc =
2393 (lpHrRenameConnection) GetProcAddress (hNetShell,
2394 "HrRenameConnection");
2395 if (RenameConnectionFunc == NULL)
2396 {
2397 FreeLibrary (hNetShell);
2398 return E_FAIL;
2399 }
2400 status = RenameConnectionFunc (&clsid, NewName);
2401 FreeLibrary (hNetShell);
2402 }
2403 if (FAILED (status))
2404 return status;
2405
2406 return S_OK;
2407}
2408
2409#define DRIVERHWID _T("sun_VBoxNetAdp")
2410
2411#define SetErrBreak(strAndArgs) \
2412 if (1) { \
2413 hrc = E_FAIL; \
2414 NonStandardLog strAndArgs; \
2415 break; \
2416 } else do {} while (0)
2417
2418VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg)
2419{
2420 HRESULT hrc = S_OK;
2421
2422 do
2423 {
2424 TCHAR lszPnPInstanceId [512] = {0};
2425
2426 /* We have to find the device instance ID through a registry search */
2427
2428 HKEY hkeyNetwork = 0;
2429 HKEY hkeyConnection = 0;
2430
2431 do
2432 {
2433 WCHAR strRegLocation [256];
2434 WCHAR wszGuid[50];
2435
2436 int length = StringFromGUID2(*pGUID, wszGuid, RT_ELEMENTS(wszGuid));
2437 if (!length)
2438 SetErrBreak(("Failed to create a Guid string"));
2439
2440 swprintf (strRegLocation,
2441 L"SYSTEM\\CurrentControlSet\\Control\\Network\\"
2442 L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
2443 wszGuid);
2444
2445 LONG status;
2446 status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, strRegLocation, 0,
2447 KEY_READ, &hkeyNetwork);
2448 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
2449 SetErrBreak (("Host interface network is not found in registry (%S) [1]",
2450 strRegLocation));
2451
2452 status = RegOpenKeyExW (hkeyNetwork, L"Connection", 0,
2453 KEY_READ, &hkeyConnection);
2454 if ((status != ERROR_SUCCESS) || !hkeyConnection)
2455 SetErrBreak (("Host interface network is not found in registry (%S) [2]",
2456 strRegLocation));
2457
2458 DWORD len = sizeof (lszPnPInstanceId);
2459 DWORD dwKeyType;
2460 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
2461 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
2462 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
2463 SetErrBreak (("Host interface network is not found in registry (%S) [3]",
2464 strRegLocation));
2465 }
2466 while (0);
2467
2468 if (hkeyConnection)
2469 RegCloseKey (hkeyConnection);
2470 if (hkeyNetwork)
2471 RegCloseKey (hkeyNetwork);
2472
2473 if (FAILED (hrc))
2474 break;
2475
2476 /*
2477 * Now we are going to enumerate all network devices and
2478 * wait until we encounter the right device instance ID
2479 */
2480
2481 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2482
2483 do
2484 {
2485 BOOL ok;
2486 DWORD ret = 0;
2487 GUID netGuid;
2488 SP_DEVINFO_DATA DeviceInfoData;
2489 DWORD index = 0;
2490 BOOL found = FALSE;
2491 DWORD size = 0;
2492
2493 /* initialize the structure size */
2494 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2495
2496 /* copy the net class GUID */
2497 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
2498
2499 /* return a device info set contains all installed devices of the Net class */
2500 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
2501
2502 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2503 SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
2504
2505 /* enumerate the driver info list */
2506 while (TRUE)
2507 {
2508 TCHAR *deviceHwid;
2509
2510 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
2511
2512 if (!ok)
2513 {
2514 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2515 break;
2516 else
2517 {
2518 index++;
2519 continue;
2520 }
2521 }
2522
2523 /* try to get the hardware ID registry property */
2524 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2525 &DeviceInfoData,
2526 SPDRP_HARDWAREID,
2527 NULL,
2528 NULL,
2529 0,
2530 &size);
2531 if (!ok)
2532 {
2533 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2534 {
2535 index++;
2536 continue;
2537 }
2538
2539 deviceHwid = (TCHAR *) malloc (size);
2540 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
2541 &DeviceInfoData,
2542 SPDRP_HARDWAREID,
2543 NULL,
2544 (PBYTE)deviceHwid,
2545 size,
2546 NULL);
2547 if (!ok)
2548 {
2549 free (deviceHwid);
2550 deviceHwid = NULL;
2551 index++;
2552 continue;
2553 }
2554 }
2555 else
2556 {
2557 /* something is wrong. This shouldn't have worked with a NULL buffer */
2558 index++;
2559 continue;
2560 }
2561
2562 for (TCHAR *t = deviceHwid;
2563 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
2564 t += _tcslen (t) + 1)
2565 {
2566 if (!_tcsicmp (DRIVERHWID, t))
2567 {
2568 /* get the device instance ID */
2569 TCHAR devId[MAX_DEVICE_ID_LEN];
2570 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
2571 devId, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
2572 {
2573 /* compare to what we determined before */
2574 if (wcscmp(devId, lszPnPInstanceId) == 0)
2575 {
2576 found = TRUE;
2577 break;
2578 }
2579 }
2580 }
2581 }
2582
2583 if (deviceHwid)
2584 {
2585 free (deviceHwid);
2586 deviceHwid = NULL;
2587 }
2588
2589 if (found)
2590 break;
2591
2592 index++;
2593 }
2594
2595 if (found == FALSE)
2596 SetErrBreak (("Host Interface Network driver not found (0x%08X)",
2597 GetLastError()));
2598
2599 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2600 if (!ok)
2601 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2602 GetLastError()));
2603
2604 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2605 if (!ok)
2606 SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
2607 GetLastError()));
2608 }
2609 while (0);
2610
2611 /* clean up the device info set */
2612 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2613 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2614
2615 if (FAILED (hrc))
2616 break;
2617 }
2618 while (0);
2619
2620 return hrc;
2621}
2622
2623VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUpdateHostOnlyNetworkInterface(LPCWSTR pcsxwInf, BOOL *pbRebootRequired, LPCWSTR pcsxwId)
2624{
2625 return VBoxDrvCfgDrvUpdate(pcsxwId, pcsxwInf, pbRebootRequired);
2626}
2627
2628VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pInfPath, IN bool bIsInfPathFile,
2629 OUT GUID *pGuid, OUT BSTR *lppszName, OUT BSTR *pErrMsg)
2630{
2631 HRESULT hrc = S_OK;
2632
2633 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2634 SP_DEVINFO_DATA DeviceInfoData;
2635 PVOID pQueueCallbackContext = NULL;
2636 DWORD ret = 0;
2637 BOOL found = FALSE;
2638 BOOL registered = FALSE;
2639 BOOL destroyList = FALSE;
2640 WCHAR pWCfgGuidString [50];
2641 WCHAR DevName[256];
2642
2643 do
2644 {
2645 GUID netGuid;
2646 SP_DRVINFO_DATA DriverInfoData;
2647 SP_DEVINSTALL_PARAMS DeviceInstallParams;
2648 TCHAR className [MAX_PATH];
2649 DWORD index = 0;
2650 PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
2651 /* for our purposes, 2k buffer is more
2652 * than enough to obtain the hardware ID
2653 * of the VBoxNetAdp driver. */
2654 DWORD detailBuf [2048];
2655
2656 HKEY hkey = NULL;
2657 DWORD cbSize;
2658 DWORD dwValueType;
2659
2660 /* initialize the structure size */
2661 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
2662 DriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
2663
2664 /* copy the net class GUID */
2665 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
2666
2667 /* create an empty device info set associated with the net class GUID */
2668 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
2669 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2670 SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
2671 GetLastError()));
2672
2673 /* get the class name from GUID */
2674 BOOL fResult = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
2675 if (!fResult)
2676 SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
2677 GetLastError()));
2678
2679 /* create a device info element and add the new device instance
2680 * key to registry */
2681 fResult = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
2682 DICD_GENERATE_ID, &DeviceInfoData);
2683 if (!fResult)
2684 SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
2685 GetLastError()));
2686
2687 /* select the newly created device info to be the currently
2688 selected member */
2689 fResult = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
2690 if (!fResult)
2691 SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
2692 GetLastError()));
2693
2694 if (pInfPath)
2695 {
2696 /* get the device install parameters and disable filecopy */
2697 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2698 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2699 &DeviceInstallParams);
2700 if (fResult)
2701 {
2702 memset(DeviceInstallParams.DriverPath, 0, sizeof(DeviceInstallParams.DriverPath));
2703 size_t pathLenght = wcslen(pInfPath) + 1/* null terminator */;
2704 if (pathLenght < sizeof(DeviceInstallParams.DriverPath)/sizeof(DeviceInstallParams.DriverPath[0]))
2705 {
2706 memcpy(DeviceInstallParams.DriverPath, pInfPath, pathLenght*sizeof(DeviceInstallParams.DriverPath[0]));
2707
2708 if (bIsInfPathFile)
2709 {
2710 DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
2711 }
2712
2713 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2714 &DeviceInstallParams);
2715 if (!fResult)
2716 {
2717 DWORD winEr = GetLastError();
2718 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2719 break;
2720 }
2721 }
2722 else
2723 {
2724 NonStandardLogFlow(("SetupDiSetDeviceInstallParams faileed: INF path is too long\n"));
2725 break;
2726 }
2727 }
2728 else
2729 {
2730 DWORD winEr = GetLastError();
2731 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2732 }
2733 }
2734
2735 /* build a list of class drivers */
2736 fResult = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
2737 SPDIT_CLASSDRIVER);
2738 if (!fResult)
2739 SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
2740 GetLastError()));
2741
2742 destroyList = TRUE;
2743
2744 /* enumerate the driver info list */
2745 while (TRUE)
2746 {
2747 BOOL ret;
2748
2749 ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
2750 SPDIT_CLASSDRIVER, index, &DriverInfoData);
2751
2752 /* if the function failed and GetLastError() returned
2753 * ERROR_NO_MORE_ITEMS, then we have reached the end of the
2754 * list. Otherwise there was something wrong with this
2755 * particular driver. */
2756 if (!ret)
2757 {
2758 if (GetLastError() == ERROR_NO_MORE_ITEMS)
2759 break;
2760 else
2761 {
2762 index++;
2763 continue;
2764 }
2765 }
2766
2767 pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
2768 pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
2769
2770 /* if we successfully find the hardware ID and it turns out to
2771 * be the one for the loopback driver, then we are done. */
2772 if (SetupDiGetDriverInfoDetail (hDeviceInfo,
2773 &DeviceInfoData,
2774 &DriverInfoData,
2775 pDriverInfoDetail,
2776 sizeof (detailBuf),
2777 NULL))
2778 {
2779 TCHAR * t;
2780
2781 /* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
2782 * whole list and see if there is a match somewhere. */
2783 t = pDriverInfoDetail->HardwareID;
2784 while (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2785 {
2786 if (!_tcsicmp(t, DRIVERHWID))
2787 break;
2788
2789 t += _tcslen(t) + 1;
2790 }
2791
2792 if (t && *t && t < (TCHAR *) &detailBuf [RT_ELEMENTS(detailBuf)])
2793 {
2794 found = TRUE;
2795 break;
2796 }
2797 }
2798
2799 index ++;
2800 }
2801
2802 if (!found)
2803 SetErrBreak(("Could not find Host Interface Networking driver! Please reinstall"));
2804
2805 /* set the loopback driver to be the currently selected */
2806 fResult = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
2807 &DriverInfoData);
2808 if (!fResult)
2809 SetErrBreak(("SetupDiSetSelectedDriver failed (0x%08X)",
2810 GetLastError()));
2811
2812 /* register the phantom device to prepare for install */
2813 fResult = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
2814 &DeviceInfoData);
2815 if (!fResult)
2816 {
2817 DWORD err = GetLastError();
2818 SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
2819 err));
2820 }
2821
2822 /* registered, but remove if errors occur in the following code */
2823 registered = TRUE;
2824
2825 /* ask the installer if we can install the device */
2826 fResult = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
2827 &DeviceInfoData);
2828 if (!fResult)
2829 {
2830 if (GetLastError() != ERROR_DI_DO_DEFAULT)
2831 SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
2832 GetLastError()));
2833 /* that's fine */
2834 }
2835
2836 /* get the device install parameters and disable filecopy */
2837 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2838 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2839 &DeviceInstallParams);
2840 if (fResult)
2841 {
2842 pQueueCallbackContext = SetupInitDefaultQueueCallback(NULL);
2843 if (pQueueCallbackContext)
2844 {
2845 DeviceInstallParams.InstallMsgHandlerContext = pQueueCallbackContext;
2846 DeviceInstallParams.InstallMsgHandler = (PSP_FILE_CALLBACK)vboxNetCfgWinPspFileCallback;
2847 fResult = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2848 &DeviceInstallParams);
2849 if (!fResult)
2850 {
2851 DWORD winEr = GetLastError();
2852 NonStandardLogFlow(("SetupDiSetDeviceInstallParams failed, winEr (%d)\n", winEr));
2853 }
2854 Assert(fResult);
2855 }
2856 else
2857 {
2858 DWORD winEr = GetLastError();
2859 NonStandardLogFlow(("SetupInitDefaultQueueCallback failed, winEr (%d)\n", winEr));
2860 }
2861 }
2862 else
2863 {
2864 DWORD winEr = GetLastError();
2865 NonStandardLogFlow(("SetupDiGetDeviceInstallParams failed, winEr (%d)\n", winEr));
2866 }
2867
2868 /* install the files first */
2869 fResult = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
2870 &DeviceInfoData);
2871 if (!fResult)
2872 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
2873 GetLastError()));
2874 /* get the device install parameters and disable filecopy */
2875 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
2876 fResult = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
2877 &DeviceInstallParams);
2878 if (fResult)
2879 {
2880 DeviceInstallParams.Flags |= DI_NOFILECOPY;
2881 fResult = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
2882 &DeviceInstallParams);
2883 if (!fResult)
2884 SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
2885 GetLastError()));
2886 }
2887
2888 /*
2889 * Register any device-specific co-installers for this device,
2890 */
2891 fResult = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
2892 hDeviceInfo,
2893 &DeviceInfoData);
2894 if (!fResult)
2895 SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
2896 GetLastError()));
2897
2898 /*
2899 * install any installer-specified interfaces.
2900 * and then do the real install
2901 */
2902 fResult = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
2903 hDeviceInfo,
2904 &DeviceInfoData);
2905 if (!fResult)
2906 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
2907 GetLastError()));
2908
2909 fResult = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
2910 hDeviceInfo,
2911 &DeviceInfoData);
2912 if (!fResult)
2913 SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
2914 GetLastError()));
2915
2916 /* Figure out NetCfgInstanceId */
2917 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
2918 &DeviceInfoData,
2919 DICS_FLAG_GLOBAL,
2920 0,
2921 DIREG_DRV,
2922 KEY_READ);
2923 if (hkey == INVALID_HANDLE_VALUE)
2924 SetErrBreak(("SetupDiOpenDevRegKey failed (0x%08X)", GetLastError()));
2925
2926 cbSize = sizeof(pWCfgGuidString);
2927 DWORD ret;
2928 ret = RegQueryValueExW (hkey, L"NetCfgInstanceId", NULL,
2929 &dwValueType, (LPBYTE) pWCfgGuidString, &cbSize);
2930
2931 RegCloseKey (hkey);
2932
2933 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2934 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
2935 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2936 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2937 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2938 NULL /*OUT PDWORD RequiredSize OPTIONAL*/))
2939 {
2940 int err = GetLastError();
2941 if (err != ERROR_INVALID_DATA)
2942 {
2943 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2944 err));
2945 }
2946
2947 if (!SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &DeviceInfoData,
2948 SPDRP_DEVICEDESC, /* IN DWORD Property,*/
2949 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
2950 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
2951 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
2952 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
2953 ))
2954 {
2955 err = GetLastError();
2956 SetErrBreak (("SetupDiGetDeviceRegistryProperty failed (0x%08X)",
2957 err));
2958 }
2959 }
2960 }
2961 while (0);
2962
2963 /*
2964 * cleanup
2965 */
2966 if (pQueueCallbackContext)
2967 SetupTermDefaultQueueCallback(pQueueCallbackContext);
2968
2969 if (hDeviceInfo != INVALID_HANDLE_VALUE)
2970 {
2971 /* an error has occurred, but the device is registered, we must remove it */
2972 if (ret != 0 && registered)
2973 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
2974
2975 found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
2976
2977 /* destroy the driver info list */
2978 if (destroyList)
2979 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
2980 SPDIT_CLASSDRIVER);
2981 /* clean up the device info set */
2982 SetupDiDestroyDeviceInfoList (hDeviceInfo);
2983 }
2984
2985 /* return the network connection GUID on success */
2986 if (SUCCEEDED(hrc))
2987 {
2988 WCHAR ConnectoinName[128];
2989 ULONG cbName = sizeof(ConnectoinName);
2990
2991 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName(DevName, ConnectoinName, &cbName);
2992 if (SUCCEEDED(hr))
2993 hr = VBoxNetCfgWinRenameConnection(pWCfgGuidString, ConnectoinName);
2994
2995 if (lppszName)
2996 {
2997 *lppszName = SysAllocString((const OLECHAR *) DevName);
2998 if (!*lppszName)
2999 {
3000 NonStandardLogFlow(("SysAllocString failed\n"));
3001 hrc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
3002 }
3003 }
3004
3005 if (pGuid)
3006 {
3007 hrc = CLSIDFromString(pWCfgGuidString, (LPCLSID)pGuid);
3008 if (FAILED(hrc))
3009 NonStandardLogFlow(("CLSIDFromString failed, hrc (0x%x)\n", hrc));
3010 }
3011
3012 INetCfg *pNetCfg = NULL;
3013 LPWSTR lpszApp = NULL;
3014 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, TRUE, L"VirtualBox Host-Only Creation",
3015 30 * 1000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec. */
3016 /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */
3017 &lpszApp);
3018 if (hr == S_OK)
3019 {
3020 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3021 &GUID_DEVCLASS_NETSERVICE,
3022 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3023 pGuid);
3024 if (SUCCEEDED(hr))
3025 {
3026 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3027 &GUID_DEVCLASS_NETTRANS,
3028 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3029 pGuid);
3030 if (SUCCEEDED(hr))
3031 hr = vboxNetCfgWinEnumNetCfgComponents(pNetCfg,
3032 &GUID_DEVCLASS_NETCLIENT,
3033 vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority,
3034 pGuid);
3035 }
3036
3037 if (SUCCEEDED(hr))
3038 {
3039 hr = pNetCfg->Apply();
3040 }
3041 else
3042 NonStandardLogFlow(("Enumeration failed, hr 0x%x\n", hr));
3043 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
3044 }
3045 else if (hr == NETCFG_E_NO_WRITE_LOCK && lpszApp)
3046 {
3047 NonStandardLogFlow(("Application %ws is holding the lock, failed\n", lpszApp));
3048 CoTaskMemFree(lpszApp);
3049 }
3050 else
3051 NonStandardLogFlow(("VBoxNetCfgWinQueryINetCfg failed, hr 0x%x\n", hr));
3052 }
3053 return hrc;
3054}
3055
3056#undef SetErrBreak
3057
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