VirtualBox

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

Last change on this file since 106061 was 106061, checked in by vboxsync, 5 months ago

Copyright year updates by scm.

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