summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h')
-rw-r--r--src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h972
1 files changed, 972 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h b/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h
new file mode 100644
index 00000000..36235409
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.h
@@ -0,0 +1,972 @@
+/* $Id: VBoxNetFltRt-win.h $ */
+/** @file
+ * VBoxNetFltRt-win.h - Bridged Networking Driver, Windows Specific Code.
+ * NetFlt Runtime API
+ */
+/*
+ * 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_drv_VBoxNetFltRt_win_h
+#define VBOX_INCLUDED_SRC_VBoxNetFlt_win_drv_VBoxNetFltRt_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+DECLHIDDEN(VOID) vboxNetFltWinUnload(IN PDRIVER_OBJECT DriverObject);
+
+#ifndef VBOXNETADP
+# if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
+DECLHIDDEN(bool) vboxNetFltWinMatchPackets(PNDIS_PACKET pPacket1, PNDIS_PACKET pPacket2, const INT cbMatch);
+DECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG pSG, const INT cbMatch);
+# endif
+#endif
+
+/*************************
+ * packet queue API *
+ *************************/
+
+
+#define LIST_ENTRY_2_PACKET_INFO(pListEntry) \
+ ( (PVBOXNETFLT_PACKET_INFO)((uint8_t *)(pListEntry) - RT_UOFFSETOF(VBOXNETFLT_PACKET_INFO, ListEntry)) )
+
+#if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
+
+#define VBOX_SLE_2_PKTRSVD_PT(_pEntry) \
+ ( (PVBOXNETFLT_PKTRSVD_PT)((uint8_t *)(_pEntry) - RT_UOFFSETOF(VBOXNETFLT_PKTRSVD_PT, ListEntry)) )
+
+#define VBOX_SLE_2_SENDPACKET(_pEntry) \
+ ( (PNDIS_PACKET)((uint8_t *)(VBOX_SLE_2_PKTRSVD_PT(_pEntry)) - RT_UOFFSETOF(NDIS_PACKET, ProtocolReserved)) )
+
+#endif
+/**
+ * enqueus the packet info to the tail of the queue
+ */
+DECLINLINE(void) vboxNetFltWinQuEnqueueTail(PVBOXNETFLT_PACKET_QUEUE pQueue, PVBOXNETFLT_PACKET_INFO pPacketInfo)
+{
+ InsertTailList(pQueue, &pPacketInfo->ListEntry);
+}
+
+DECLINLINE(void) vboxNetFltWinQuEnqueueHead(PVBOXNETFLT_PACKET_QUEUE pQueue, PVBOXNETFLT_PACKET_INFO pPacketInfo)
+{
+ Assert(pPacketInfo->pPool);
+ InsertHeadList(pQueue, &pPacketInfo->ListEntry);
+}
+
+/**
+ * enqueus the packet info to the tail of the queue
+ */
+DECLINLINE(void) vboxNetFltWinQuInterlockedEnqueueTail(PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE pQueue, PVBOXNETFLT_PACKET_INFO pPacketInfo)
+{
+ Assert(pPacketInfo->pPool);
+ NdisAcquireSpinLock(&pQueue->Lock);
+ vboxNetFltWinQuEnqueueTail(&pQueue->Queue, pPacketInfo);
+ NdisReleaseSpinLock(&pQueue->Lock);
+}
+
+DECLINLINE(void) vboxNetFltWinQuInterlockedEnqueueHead(PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE pQueue, PVBOXNETFLT_PACKET_INFO pPacketInfo)
+{
+ NdisAcquireSpinLock(&pQueue->Lock);
+ vboxNetFltWinQuEnqueueHead(&pQueue->Queue, pPacketInfo);
+ NdisReleaseSpinLock(&pQueue->Lock);
+}
+
+/**
+ * dequeus the packet info from the head of the queue
+ */
+DECLINLINE(PVBOXNETFLT_PACKET_INFO) vboxNetFltWinQuDequeueHead(PVBOXNETFLT_PACKET_QUEUE pQueue)
+{
+ PLIST_ENTRY pListEntry = RemoveHeadList(pQueue);
+ if (pListEntry != pQueue)
+ {
+ PVBOXNETFLT_PACKET_INFO pInfo = LIST_ENTRY_2_PACKET_INFO(pListEntry);
+ Assert(pInfo->pPool);
+ return pInfo;
+ }
+ return NULL;
+}
+
+DECLINLINE(PVBOXNETFLT_PACKET_INFO) vboxNetFltWinQuDequeueTail(PVBOXNETFLT_PACKET_QUEUE pQueue)
+{
+ PLIST_ENTRY pListEntry = RemoveTailList(pQueue);
+ if (pListEntry != pQueue)
+ {
+ PVBOXNETFLT_PACKET_INFO pInfo = LIST_ENTRY_2_PACKET_INFO(pListEntry);
+ Assert(pInfo->pPool);
+ return pInfo;
+ }
+ return NULL;
+}
+
+DECLINLINE(PVBOXNETFLT_PACKET_INFO) vboxNetFltWinQuInterlockedDequeueHead(PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE pInterlockedQueue)
+{
+ PVBOXNETFLT_PACKET_INFO pInfo;
+ NdisAcquireSpinLock(&pInterlockedQueue->Lock);
+ pInfo = vboxNetFltWinQuDequeueHead(&pInterlockedQueue->Queue);
+ NdisReleaseSpinLock(&pInterlockedQueue->Lock);
+ return pInfo;
+}
+
+DECLINLINE(PVBOXNETFLT_PACKET_INFO) vboxNetFltWinQuInterlockedDequeueTail(PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE pInterlockedQueue)
+{
+ PVBOXNETFLT_PACKET_INFO pInfo;
+ NdisAcquireSpinLock(&pInterlockedQueue->Lock);
+ pInfo = vboxNetFltWinQuDequeueTail(&pInterlockedQueue->Queue);
+ NdisReleaseSpinLock(&pInterlockedQueue->Lock);
+ return pInfo;
+}
+
+DECLINLINE(void) vboxNetFltWinQuDequeue(PVBOXNETFLT_PACKET_INFO pInfo)
+{
+ RemoveEntryList(&pInfo->ListEntry);
+}
+
+DECLINLINE(void) vboxNetFltWinQuInterlockedDequeue(PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE pInterlockedQueue, PVBOXNETFLT_PACKET_INFO pInfo)
+{
+ NdisAcquireSpinLock(&pInterlockedQueue->Lock);
+ vboxNetFltWinQuDequeue(pInfo);
+ NdisReleaseSpinLock(&pInterlockedQueue->Lock);
+}
+
+/**
+ * allocates the packet info from the pool
+ */
+DECLINLINE(PVBOXNETFLT_PACKET_INFO) vboxNetFltWinPpAllocPacketInfo(PVBOXNETFLT_PACKET_INFO_POOL pPool)
+{
+ return vboxNetFltWinQuInterlockedDequeueHead(&pPool->Queue);
+}
+
+/**
+ * returns the packet info to the pool
+ */
+DECLINLINE(void) vboxNetFltWinPpFreePacketInfo(PVBOXNETFLT_PACKET_INFO pInfo)
+{
+ PVBOXNETFLT_PACKET_INFO_POOL pPool = pInfo->pPool;
+ vboxNetFltWinQuInterlockedEnqueueHead(&pPool->Queue, pInfo);
+}
+
+/** initializes the packet queue */
+#define INIT_PACKET_QUEUE(_pQueue) InitializeListHead((_pQueue))
+
+/** initializes the packet queue */
+#define INIT_INTERLOCKED_PACKET_QUEUE(_pQueue) \
+ { \
+ INIT_PACKET_QUEUE(&(_pQueue)->Queue); \
+ NdisAllocateSpinLock(&(_pQueue)->Lock); \
+ }
+
+/** delete the packet queue */
+#define FINI_INTERLOCKED_PACKET_QUEUE(_pQueue) NdisFreeSpinLock(&(_pQueue)->Lock)
+
+/** returns the packet the packet info contains */
+#define GET_PACKET_FROM_INFO(_pPacketInfo) (ASMAtomicUoReadPtr((void * volatile *)&(_pPacketInfo)->pPacket))
+
+/** assignes the packet to the packet info */
+#define SET_PACKET_TO_INFO(_pPacketInfo, _pPacket) (ASMAtomicUoWritePtr(&(_pPacketInfo)->pPacket, (_pPacket)))
+
+/** returns the flags the packet info contains */
+#define GET_FLAGS_FROM_INFO(_pPacketInfo) (ASMAtomicUoReadU32((volatile uint32_t *)&(_pPacketInfo)->fFlags))
+
+/** sets flags to the packet info */
+#define SET_FLAGS_TO_INFO(_pPacketInfo, _fFlags) (ASMAtomicUoWriteU32((volatile uint32_t *)&(_pPacketInfo)->fFlags, (_fFlags)))
+
+#ifdef VBOXNETFLT_NO_PACKET_QUEUE
+DECLHIDDEN(bool) vboxNetFltWinPostIntnet(PVBOXNETFLTINS pInstance, PVOID pvPacket, const UINT fFlags);
+#else
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, PVOID pPacket, const UINT fPacketFlags);
+DECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance);
+DECLHIDDEN(NTSTATUS) vboxNetFltWinQuInitPacketQueue(PVBOXNETFLTINS pInstance);
+#endif /* #ifndef VBOXNETFLT_NO_PACKET_QUEUE */
+
+
+#ifndef VBOXNETADP
+/**
+ * searches the list entry in a single-linked list
+ */
+DECLINLINE(bool) vboxNetFltWinSearchListEntry(PVBOXNETFLT_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry2Search, bool bRemove)
+{
+ PSINGLE_LIST_ENTRY pHead = &pList->Head;
+ PSINGLE_LIST_ENTRY pCur;
+ PSINGLE_LIST_ENTRY pPrev;
+ for (pCur = pHead->Next, pPrev = pHead; pCur; pPrev = pCur, pCur = pCur->Next)
+ {
+ if (pEntry2Search == pCur)
+ {
+ if (bRemove)
+ {
+ pPrev->Next = pCur->Next;
+ if (pCur == pList->pTail)
+ {
+ pList->pTail = pPrev;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+#if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinSearchPacket(PVBOXNETFLT_SINGLE_LIST pList, PNDIS_PACKET pPacket2Search, int cbMatch, bool bRemove)
+{
+ PSINGLE_LIST_ENTRY pHead = &pList->Head;
+ PSINGLE_LIST_ENTRY pCur;
+ PSINGLE_LIST_ENTRY pPrev;
+ PNDIS_PACKET pCurPacket;
+ for (pCur = pHead->Next, pPrev = pHead; pCur; pPrev = pCur, pCur = pCur->Next)
+ {
+ pCurPacket = VBOX_SLE_2_SENDPACKET(pCur);
+ if (pCurPacket == pPacket2Search || vboxNetFltWinMatchPackets(pPacket2Search, pCurPacket, cbMatch))
+ {
+ if (bRemove)
+ {
+ pPrev->Next = pCur->Next;
+ if (pCur == pList->pTail)
+ {
+ pList->pTail = pPrev;
+ }
+ }
+ return pCurPacket;
+ }
+ }
+ return NULL;
+}
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinSearchPacketBySG(PVBOXNETFLT_SINGLE_LIST pList, PINTNETSG pSG, int cbMatch, bool bRemove)
+{
+ PSINGLE_LIST_ENTRY pHead = &pList->Head;
+ PSINGLE_LIST_ENTRY pCur;
+ PSINGLE_LIST_ENTRY pPrev;
+ PNDIS_PACKET pCurPacket;
+ for (pCur = pHead->Next, pPrev = pHead; pCur; pPrev = pCur, pCur = pCur->Next)
+ {
+ pCurPacket = VBOX_SLE_2_SENDPACKET(pCur);
+ if (vboxNetFltWinMatchPacketAndSG(pCurPacket, pSG, cbMatch))
+ {
+ if (bRemove)
+ {
+ pPrev->Next = pCur->Next;
+ if (pCur == pList->pTail)
+ {
+ pList->pTail = pPrev;
+ }
+ }
+ return pCurPacket;
+ }
+ }
+ return NULL;
+}
+
+#endif /* #if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS) */
+
+DECLINLINE(bool) vboxNetFltWinSListIsEmpty(PVBOXNETFLT_SINGLE_LIST pList)
+{
+ return !pList->Head.Next;
+}
+
+DECLINLINE(void) vboxNetFltWinPutTail(PVBOXNETFLT_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry)
+{
+ pList->pTail->Next = pEntry;
+ pList->pTail = pEntry;
+ pEntry->Next = NULL;
+}
+
+DECLINLINE(void) vboxNetFltWinPutHead(PVBOXNETFLT_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry)
+{
+ pEntry->Next = pList->Head.Next;
+ pList->Head.Next = pEntry;
+ if (!pEntry->Next)
+ pList->pTail = pEntry;
+}
+
+DECLINLINE(PSINGLE_LIST_ENTRY) vboxNetFltWinGetHead(PVBOXNETFLT_SINGLE_LIST pList)
+{
+ PSINGLE_LIST_ENTRY pEntry = pList->Head.Next;
+ if (pEntry && pEntry == pList->pTail)
+ {
+ pList->Head.Next = NULL;
+ pList->pTail = &pList->Head;
+ }
+ return pEntry;
+}
+
+DECLINLINE(bool) vboxNetFltWinInterlockedSearchListEntry(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry2Search, bool bRemove)
+{
+ bool bFound;
+ NdisAcquireSpinLock(&pList->Lock);
+ bFound = vboxNetFltWinSearchListEntry(&pList->List, pEntry2Search, bRemove);
+ NdisReleaseSpinLock(&pList->Lock);
+ return bFound;
+}
+
+#if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinInterlockedSearchPacket(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket2Search, int cbMatch, bool bRemove)
+{
+ PNDIS_PACKET pFound;
+ NdisAcquireSpinLock(&pList->Lock);
+ pFound = vboxNetFltWinSearchPacket(&pList->List, pPacket2Search, cbMatch, bRemove);
+ NdisReleaseSpinLock(&pList->Lock);
+ return pFound;
+}
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinInterlockedSearchPacketBySG(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PINTNETSG pSG, int cbMatch, bool bRemove)
+{
+ PNDIS_PACKET pFound;
+ NdisAcquireSpinLock(&pList->Lock);
+ pFound = vboxNetFltWinSearchPacketBySG(&pList->List, pSG, cbMatch, bRemove);
+ NdisReleaseSpinLock(&pList->Lock);
+ return pFound;
+}
+#endif /* #if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS) */
+
+DECLINLINE(void) vboxNetFltWinInterlockedPutTail(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry)
+{
+ NdisAcquireSpinLock(&pList->Lock);
+ vboxNetFltWinPutTail(&pList->List, pEntry);
+ NdisReleaseSpinLock(&pList->Lock);
+}
+
+DECLINLINE(void) vboxNetFltWinInterlockedPutHead(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PSINGLE_LIST_ENTRY pEntry)
+{
+ NdisAcquireSpinLock(&pList->Lock);
+ vboxNetFltWinPutHead(&pList->List, pEntry);
+ NdisReleaseSpinLock(&pList->Lock);
+}
+
+DECLINLINE(PSINGLE_LIST_ENTRY) vboxNetFltWinInterlockedGetHead(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList)
+{
+ PSINGLE_LIST_ENTRY pEntry;
+ NdisAcquireSpinLock(&pList->Lock);
+ pEntry = vboxNetFltWinGetHead(&pList->List);
+ NdisReleaseSpinLock(&pList->Lock);
+ return pEntry;
+}
+
+# if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
+DECLINLINE(void) vboxNetFltWinLbPutSendPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, bool bFromIntNet)
+{
+ PVBOXNETFLT_PKTRSVD_PT pSrv = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
+ pSrv->bFromIntNet = bFromIntNet;
+ vboxNetFltWinInterlockedPutHead(&pNetFlt->u.s.WinIf.SendPacketQueue, &pSrv->ListEntry);
+}
+
+DECLINLINE(bool) vboxNetFltWinLbIsFromIntNet(PNDIS_PACKET pPacket)
+{
+ PVBOXNETFLT_PKTRSVD_PT pSrv = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
+ return pSrv->bFromIntNet;
+}
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinLbSearchLoopBack(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, bool bRemove)
+{
+ return vboxNetFltWinInterlockedSearchPacket(&pNetFlt->u.s.WinIf.SendPacketQueue, pPacket, VBOXNETFLT_PACKETMATCH_LENGTH, bRemove);
+}
+
+DECLINLINE(PNDIS_PACKET) vboxNetFltWinLbSearchLoopBackBySG(PVBOXNETFLTINS pNetFlt, PINTNETSG pSG, bool bRemove)
+{
+ return vboxNetFltWinInterlockedSearchPacketBySG(&pNetFlt->u.s.WinIf.SendPacketQueue, pSG, VBOXNETFLT_PACKETMATCH_LENGTH, bRemove);
+}
+
+DECLINLINE(bool) vboxNetFltWinLbRemoveSendPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket)
+{
+ PVBOXNETFLT_PKTRSVD_PT pSrv = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
+ bool bRet = vboxNetFltWinInterlockedSearchListEntry(&pNetFlt->u.s.WinIf.SendPacketQueue, &pSrv->ListEntry, true);
+#ifdef DEBUG_misha
+ Assert(bRet == (pNetFlt->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE));
+#endif
+ return bRet;
+}
+
+# endif
+
+#endif
+
+#ifdef DEBUG_misha
+DECLHIDDEN(bool) vboxNetFltWinCheckMACs(PNDIS_PACKET pPacket, PRTMAC pDst, PRTMAC pSrc);
+DECLHIDDEN(bool) vboxNetFltWinCheckMACsSG(PINTNETSG pSG, PRTMAC pDst, PRTMAC pSrc);
+extern RTMAC g_vboxNetFltWinVerifyMACBroadcast;
+extern RTMAC g_vboxNetFltWinVerifyMACGuest;
+
+# define VBOXNETFLT_LBVERIFY(_pnf, _p) \
+ do { \
+ Assert(!vboxNetFltWinCheckMACs(_p, NULL, &g_vboxNetFltWinVerifyMACGuest)); \
+ Assert(!vboxNetFltWinCheckMACs(_p, NULL, &(_pnf)->u.s.MacAddr)); \
+ } while (0)
+
+# define VBOXNETFLT_LBVERIFYSG(_pnf, _p) \
+ do { \
+ Assert(!vboxNetFltWinCheckMACsSG(_p, NULL, &g_vboxNetFltWinVerifyMACGuest)); \
+ Assert(!vboxNetFltWinCheckMACsSG(_p, NULL, &(_pnf)->u.s.MacAddr)); \
+ } while (0)
+
+#else
+# define VBOXNETFLT_LBVERIFY(_pnf, _p) do { } while (0)
+# define VBOXNETFLT_LBVERIFYSG(_pnf, _p) do { } while (0)
+#endif
+
+/** initializes the list */
+#define INIT_SINGLE_LIST(_pList) \
+ { \
+ (_pList)->Head.Next = NULL; \
+ (_pList)->pTail = &(_pList)->Head; \
+ }
+
+/** initializes the list */
+#define INIT_INTERLOCKED_SINGLE_LIST(_pList) \
+ do { \
+ INIT_SINGLE_LIST(&(_pList)->List); \
+ NdisAllocateSpinLock(&(_pList)->Lock); \
+ } while (0)
+
+/** delete the packet queue */
+#define FINI_INTERLOCKED_SINGLE_LIST(_pList) \
+ do { \
+ Assert(vboxNetFltWinSListIsEmpty(&(_pList)->List)); \
+ NdisFreeSpinLock(&(_pList)->Lock); \
+ } while (0)
+
+
+/**************************************************************************
+ * PVBOXNETFLTINS , WinIf reference/dereference (i.e. retain/release) API *
+ **************************************************************************/
+
+
+DECLHIDDEN(void) vboxNetFltWinWaitDereference(PVBOXNETFLT_WINIF_DEVICE pState);
+
+DECLINLINE(void) vboxNetFltWinReferenceModeNetFlt(PVBOXNETFLTINS pIns)
+{
+ ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs);
+}
+
+DECLINLINE(void) vboxNetFltWinReferenceModePassThru(PVBOXNETFLTINS pIns)
+{
+ ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs);
+}
+
+DECLINLINE(void) vboxNetFltWinIncReferenceModeNetFlt(PVBOXNETFLTINS pIns, uint32_t v)
+{
+ ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, v);
+}
+
+DECLINLINE(void) vboxNetFltWinIncReferenceModePassThru(PVBOXNETFLTINS pIns, uint32_t v)
+{
+ ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, v);
+}
+
+DECLINLINE(void) vboxNetFltWinDereferenceModeNetFlt(PVBOXNETFLTINS pIns)
+{
+ ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs);
+}
+
+DECLINLINE(void) vboxNetFltWinDereferenceModePassThru(PVBOXNETFLTINS pIns)
+{
+ ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs);
+}
+
+DECLINLINE(void) vboxNetFltWinDecReferenceModeNetFlt(PVBOXNETFLTINS pIns, uint32_t v)
+{
+ Assert(v);
+ ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, (uint32_t)(-((int32_t)v)));
+}
+
+DECLINLINE(void) vboxNetFltWinDecReferenceModePassThru(PVBOXNETFLTINS pIns, uint32_t v)
+{
+ Assert(v);
+ ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, (uint32_t)(-((int32_t)v)));
+}
+
+DECLINLINE(void) vboxNetFltWinSetPowerState(PVBOXNETFLT_WINIF_DEVICE pState, NDIS_DEVICE_POWER_STATE State)
+{
+ ASMAtomicUoWriteU32((volatile uint32_t *)&pState->PowerState, State);
+}
+
+DECLINLINE(NDIS_DEVICE_POWER_STATE) vboxNetFltWinGetPowerState(PVBOXNETFLT_WINIF_DEVICE pState)
+{
+ return (NDIS_DEVICE_POWER_STATE)ASMAtomicUoReadU32((volatile uint32_t *)&pState->PowerState);
+}
+
+DECLINLINE(void) vboxNetFltWinSetOpState(PVBOXNETFLT_WINIF_DEVICE pState, VBOXNETDEVOPSTATE State)
+{
+ ASMAtomicUoWriteU32((volatile uint32_t *)&pState->OpState, State);
+}
+
+DECLINLINE(VBOXNETDEVOPSTATE) vboxNetFltWinGetOpState(PVBOXNETFLT_WINIF_DEVICE pState)
+{
+ return (VBOXNETDEVOPSTATE)ASMAtomicUoReadU32((volatile uint32_t *)&pState->OpState);
+}
+
+DECLINLINE(bool) vboxNetFltWinDoReferenceDevice(PVBOXNETFLT_WINIF_DEVICE pState)
+{
+ if (vboxNetFltWinGetPowerState(pState) == NdisDeviceStateD0 && vboxNetFltWinGetOpState(pState) == kVBoxNetDevOpState_Initialized)
+ {
+ /** @todo r=bird: Since this is a volatile member, why don't you declare it as
+ * such and save yourself all the casting? */
+ ASMAtomicIncU32((uint32_t volatile *)&pState->cReferences);
+ return true;
+ }
+ return false;
+}
+
+#ifndef VBOXNETADP
+DECLINLINE(bool) vboxNetFltWinDoReferenceDevices(PVBOXNETFLT_WINIF_DEVICE pState1, PVBOXNETFLT_WINIF_DEVICE pState2)
+{
+ if (vboxNetFltWinGetPowerState(pState1) == NdisDeviceStateD0
+ && vboxNetFltWinGetOpState(pState1) == kVBoxNetDevOpState_Initialized
+ && vboxNetFltWinGetPowerState(pState2) == NdisDeviceStateD0
+ && vboxNetFltWinGetOpState(pState2) == kVBoxNetDevOpState_Initialized)
+ {
+ ASMAtomicIncU32((uint32_t volatile *)&pState1->cReferences);
+ ASMAtomicIncU32((uint32_t volatile *)&pState2->cReferences);
+ return true;
+ }
+ return false;
+}
+#endif
+
+DECLINLINE(void) vboxNetFltWinDereferenceDevice(PVBOXNETFLT_WINIF_DEVICE pState)
+{
+ ASMAtomicDecU32((uint32_t volatile *)&pState->cReferences);
+ /** @todo r=bird: Add comment explaining why these cannot hit 0 or why
+ * reference are counted */
+}
+
+#ifndef VBOXNETADP
+DECLINLINE(void) vboxNetFltWinDereferenceDevices(PVBOXNETFLT_WINIF_DEVICE pState1, PVBOXNETFLT_WINIF_DEVICE pState2)
+{
+ ASMAtomicDecU32((uint32_t volatile *)&pState1->cReferences);
+ ASMAtomicDecU32((uint32_t volatile *)&pState2->cReferences);
+}
+#endif
+
+DECLINLINE(void) vboxNetFltWinDecReferenceDevice(PVBOXNETFLT_WINIF_DEVICE pState, uint32_t v)
+{
+ Assert(v);
+ ASMAtomicAddU32((uint32_t volatile *)&pState->cReferences, (uint32_t)(-((int32_t)v)));
+}
+
+#ifndef VBOXNETADP
+DECLINLINE(void) vboxNetFltWinDecReferenceDevices(PVBOXNETFLT_WINIF_DEVICE pState1, PVBOXNETFLT_WINIF_DEVICE pState2, uint32_t v)
+{
+ ASMAtomicAddU32((uint32_t volatile *)&pState1->cReferences, (uint32_t)(-((int32_t)v)));
+ ASMAtomicAddU32((uint32_t volatile *)&pState2->cReferences, (uint32_t)(-((int32_t)v)));
+}
+#endif
+
+DECLINLINE(bool) vboxNetFltWinDoIncReferenceDevice(PVBOXNETFLT_WINIF_DEVICE pState, uint32_t v)
+{
+ Assert(v);
+ if (vboxNetFltWinGetPowerState(pState) == NdisDeviceStateD0 && vboxNetFltWinGetOpState(pState) == kVBoxNetDevOpState_Initialized)
+ {
+ ASMAtomicAddU32((uint32_t volatile *)&pState->cReferences, v);
+ return true;
+ }
+ return false;
+}
+
+#ifndef VBOXNETADP
+DECLINLINE(bool) vboxNetFltWinDoIncReferenceDevices(PVBOXNETFLT_WINIF_DEVICE pState1, PVBOXNETFLT_WINIF_DEVICE pState2, uint32_t v)
+{
+ if (vboxNetFltWinGetPowerState(pState1) == NdisDeviceStateD0
+ && vboxNetFltWinGetOpState(pState1) == kVBoxNetDevOpState_Initialized
+ && vboxNetFltWinGetPowerState(pState2) == NdisDeviceStateD0
+ && vboxNetFltWinGetOpState(pState2) == kVBoxNetDevOpState_Initialized)
+ {
+ ASMAtomicAddU32((uint32_t volatile *)&pState1->cReferences, v);
+ ASMAtomicAddU32((uint32_t volatile *)&pState2->cReferences, v);
+ return true;
+ }
+ return false;
+}
+#endif
+
+
+DECLINLINE(bool) vboxNetFltWinReferenceWinIfNetFlt(PVBOXNETFLTINS pNetFlt, bool * pbNetFltActive)
+{
+ RTSpinlockAcquire((pNetFlt)->hSpinlock);
+#ifndef VBOXNETADP
+ if (!vboxNetFltWinDoReferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState))
+#else
+ if (!vboxNetFltWinDoReferenceDevice(&pNetFlt->u.s.WinIf.MpState))
+#endif
+ {
+ RTSpinlockRelease((pNetFlt)->hSpinlock);
+ *pbNetFltActive = false;
+ return false;
+ }
+
+ if (pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE)
+ {
+ vboxNetFltWinReferenceModePassThru(pNetFlt);
+ RTSpinlockRelease((pNetFlt)->hSpinlock);
+ *pbNetFltActive = false;
+ return true;
+ }
+
+ vboxNetFltRetain((pNetFlt), true /* fBusy */);
+ vboxNetFltWinReferenceModeNetFlt(pNetFlt);
+ RTSpinlockRelease((pNetFlt)->hSpinlock);
+
+ *pbNetFltActive = true;
+ return true;
+}
+
+DECLINLINE(bool) vboxNetFltWinIncReferenceWinIfNetFlt(PVBOXNETFLTINS pNetFlt, uint32_t v, bool *pbNetFltActive)
+{
+ uint32_t i;
+
+ Assert(v);
+ if (!v)
+ {
+ *pbNetFltActive = false;
+ return false;
+ }
+
+ RTSpinlockAcquire((pNetFlt)->hSpinlock);
+#ifndef VBOXNETADP
+ if (!vboxNetFltWinDoIncReferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState, v))
+#else
+ if (!vboxNetFltWinDoIncReferenceDevice(&pNetFlt->u.s.WinIf.MpState, v))
+#endif
+ {
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+ *pbNetFltActive = false;
+ return false;
+ }
+
+ if (pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE)
+ {
+ vboxNetFltWinIncReferenceModePassThru(pNetFlt, v);
+
+ RTSpinlockRelease((pNetFlt)->hSpinlock);
+ *pbNetFltActive = false;
+ return true;
+ }
+
+ vboxNetFltRetain(pNetFlt, true /* fBusy */);
+
+ vboxNetFltWinIncReferenceModeNetFlt(pNetFlt, v);
+
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+
+ /* we have marked it as busy, so can do the res references outside the lock */
+ for (i = 0; i < v-1; i++)
+ {
+ vboxNetFltRetain(pNetFlt, true /* fBusy */);
+ }
+
+ *pbNetFltActive = true;
+
+ return true;
+}
+
+DECLINLINE(void) vboxNetFltWinDecReferenceNetFlt(PVBOXNETFLTINS pNetFlt, uint32_t n)
+{
+ uint32_t i;
+ for (i = 0; i < n; i++)
+ {
+ vboxNetFltRelease(pNetFlt, true);
+ }
+
+ vboxNetFltWinDecReferenceModeNetFlt(pNetFlt, n);
+}
+
+DECLINLINE(void) vboxNetFltWinDereferenceNetFlt(PVBOXNETFLTINS pNetFlt)
+{
+ vboxNetFltRelease(pNetFlt, true);
+
+ vboxNetFltWinDereferenceModeNetFlt(pNetFlt);
+}
+
+DECLINLINE(void) vboxNetFltWinDecReferenceWinIf(PVBOXNETFLTINS pNetFlt, uint32_t v)
+{
+#ifdef VBOXNETADP
+ vboxNetFltWinDecReferenceDevice(&pNetFlt->u.s.WinIf.MpState, v);
+#else
+ vboxNetFltWinDecReferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState, v);
+#endif
+}
+
+DECLINLINE(void) vboxNetFltWinDereferenceWinIf(PVBOXNETFLTINS pNetFlt)
+{
+#ifdef VBOXNETADP
+ vboxNetFltWinDereferenceDevice(&pNetFlt->u.s.WinIf.MpState);
+#else
+ vboxNetFltWinDereferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState);
+#endif
+}
+
+DECLINLINE(bool) vboxNetFltWinIncReferenceWinIf(PVBOXNETFLTINS pNetFlt, uint32_t v)
+{
+ Assert(v);
+ if (!v)
+ {
+ return false;
+ }
+
+ RTSpinlockAcquire(pNetFlt->hSpinlock);
+#ifdef VBOXNETADP
+ if (vboxNetFltWinDoIncReferenceDevice(&pNetFlt->u.s.WinIf.MpState, v))
+#else
+ if (vboxNetFltWinDoIncReferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState, v))
+#endif
+ {
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+ return true;
+ }
+
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+ return false;
+}
+
+DECLINLINE(bool) vboxNetFltWinReferenceWinIf(PVBOXNETFLTINS pNetFlt)
+{
+ RTSpinlockAcquire(pNetFlt->hSpinlock);
+#ifdef VBOXNETADP
+ if (vboxNetFltWinDoReferenceDevice(&pNetFlt->u.s.WinIf.MpState))
+#else
+ if (vboxNetFltWinDoReferenceDevices(&pNetFlt->u.s.WinIf.MpState, &pNetFlt->u.s.WinIf.PtState))
+#endif
+ {
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+ return true;
+ }
+
+ RTSpinlockRelease(pNetFlt->hSpinlock);
+ return false;
+}
+
+/***********************************************
+ * methods for accessing the network card info *
+ ***********************************************/
+
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinGetMacAddress(PVBOXNETFLTINS pNetFlt, PRTMAC pMac);
+DECLHIDDEN(bool) vboxNetFltWinIsPromiscuous(PVBOXNETFLTINS pNetFlt);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PVBOXNETFLTINS pNetFlt, bool bYes);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQueryPhysicalMedium(PVBOXNETFLTINS pNetFlt, NDIS_PHYSICAL_MEDIUM * pMedium);
+
+/*********************
+ * mem alloc API *
+ *********************/
+
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMemAlloc(PVOID* ppMemBuf, UINT cbLength);
+
+DECLHIDDEN(void) vboxNetFltWinMemFree(PVOID pMemBuf);
+
+/* convenience method used which allocates and initializes the PINTNETSG containing one
+ * segment referring the buffer of size cbBufSize
+ * the allocated PINTNETSG should be freed with the vboxNetFltWinMemFree.
+ *
+ * This is used when our ProtocolReceive callback is called and we have to return the indicated NDIS_PACKET
+ * on a callback exit. This is why we allocate the PINTNETSG and put the packet info there and enqueue it
+ * for the packet queue */
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbBufSize, PINTNETSG *ppSG);
+
+/************************
+ * WinIf init/fini API *
+ ************************/
+#if defined(VBOXNETADP)
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PVBOXNETFLTINS *ppNetFlt, NDIS_HANDLE hMiniportAdapter, PNDIS_STRING pBindToMiniportName /* actually this is our miniport name*/, NDIS_HANDLE hWrapperConfigurationContext);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitWinIf(PVBOXNETFLTWIN pWinIf);
+#else
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PVBOXNETFLTINS *ppNetFlt, PNDIS_STRING pOurMiniportName, PNDIS_STRING pBindToMiniportName);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitWinIf(PVBOXNETFLTWIN pWinIf, PNDIS_STRING pOurDeviceName);
+#endif
+
+DECLHIDDEN(VOID) vboxNetFltWinPtFiniWinIf(PVBOXNETFLTWIN pWinIf);
+
+/************************************
+ * Execute Job at passive level API *
+ ************************************/
+
+typedef VOID (*PFNVBOXNETFLT_JOB_ROUTINE) (PVOID pContext);
+
+DECLHIDDEN(VOID) vboxNetFltWinJobSynchExecAtPassive(PFNVBOXNETFLT_JOB_ROUTINE pfnRoutine, PVOID pContext);
+
+/*******************************
+ * Ndis Packets processing API *
+ *******************************/
+DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PVBOXNETFLTINS pNetFlt, PINTNETSG pSG, PVOID pBufToFree, bool bToWire, bool bCopyMemory);
+
+DECLHIDDEN(void) vboxNetFltWinFreeSGNdisPacket(PNDIS_PACKET pPacket, bool bFreeMem);
+
+#ifdef DEBUG_NETFLT_PACKETS
+#define DBG_CHECK_PACKETS(_p1, _p2) \
+ { \
+ bool _b = vboxNetFltWinMatchPackets(_p1, _p2, -1); \
+ Assert(_b); \
+ }
+
+#define DBG_CHECK_PACKET_AND_SG(_p, _sg) \
+ { \
+ bool _b = vboxNetFltWinMatchPacketAndSG(_p, _sg, -1); \
+ Assert(_b); \
+ }
+
+#define DBG_CHECK_SGS(_sg1, _sg2) \
+ { \
+ bool _b = vboxNetFltWinMatchSGs(_sg1, _sg2, -1); \
+ Assert(_b); \
+ }
+
+#else
+#define DBG_CHECK_PACKETS(_p1, _p2)
+#define DBG_CHECK_PACKET_AND_SG(_p, _sg)
+#define DBG_CHECK_SGS(_sg1, _sg2)
+#endif
+
+/**
+ * Ndis loops back broadcast packets posted to the wire by IntNet
+ * This routine is used in the mechanism of preventing this looping
+ *
+ * @param pAdapt
+ * @param pPacket
+ * @param bOnRecv true is we are receiving the packet from the wire
+ * false otherwise (i.e. the packet is from the host)
+ *
+ * @return true if the packet is a looped back one, false otherwise
+ */
+#ifdef VBOX_LOOPBACK_USEFLAGS
+DECLINLINE(bool) vboxNetFltWinIsLoopedBackPacket(PNDIS_PACKET pPacket)
+{
+ return (NdisGetPacketFlags(pPacket) & g_fPacketIsLoopedBack) == g_fPacketIsLoopedBack;
+}
+#endif
+
+/**************************************************************
+ * utility methods for ndis packet creation/initialization *
+ **************************************************************/
+
+#define VBOXNETFLT_OOB_INIT(_p) \
+ { \
+ NdisZeroMemory(NDIS_OOB_DATA_FROM_PACKET(_p), sizeof(NDIS_PACKET_OOB_DATA)); \
+ NDIS_SET_PACKET_HEADER_SIZE(_p, VBOXNETFLT_PACKET_ETHEADER_SIZE); \
+ }
+
+#ifndef VBOXNETADP
+
+DECLINLINE(NDIS_STATUS) vboxNetFltWinCopyPacketInfoOnRecv(PNDIS_PACKET pDstPacket, PNDIS_PACKET pSrcPacket, bool bForceStatusResources)
+{
+ NDIS_STATUS Status = bForceStatusResources ? NDIS_STATUS_RESOURCES : NDIS_GET_PACKET_STATUS(pSrcPacket);
+ NDIS_SET_PACKET_STATUS(pDstPacket, Status);
+
+ NDIS_PACKET_FIRST_NDIS_BUFFER(pDstPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(pSrcPacket);
+ NDIS_PACKET_LAST_NDIS_BUFFER(pDstPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(pSrcPacket);
+
+ NdisGetPacketFlags(pDstPacket) = NdisGetPacketFlags(pSrcPacket);
+
+ NDIS_SET_ORIGINAL_PACKET(pDstPacket, NDIS_GET_ORIGINAL_PACKET(pSrcPacket));
+ NDIS_SET_PACKET_HEADER_SIZE(pDstPacket, NDIS_GET_PACKET_HEADER_SIZE(pSrcPacket));
+
+ return Status;
+}
+
+DECLINLINE(void) vboxNetFltWinCopyPacketInfoOnSend(PNDIS_PACKET pDstPacket, PNDIS_PACKET pSrcPacket)
+{
+ NDIS_PACKET_FIRST_NDIS_BUFFER(pDstPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(pSrcPacket);
+ NDIS_PACKET_LAST_NDIS_BUFFER(pDstPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(pSrcPacket);
+
+ NdisGetPacketFlags(pDstPacket) = NdisGetPacketFlags(pSrcPacket);
+
+ NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(pDstPacket),
+ NDIS_OOB_DATA_FROM_PACKET(pSrcPacket),
+ sizeof (NDIS_PACKET_OOB_DATA));
+
+ NdisIMCopySendPerPacketInfo(pDstPacket, pSrcPacket);
+
+ PVOID pMediaSpecificInfo = NULL;
+ UINT fMediaSpecificInfoSize = 0;
+
+ NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(pSrcPacket, &pMediaSpecificInfo, &fMediaSpecificInfoSize);
+
+ if (pMediaSpecificInfo || fMediaSpecificInfoSize)
+ {
+ NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(pDstPacket, pMediaSpecificInfo, fMediaSpecificInfoSize);
+ }
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPrepareSendPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, PNDIS_PACKET *ppMyPacket);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPrepareRecvPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, PNDIS_PACKET *ppMyPacket, bool bDpr);
+#endif
+
+DECLHIDDEN(void) vboxNetFltWinSleep(ULONG milis);
+
+#define MACS_EQUAL(_m1, _m2) \
+ ((_m1).au16[0] == (_m2).au16[0] \
+ && (_m1).au16[1] == (_m2).au16[1] \
+ && (_m1).au16[2] == (_m2).au16[2])
+
+
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinDetachFromInterface(PVBOXNETFLTINS pNetFlt, bool bOnUnbind);
+DECLHIDDEN(NDIS_STATUS) vboxNetFltWinCopyString(PNDIS_STRING pDst, PNDIS_STRING pSrc);
+
+
+/**
+ * Sets the enmState member atomically.
+ *
+ * Used for all updates.
+ *
+ * @param pThis The instance.
+ * @param enmNewState The new value.
+ */
+DECLINLINE(void) vboxNetFltWinSetWinIfState(PVBOXNETFLTINS pNetFlt, VBOXNETFLT_WINIFSTATE enmNewState)
+{
+ ASMAtomicWriteU32((uint32_t volatile *)&pNetFlt->u.s.WinIf.enmState, enmNewState);
+}
+
+/**
+ * Gets the enmState member atomically.
+ *
+ * Used for all reads.
+ *
+ * @returns The enmState value.
+ * @param pThis The instance.
+ */
+DECLINLINE(VBOXNETFLT_WINIFSTATE) vboxNetFltWinGetWinIfState(PVBOXNETFLTINS pNetFlt)
+{
+ return (VBOXNETFLT_WINIFSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pNetFlt->u.s.WinIf.enmState);
+}
+
+/* reference the driver module to prevent driver unload */
+DECLHIDDEN(void) vboxNetFltWinDrvReference();
+/* dereference the driver module to prevent driver unload */
+DECLHIDDEN(void) vboxNetFltWinDrvDereference();
+
+
+#ifndef VBOXNETADP
+# define VBOXNETFLT_PROMISCUOUS_SUPPORTED(_pNetFlt) (!(_pNetFlt)->fDisablePromiscuous)
+#else
+# define STATISTIC_INCREASE(_s) ASMAtomicIncU32((uint32_t volatile *)&(_s));
+
+DECLHIDDEN(void) vboxNetFltWinGenerateMACAddress(RTMAC *pMac);
+DECLHIDDEN(int) vboxNetFltWinMAC2NdisString(RTMAC *pMac, PNDIS_STRING pNdisString);
+DECLHIDDEN(int) vboxNetFltWinMACFromNdisString(RTMAC *pMac, PNDIS_STRING pNdisString);
+
+#endif
+#endif /* !VBOX_INCLUDED_SRC_VBoxNetFlt_win_drv_VBoxNetFltRt_win_h */