VirtualBox

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

Last change on this file since 79846 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: VBoxNetFltNobj.cpp 76553 2019-01-01 01:45:53Z 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-2019 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26#include "VBoxNetFltNobj.h"
27#include <iprt/win/ntddndis.h>
28#include <assert.h>
29#include <stdio.h>
30
31#include <VBoxNetFltNobjT_i.c>
32
33#include <Olectl.h>
34
35//# define VBOXNETFLTNOTIFY_DEBUG_BIND
36
37#ifdef DEBUG
38# define NonStandardAssert(a) assert(a)
39# define NonStandardAssertBreakpoint() assert(0)
40#else
41# define NonStandardAssert(a) do{}while (0)
42# define NonStandardAssertBreakpoint() do{}while (0)
43#endif
44
45VBoxNetFltNobj::VBoxNetFltNobj() :
46 mpNetCfg(NULL),
47 mpNetCfgComponent(NULL),
48 mbInstalling(FALSE)
49{
50}
51
52VBoxNetFltNobj::~VBoxNetFltNobj()
53{
54 cleanup();
55}
56
57void VBoxNetFltNobj::cleanup()
58{
59 if (mpNetCfg)
60 {
61 mpNetCfg->Release();
62 mpNetCfg = NULL;
63 }
64
65 if (mpNetCfgComponent)
66 {
67 mpNetCfgComponent->Release();
68 mpNetCfgComponent = NULL;
69 }
70}
71
72void VBoxNetFltNobj::init(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
73{
74 cleanup();
75
76 NonStandardAssert(pNetCfg);
77 NonStandardAssert(pNetCfgComponent);
78 if (pNetCfg)
79 {
80 pNetCfg->AddRef();
81 mpNetCfg = pNetCfg;
82 }
83
84 if (pNetCfgComponent)
85 {
86 pNetCfgComponent->AddRef();
87 mpNetCfgComponent = pNetCfgComponent;
88 }
89
90 mbInstalling = bInstalling;
91}
92
93/* INetCfgComponentControl methods */
94STDMETHODIMP VBoxNetFltNobj::Initialize(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
95{
96 init(pNetCfgComponent, pNetCfg, bInstalling);
97 return S_OK;
98}
99
100STDMETHODIMP VBoxNetFltNobj::ApplyRegistryChanges()
101{
102 return S_OK;
103}
104
105STDMETHODIMP VBoxNetFltNobj::ApplyPnpChanges(IN INetCfgPnpReconfigCallback *pCallback)
106{
107 RT_NOREF1(pCallback);
108 return S_OK;
109}
110
111STDMETHODIMP VBoxNetFltNobj::CancelChanges()
112{
113 return S_OK;
114}
115
116static HRESULT vboxNetFltWinQueryInstanceKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
117{
118 LPWSTR pPnpId;
119 HRESULT hr = pComponent->GetPnpDevNodeId(&pPnpId);
120 if (hr == S_OK)
121 {
122 WCHAR KeyName[MAX_PATH];
123 wcscpy(KeyName, L"SYSTEM\\CurrentControlSet\\Enum\\");
124 wcscat(KeyName,pPnpId);
125
126 LONG winEr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyName,
127 0, /*__reserved DWORD ulOptions*/
128 KEY_READ, /*__in REGSAM samDesired*/
129 phKey);
130
131 if (winEr != ERROR_SUCCESS)
132 {
133 hr = HRESULT_FROM_WIN32(winEr);
134 NonStandardAssertBreakpoint();
135 }
136
137 CoTaskMemFree(pPnpId);
138 }
139 else
140 {
141 NonStandardAssertBreakpoint();
142 }
143
144 return hr;
145}
146
147static HRESULT vboxNetFltWinQueryDriverKey(IN HKEY InstanceKey, OUT PHKEY phKey)
148{
149 DWORD Type = REG_SZ;
150 WCHAR Value[MAX_PATH];
151 DWORD cbValue = sizeof(Value);
152 HRESULT hr = S_OK;
153 LONG winEr = RegQueryValueExW(InstanceKey,
154 L"Driver", /*__in_opt LPCTSTR lpValueName*/
155 0, /*__reserved LPDWORD lpReserved*/
156 &Type, /*__out_opt LPDWORD lpType*/
157 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
158 &cbValue/*__inout_opt LPDWORD lpcbData*/
159 );
160
161 if (winEr == ERROR_SUCCESS)
162 {
163 WCHAR KeyName[MAX_PATH];
164 wcscpy(KeyName, L"SYSTEM\\CurrentControlSet\\Control\\Class\\");
165 wcscat(KeyName,Value);
166
167 winEr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyName,
168 0, /*__reserved DWORD ulOptions*/
169 KEY_READ, /*__in REGSAM samDesired*/
170 phKey);
171
172 if (winEr != ERROR_SUCCESS)
173 {
174 hr = HRESULT_FROM_WIN32(winEr);
175 NonStandardAssertBreakpoint();
176 }
177 }
178 else
179 {
180 hr = HRESULT_FROM_WIN32(winEr);
181 NonStandardAssertBreakpoint();
182 }
183
184 return hr;
185}
186
187static HRESULT vboxNetFltWinQueryDriverKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
188{
189 HKEY InstanceKey;
190 HRESULT hr = vboxNetFltWinQueryInstanceKey(pComponent, &InstanceKey);
191 if (hr == S_OK)
192 {
193 hr = vboxNetFltWinQueryDriverKey(InstanceKey, phKey);
194 if (hr != S_OK)
195 {
196 NonStandardAssertBreakpoint();
197 }
198 RegCloseKey(InstanceKey);
199 }
200 else
201 {
202 NonStandardAssertBreakpoint();
203 }
204
205 return hr;
206}
207
208static HRESULT vboxNetFltWinNotifyCheckNetAdp(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
209{
210 HRESULT hr;
211 LPWSTR pDevId;
212 hr = pComponent->GetId(&pDevId);
213 if (hr == S_OK)
214 {
215 if (!_wcsnicmp(pDevId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
216 {
217 *pbShouldBind = false;
218 }
219 else
220 {
221 hr = S_FALSE;
222 }
223 CoTaskMemFree(pDevId);
224 }
225 else
226 {
227 NonStandardAssertBreakpoint();
228 }
229
230 return hr;
231}
232
233static HRESULT vboxNetFltWinNotifyCheckMsLoop(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
234{
235 HRESULT hr;
236 LPWSTR pDevId;
237 hr = pComponent->GetId(&pDevId);
238 if (hr == S_OK)
239 {
240 if (!_wcsnicmp(pDevId, L"*msloop", sizeof(L"*msloop")/2))
241 {
242 /* we need to detect the medium the adapter is presenting
243 * to do that we could examine in the registry the *msloop params */
244 HKEY DriverKey;
245 hr = vboxNetFltWinQueryDriverKey(pComponent, &DriverKey);
246 if (hr == S_OK)
247 {
248 DWORD Type = REG_SZ;
249 WCHAR Value[64]; /* 2 should be enough actually, paranoid check for extra spaces */
250 DWORD cbValue = sizeof(Value);
251 LONG winEr = RegQueryValueExW(DriverKey,
252 L"Medium", /*__in_opt LPCTSTR lpValueName*/
253 0, /*__reserved LPDWORD lpReserved*/
254 &Type, /*__out_opt LPDWORD lpType*/
255 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
256 &cbValue/*__inout_opt LPDWORD lpcbData*/
257 );
258 if (winEr == ERROR_SUCCESS)
259 {
260 PWCHAR endPrt;
261 ULONG enmMedium = wcstoul(Value,
262 &endPrt,
263 0 /* base*/);
264
265 winEr = errno;
266 if (winEr == ERROR_SUCCESS)
267 {
268 if (enmMedium == 0) /* 0 is Ethernet */
269 {
270 *pbShouldBind = true;
271 }
272 else
273 {
274 *pbShouldBind = false;
275 }
276 }
277 else
278 {
279 NonStandardAssertBreakpoint();
280 *pbShouldBind = true;
281 }
282 }
283 else
284 {
285 /** @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 */
286 NonStandardAssertBreakpoint();
287 *pbShouldBind = true;
288 }
289
290 RegCloseKey(DriverKey);
291 }
292 else
293 {
294 NonStandardAssertBreakpoint();
295 }
296 }
297 else
298 {
299 hr = S_FALSE;
300 }
301 CoTaskMemFree(pDevId);
302 }
303 else
304 {
305 NonStandardAssertBreakpoint();
306 }
307
308 return hr;
309}
310
311static HRESULT vboxNetFltWinNotifyCheckLowerRange(IN INetCfgComponent *pComponent, OUT bool * pbShouldBind)
312{
313 HKEY DriverKey;
314 HKEY InterfacesKey;
315 HRESULT hr = vboxNetFltWinQueryDriverKey(pComponent, &DriverKey);
316 if (hr == S_OK)
317 {
318 LONG winEr = RegOpenKeyExW(DriverKey, L"Ndi\\Interfaces",
319 0, /*__reserved DWORD ulOptions*/
320 KEY_READ, /*__in REGSAM samDesired*/
321 &InterfacesKey);
322 if (winEr == ERROR_SUCCESS)
323 {
324 DWORD Type = REG_SZ;
325 WCHAR Value[MAX_PATH];
326 DWORD cbValue = sizeof(Value);
327 winEr = RegQueryValueExW(InterfacesKey,
328 L"LowerRange", /*__in_opt LPCTSTR lpValueName*/
329 0, /*__reserved LPDWORD lpReserved*/
330 &Type, /*__out_opt LPDWORD lpType*/
331 (LPBYTE)Value, /*__out_opt LPBYTE lpData*/
332 &cbValue/*__inout_opt LPDWORD lpcbData*/
333 );
334 if (winEr == ERROR_SUCCESS)
335 {
336 if (wcsstr(Value,L"ethernet") || wcsstr(Value, L"wan"))
337 {
338 *pbShouldBind = true;
339 }
340 else
341 {
342 *pbShouldBind = false;
343 }
344 }
345 else
346 {
347 /* do not set err status to it */
348 *pbShouldBind = false;
349 NonStandardAssertBreakpoint();
350 }
351
352 RegCloseKey(InterfacesKey);
353 }
354 else
355 {
356 hr = HRESULT_FROM_WIN32(winEr);
357 NonStandardAssertBreakpoint();
358 }
359
360 RegCloseKey(DriverKey);
361 }
362 else
363 {
364 NonStandardAssertBreakpoint();
365 }
366
367 return hr;
368}
369
370static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgComponent *pComponent, OUT bool *pbShouldBind)
371{
372 DWORD fCharacteristics;
373 HRESULT hr;
374
375 do
376 {
377 /* filter out only physical adapters */
378 hr = pComponent->GetCharacteristics(&fCharacteristics);
379 if (hr != S_OK)
380 {
381 NonStandardAssertBreakpoint();
382 break;
383 }
384
385
386 if (fCharacteristics & NCF_HIDDEN)
387 {
388 /* we are not binding to hidden adapters */
389 *pbShouldBind = false;
390 break;
391 }
392
393 hr = vboxNetFltWinNotifyCheckMsLoop(pComponent, pbShouldBind);
394 if (hr == S_OK)
395 {
396 /* this is a loopback adapter,
397 * the pbShouldBind already contains the result */
398 break;
399 }
400 else if (hr != S_FALSE)
401 {
402 /* error occurred */
403 break;
404 }
405
406 hr = vboxNetFltWinNotifyCheckNetAdp(pComponent, pbShouldBind);
407 if (hr == S_OK)
408 {
409 /* this is a VBoxNetAdp adapter,
410 * the pbShouldBind already contains the result */
411 break;
412 }
413 else if (hr != S_FALSE)
414 {
415 /* error occurred */
416 break;
417 }
418
419 /* hr == S_FALSE means this is not a loopback adpater, set it to S_OK */
420 hr = S_OK;
421
422// if (!(fCharacteristics & NCF_PHYSICAL))
423// {
424// /* we are binding to physical adapters only */
425// *pbShouldBind = false;
426// break;
427// }
428
429 hr = vboxNetFltWinNotifyCheckLowerRange(pComponent, pbShouldBind);
430 if (hr == S_OK)
431 {
432 /* the vboxNetFltWinNotifyCheckLowerRange ccucceeded,
433 * the pbShouldBind already contains the result */
434 break;
435 }
436 /* we are here because of the fail, nothing else to do */
437 } while (0);
438
439 return hr;
440}
441
442
443static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingInterface *pIf, OUT bool *pbShouldBind)
444{
445 INetCfgComponent * pAdapterComponent;
446 HRESULT hr = pIf->GetLowerComponent(&pAdapterComponent);
447 if (hr == S_OK)
448 {
449 hr = vboxNetFltWinNotifyShouldBind(pAdapterComponent, pbShouldBind);
450
451 pAdapterComponent->Release();
452 }
453 else
454 {
455 NonStandardAssertBreakpoint();
456 }
457
458 return hr;
459}
460
461static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath, OUT bool *pbDoBind)
462{
463 IEnumNetCfgBindingInterface *pEnumBindingIf;
464 HRESULT hr = pPath->EnumBindingInterfaces(&pEnumBindingIf);
465 if (hr == S_OK)
466 {
467 hr = pEnumBindingIf->Reset();
468 if (hr == S_OK)
469 {
470 ULONG ulCount;
471 INetCfgBindingInterface *pBindingIf;
472 do
473 {
474 hr = pEnumBindingIf->Next(1, &pBindingIf, &ulCount);
475 if (hr == S_OK)
476 {
477 hr = vboxNetFltWinNotifyShouldBind(pBindingIf, pbDoBind);
478
479 pBindingIf->Release();
480
481 if (hr == S_OK)
482 {
483 if (!(*pbDoBind))
484 {
485 break;
486 }
487 }
488 else
489 {
490 /* break on failure */
491 break;
492 }
493 }
494 else if (hr == S_FALSE)
495 {
496 /* no more elements */
497 hr = S_OK;
498 break;
499 }
500 else
501 {
502 NonStandardAssertBreakpoint();
503 /* break on falure */
504 break;
505 }
506 } while (true);
507 }
508 else
509 {
510 NonStandardAssertBreakpoint();
511 }
512
513 pEnumBindingIf->Release();
514 }
515 else
516 {
517 NonStandardAssertBreakpoint();
518 }
519
520 return hr;
521}
522
523static bool vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath)
524{
525#ifdef VBOXNETFLTNOTIFY_DEBUG_BIND
526 return VBOXNETFLTNOTIFY_DEBUG_BIND;
527#else
528 bool bShouldBind;
529 HRESULT hr = vboxNetFltWinNotifyShouldBind(pPath, &bShouldBind) ;
530 if (hr != S_OK)
531 {
532 bShouldBind = VBOXNETFLTNOTIFY_ONFAIL_BINDDEFAULT;
533 }
534
535 return bShouldBind;
536#endif
537}
538
539
540/* INetCfgComponentNotifyBinding methods */
541STDMETHODIMP VBoxNetFltNobj::NotifyBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
542{
543 if (!(dwChangeFlag & NCN_ENABLE) || (dwChangeFlag & NCN_REMOVE) || vboxNetFltWinNotifyShouldBind(pNetCfgBP))
544 return S_OK;
545 return NETCFG_S_DISABLE_QUERY;
546}
547
548STDMETHODIMP VBoxNetFltNobj::QueryBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
549{
550 RT_NOREF1(dwChangeFlag);
551 if (vboxNetFltWinNotifyShouldBind(pNetCfgBP))
552 return S_OK;
553 return NETCFG_S_DISABLE_QUERY;
554}
555
556
557static ATL::CComModule _Module;
558
559BEGIN_OBJECT_MAP(ObjectMap)
560 OBJECT_ENTRY(CLSID_VBoxNetFltNobj, VBoxNetFltNobj)
561END_OBJECT_MAP()
562
563extern "C"
564BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
565{
566 if (dwReason == DLL_PROCESS_ATTACH)
567 {
568 _Module.Init(ObjectMap, hInstance);
569 DisableThreadLibraryCalls(hInstance);
570 }
571 else if (dwReason == DLL_PROCESS_DETACH)
572 {
573 _Module.Term();
574 }
575 return TRUE;
576}
577
578STDAPI DllCanUnloadNow()
579{
580 return (_Module.GetLockCount() == 0) ? S_OK : S_FALSE;
581}
582
583STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
584{
585 return _Module.GetClassObject(rclsid, riid, ppv);
586}
587
588/*
589 * ATL::CComModule does not suport server registration/unregistration methods,
590 * so we need to do it manually. Since this is the only place we do registraton
591 * manually, we do it the quick-and-dirty way.
592 */
593
594/* Someday we may want to log errors. */
595class AdHocRegError
596{
597public:
598 AdHocRegError(LSTATUS rc) { RT_NOREF1(rc); };
599};
600
601/* A simple wrapper on Windows registry functions. */
602class AdHocRegKey
603{
604public:
605 AdHocRegKey(HKEY hKey) : m_hKey(hKey) {};
606 AdHocRegKey(LPCWSTR pcwszName, HKEY hParent = HKEY_CLASSES_ROOT);
607 ~AdHocRegKey() { RegCloseKey(m_hKey); };
608
609 AdHocRegKey *create(LPCWSTR pcwszSubkey, LPCWSTR pcwszDefaultValue = NULL);
610 void remove(LPCWSTR pcwszSubkey);
611 void setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue);
612 HKEY getKey(void) { return m_hKey; };
613private:
614 HKEY m_hKey;
615};
616
617AdHocRegKey::AdHocRegKey(LPCWSTR pcwszName, HKEY hParent)
618{
619 LSTATUS rc = RegOpenKeyExW(hParent, pcwszName, 0, KEY_ALL_ACCESS, &m_hKey);
620 if (rc != ERROR_SUCCESS)
621 throw AdHocRegError(rc);
622}
623
624void AdHocRegKey::remove(LPCWSTR pcwszSubkey)
625{
626 LSTATUS rc;
627 WCHAR wszName[256];
628 DWORD dwName;
629
630 /* Remove all subkeys of subkey first */
631 AdHocRegKey *subkey = new AdHocRegKey(pcwszSubkey, m_hKey);
632 for (;;)
633 {
634 /* Always ask for the first subkey, because we remove it before calling RegEnumKeyEx again */
635 dwName = 255;
636 rc = RegEnumKeyExW(subkey->getKey(), 0, wszName, &dwName, NULL, NULL, NULL, NULL);
637 if (rc != ERROR_SUCCESS)
638 break;
639 subkey->remove(wszName);
640 }
641 delete subkey;
642
643 /* Remove the subkey itself */
644 rc = RegDeleteKeyW(m_hKey, pcwszSubkey);
645 if (rc != ERROR_SUCCESS)
646 throw AdHocRegError(rc);
647}
648
649AdHocRegKey *AdHocRegKey::create(LPCWSTR pcwszSubkey, LPCWSTR pcwszDefaultValue)
650{
651 HKEY hSubkey;
652 LSTATUS rc = RegCreateKeyExW(m_hKey, pcwszSubkey,
653 0 /*Reserved*/, NULL /*pszClass*/, 0 /*fOptions*/,
654 KEY_ALL_ACCESS, NULL /*pSecAttr*/, &hSubkey, NULL /*pdwDisposition*/);
655 if (rc != ERROR_SUCCESS)
656 throw AdHocRegError(rc);
657 AdHocRegKey *pSubkey = new AdHocRegKey(hSubkey);
658 if (pcwszDefaultValue)
659 pSubkey->setValue(NULL, pcwszDefaultValue);
660 return pSubkey;
661}
662
663void AdHocRegKey::setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue)
664{
665 LSTATUS rc = RegSetValueExW(m_hKey, pcwszName, 0, REG_SZ, (const BYTE *)pcwszValue,
666 (DWORD)((wcslen(pcwszValue) + 1) * sizeof(WCHAR)));
667 if (rc != ERROR_SUCCESS)
668 throw AdHocRegError(rc);
669}
670
671/*
672 * Auxiliary class that facilitates automatic destruction of AdHocRegKey objects
673 * allocated in heap. No reference counting here!
674 */
675class AdHocRegKeyPtr
676{
677public:
678 AdHocRegKeyPtr(AdHocRegKey *pKey) : m_pKey(pKey) {};
679 ~AdHocRegKeyPtr() { delete m_pKey; };
680
681 AdHocRegKey *create(LPCWSTR pcwszSubkey, LPCWSTR pcwszDefaultValue = NULL)
682 { return m_pKey->create(pcwszSubkey, pcwszDefaultValue); };
683 void remove(LPCWSTR pcwszSubkey)
684 { return m_pKey->remove(pcwszSubkey); };
685 void setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue)
686 { return m_pKey->setValue(pcwszName, pcwszValue); };
687private:
688 AdHocRegKey *m_pKey;
689 /* Prevent copying, since we do not support reference counting */
690 AdHocRegKeyPtr(const AdHocRegKeyPtr&);
691 AdHocRegKeyPtr& operator=(const AdHocRegKeyPtr&);
692};
693
694
695STDAPI DllRegisterServer()
696{
697 WCHAR wszModule[MAX_PATH + 1];
698 if (GetModuleFileNameW(GetModuleHandleW(L"VBoxNetFltNobj"), wszModule, MAX_PATH) == 0)
699 return SELFREG_E_CLASS;
700
701 try {
702 AdHocRegKey keyCLSID(L"CLSID");
703 AdHocRegKeyPtr pkeyNobjClass(keyCLSID.create(L"{f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}",
704 L"VirtualBox Bridged Networking Driver Notify Object v1.1"));
705 AdHocRegKeyPtr pkeyNobjSrv(pkeyNobjClass.create(L"InProcServer32", wszModule));
706 pkeyNobjSrv.setValue(L"ThreadingModel", L"Both");
707 }
708 catch (AdHocRegError)
709 {
710 return SELFREG_E_CLASS;
711 }
712
713 try {
714 AdHocRegKey keyTypeLib(L"TypeLib");
715 AdHocRegKeyPtr pkeyNobjLib(keyTypeLib.create(L"{2A0C94D1-40E1-439C-8FE8-24107CAB0840}\\1.1",
716 L"VirtualBox Bridged Networking Driver Notify Object v1.1 Type Library"));
717 AdHocRegKeyPtr pkeyNobjLib0(pkeyNobjLib.create(L"0\\win64", wszModule));
718 AdHocRegKeyPtr pkeyNobjLibFlags(pkeyNobjLib.create(L"FLAGS", L"0"));
719 if (GetSystemDirectoryW(wszModule, MAX_PATH) == 0)
720 return SELFREG_E_TYPELIB;
721 AdHocRegKeyPtr pkeyNobjLibHelpDir(pkeyNobjLib.create(L"HELPDIR", wszModule));
722 }
723 catch (AdHocRegError)
724 {
725 return SELFREG_E_CLASS;
726 }
727
728 return S_OK;
729}
730
731STDAPI DllUnregisterServer()
732{
733 try {
734 AdHocRegKey keyTypeLib(L"TypeLib");
735 keyTypeLib.remove(L"{2A0C94D1-40E1-439C-8FE8-24107CAB0840}");
736 }
737 catch (AdHocRegError) { return SELFREG_E_TYPELIB; }
738
739 try {
740 AdHocRegKey keyCLSID(L"CLSID");
741 keyCLSID.remove(L"{f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}");
742 }
743 catch (AdHocRegError) { return SELFREG_E_CLASS; }
744
745 return S_OK;
746}
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