VBoxNetFltCmn-win.h revision 7e9ca60730092c625220814121c54a593ad20997
/* $Id$ */
/** @file
* VBoxNetFltCmn-win.h - Bridged Networking Driver, Windows Specific Code.
* Common header with configuration defines and global defs
*/
/*
* Copyright (C) 2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef ___VBoxNetFltCmn_win_h___
#define ___VBoxNetFltCmn_win_h___
#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
/* debugging flags */
#ifdef DEBUG
//# define DEBUG_NETFLT_PACKETS
# ifndef DEBUG_misha
# define RT_NO_STRICT
# endif
/* # define DEBUG_NETFLT_LOOPBACK */
/* receive logic has several branches */
/* the DEBUG_NETFLT_RECV* macros used to debug the ProtocolReceive callback
* which is typically not used in case the underlying miniport indicates the packets with NdisMIndicateReceivePacket
* the best way to debug the ProtocolReceive (which in turn has several branches) is to enable the DEBUG_NETFLT_RECV
* one by one in the below order, i.e.
* first DEBUG_NETFLT_RECV
* then DEBUG_NETFLT_RECV + DEBUG_NETFLT_RECV_NOPACKET */
//# define DEBUG_NETFLT_RECV
//# define DEBUG_NETFLT_RECV_NOPACKET
//# define DEBUG_NETFLT_RECV_TRANSFERDATA
/* use ExAllocatePoolWithTag instead of NdisAllocateMemoryWithTag */
// #define DEBUG_NETFLT_USE_EXALLOC
#endif
#include <VBox/intnet.h>
#include <VBox/log.h>
#include <VBox/err.h>
#include <VBox/version.h>
#include <iprt/initterm.h>
#include <iprt/assert.h>
#include <iprt/spinlock.h>
#include <iprt/semaphore.h>
#include <iprt/process.h>
#include <iprt/alloc.h>
#include <iprt/alloca.h>
#include <iprt/time.h>
#include <iprt/net.h>
RT_C_DECLS_BEGIN
/* ntddk.h has a missing #pragma pack(), work around it
* see #ifdef VBOX_WITH_WORKAROUND_MISSING_PACK below for detail */
#define VBOX_WITH_WORKAROUND_MISSING_PACK
#if (_MSC_VER >= 1400) && !defined(VBOX_WITH_PATCHED_DDK)
# define _InterlockedExchange _InterlockedExchange_StupidDDKVsCompilerCrap
# define _InterlockedExchangeAdd _InterlockedExchangeAdd_StupidDDKVsCompilerCrap
# define _InterlockedCompareExchange _InterlockedCompareExchange_StupidDDKVsCompilerCrap
# define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
# define _interlockedbittestandset _interlockedbittestandset_StupidDDKVsCompilerCrap
# define _interlockedbittestandreset _interlockedbittestandreset_StupidDDKVsCompilerCrap
# define _interlockedbittestandset64 _interlockedbittestandset64_StupidDDKVsCompilerCrap
# define _interlockedbittestandreset64 _interlockedbittestandreset64_StupidDDKVsCompilerCrap
# pragma warning(disable : 4163)
# ifdef VBOX_WITH_WORKAROUND_MISSING_PACK
# pragma warning(disable : 4103)
# endif
# include <ntddk.h>
# pragma warning(default : 4163)
# ifdef VBOX_WITH_WORKAROUND_MISSING_PACK
# pragma pack()
# pragma warning(default : 4103)
# endif
# undef _InterlockedExchange
# undef _InterlockedExchangeAdd
# undef _InterlockedCompareExchange
# undef _InterlockedAddLargeStatistic
# undef _interlockedbittestandset
# undef _interlockedbittestandreset
# undef _interlockedbittestandset64
# undef _interlockedbittestandreset64
# include <ndis.h>
#else
//# include <ntddk.h>
/* can include ndis.h right away */
# include <ndis.h>
#endif
RT_C_DECLS_END
#define VBOXNETFLT_OS_SPECFIC 1
/** version
* NOTE: we are NOT using NDIS 5.1 features now */
#ifdef NDIS51_MINIPORT
# define VBOXNETFLT_VERSION_MP_NDIS_MAJOR 5
# define VBOXNETFLT_VERSION_MP_NDIS_MINOR 1
#else
# define VBOXNETFLT_VERSION_MP_NDIS_MAJOR 5
# define VBOXNETFLT_VERSION_MP_NDIS_MINOR 0
#endif
#ifndef VBOXNETADP
#ifdef NDIS51
# define VBOXNETFLT_VERSION_PT_NDIS_MAJOR 5
# define VBOXNETFLT_VERSION_PT_NDIS_MINOR 1 /* todo: use 0 here as well ? */
#else
# define VBOXNETFLT_VERSION_PT_NDIS_MAJOR 5
# define VBOXNETFLT_VERSION_PT_NDIS_MINOR 0
#endif
# define VBOXNETFLT_NAME_PROTOCOL L"VBoxNetFlt"
/** device to be used to prevent the driver unload & ioctl interface (if necessary in the future) */
# define VBOXNETFLT_NAME_LINK L"\\DosDevices\\Global\\VBoxNetFlt"
# define VBOXNETFLT_NAME_DEVICE L"\\Device\\VBoxNetFlt"
#else
# define VBOXNETFLT_NAME_LINK L"\\DosDevices\\Global\\VBoxNetAdp"
# define VBOXNETFLT_NAME_DEVICE L"\\Device\\VBoxNetAdp"
#endif
typedef struct VBOXNETFLTINS *PVBOXNETFLTINS;
/** configuration */
/** Ndis Packet pool settings
* these are applied to both receive and send packet pools */
/* number of packets for normal used */
#define VBOXNETFLT_PACKET_POOL_SIZE_NORMAL 0x000000FF
/* number of additional overflow packets */
#define VBOXNETFLT_PACKET_POOL_SIZE_OVERFLOW 0x0000FF00
/** packet queue size used when the driver is working in the "active" mode */
#define VBOXNETFLT_PACKET_INFO_POOL_SIZE 0x0000FFFF
#ifndef VBOXNETADP
/** memory tag used for memory allocations
* (VBNF stands for VBox NetFlt) */
# define VBOXNETFLT_MEM_TAG 'FNBV'
#else
/** memory tag used for memory allocations
* (VBNA stands for VBox NetAdp) */
# define VBOXNETFLT_MEM_TAG 'ANBV'
#endif
/** receive and transmit Ndis buffer pool size */
#define VBOXNETFLT_BUFFER_POOL_SIZE_TX 128
#define VBOXNETFLT_BUFFER_POOL_SIZE_RX 128
#define VBOXNETFLT_PACKET_ETHEADER_SIZE 14
#define VBOXNETFLT_PACKET_HEADER_MATCH_SIZE 24
#define VBOXNETFLT_PACKET_QUEUE_SG_SEGS_ALLOC 32
#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
# define VBOXNETFLT_PACKETMATCH_LENGTH (VBOXNETFLT_PACKET_ETHEADER_SIZE + 2)
#endif
#ifdef VBOXNETADP
#define VBOXNETADP_HEADER_SIZE 14
#define VBOXNETADP_MAX_DATA_SIZE 1500
#define VBOXNETADP_MAX_PACKET_SIZE (VBOXNETADP_HEADER_SIZE + VBOXNETADP_MAX_DATA_SIZE)
#define VBOXNETADP_MIN_PACKET_SIZE 60
/* link speed 100Mbps (measured in 100 bps) */
#define VBOXNETADP_LINK_SPEED 1000000
#define VBOXNETADP_MAX_LOOKAHEAD_SIZE VBOXNETADP_MAX_DATA_SIZE
#define VBOXNETADP_VENDOR_ID 0x080027
#define VBOXNETADP_VENDOR_DRIVER_VERSION 0x00010000
#define VBOXNETADP_VENDOR_DESC "Sun"
#define VBOXNETADP_MAX_MCAST_LIST 32
#define VBOXNETADP_ETH_ADDRESS_LENGTH 6
//#define VBOXNETADP_REPORT_DISCONNECTED
#endif
/* type defs */
/** Flag specifying that the type of enqueued packet
* if set the info contains the PINTNETSG packet
* if clear the packet info contains the PNDIS_PACKET packet
* Typically the packet queue we are maintaining contains PNDIS_PACKETs only,
* however in case the underlying miniport indicates a packet with the NDIS_STATUS_RESOURCES status
* we MUST return the packet back to the miniport immediately
* this is why we are creating the INTNETSG, copying the ndis packet info there and enqueueing it */
#define VBOXNETFLT_PACKET_SG 0x00000001
/** the flag specifying that the packet source
* if set the packet comes from the host (upperlying protocol)
* if clear the packet comes from the wire (underlying miniport) */
#define VBOXNETFLT_PACKET_SRC_HOST 0x00000002
#ifndef VBOXNETFLT_NO_PACKET_QUEUE
/** flag specifying the packet was originated by our driver
* i.e. we could use it on our needs and should not return it
* we are enqueueing "our" packets on ProtocolReceive call-back when
* Ndis does not give us a receive packet (the driver below us has called NdisM..IndicateReceive)
* this is supported for Ndis Packet only */
#define VBOXNETFLT_PACKET_MINE 0x00000004
/** flag passed to vboxNetFltWinQuEnqueuePacket specifying that the packet should be copied
* this is supported for Ndis Packet only */
#define VBOXNETFLT_PACKET_COPY 0x00000008
#endif
/** packet queue element containing the packet info */
typedef struct VBOXNETFLT_PACKET_INFO
{
/** list entry used for enqueueing the info */
LIST_ENTRY ListEntry;
/** pointer to the pool containing this packet info */
struct VBOXNETFLT_PACKET_INFO_POOL *pPool;
/** flags describing the referenced packet. Contains PACKET_xxx flags (i.e. PACKET_SG, PACKET_SRC_HOST) */
uint32_t fFlags;
/** pointer to the packet this info represents */
PVOID pPacket;
} VBOXNETFLT_PACKET_INFO, *PVBOXNETFLT_PACKET_INFO;
/* paranoid check to make sure the elements in the packet info array are properly aligned */
AssertCompile((sizeof(VBOXNETFLT_PACKET_INFO) & (sizeof(PVOID) - 1)) == 0);
/** represents the packet queue */
typedef LIST_ENTRY PVBOXNETFLT_ACKET_QUEUE, *PVBOXNETFLT_PACKET_QUEUE;
/*
* we are using non-interlocked versions of LIST_ENTRY-related operations macros and synchronize
* access to the queue and its elements by acquiring/releasing a spinlock using Ndis[Acquire,Release]Spinlock
*
* we are NOT using interlocked versions of insert/remove head/tail list functions because we need to iterate though
* the queue elements as well as remove elements from the midle of the queue
*
* * @todo: it seems that we can switch to using interlocked versions of list-entry functions
* since we have removed all functionality (mentioned above, i.e. queue elements iteration, etc.) that might prevent us from doing this
*/
typedef struct VBOXNETFLT_INTERLOCKED_PACKET_QUEUE
{
/** queue */
PVBOXNETFLT_ACKET_QUEUE Queue;
/** queue lock */
NDIS_SPIN_LOCK Lock;
} VBOXNETFLT_INTERLOCKED_PACKET_QUEUE, *PVBOXNETFLT_INTERLOCKED_PACKET_QUEUE;
typedef struct VBOXNETFLT_SINGLE_LIST
{
/** queue */
SINGLE_LIST_ENTRY Head;
/** pointer to the list tail. used to enqueue elements to the tail of the list */
PSINGLE_LIST_ENTRY pTail;
} VBOXNETFLT_SINGLE_LIST, *PVBOXNETFLT_SINGLE_LIST;
typedef struct VBOXNETFLT_INTERLOCKED_SINGLE_LIST
{
/** queue */
VBOXNETFLT_SINGLE_LIST List;
/** queue lock */
NDIS_SPIN_LOCK Lock;
} VBOXNETFLT_INTERLOCKED_SINGLE_LIST, *PVBOXNETFLT_INTERLOCKED_SINGLE_LIST;
/** packet info pool contains free packet info elements to be used for the packet queue
* we are using the pool mechanism to allocate packet queue elements
* the pool mechanism is pretty simple now, we are allocating a bunch of memory
* for maintaining VBOXNETFLT_PACKET_INFO_POOL_SIZE queue elements and just returning null when the pool is exhausted
* This mechanism seems to be enough for now since we are using VBOXNETFLT_PACKET_INFO_POOL_SIZE = 0xffff which is
* the maximum size of packets the ndis packet pool supports */
typedef struct VBOXNETFLT_PACKET_INFO_POOL
{
/** free packet info queue */
VBOXNETFLT_INTERLOCKED_PACKET_QUEUE Queue;
/** memory bugger used by the pool */
PVOID pBuffer;
} VBOXNETFLT_PACKET_INFO_POOL, *PVBOXNETFLT_PACKET_INFO_POOL;
typedef enum VBOXNETDEVOPSTATE
{
kVBoxNetDevOpState_InvalidValue = 0,
kVBoxNetDevOpState_Initializing,
kVBoxNetDevOpState_Initialized,
kVBoxNetDevOpState_Deinitializing,
kVBoxNetDevOpState_Deinitialized,
} VBOXNETDEVOPSTATE;
typedef enum VBOXNETFLT_WINIFSTATE
{
/** The usual invalid state. */
kVBoxWinIfState_Invalid = 0,
/** Initialization. */
kVBoxWinIfState_Connecting,
/** Connected fuly functional state */
kVBoxWinIfState_Connected,
/** Disconnecting */
kVBoxWinIfState_Disconnecting,
/** Disconnected */
kVBoxWinIfState_Disconnected,
} VBOXNETFLT_WINIFSTATE;
/** structure used to maintain the state and reference count of the miniport and protocol */
typedef struct VBOXNETFLT_WINIF_DEVICE
{
/** initialize state */
VBOXNETDEVOPSTATE OpState;
/** ndis power state */
NDIS_DEVICE_POWER_STATE PowerState;
/** reference count */
uint32_t cReferences;
} VBOXNETFLT_WINIF_DEVICE, *PVBOXNETFLT_WINIF_DEVICE;
#define VBOXNDISREQUEST_INPROGRESS 1
#define VBOXNDISREQUEST_QUEUED 2
typedef struct VBOXNETFLTWIN_STATE
{
union
{
struct
{
UINT fRequestInfo : 2;
UINT fInterfaceClosing : 1;
UINT fStandBy : 1;
UINT fProcessingPacketFilter : 1;
UINT fPPFNetFlt : 1;
UINT fUpperProtSetFilterInitialized : 1;
UINT Reserved : 25;
};
UINT Value;
};
} VBOXNETFLTWIN_STATE, *PVBOXNETFLTWIN_STATE;
DECLINLINE(VBOXNETFLTWIN_STATE) vboxNetFltWinAtomicUoReadWinState(VBOXNETFLTWIN_STATE State)
{
UINT fValue = ASMAtomicUoReadU32((volatile uint32_t *)&State.Value);
return *((PVBOXNETFLTWIN_STATE)((void*)&fValue));
}
/* miniport layer globals */
typedef struct VBOXNETFLTGLOBALS_MP
{
/** our miniport handle */
NDIS_HANDLE hMiniport;
/** ddis wrapper handle */
NDIS_HANDLE hNdisWrapper;
} VBOXNETFLTGLOBALS_MP, *PVBOXNETFLTGLOBALS_MP;
#ifndef VBOXNETADP
/* protocol layer globals */
typedef struct VBOXNETFLTGLOBALS_PT
{
/** our protocol handle */
NDIS_HANDLE hProtocol;
} VBOXNETFLTGLOBALS_PT, *PVBOXNETFLTGLOBALS_PT;
#endif /* #ifndef VBOXNETADP */
typedef struct VBOXNETFLTGLOBALS_WIN
{
/** synch event used for device creation synchronization */
KEVENT SynchEvent;
/** Device reference count */
int cDeviceRefs;
/** ndis device */
NDIS_HANDLE hDevice;
/** device object */
PDEVICE_OBJECT pDevObj;
/* loopback flags */
/* ndis packet flags to disable packet loopback */
UINT fPacketDontLoopBack;
/* ndis packet flags specifying whether the packet is looped back */
UINT fPacketIsLoopedBack;
/* Minport info */
VBOXNETFLTGLOBALS_MP Mp;
#ifndef VBOXNETADP
/* Protocol info */
VBOXNETFLTGLOBALS_PT Pt;
#endif
} VBOXNETFLTGLOBALS_WIN, *PVBOXNETFLTGLOBALS_WIN;
extern VBOXNETFLTGLOBALS_WIN g_VBoxNetFltGlobalsWin;
/** represents filter driver device context*/
typedef struct VBOXNETFLTWIN
{
/** handle used by miniport edge for ndis calls */
NDIS_HANDLE hMiniport;
/** miniport edge state */
VBOXNETFLT_WINIF_DEVICE MpState;
/** ndis packet pool used for receives */
NDIS_HANDLE hRecvPacketPool;
/** ndis buffer pool used for receives */
NDIS_HANDLE hRecvBufferPool;
/** driver bind adapter state. */
VBOXNETFLT_WINIFSTATE enmState;
#ifndef VBOXNETADP
/* misc state flags */
VBOXNETFLTWIN_STATE StateFlags;
/** handle used by protocol edge for ndis calls */
NDIS_HANDLE hBinding;
/** protocol edge state */
VBOXNETFLT_WINIF_DEVICE PtState;
/** ndis packet pool used for receives */
NDIS_HANDLE hSendPacketPool;
/** ndis buffer pool used for receives */
NDIS_HANDLE hSendBufferPool;
/** used for maintaining the pending send packets for handling packet loopback */
VBOXNETFLT_INTERLOCKED_SINGLE_LIST SendPacketQueue;
/** used for serializing calls to the NdisRequest in the vboxNetFltWinSynchNdisRequest */
RTSEMFASTMUTEX hSynchRequestMutex;
/** event used to synchronize with the Ndis Request completion in the vboxNetFltWinSynchNdisRequest */
KEVENT hSynchCompletionEvent;
/** status of the Ndis Request initiated by the vboxNetFltWinSynchNdisRequest */
NDIS_STATUS volatile SynchCompletionStatus;
/** pointer to the Ndis Request being executed by the vboxNetFltWinSynchNdisRequest */
PNDIS_REQUEST volatile pSynchRequest;
/** open/close adapter status.
* Since ndis adapter open and close requests may complete asynchronously,
* we are using event mechanism to wait for open/close completion
* the status field is being set by the completion call-back */
NDIS_STATUS OpenCloseStatus;
/** open/close adaptor completion event */
NDIS_EVENT OpenCloseEvent;
/** medium we are attached to */
NDIS_MEDIUM enmMedium;
/**
* Passdown request info
*/
/** ndis request we pass down to the miniport below */
NDIS_REQUEST PassDownRequest;
/** Ndis pass down request bytes read or written original pointer */
PULONG pcPDRBytesRW;
/** Ndis pass down request bytes needed original pointer */
PULONG pcPDRBytesNeeded;
/** true if we should indicate the receive complete used by the ProtocolReceive mechanism.
* We need to indicate it only with the ProtocolReceive + NdisMEthIndicateReceive path.
* Note: we're using KeGetCurrentProcessorNumber, which is not entirely correct in case
* we're running on 64bit win7+, which can handle > 64 CPUs, however since KeGetCurrentProcessorNumber
* always returns the number < than the number of CPUs in the first group, we're guaranteed to have CPU index < 64
* @todo: use KeGetCurrentProcessorNumberEx for Win7+ 64 and dynamically extended array */
bool abIndicateRxComplete[64];
/** Pending transfer data packet queue (i.e. packets that were indicated as pending on NdisTransferData call */
VBOXNETFLT_INTERLOCKED_SINGLE_LIST TransferDataList;
/* mac options initialized on OID_GEN_MAC_OPTIONS */
ULONG fMacOptions;
/** our miniport devuice name */
NDIS_STRING MpDeviceName;
/** synchronize with unbind with Miniport initialization */
NDIS_EVENT MpInitCompleteEvent;
/** media connect status that we indicated */
NDIS_STATUS MpIndicatedMediaStatus;
/** media connect status pending to indicate */
NDIS_STATUS MpUnindicatedMediaStatus;
/** packet filter flags set by the upper protocols */
ULONG fUpperProtocolSetFilter;
/** packet filter flags set by the upper protocols */
ULONG fSetFilterBuffer;
/** packet filter flags set by us */
ULONG fOurSetFilter;
#else
volatile ULONG cTxSuccess;
volatile ULONG cRxSuccess;
volatile ULONG cTxError;
volatile ULONG cRxError;
#endif
} VBOXNETFLTWIN, *PVBOXNETFLTWIN;
typedef struct VBOXNETFLT_PACKET_QUEUE_WORKER
{
/** this event is used to initiate a packet queue worker thread kill */
KEVENT KillEvent;
/** this event is used to notify a worker thread that the packets are added to the queue */
KEVENT NotifyEvent;
/** pointer to the packet queue worker thread object */
PKTHREAD pThread;
/** pointer to the SG used by the packet queue for IntNet receive notifications */
PINTNETSG pSG;
/** Packet queue */
VBOXNETFLT_INTERLOCKED_PACKET_QUEUE PacketQueue;
/** Packet info pool, i.e. the pool for the packet queue elements */
VBOXNETFLT_PACKET_INFO_POOL PacketInfoPool;
} VBOXNETFLT_PACKET_QUEUE_WORKER, *PVBOXNETFLT_PACKET_QUEUE_WORKER;
/* protocol reserved data held in ndis packet */
typedef struct VBOXNETFLT_PKTRSVD_PT
{
/** original packet received from the upperlying protocol
* can be null if the packet was originated by intnet */
PNDIS_PACKET pOrigPacket;
/** pointer to the buffer to be freed on send completion
* can be null if no buffer is to be freed */
PVOID pBufToFree;
#if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
SINGLE_LIST_ENTRY ListEntry;
/* true if the packet is from IntNet */
bool bFromIntNet;
#endif
} VBOXNETFLT_PKTRSVD_PT, *PVBOXNETFLT_PKTRSVD_PT;
/** miniport reserved data held in ndis packet */
typedef struct VBOXNETFLT_PKTRSVD_MP
{
/** original packet received from the underling miniport
* can be null if the packet was originated by intnet */
PNDIS_PACKET pOrigPacket;
/** pointer to the buffer to be freed on receive completion
* can be null if no buffer is to be freed */
PVOID pBufToFree;
} VBOXNETFLT_PKTRSVD_MP, *PVBOXNETFLT_PKTRSVD_MP;
/** represents the data stored in the protocol reserved field of ndis packet on NdisTransferData processing */
typedef struct VBOXNETFLT_PKTRSVD_TRANSFERDATA_PT
{
/** next packet in a list */
SINGLE_LIST_ENTRY ListEntry;
/* packet buffer start */
PNDIS_BUFFER pOrigBuffer;
} VBOXNETFLT_PKTRSVD_TRANSFERDATA_PT, *PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT;
/* VBOXNETFLT_PKTRSVD_TRANSFERDATA_PT should fit into PROTOCOL_RESERVED_SIZE_IN_PACKET because we use protocol reserved part
* of our miniport edge on transfer data processing for honding our own info */
AssertCompile(sizeof (VBOXNETFLT_PKTRSVD_TRANSFERDATA_PT) <= PROTOCOL_RESERVED_SIZE_IN_PACKET);
/* this should fit in MiniportReserved */
AssertCompile(sizeof (VBOXNETFLT_PKTRSVD_MP) <= RT_SIZEOFMEMB(NDIS_PACKET, MiniportReserved));
/* we use RTAsmAtomic*U32 for those, make sure we're correct */
AssertCompile(sizeof (NDIS_DEVICE_POWER_STATE) == sizeof (uint32_t));
AssertCompile(sizeof (UINT) == sizeof (uint32_t));
#define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x400
#include "../../VBoxNetFltInternal.h"
#include "VBoxNetFltRt-win.h"
#ifndef VBOXNETADP
# include "VBoxNetFltP-win.h"
#endif
#include "VBoxNetFltM-win.h"
#endif /* #ifndef ___VBoxNetFltCmn_win_h___ */