VirtualBox

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

Last change on this file since 36920 was 36184, checked in by vboxsync, 14 years ago

rework NetFlt/Adp

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