summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostDrivers/VBoxNetFlt/win/nobj
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostDrivers/VBoxNetFlt/win/nobj')
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/Makefile.kup0
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.cpp747
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.def42
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h96
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rc78
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rgs13
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h46
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjT.idl55
8 files changed, 1077 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/Makefile.kup b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/Makefile.kup
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.cpp
new file mode 100644
index 00000000..a5cf004c
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.cpp
@@ -0,0 +1,747 @@
+/* $Id: VBoxNetFltNobj.cpp $ */
+/** @file
+ * VBoxNetFltNobj.cpp - Notify Object for Bridged Networking Driver.
+ *
+ * Used to filter Bridged Networking Driver bindings
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "VBoxNetFltNobj.h"
+#include <iprt/win/ntddndis.h>
+#include <iprt/win/windows.h>
+#include <winreg.h>
+#include <Olectl.h>
+
+#include <VBoxNetFltNobjT_i.c>
+
+#include <iprt/assert.h>
+#include <iprt/utf16.h>
+#include <iprt/string.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+//# define VBOXNETFLTNOTIFY_DEBUG_BIND
+
+#ifdef DEBUG
+# define NonStandardAssert(a) Assert(a)
+# define NonStandardAssertBreakpoint() AssertFailed()
+#else
+# define NonStandardAssert(a) do{}while (0)
+# define NonStandardAssertBreakpoint() do{}while (0)
+#endif
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+static HMODULE g_hModSelf = (HMODULE)~(uintptr_t)0;
+
+
+VBoxNetFltNobj::VBoxNetFltNobj()
+ : mpNetCfg(NULL)
+ , mpNetCfgComponent(NULL)
+ , mbInstalling(FALSE)
+{
+}
+
+VBoxNetFltNobj::~VBoxNetFltNobj()
+{
+ cleanup();
+}
+
+void VBoxNetFltNobj::cleanup()
+{
+ if (mpNetCfg)
+ {
+ mpNetCfg->Release();
+ mpNetCfg = NULL;
+ }
+
+ if (mpNetCfgComponent)
+ {
+ mpNetCfgComponent->Release();
+ mpNetCfgComponent = NULL;
+ }
+}
+
+void VBoxNetFltNobj::init(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
+{
+ cleanup();
+
+ NonStandardAssert(pNetCfg);
+ NonStandardAssert(pNetCfgComponent);
+ if (pNetCfg)
+ {
+ pNetCfg->AddRef();
+ mpNetCfg = pNetCfg;
+ }
+
+ if (pNetCfgComponent)
+ {
+ pNetCfgComponent->AddRef();
+ mpNetCfgComponent = pNetCfgComponent;
+ }
+
+ mbInstalling = bInstalling;
+}
+
+/* INetCfgComponentControl methods */
+STDMETHODIMP VBoxNetFltNobj::Initialize(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling)
+{
+ init(pNetCfgComponent, pNetCfg, bInstalling);
+ return S_OK;
+}
+
+STDMETHODIMP VBoxNetFltNobj::ApplyRegistryChanges()
+{
+ return S_OK;
+}
+
+STDMETHODIMP VBoxNetFltNobj::ApplyPnpChanges(IN INetCfgPnpReconfigCallback *pCallback)
+{
+ RT_NOREF1(pCallback);
+ return S_OK;
+}
+
+STDMETHODIMP VBoxNetFltNobj::CancelChanges()
+{
+ return S_OK;
+}
+
+static HRESULT vboxNetFltWinQueryInstanceKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
+{
+ LPWSTR pwszPnpId;
+ HRESULT hrc = pComponent->GetPnpDevNodeId(&pwszPnpId);
+ if (hrc == S_OK)
+ {
+ WCHAR wszKeyName[MAX_PATH];
+ RTUtf16Copy(wszKeyName, MAX_PATH, L"SYSTEM\\CurrentControlSet\\Enum\\");
+ int rc = RTUtf16Cat(wszKeyName, MAX_PATH, pwszPnpId);
+ if (RT_SUCCESS(rc))
+ {
+ LSTATUS lrc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszKeyName, 0 /*ulOptions*/, KEY_READ, phKey);
+ if (lrc != ERROR_SUCCESS)
+ {
+ hrc = HRESULT_FROM_WIN32(lrc);
+ NonStandardAssertBreakpoint();
+ }
+ }
+ else
+ AssertRCStmt(rc, hrc = ERROR_BUFFER_OVERFLOW);
+
+ CoTaskMemFree(pwszPnpId);
+ }
+ else
+ NonStandardAssertBreakpoint();
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinQueryDriverKey(IN HKEY InstanceKey, OUT PHKEY phKey)
+{
+ HRESULT hrc = S_OK;
+
+ WCHAR wszValue[MAX_PATH];
+ DWORD cbValue = sizeof(wszValue) - sizeof(WCHAR);
+ DWORD dwType = REG_SZ;
+ LSTATUS lrc = RegQueryValueExW(InstanceKey, L"Driver", NULL /*lpReserved*/, &dwType, (LPBYTE)wszValue, &cbValue);
+ if (lrc == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ)
+ {
+ wszValue[RT_ELEMENTS(wszValue) - 1] = '\0'; /* registry strings does not need to be zero terminated. */
+
+ WCHAR wszKeyName[MAX_PATH];
+ RTUtf16Copy(wszKeyName, MAX_PATH, L"SYSTEM\\CurrentControlSet\\Control\\Class\\");
+ int rc = RTUtf16Cat(wszKeyName, MAX_PATH, wszValue);
+ if (RT_SUCCESS(rc))
+ {
+ lrc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszKeyName, 0 /*ulOptions*/, KEY_READ, phKey);
+ if (lrc != ERROR_SUCCESS)
+ {
+ hrc = HRESULT_FROM_WIN32(lrc);
+ NonStandardAssertBreakpoint();
+ }
+ }
+ else
+ AssertRCStmt(rc, hrc = ERROR_BUFFER_OVERFLOW);
+ }
+ else
+ {
+ hrc = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
+ NonStandardAssertBreakpoint();
+ }
+ }
+ else
+ {
+ hrc = HRESULT_FROM_WIN32(lrc);
+ NonStandardAssertBreakpoint();
+ }
+
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinQueryDriverKey(IN INetCfgComponent *pComponent, OUT PHKEY phKey)
+{
+ HKEY hKeyInstance = NULL;
+ HRESULT hrc = vboxNetFltWinQueryInstanceKey(pComponent, &hKeyInstance);
+ if (hrc == S_OK)
+ {
+ hrc = vboxNetFltWinQueryDriverKey(hKeyInstance, phKey);
+ if (hrc != S_OK)
+ NonStandardAssertBreakpoint();
+ RegCloseKey(hKeyInstance);
+ }
+ else
+ NonStandardAssertBreakpoint();
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinNotifyCheckNetAdp(IN INetCfgComponent *pComponent, OUT bool *pfShouldBind)
+{
+ *pfShouldBind = false;
+
+ LPWSTR pwszDevId = NULL;
+ HRESULT hrc = pComponent->GetId(&pwszDevId);
+ if (hrc == S_OK)
+ {
+ /** @todo r=bird: This was _wcsnicmp(pwszDevId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
+ * which includes the terminator, so it translates to a full compare. Goes way back. */
+ if (RTUtf16ICmpAscii(pwszDevId, "sun_VBoxNetAdp") == 0)
+ *pfShouldBind = false;
+ else
+ hrc = S_FALSE;
+ CoTaskMemFree(pwszDevId);
+ }
+ else
+ NonStandardAssertBreakpoint();
+
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinNotifyCheckMsLoop(IN INetCfgComponent *pComponent, OUT bool *pfShouldBind)
+{
+ *pfShouldBind = false;
+
+ LPWSTR pwszDevId = NULL;
+ HRESULT hrc = pComponent->GetId(&pwszDevId);
+ if (hrc == S_OK)
+ {
+ /** @todo r=bird: This was _wcsnicmp(pwszDevId, L"*msloop", sizeof(L"*msloop")/2)
+ * which includes the terminator, making it a full compare. Goes way back. */
+ if (RTUtf16ICmpAscii(pwszDevId, "*msloop") == 0)
+ {
+ /* we need to detect the medium the adapter is presenting
+ * to do that we could examine in the registry the *msloop params */
+ HKEY hKeyDriver;
+ hrc = vboxNetFltWinQueryDriverKey(pComponent, &hKeyDriver);
+ if (hrc == S_OK)
+ {
+ WCHAR wszValue[64]; /* 2 should be enough actually, paranoid check for extra spaces */
+ DWORD cbValue = sizeof(wszValue) - sizeof(WCHAR);
+ DWORD dwType = REG_SZ;
+ LSTATUS lrc = RegQueryValueExW(hKeyDriver, L"Medium", NULL /*lpReserved*/, &dwType, (LPBYTE)wszValue, &cbValue);
+ if (lrc == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ)
+ {
+ wszValue[RT_ELEMENTS(wszValue) - 1] = '\0';
+
+ char szUtf8[256];
+ char *pszUtf8 = szUtf8;
+ RTUtf16ToUtf8Ex(wszValue, RTSTR_MAX, &pszUtf8, sizeof(szUtf8), NULL);
+ pszUtf8 = RTStrStrip(pszUtf8);
+
+ uint64_t uValue = 0;
+ int rc = RTStrToUInt64Ex(pszUtf8, NULL, 0, &uValue);
+ if (RT_SUCCESS(rc))
+ {
+ if (uValue == 0) /* 0 is Ethernet */
+ *pfShouldBind = true;
+ else
+ *pfShouldBind = false;
+ }
+ else
+ {
+ NonStandardAssertBreakpoint();
+ *pfShouldBind = true;
+ }
+ }
+ else
+ NonStandardAssertBreakpoint();
+ }
+ else
+ {
+ /** @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 */
+ NonStandardAssertBreakpoint();
+ *pfShouldBind = true;
+ }
+
+ RegCloseKey(hKeyDriver);
+ }
+ else
+ NonStandardAssertBreakpoint();
+ }
+ else
+ hrc = S_FALSE;
+ CoTaskMemFree(pwszDevId);
+ }
+ else
+ NonStandardAssertBreakpoint();
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinNotifyCheckLowerRange(IN INetCfgComponent *pComponent, OUT bool *pfShouldBind)
+{
+ *pfShouldBind = false;
+
+ HKEY hKeyDriver = NULL;
+ HRESULT hrc = vboxNetFltWinQueryDriverKey(pComponent, &hKeyDriver);
+ if (hrc == S_OK)
+ {
+ HKEY hKeyInterfaces = NULL;
+ LSTATUS lrc = RegOpenKeyExW(hKeyDriver, L"Ndi\\Interfaces", 0 /*ulOptions*/, KEY_READ, &hKeyInterfaces);
+ if (lrc == ERROR_SUCCESS)
+ {
+ WCHAR wszValue[MAX_PATH];
+ DWORD cbValue = sizeof(wszValue) - sizeof(WCHAR);
+ DWORD dwType = REG_SZ;
+ lrc = RegQueryValueExW(hKeyInterfaces, L"LowerRange", NULL /*lpReserved*/, &dwType, (LPBYTE)wszValue, &cbValue);
+ if (lrc == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ)
+ {
+ if (RTUtf16FindAscii(wszValue, "ethernet") >= 0 || RTUtf16FindAscii(wszValue, "wan") >= 0)
+ *pfShouldBind = true;
+ else
+ *pfShouldBind = false;
+ }
+ }
+ else
+ {
+ /* do not set err status to it */
+ *pfShouldBind = false;
+ NonStandardAssertBreakpoint();
+ }
+
+ RegCloseKey(hKeyInterfaces);
+ }
+ else
+ {
+ hrc = HRESULT_FROM_WIN32(lrc);
+ NonStandardAssertBreakpoint();
+ }
+
+ RegCloseKey(hKeyDriver);
+ }
+ else
+ NonStandardAssertBreakpoint();
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgComponent *pComponent, OUT bool *pfShouldBind)
+{
+ *pfShouldBind = false;
+
+ /* filter out only physical adapters */
+ DWORD fCharacteristics = 0;
+ HRESULT hrc = pComponent->GetCharacteristics(&fCharacteristics);
+ if (hrc != S_OK)
+ {
+ NonStandardAssertBreakpoint();
+ return hrc;
+ }
+
+ /* we are not binding to hidden adapters */
+ if (fCharacteristics & NCF_HIDDEN)
+ return S_OK;
+
+ hrc = vboxNetFltWinNotifyCheckMsLoop(pComponent, pfShouldBind);
+ if ( hrc == S_OK /* this is a loopback adapter, the pfShouldBind already contains the result */
+ || hrc != S_FALSE /* error occurred */)
+ return hrc;
+
+ hrc = vboxNetFltWinNotifyCheckNetAdp(pComponent, pfShouldBind);
+ if ( hrc == S_OK /* this is a VBoxNetAdp adapter, the pfShouldBind already contains the result */
+ || hrc != S_FALSE /* error occurred */)
+ return hrc;
+
+ //if (!(fCharacteristics & NCF_PHYSICAL))
+ //{
+ // *pfShouldBind = false; /* we are binding to physical adapters only */
+ // return S_OK;
+ //}
+
+ return vboxNetFltWinNotifyCheckLowerRange(pComponent, pfShouldBind);
+}
+
+
+static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingInterface *pIf, OUT bool *pfShouldBind)
+{
+ INetCfgComponent *pAdapterComponent = NULL;
+ HRESULT hrc = pIf->GetLowerComponent(&pAdapterComponent);
+ if (hrc == S_OK)
+ {
+ hrc = vboxNetFltWinNotifyShouldBind(pAdapterComponent, pfShouldBind);
+
+ pAdapterComponent->Release();
+ }
+ else
+ {
+ NonStandardAssertBreakpoint();
+ *pfShouldBind = false;
+ }
+ return hrc;
+}
+
+static HRESULT vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath, OUT bool *pfShouldBind)
+{
+ *pfShouldBind = false;
+
+ IEnumNetCfgBindingInterface *pIEnumBinding = NULL;
+ HRESULT hrc = pPath->EnumBindingInterfaces(&pIEnumBinding);
+ if (hrc == S_OK)
+ {
+ hrc = pIEnumBinding->Reset();
+ if (hrc == S_OK)
+ {
+ for (;;)
+ {
+ ULONG uCount = 0;
+ INetCfgBindingInterface *pIBinding = NULL;
+ hrc = pIEnumBinding->Next(1, &pIBinding, &uCount);
+ if (hrc == S_OK)
+ {
+ hrc = vboxNetFltWinNotifyShouldBind(pIBinding, pfShouldBind);
+ pIBinding->Release();
+
+ if (hrc != S_OK)
+ break; /* break on failure. */
+ if (!*pfShouldBind)
+ break;
+ }
+ else if (hrc == S_FALSE)
+ {
+ /* no more elements */
+ hrc = S_OK;
+ break;
+ }
+ else
+ {
+ NonStandardAssertBreakpoint();
+ /* break on falure */
+ break;
+ }
+ }
+ }
+ else
+ NonStandardAssertBreakpoint();
+
+ pIEnumBinding->Release();
+ }
+ else
+ NonStandardAssertBreakpoint();
+ return hrc;
+}
+
+static bool vboxNetFltWinNotifyShouldBind(IN INetCfgBindingPath *pPath)
+{
+#ifdef VBOXNETFLTNOTIFY_DEBUG_BIND
+ return VBOXNETFLTNOTIFY_DEBUG_BIND;
+#else
+ bool fShouldBind;
+ HRESULT hrc = vboxNetFltWinNotifyShouldBind(pPath, &fShouldBind);
+ if (hrc != S_OK)
+ fShouldBind = VBOXNETFLTNOTIFY_ONFAIL_BINDDEFAULT;
+
+ return fShouldBind;
+#endif
+}
+
+
+/* INetCfgComponentNotifyBinding methods */
+STDMETHODIMP VBoxNetFltNobj::NotifyBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
+{
+ if (!(dwChangeFlag & NCN_ENABLE) || (dwChangeFlag & NCN_REMOVE) || vboxNetFltWinNotifyShouldBind(pNetCfgBP))
+ return S_OK;
+ return NETCFG_S_DISABLE_QUERY;
+}
+
+STDMETHODIMP VBoxNetFltNobj::QueryBindingPath(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP)
+{
+ RT_NOREF1(dwChangeFlag);
+ if (vboxNetFltWinNotifyShouldBind(pNetCfgBP))
+ return S_OK;
+ return NETCFG_S_DISABLE_QUERY;
+}
+
+
+static ATL::CComModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+ OBJECT_ENTRY(CLSID_VBoxNetFltNobj, VBoxNetFltNobj)
+END_OBJECT_MAP()
+
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hModSelf = (HMODULE)hInstance;
+
+ _Module.Init(ObjectMap, hInstance);
+ DisableThreadLibraryCalls(hInstance);
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ {
+ _Module.Term();
+ }
+ return TRUE;
+}
+
+STDAPI DllCanUnloadNow(void)
+{
+ return _Module.GetLockCount() == 0 ? S_OK : S_FALSE;
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+ return _Module.GetClassObject(rclsid, riid, ppv);
+}
+
+
+/*
+ * ATL::CComModule does not suport server registration/unregistration methods,
+ * so we need to do it manually. Since this is the only place we do registraton
+ * manually, we do it the quick-and-dirty way.
+ */
+
+#ifdef RT_EXCEPTIONS_ENABLED
+/* Someday we may want to log errors. */
+class AdHocRegError
+{
+public:
+ AdHocRegError(LSTATUS rc) { RT_NOREF1(rc); };
+};
+#endif
+
+/**
+ * A simple wrapper on Windows registry functions.
+ */
+class AdHocRegKey
+{
+public:
+ AdHocRegKey(HKEY hKey) : m_hKey(hKey) {};
+ AdHocRegKey(LPCWSTR pcwszName, HKEY hParent = HKEY_CLASSES_ROOT);
+ ~AdHocRegKey() { RegCloseKey(m_hKey); };
+
+ AdHocRegKey *create(LPCWSTR pcwszSubkey);
+ LSTATUS setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue);
+ HKEY getKey(void) { return m_hKey; };
+private:
+ HKEY m_hKey;
+};
+
+AdHocRegKey::AdHocRegKey(LPCWSTR pcwszName, HKEY hParent) : m_hKey(NULL)
+{
+ LSTATUS rc = RegOpenKeyExW(hParent, pcwszName, 0, KEY_ALL_ACCESS, &m_hKey);
+ if (rc != ERROR_SUCCESS)
+#ifdef RT_EXCEPTIONS_ENABLED
+ throw AdHocRegError(rc);
+#else
+ m_hKey = NULL;
+#endif
+}
+
+AdHocRegKey *AdHocRegKey::create(LPCWSTR pcwszSubkey)
+{
+ HKEY hSubkey;
+ LSTATUS rc = RegCreateKeyExW(m_hKey, pcwszSubkey,
+ 0 /*Reserved*/, NULL /*pszClass*/, 0 /*fOptions*/,
+ KEY_ALL_ACCESS, NULL /*pSecAttr*/, &hSubkey, NULL /*pdwDisposition*/);
+ if (rc != ERROR_SUCCESS)
+#ifdef RT_EXCEPTIONS_ENABLED
+ throw AdHocRegError(rc);
+#else
+ return NULL;
+#endif
+ AdHocRegKey *pSubkey = new AdHocRegKey(hSubkey);
+ if (!pSubkey)
+ RegCloseKey(hSubkey);
+ return pSubkey;
+}
+
+LSTATUS AdHocRegKey::setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue)
+{
+ LSTATUS rc = RegSetValueExW(m_hKey, pcwszName, 0, REG_SZ, (const BYTE *)pcwszValue,
+ (DWORD)((RTUtf16Len(pcwszValue) + 1) * sizeof(WCHAR)));
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (rc != ERROR_SUCCESS)
+ throw AdHocRegError(rc);
+#endif
+ return rc;
+}
+
+/**
+ * Auxiliary class that facilitates automatic destruction of AdHocRegKey objects
+ * allocated in heap. No reference counting here!
+ */
+class AdHocRegKeyPtr
+{
+public:
+ AdHocRegKeyPtr(AdHocRegKey *pKey) : m_pKey(pKey) {};
+ ~AdHocRegKeyPtr()
+ {
+ if (m_pKey)
+ {
+ delete m_pKey;
+ m_pKey = NULL;
+ }
+ }
+
+ AdHocRegKey *create(LPCWSTR pcwszSubkey)
+ { return m_pKey ? m_pKey->create(pcwszSubkey) : NULL; };
+
+ LSTATUS setValue(LPCWSTR pcwszName, LPCWSTR pcwszValue)
+ { return m_pKey ? m_pKey->setValue(pcwszName, pcwszValue) : ERROR_INVALID_STATE; };
+
+private:
+ AdHocRegKey *m_pKey;
+ /* Prevent copying, since we do not support reference counting */
+ AdHocRegKeyPtr(const AdHocRegKeyPtr&);
+ AdHocRegKeyPtr& operator=(const AdHocRegKeyPtr&);
+};
+
+
+STDAPI DllRegisterServer(void)
+{
+ /* Get the path to the DLL we're running inside. */
+ WCHAR wszModule[MAX_PATH + 1];
+ UINT cwcModule = GetModuleFileNameW(g_hModSelf, wszModule, MAX_PATH);
+ if (cwcModule == 0 || cwcModule > MAX_PATH)
+ return SELFREG_E_CLASS;
+ wszModule[MAX_PATH] = '\0';
+
+ /*
+ * Create registry keys and values. When exceptions are disabled, we depend
+ * on setValue() to propagate fail key creation failures.
+ */
+#ifdef RT_EXCEPTIONS_ENABLED
+ try
+#endif
+ {
+ AdHocRegKey keyCLSID(L"CLSID");
+ AdHocRegKeyPtr pkeyNobjClass(keyCLSID.create(L"{f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}"));
+ LSTATUS lrc = pkeyNobjClass.setValue(NULL, L"VirtualBox Bridged Networking Driver Notify Object v1.1");
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_CLASS;
+
+ AdHocRegKeyPtr pkeyNobjSrv(pkeyNobjClass.create(L"InProcServer32"));
+ lrc = pkeyNobjSrv.setValue(NULL, wszModule);
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_CLASS;
+ lrc = pkeyNobjSrv.setValue(L"ThreadingModel", L"Both");
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_CLASS;
+ }
+#ifdef RT_EXCEPTIONS_ENABLED
+ catch (AdHocRegError) { return SELFREG_E_CLASS; }
+#endif
+
+#ifdef RT_EXCEPTIONS_ENABLED
+ try
+#endif
+ {
+ AdHocRegKey keyTypeLib(L"TypeLib");
+ AdHocRegKeyPtr pkeyNobjLib(keyTypeLib.create(L"{2A0C94D1-40E1-439C-8FE8-24107CAB0840}\\1.1"));
+ LSTATUS lrc = pkeyNobjLib.setValue(NULL, L"VirtualBox Bridged Networking Driver Notify Object v1.1 Type Library");
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_TYPELIB;
+
+ AdHocRegKeyPtr pkeyNobjLib0(pkeyNobjLib.create(L"0\\win64"));
+ lrc = pkeyNobjLib0.setValue(NULL, wszModule);
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_TYPELIB;
+ AdHocRegKeyPtr pkeyNobjLibFlags(pkeyNobjLib.create(L"FLAGS"));
+ lrc = pkeyNobjLibFlags.setValue(NULL, L"0");
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_TYPELIB;
+
+ if (GetSystemDirectoryW(wszModule, MAX_PATH) == 0)
+ return SELFREG_E_TYPELIB;
+ AdHocRegKeyPtr pkeyNobjLibHelpDir(pkeyNobjLib.create(L"HELPDIR"));
+ lrc = pkeyNobjLibHelpDir.setValue(NULL, wszModule);
+ if (lrc != ERROR_SUCCESS)
+ return SELFREG_E_TYPELIB;
+ }
+#ifdef RT_EXCEPTIONS_ENABLED
+ catch (AdHocRegError) { return SELFREG_E_TYPELIB; }
+#endif
+
+ return S_OK;
+}
+
+
+STDAPI DllUnregisterServer(void)
+{
+ static struct { HKEY hKeyRoot; wchar_t const *pwszParentKey; wchar_t const *pwszKeyToDelete; HRESULT hrcFail; }
+ s_aKeys[] =
+ {
+ { HKEY_CLASSES_ROOT, L"TypeLib", L"{2A0C94D1-40E1-439C-8FE8-24107CAB0840}", SELFREG_E_TYPELIB },
+ { HKEY_CLASSES_ROOT, L"CLSID", L"{f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}", SELFREG_E_CLASS },
+ };
+
+ HRESULT hrc = S_OK;
+ for (size_t i = 0; i < RT_ELEMENTS(s_aKeys); i++)
+ {
+ HKEY hKey = NULL;
+ LSTATUS lrc = RegOpenKeyExW(s_aKeys[i].hKeyRoot, s_aKeys[i].pwszParentKey, 0, KEY_ALL_ACCESS, &hKey);
+ if (lrc == ERROR_SUCCESS)
+ {
+ lrc = RegDeleteTreeW(hKey, s_aKeys[i].pwszKeyToDelete); /* Vista and later */
+ RegCloseKey(hKey);
+ }
+
+ if (lrc != ERROR_SUCCESS && lrc != ERROR_FILE_NOT_FOUND && hrc == S_OK)
+ hrc = s_aKeys[i].hrcFail;
+ }
+
+ return S_OK;
+}
+
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.def b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.def
new file mode 100644
index 00000000..abfe3834
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.def
@@ -0,0 +1,42 @@
+; $Id: VBoxNetFltNobj.def $
+; @file
+; VBoxNetFltNobj.def - Notify Object for Bridged Networking Driver.
+; Library def file
+;
+
+;
+; Copyright (C) 2011-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+LIBRARY VBoxNetFltNobj
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h
new file mode 100644
index 00000000..87eed992
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.h
@@ -0,0 +1,96 @@
+/* $Id: VBoxNetFltNobj.h $ */
+/** @file
+ * VBoxNetFltNobj.h - Notify Object for Bridged Networking Driver.
+ * Used to filter Bridged Networking Driver bindings
+ */
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobj_h
+#define VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobj_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/windows.h>
+
+#include "VBox/com/defs.h"
+#include "VBoxNetFltNobjT.h"
+#include "VBoxNetFltNobjRc.h"
+
+#define VBOXNETFLTNOTIFY_ONFAIL_BINDDEFAULT false
+
+/*
+ * VirtualBox Bridging driver notify object.
+ * Needed to make our driver bind to "real" host adapters only
+ */
+class ATL_NO_VTABLE VBoxNetFltNobj
+ : public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>
+ , public ATL::CComCoClass<VBoxNetFltNobj, &CLSID_VBoxNetFltNobj>
+ , public INetCfgComponentControl
+ , public INetCfgComponentNotifyBinding
+{
+public:
+ VBoxNetFltNobj();
+ virtual ~VBoxNetFltNobj();
+
+ BEGIN_COM_MAP(VBoxNetFltNobj)
+ COM_INTERFACE_ENTRY(INetCfgComponentControl)
+ COM_INTERFACE_ENTRY(INetCfgComponentNotifyBinding)
+ END_COM_MAP()
+
+ // this is a "just in case" conditional, which is not defined
+#ifdef VBOX_FORCE_REGISTER_SERVER
+ DECLARE_REGISTRY_RESOURCEID(IDR_VBOXNETFLT_NOBJ)
+#endif
+
+ /* INetCfgComponentControl methods */
+ STDMETHOD(Initialize)(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling);
+ STDMETHOD(ApplyRegistryChanges)();
+ STDMETHOD(ApplyPnpChanges)(IN INetCfgPnpReconfigCallback *pCallback);
+ STDMETHOD(CancelChanges)();
+
+ /* INetCfgComponentNotifyBinding methods */
+ STDMETHOD(NotifyBindingPath)(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP);
+ STDMETHOD(QueryBindingPath)(IN DWORD dwChangeFlag, IN INetCfgBindingPath *pNetCfgBP);
+private:
+
+ void init(IN INetCfgComponent *pNetCfgComponent, IN INetCfg *pNetCfg, IN BOOL bInstalling);
+ void cleanup();
+
+ /* these two used to maintain the component info passed to
+ * INetCfgComponentControl::Initialize */
+ INetCfg *mpNetCfg;
+ INetCfgComponent *mpNetCfgComponent;
+ BOOL mbInstalling;
+};
+
+#endif /* !VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobj_h */
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rc b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rc
new file mode 100644
index 00000000..4a1398c6
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rc
@@ -0,0 +1,78 @@
+/* $Id: VBoxNetFltNobj.rc $ */
+/** @file
+ * VBoxNetFltNobj - Resource file containing version info and icon.
+ */
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+#include "VBoxNetFltNobjRc.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
+ BEGIN
+ VALUE "FileDescription", "VirtualBox Bridged Networking Driver Notify Object v1.1\0"
+ VALUE "InternalName", "VBoxNetFltNobj\0"
+ VALUE "OriginalFilename", "VBoxNetFltNobj.dll\0"
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_VBOXNETFLT_NOBJ REGISTRY "VBoxNetFltNobj.rgs"
+
+1 TYPELIB "VBoxNetFltNobjT.tlb"
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rgs b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rgs
new file mode 100644
index 00000000..d6f9bae3
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobj.rgs
@@ -0,0 +1,13 @@
+HKCR
+{
+ NoRemove CLSID
+ {
+ ForceRemove {f374d1a0-bf08-4bdc-9cb2-c15ddaeef955} = s 'VirtualBox Bridged Networking Driver Notify Object v1.1'
+ {
+ InProcServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Both'
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h
new file mode 100644
index 00000000..187af500
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjRc.h
@@ -0,0 +1,46 @@
+/* $Id: VBoxNetFltNobjRc.h $ */
+/** @file
+ * VBoxNetFltNobjRc.h - Notify Object for Bridged Networking Driver.
+ * Resource definitions
+ */
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobjRc_h
+#define VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobjRc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* registry script rc ID */
+#define IDR_VBOXNETFLT_NOBJ 101
+
+#endif /* !VBOX_INCLUDED_SRC_VBoxNetFlt_win_nobj_VBoxNetFltNobjRc_h */
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjT.idl b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjT.idl
new file mode 100644
index 00000000..9bf8b6f9
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/nobj/VBoxNetFltNobjT.idl
@@ -0,0 +1,55 @@
+/* $Id: VBoxNetFltNobjT.idl $ */
+/** @file
+ * VBoxNetFltNobjT.idl - Notify Object for Bridged Networking Driver, typelib definition.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <netcfgn.idl>
+
+[
+ uuid(2a0c94d1-40e1-439c-8fe8-24107cab0840),
+ version(1.1),
+ helpstring("VirtualBox Bridged Networking Driver Notify Object v1.1 Type Library")
+]
+library VBoxNetFltNobjLib
+{
+ [
+ uuid(f374d1a0-bf08-4bdc-9cb2-c15ddaeef955),
+ helpstring("VirtualBox Bridged Networking Driver Notify Object Class")
+ ]
+ coclass VBoxNetFltNobj
+ {
+ [restricted] interface INetCfgComponentControl;
+ [restricted] interface INetCfgComponentNotifyBinding;
+ };
+};