VirtualBox

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

Last change on this file since 57639 was 57639, checked in by vboxsync, 9 years ago

Main/Network: report errors from VBoxNetCfg back to VBoxManage (#7973)

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