VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.cpp@ 62534

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

API: stop using ATL and use a vastly smaller lookalike instead, plus a lot of cleanups

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1/* $Id: VBoxNetFltNobj.cpp 60765 2016-04-29 14:26:58Z vboxsync $ */
2/** @file
3 * VBoxNetFltNobj.cpp - Notify Object for Bridged Networking Driver.
4 * Used to filter Bridged Networking Driver bindings
5 */
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#include "VBoxNetFltNobj.h"
18#include <Ntddndis.h>
19#include <assert.h>
20#include <stdio.h>
21
22#include <VBoxNetFltNobjT_i.c>
23
24//# define VBOXNETFLTNOTIFY_DEBUG_BIND
25
26#ifdef DEBUG
27# define NonStandardAssert(a) assert(a)
28# define NonStandardAssertBreakpoint() assert(0)
29#else
30# define NonStandardAssert(a) do{}while (0)
31# define NonStandardAssertBreakpoint() do{}while (0)
32#endif
33
34VBoxNetFltNobj::VBoxNetFltNobj() :
35 mpNetCfg(NULL),
36 mpNetCfgComponent(NULL),
37 mbInstalling(FALSE)
38{
39}
40
41VBoxNetFltNobj::~VBoxNetFltNobj()
42{
43 cleanup();
44}
45
46void VBoxNetFltNobj::cleanup()
47{
48 if (mpNetCfg)
49 {
50 mpNetCfg->Release();
51 mpNetCfg = NULL;
52 }
53
54 if (mpNetCfgComponent)
55 {
56 mpNetCfgComponent->Release();
57 mpNetCfgComponent = NULL;
58 }
59}
60
61void VBoxNetFltNobj::init(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
62{
63 cleanup();
64
65 NonStandardAssert(pNetCfg);
66 NonStandardAssert(pNetCfgComponent);
67 if (pNetCfg)
68 {
69 pNetCfg->AddRef();
70 mpNetCfg = pNetCfg;
71 }
72
73 if (pNetCfgComponent)
74 {
75 pNetCfgComponent->AddRef();
76 mpNetCfgComponent = pNetCfgComponent;
77 }
78
79 mbInstalling = bInstalling;
80}
81
82/* INetCfgComponentControl methods */
83STDMETHODIMP VBoxNetFltNobj::Initialize(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
84{
85 init(pNetCfgComponent, pNetCfg, bInstalling);
86 return S_OK;
87}
88
89STDMETHODIMP VBoxNetFltNobj::ApplyRegistryChanges()
90{
91 return S_OK;
92}
93
94STDMETHODIMP VBoxNetFltNobj::ApplyPnpChanges(IN INetCfgPnpReconfigCallback *pCallback)
95{
96 return S_OK;
97}
98
99STDMETHODIMP VBoxNetFltNobj::CancelChanges()
100{
101 return S_OK;
102}
103
104static HRESULT vboxNetFltWinQueryInstanceKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
105{
106 LPWSTR pPnpId;
107 HRESULT hr = pComponent->GetPnpDevNodeId(&pPnpId);
108 if (hr == S_OK)
109 {
110 WCHAR KeyName[MAX_PATH];
111 wcscpy(KeyName, L"SYSTEM\\CurrentControlSet\\Enum\\");
112 wcscat(KeyName,pPnpId);
113
114 LONG winEr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyName,
115 0, /*__reserved DWORD ulOptions*/
116 KEY_READ, /*__in REGSAM samDesired*/
117 phKey);
118
119 if (winEr != ERROR_SUCCESS)
120 {
121 hr = HRESULT_FROM_WIN32(winEr);
122 NonStandardAssertBreakpoint();
123 }
124
125 CoTaskMemFree(pPnpId);
126 }
127 else
128 {
129 NonStandardAssertBreakpoint();
130 }
131
132 return hr;
133}
134
135static HRESULT vboxNetFltWinQueryDriverKey(IN HKEY InstanceKey, OUT PHKEY phKey)
136{
137 DWORD Type = REG_SZ;
138 WCHAR Value[MAX_PATH];
139 DWORD cbValue = sizeof(Value);
140 HRESULT hr = S_OK;
141 LONG winEr = RegQueryValueExW(InstanceKey,
142 L"Driver", /*__in_opt LPCTSTR lpValueName*/
143 0, /*__reserved LPDWORD lpReserved*/
144 &Type, /*__out_opt LPDWORD lpType*/
145 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
146 &cbValue/*__inout_opt LPDWORD lpcbData*/
147 );
148
149 if (winEr == ERROR_SUCCESS)
150 {
151 WCHAR KeyName[MAX_PATH];
152 wcscpy(KeyName, L"SYSTEM\\CurrentControlSet\\Control\\Class\\");
153 wcscat(KeyName,Value);
154
155 winEr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyName,
156 0, /*__reserved DWORD ulOptions*/
157 KEY_READ, /*__in REGSAM samDesired*/
158 phKey);
159
160 if (winEr != ERROR_SUCCESS)
161 {
162 hr = HRESULT_FROM_WIN32(winEr);
163 NonStandardAssertBreakpoint();
164 }
165 }
166 else
167 {
168 hr = HRESULT_FROM_WIN32(winEr);
169 NonStandardAssertBreakpoint();
170 }
171
172 return hr;
173}
174
175static HRESULT vboxNetFltWinQueryDriverKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
176{
177 HKEY InstanceKey;
178 HRESULT hr = vboxNetFltWinQueryInstanceKey(pComponent, &InstanceKey);
179 if (hr == S_OK)
180 {
181 hr = vboxNetFltWinQueryDriverKey(InstanceKey, phKey);
182 if (hr != S_OK)
183 {
184 NonStandardAssertBreakpoint();
185 }
186 RegCloseKey(InstanceKey);
187 }
188 else
189 {
190 NonStandardAssertBreakpoint();
191 }
192
193 return hr;
194}
195
196static HRESULT vboxNetFltWinNotifyCheckNetAdp(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
197{
198 HRESULT hr;
199 LPWSTR pDevId;
200 hr = pComponent->GetId(&pDevId);
201 if (hr == S_OK)
202 {
203 if (!_wcsnicmp(pDevId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
204 {
205 *pbShouldBind = false;
206 }
207 else
208 {
209 hr = S_FALSE;
210 }
211 CoTaskMemFree(pDevId);
212 }
213 else
214 {
215 NonStandardAssertBreakpoint();
216 }
217
218 return hr;
219}
220
221static HRESULT vboxNetFltWinNotifyCheckMsLoop(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
222{
223 HRESULT hr;
224 LPWSTR pDevId;
225 hr = pComponent->GetId(&pDevId);
226 if (hr == S_OK)
227 {
228 if (!_wcsnicmp(pDevId, L"*msloop", sizeof(L"*msloop")/2))
229 {
230 /* we need to detect the medium the adapter is presenting
231 * to do that we could examine in the registry the *msloop params */
232 HKEY DriverKey;
233 hr = vboxNetFltWinQueryDriverKey(pComponent, &DriverKey);
234 if (hr == S_OK)
235 {
236 DWORD Type = REG_SZ;
237 WCHAR Value[64]; /* 2 should be enough actually, paranoid check for extra spaces */
238 DWORD cbValue = sizeof(Value);
239 LONG winEr = RegQueryValueExW(DriverKey,
240 L"Medium", /*__in_opt LPCTSTR lpValueName*/
241 0, /*__reserved LPDWORD lpReserved*/
242 &Type, /*__out_opt LPDWORD lpType*/
243 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
244 &cbValue/*__inout_opt LPDWORD lpcbData*/
245 );
246 if (winEr == ERROR_SUCCESS)
247 {
248 PWCHAR endPrt;
249 ULONG enmMedium = wcstoul(Value,
250 &endPrt,
251 0 /* base*/);
252
253 winEr = errno;
254 if (winEr == ERROR_SUCCESS)
255 {
256 if (enmMedium == 0) /* 0 is Ethernet */
257 {
258 *pbShouldBind = true;
259 }
260 else
261 {
262 *pbShouldBind = false;
263 }
264 }
265 else
266 {
267 NonStandardAssertBreakpoint();
268 *pbShouldBind = true;
269 }
270 }
271 else
272 {
273 /* TODO: we should check the default medium in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\<driver_id>\Ndi\Params\Medium, REG_SZ "Default" value */
274 NonStandardAssertBreakpoint();
275 *pbShouldBind = true;
276 }
277
278 RegCloseKey(DriverKey);
279 }
280 else
281 {
282 NonStandardAssertBreakpoint();
283 }
284 }
285 else
286 {
287 hr = S_FALSE;
288 }
289 CoTaskMemFree(pDevId);
290 }
291 else
292 {
293 NonStandardAssertBreakpoint();
294 }
295
296 return hr;
297}
298
299static HRESULT vboxNetFltWinNotifyCheckLowerRange(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
300{
301 HKEY DriverKey;
302 HKEY InterfacesKey;
303 HRESULT hr = vboxNetFltWinQueryDriverKey(pComponent, &DriverKey);
304 if (hr == S_OK)
305 {
306 LONG winEr = RegOpenKeyExW(DriverKey, L"Ndi\\Interfaces",
307 0, /*__reserved DWORD ulOptions*/
308 KEY_READ, /*__in REGSAM samDesired*/
309 &InterfacesKey);
310 if (winEr == ERROR_SUCCESS)
311 {
312 DWORD Type = REG_SZ;
313 WCHAR Value[MAX_PATH];
314 DWORD cbValue = sizeof(Value);
315 winEr = RegQueryValueExW(InterfacesKey,
316 L"LowerRange", /*__in_opt LPCTSTR lpValueName*/
317 0, /*__reserved LPDWORD lpReserved*/
318 &Type, /*__out_opt LPDWORD lpType*/
319 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
320 &cbValue/*__inout_opt LPDWORD lpcbData*/
321 );
322 if (winEr == ERROR_SUCCESS)
323 {
324 if (wcsstr(Value,L"ethernet") || wcsstr(Value, L"wan"))
325 {
326 *pbShouldBind = true;
327 }
328 else
329 {
330 *pbShouldBind = false;
331 }
332 }
333 else
334 {
335 /* do not set err status to it */
336 *pbShouldBind = false;
337 NonStandardAssertBreakpoint();
338 }
339
340 RegCloseKey(InterfacesKey);
341 }
342 else
343 {
344 hr = HRESULT_FROM_WIN32(winEr);
345 NonStandardAssertBreakpoint();
346 }
347
348 RegCloseKey(DriverKey);
349 }
350 else
351 {
352 NonStandardAssertBreakpoint();
353 }
354
355 return hr;
356}
357
358static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgComponent *pComponent, OUT bool *pbShouldBind)
359{
360 DWORD fCharacteristics;
361 HRESULT hr;
362
363 do
364 {
365 /* filter out only physical adapters */
366 hr = pComponent->GetCharacteristics(&fCharacteristics);
367 if (hr != S_OK)
368 {
369 NonStandardAssertBreakpoint();
370 break;
371 }
372
373
374 if (fCharacteristics & NCF_HIDDEN)
375 {
376 /* we are not binding to hidden adapters */
377 *pbShouldBind = false;
378 break;
379 }
380
381 hr = vboxNetFltWinNotifyCheckMsLoop(pComponent, pbShouldBind);
382 if (hr == S_OK)
383 {
384 /* this is a loopback adapter,
385 * the pbShouldBind already contains the result */
386 break;
387 }
388 else if (hr != S_FALSE)
389 {
390 /* error occurred */
391 break;
392 }
393
394 hr = vboxNetFltWinNotifyCheckNetAdp(pComponent, pbShouldBind);
395 if (hr == S_OK)
396 {
397 /* this is a VBoxNetAdp adapter,
398 * the pbShouldBind already contains the result */
399 break;
400 }
401 else if (hr != S_FALSE)
402 {
403 /* error occurred */
404 break;
405 }
406
407 /* hr == S_FALSE means this is not a loopback adpater, set it to S_OK */
408 hr = S_OK;
409
410// if (!(fCharacteristics & NCF_PHYSICAL))
411// {
412// /* we are binding to physical adapters only */
413// *pbShouldBind = false;
414// break;
415// }
416
417 hr = vboxNetFltWinNotifyCheckLowerRange(pComponent, pbShouldBind);
418 if (hr == S_OK)
419 {
420 /* the vboxNetFltWinNotifyCheckLowerRange ccucceeded,
421 * the pbShouldBind already contains the result */
422 break;
423 }
424 /* we are here because of the fail, nothing else to do */
425 } while (0);
426
427 return hr;
428}
429
430
431static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingInterface *pIf, OUT bool *pbShouldBind)
432{
433 INetCfgComponent * pAdapterComponent;
434 HRESULT hr = pIf->GetLowerComponent(&pAdapterComponent);
435 if (hr == S_OK)
436 {
437 hr = vboxNetFltWinNotifyShouldBind(pAdapterComponent, pbShouldBind);
438
439 pAdapterComponent->Release();
440 }
441 else
442 {
443 NonStandardAssertBreakpoint();
444 }
445
446 return hr;
447}
448
449static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath, OUT bool *pbDoBind)
450{
451 IEnumNetCfgBindingInterface *pEnumBindingIf;
452 HRESULT hr = pPath->EnumBindingInterfaces(&pEnumBindingIf);
453 if (hr == S_OK)
454 {
455 hr = pEnumBindingIf->Reset();
456 if (hr == S_OK)
457 {
458 ULONG ulCount;
459 INetCfgBindingInterface *pBindingIf;
460 do
461 {
462 hr = pEnumBindingIf->Next(1, &pBindingIf, &ulCount);
463 if (hr == S_OK)
464 {
465 hr = vboxNetFltWinNotifyShouldBind(pBindingIf, pbDoBind);
466
467 pBindingIf->Release();
468
469 if (hr == S_OK)
470 {
471 if (!(*pbDoBind))
472 {
473 break;
474 }
475 }
476 else
477 {
478 /* break on failure */
479 break;
480 }
481 }
482 else if (hr == S_FALSE)
483 {
484 /* no more elements */
485 hr = S_OK;
486 break;
487 }
488 else
489 {
490 NonStandardAssertBreakpoint();
491 /* break on falure */
492 break;
493 }
494 } while (true);
495 }
496 else
497 {
498 NonStandardAssertBreakpoint();
499 }
500
501 pEnumBindingIf->Release();
502 }
503 else
504 {
505 NonStandardAssertBreakpoint();
506 }
507
508 return hr;
509}
510
511static bool vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath)
512{
513#ifdef VBOXNETFLTNOTIFY_DEBUG_BIND
514 return VBOXNETFLTNOTIFY_DEBUG_BIND;
515#else
516 bool bShouldBind;
517 HRESULT hr = vboxNetFltWinNotifyShouldBind(pPath, &bShouldBind) ;
518 if (hr != S_OK)
519 {
520 bShouldBind = VBOXNETFLTNOTIFY_ONFAIL_BINDDEFAULT;
521 }
522
523 return bShouldBind;
524#endif
525}
526
527
528/* INetCfgComponentNotifyBinding methods */
529STDMETHODIMP VBoxNetFltNobj::NotifyBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
530{
531 if (!(dwChangeFlag & NCN_ENABLE) || (dwChangeFlag & NCN_REMOVE) || vboxNetFltWinNotifyShouldBind(pNetCfgBP))
532 return S_OK;
533 return NETCFG_S_DISABLE_QUERY;
534}
535
536STDMETHODIMP VBoxNetFltNobj::QueryBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
537{
538 if (vboxNetFltWinNotifyShouldBind(pNetCfgBP))
539 return S_OK;
540 return NETCFG_S_DISABLE_QUERY;
541}
542
543
544static ATL::CComModule _Module;
545
546BEGIN_OBJECT_MAP(ObjectMap)
547 OBJECT_ENTRY(CLSID_VBoxNetFltNobj, VBoxNetFltNobj)
548END_OBJECT_MAP()
549
550extern "C"
551BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
552{
553 if (dwReason == DLL_PROCESS_ATTACH)
554 {
555 _Module.Init(ObjectMap, hInstance);
556 DisableThreadLibraryCalls(hInstance);
557 }
558 else if (dwReason == DLL_PROCESS_DETACH)
559 {
560 _Module.Term();
561 }
562 return TRUE;
563}
564
565STDAPI DllCanUnloadNow()
566{
567 return (_Module.GetLockCount() == 0) ? S_OK : S_FALSE;
568}
569
570STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
571{
572 return _Module.GetClassObject(rclsid, riid, ppv);
573}
574
575STDAPI DllRegisterServer()
576{
577// this is a "just in case" conditional, which is not defined
578#ifdef VBOX_FORCE_REGISTER_SERVER
579 return _Module.RegisterServer(TRUE);
580#else
581 return S_OK;
582#endif
583}
584
585STDAPI DllUnregisterServer()
586{
587// this is a "just in case" conditional, which is not defined
588#ifdef VBOX_FORCE_REGISTER_SERVER
589 return _Module.UnregisterServer(TRUE);
590#else
591 return S_OK;
592#endif
593}
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