Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.cpp	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.cpp	(revision 52630)
@@ -0,0 +1,748 @@
+/* $Id$ */
+/** @file
+ * VBoxNetAdp-win.cpp - NDIS6 Host-only Networking Driver, Windows-specific code.
+ */
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
+
+#include <VBox/log.h>
+#include <VBox/version.h>
+#include <VBox/err.h>
+#include <iprt/initterm.h>
+#include <iprt/assert.h>
+
+RT_C_DECLS_BEGIN
+#include <ndis.h>
+RT_C_DECLS_END
+
+#include "VBoxNetAdp-win.h"
+#include "VBoxNetCmn-win.h"
+
+/* Forward declarations */
+MINIPORT_INITIALIZE                vboxNetAdpWinInitializeEx;
+MINIPORT_HALT                      vboxNetAdpWinHaltEx;
+MINIPORT_UNLOAD                    vboxNetAdpWinUnload;
+MINIPORT_PAUSE                     vboxNetAdpWinPause;
+MINIPORT_RESTART                   vboxNetAdpWinRestart;
+MINIPORT_OID_REQUEST               vboxNetAdpWinOidRequest;
+MINIPORT_SEND_NET_BUFFER_LISTS     vboxNetAdpWinSendNetBufferLists;
+MINIPORT_RETURN_NET_BUFFER_LISTS   vboxNetAdpWinReturnNetBufferLists;
+MINIPORT_CANCEL_SEND               vboxNetAdpWinCancelSend;
+MINIPORT_CHECK_FOR_HANG            vboxNetAdpWinCheckForHangEx;
+MINIPORT_RESET                     vboxNetAdpWinResetEx;
+MINIPORT_DEVICE_PNP_EVENT_NOTIFY   vboxNetAdpWinDevicePnPEventNotify;
+MINIPORT_SHUTDOWN                  vboxNetAdpWinShutdownEx;
+MINIPORT_CANCEL_OID_REQUEST        vboxNetAdpWinCancelOidRequest;
+
+
+typedef struct _VBOXNETADPGLOBALS
+{
+    /** ndis device */
+    NDIS_HANDLE hDevice;
+    /** device object */
+    PDEVICE_OBJECT pDevObj;
+    /** our miniport driver handle */
+    NDIS_HANDLE hMiniportDriver;
+    /** power management capabilities, shared by all instances, do not change after init */
+    NDIS_PNP_CAPABILITIES PMCaps;
+} VBOXNETADPGLOBALS, *PVBOXNETADPGLOBALS;
+
+/* win-specific global data */
+VBOXNETADPGLOBALS g_VBoxNetAdpGlobals;
+
+
+typedef struct _VBOXNETADP_ADAPTER {
+    NDIS_HANDLE hAdapter;
+    PVBOXNETADPGLOBALS pGlobals;
+    RTMAC MacAddr;
+} VBOXNETADP_ADAPTER;
+typedef VBOXNETADP_ADAPTER *PVBOXNETADP_ADAPTER;
+
+
+static NTSTATUS vboxNetAdpWinDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
+{
+    PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    switch (pIrpSl->MajorFunction)
+    {
+        case IRP_MJ_DEVICE_CONTROL:
+            Status = STATUS_NOT_SUPPORTED; // TODO: add/remove ioctls
+            break;
+        case IRP_MJ_CREATE:
+        case IRP_MJ_CLEANUP:
+        case IRP_MJ_CLOSE:
+            break;
+        default:
+            Assert(0);
+            break;
+    }
+
+    pIrp->IoStatus.Status = Status;
+    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+static NDIS_STATUS vboxNetAdpWinDevCreate(PVBOXNETADPGLOBALS pGlobals)
+{
+    NDIS_STRING DevName, LinkName;
+    PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
+    NdisInitUnicodeString(&DevName, VBOXNETADP_NAME_DEVICE);
+    NdisInitUnicodeString(&LinkName, VBOXNETADP_NAME_LINK);
+
+    Assert(!pGlobals->hDevice);
+    Assert(!pGlobals->pDevObj);
+    NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
+    aMajorFunctions[IRP_MJ_CREATE] = vboxNetAdpWinDevDispatch;
+    aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetAdpWinDevDispatch;
+    aMajorFunctions[IRP_MJ_CLOSE] = vboxNetAdpWinDevDispatch;
+    aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetAdpWinDevDispatch;
+
+    NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttributes;
+    NdisZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
+    DeviceAttributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
+    DeviceAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
+    DeviceAttributes.Header.Size = sizeof(DeviceAttributes);
+    DeviceAttributes.DeviceName = &DevName;
+    DeviceAttributes.SymbolicName = &LinkName;
+    DeviceAttributes.MajorFunctions = aMajorFunctions;
+
+    NDIS_STATUS Status = NdisRegisterDeviceEx(pGlobals->hMiniportDriver,
+                                              &DeviceAttributes,
+                                              &pGlobals->pDevObj,
+                                              &pGlobals->hDevice);
+    Log(("vboxNetAdpWinDevCreate: NdisRegisterDeviceEx returned 0x%x\n", Status));
+    Assert(Status == NDIS_STATUS_SUCCESS);
+    return Status;
+}
+
+static void vboxNetAdpWinDevDestroy(PVBOXNETADPGLOBALS pGlobals)
+{
+    Assert(pGlobals->hDevice);
+    Assert(pGlobals->pDevObj);
+    NdisDeregisterDeviceEx(pGlobals->hDevice);
+    pGlobals->hDevice = NULL;
+    pGlobals->pDevObj = NULL;
+}
+
+
+
+
+
+NDIS_OID g_SupportedOids[] =
+{
+    OID_GEN_CURRENT_LOOKAHEAD,
+    OID_GEN_CURRENT_PACKET_FILTER,
+    OID_GEN_INTERRUPT_MODERATION,
+    OID_GEN_LINK_PARAMETERS,
+    OID_GEN_MAXIMUM_TOTAL_SIZE,
+    OID_GEN_RCV_OK,
+    OID_GEN_RECEIVE_BLOCK_SIZE,
+    OID_GEN_RECEIVE_BUFFER_SPACE,
+    OID_GEN_STATISTICS,
+    OID_GEN_TRANSMIT_BLOCK_SIZE,
+    OID_GEN_TRANSMIT_BUFFER_SPACE,
+    OID_GEN_VENDOR_DESCRIPTION,
+    OID_GEN_VENDOR_DRIVER_VERSION,
+    OID_GEN_VENDOR_ID,
+    OID_GEN_XMIT_OK,
+    OID_802_3_PERMANENT_ADDRESS,
+    OID_802_3_CURRENT_ADDRESS,
+    OID_802_3_MULTICAST_LIST,
+    OID_802_3_MAXIMUM_LIST_SIZE,
+    OID_PNP_CAPABILITIES,
+    OID_PNP_QUERY_POWER,
+    OID_PNP_SET_POWER
+};
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinAllocAdapter(NDIS_HANDLE hAdapter, PVBOXNETADP_ADAPTER *ppAdapter, ULONG64 NetLuid)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    PVBOXNETADP_ADAPTER pAdapter = NULL;
+
+    LogFlow(("==>"__FUNCTION__": adapter handle=%p\n", hAdapter));
+    
+    *ppAdapter = NULL;
+
+    pAdapter = (PVBOXNETADP_ADAPTER)NdisAllocateMemoryWithTagPriority(g_VBoxNetAdpGlobals.hMiniportDriver,
+                                                                         sizeof(VBOXNETADP_ADAPTER),
+                                                                         VBOXNETADPWIN_TAG,
+                                                                         NormalPoolPriority);
+    if (!pAdapter)
+    {
+        Status = NDIS_STATUS_RESOURCES;
+        Log((__FUNCTION__": Out of memory while allocating adapter context (size=%d)\n", sizeof(VBOXNETADP_ADAPTER)));
+    }
+    else
+    {
+        NdisZeroMemory(pAdapter, sizeof(VBOXNETADP_ADAPTER));
+        pAdapter->hAdapter = hAdapter;
+        pAdapter->pGlobals = &g_VBoxNetAdpGlobals;
+        // TODO: Use netadp structure instead!
+    /* Use a locally administered version of the OUI we use for the guest NICs. */
+    pAdapter->MacAddr.au8[0] = 0x08 | 2;
+    pAdapter->MacAddr.au8[1] = 0x00;
+    pAdapter->MacAddr.au8[2] = 0x27;
+
+    pAdapter->MacAddr.au8[3] = (NetLuid >> 16) & 0xFF;
+    pAdapter->MacAddr.au8[4] = (NetLuid >> 8) & 0xFF;
+    pAdapter->MacAddr.au8[5] = NetLuid & 0xFF;
+
+        //TODO: Statistics?
+
+        *ppAdapter = pAdapter;
+    }
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(void) vboxNetAdpWinFreeAdapter(PVBOXNETADP_ADAPTER pAdapter)
+{
+    NdisFreeMemory(pAdapter, 0, 0);
+}
+
+DECLINLINE(NDIS_MEDIA_CONNECT_STATE) vboxNetAdpWinGetConnectState(PVBOXNETADP_ADAPTER pAdapter)
+{
+    return MediaConnectStateConnected;
+}
+
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinInitializeEx(IN NDIS_HANDLE NdisMiniportHandle,
+                                                  IN NDIS_HANDLE MiniportDriverContext,
+                                                  IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)
+{
+    PVBOXNETADP_ADAPTER pAdapter = NULL;
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+    LogFlow(("==>"__FUNCTION__": miniport=0x%x\n", NdisMiniportHandle));
+
+    do
+    {
+        NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RAttrs = {0};
+        NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GAttrs = {0};
+
+        Status = vboxNetAdpWinAllocAdapter(NdisMiniportHandle, &pAdapter, MiniportInitParameters->NetLuid.Value);
+        if (Status != NDIS_STATUS_SUCCESS)
+        {
+            Log((__FUNCTION__": Failed to allocate the adapter context with 0x%x\n", Status));
+            break;
+        }
+    
+        RAttrs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+        RAttrs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+        RAttrs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+        RAttrs.MiniportAdapterContext = pAdapter;
+        RAttrs.AttributeFlags = VBOXNETADPWIN_ATTR_FLAGS; // NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM
+        RAttrs.CheckForHangTimeInSeconds = VBOXNETADPWIN_HANG_CHECK_TIME; //TODO 4
+        RAttrs.InterfaceType = NdisInterfaceInternal;
+
+        Status = NdisMSetMiniportAttributes(NdisMiniportHandle,
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RAttrs);
+        if (Status != NDIS_STATUS_SUCCESS)
+        {
+            Log((__FUNCTION__": NdisMSetMiniportAttributes(registration) failed with 0x%x\n", Status));
+            break;
+        }
+
+        // TODO: Registry?
+
+        // TODO: WDM stack?
+
+        // TODO: DPC?
+
+        GAttrs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+        GAttrs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+        GAttrs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+
+        GAttrs.MediaType = NdisMedium802_3;
+        GAttrs.PhysicalMediumType = NdisPhysicalMediumUnspecified;
+        GAttrs.MtuSize = 1500; //TODO
+        GAttrs.MaxXmitLinkSpeed = 1000000000ULL;
+        GAttrs.XmitLinkSpeed = 1000000000ULL;
+        GAttrs.MaxRcvLinkSpeed = 1000000000ULL;
+        GAttrs.RcvLinkSpeed = 1000000000ULL;
+        GAttrs.MediaConnectState = vboxNetAdpWinGetConnectState(pAdapter);
+        GAttrs.MediaDuplexState = MediaDuplexStateFull;
+        GAttrs.LookaheadSize = 1500; //TODO
+        GAttrs.MacOptions = VBOXNETADP_MAC_OPTIONS;
+        GAttrs.SupportedPacketFilters = VBOXNETADP_SUPPORTED_FILTERS;
+        GAttrs.MaxMulticastListSize = 32; //TODO
+
+        GAttrs.MacAddressLength = ETH_LENGTH_OF_ADDRESS;
+        Assert(GAttrs.MacAddressLength == sizeof(pAdapter->MacAddr));
+        memcpy(GAttrs.PermanentMacAddress, pAdapter->MacAddr.au8, GAttrs.MacAddressLength);
+        memcpy(GAttrs.CurrentMacAddress, pAdapter->MacAddr.au8, GAttrs.MacAddressLength);
+
+        GAttrs.RecvScaleCapabilities = NULL;
+        GAttrs.AccessType = NET_IF_ACCESS_BROADCAST;
+        GAttrs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
+        GAttrs.ConnectionType = NET_IF_CONNECTION_DEDICATED;
+        GAttrs.IfType = IF_TYPE_ETHERNET_CSMACD;
+        GAttrs.IfConnectorPresent = false;
+        GAttrs.SupportedStatistics = VBOXNETADPWIN_SUPPORTED_STATISTICS;
+        GAttrs.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
+        GAttrs.DataBackFillSize = 0;
+        GAttrs.ContextBackFillSize = 0;
+        GAttrs.SupportedOidList = g_SupportedOids;
+        GAttrs.SupportedOidListLength = sizeof(g_SupportedOids);
+        GAttrs.AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
+        GAttrs.PowerManagementCapabilities = &g_VBoxNetAdpGlobals.PMCaps;
+
+        Status = NdisMSetMiniportAttributes(NdisMiniportHandle,
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GAttrs);
+        if (Status != NDIS_STATUS_SUCCESS)
+        {
+            Log((__FUNCTION__": NdisMSetMiniportAttributes(general) failed with 0x%x\n", Status));
+            break;
+        }
+    } while (false);
+
+    if (Status != NDIS_STATUS_SUCCESS)
+    {
+        if (pAdapter)
+            vboxNetAdpWinFreeAdapter(pAdapter);
+    }
+
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinHaltEx(IN NDIS_HANDLE MiniportAdapterContext,
+                                     IN NDIS_HALT_ACTION HaltAction)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    // TODO: Stop something?
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinPause(IN NDIS_HANDLE MiniportAdapterContext,
+                                           IN PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinRestart(IN NDIS_HANDLE MiniportAdapterContext,
+                                             IN PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqQuery(PVBOXNETADP_ADAPTER pAdapter,
+                                                PNDIS_OID_REQUEST pRequest)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    struct _NDIS_OID_REQUEST::_REQUEST_DATA::_QUERY *pQuery = &pRequest->DATA.QUERY_INFORMATION;
+
+    LogFlow(("==>"__FUNCTION__"\n"));
+
+    uint64_t u64Tmp = 0;
+    ULONG ulTmp = 0;
+    PVOID pInfo = &ulTmp;
+    ULONG cbInfo = sizeof(ulTmp);
+
+    switch (pQuery->Oid)
+    {
+        case OID_GEN_INTERRUPT_MODERATION:
+        {
+            PNDIS_INTERRUPT_MODERATION_PARAMETERS pParams =
+                (PNDIS_INTERRUPT_MODERATION_PARAMETERS)pQuery->InformationBuffer;
+            cbInfo = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+            if (cbInfo > pQuery->InformationBufferLength)
+                break;
+            pParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; 
+            pParams->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+            pParams->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+            pParams->Flags = 0;
+            pParams->InterruptModeration = NdisInterruptModerationNotSupported;
+            pInfo = NULL; /* Do not copy */
+            break;
+        }
+        case OID_GEN_MAXIMUM_TOTAL_SIZE:
+        case OID_GEN_RECEIVE_BLOCK_SIZE:
+        case OID_GEN_TRANSMIT_BLOCK_SIZE:
+            ulTmp = VBOXNETADP_MAX_FRAME_SIZE;
+            break;
+        case OID_GEN_RCV_OK:
+        case OID_GEN_XMIT_OK:
+            u64Tmp = 0;
+            pInfo = &u64Tmp;
+            cbInfo = sizeof(u64Tmp);
+            break;
+        case OID_GEN_RECEIVE_BUFFER_SPACE:
+        case OID_GEN_TRANSMIT_BUFFER_SPACE:
+            // TODO: Make configurable
+            ulTmp = VBOXNETADP_MAX_FRAME_SIZE * 40;
+            break;
+        case OID_GEN_STATISTICS:
+        {
+            PNDIS_STATISTICS_INFO pStats =
+                (PNDIS_STATISTICS_INFO)pQuery->InformationBuffer;
+            cbInfo = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
+            if (cbInfo > pQuery->InformationBufferLength)
+                break;
+            pInfo = NULL; /* Do not copy */
+            memset(pStats, 0, cbInfo);
+            pStats->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; 
+            pStats->Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
+            pStats->Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
+            // TODO: We need some stats, don't we?
+            break;
+        }
+        case OID_GEN_VENDOR_DESCRIPTION:
+            pInfo = "Oracle";
+            cbInfo = sizeof("Oracle"); //TODO
+            break;
+        case OID_GEN_VENDOR_DRIVER_VERSION:
+            ulTmp = (VBOXNETADP_VERSION_NDIS_MAJOR << 16) | VBOXNETADP_VERSION_NDIS_MINOR;
+            break;
+        case OID_GEN_VENDOR_ID:
+            ulTmp = VBOXNETADP_VENDOR_ID;
+            break;
+        case OID_802_3_PERMANENT_ADDRESS:
+        case OID_802_3_CURRENT_ADDRESS:
+            pInfo = &pAdapter->MacAddr;
+            cbInfo = sizeof(pAdapter->MacAddr);
+            break;
+            //case OID_802_3_MULTICAST_LIST:
+        case OID_802_3_MAXIMUM_LIST_SIZE:
+            ulTmp = VBOXNETADP_MCAST_LIST_SIZE;
+            break;
+        case OID_PNP_CAPABILITIES:
+            pInfo = &pAdapter->pGlobals->PMCaps;
+            cbInfo = sizeof(pAdapter->pGlobals->PMCaps);
+            break;
+        case OID_PNP_QUERY_POWER:
+            pInfo = NULL; /* Do not copy */
+            cbInfo = 0;
+            break;
+        default:
+            Status = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    }
+
+    if (Status == NDIS_STATUS_SUCCESS)
+    {
+        if (cbInfo > pQuery->InformationBufferLength)
+        {
+            pQuery->BytesNeeded = cbInfo;
+            Status = NDIS_STATUS_BUFFER_TOO_SHORT;
+        }
+        else
+        {
+            if (pInfo)
+                NdisMoveMemory(pQuery->InformationBuffer, pInfo, cbInfo);
+            pQuery->BytesWritten = cbInfo;
+        }
+    }
+
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqSet(PVBOXNETADP_ADAPTER pAdapter,
+                                              PNDIS_OID_REQUEST pRequest)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    struct _NDIS_OID_REQUEST::_REQUEST_DATA::_SET *pSet = &pRequest->DATA.SET_INFORMATION;
+
+    LogFlow(("==>"__FUNCTION__"\n"));
+
+    switch (pSet->Oid)
+    {
+        case OID_GEN_CURRENT_LOOKAHEAD:
+            if (pSet->InformationBufferLength != sizeof(ULONG))
+            {
+                pSet->BytesNeeded = sizeof(ULONG);
+                Status = NDIS_STATUS_INVALID_LENGTH;
+                break;
+            }
+            // TODO: For the time being we simply ignore lookahead settings.
+            pSet->BytesRead = sizeof(ULONG);
+            Status = NDIS_STATUS_SUCCESS;
+            break;
+
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            if (pSet->InformationBufferLength != sizeof(ULONG))
+            {
+                pSet->BytesNeeded = sizeof(ULONG);
+                Status = NDIS_STATUS_INVALID_LENGTH;
+                break;
+            }
+            // TODO: For the time being we simply ignore packet filter settings.
+            pSet->BytesRead = pSet->InformationBufferLength;
+            Status = NDIS_STATUS_SUCCESS;
+            break;
+
+        case OID_GEN_INTERRUPT_MODERATION:
+            pSet->BytesNeeded = 0;
+            pSet->BytesRead = 0;
+            Status = NDIS_STATUS_INVALID_DATA;
+            break;
+
+        case OID_PNP_SET_POWER:
+            if (pSet->InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
+            {
+                Status = NDIS_STATUS_INVALID_LENGTH;
+                break;
+            }
+            pSet->BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
+            Status = NDIS_STATUS_SUCCESS;
+            break;
+            
+        default:
+            Status = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    }
+
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRequest(IN NDIS_HANDLE MiniportAdapterContext,
+                                                IN PNDIS_OID_REQUEST NdisRequest)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    vboxNetCmnWinDumpOidRequest(__FUNCTION__, NdisRequest);
+
+    switch (NdisRequest->RequestType)
+    {
+#if 0
+        case NdisRequestMethod:
+            Status = vboxNetAdpWinOidRqMethod(pAdapter, NdisRequest);
+            break;
+#endif
+
+        case NdisRequestSetInformation:
+            Status = vboxNetAdpWinOidRqSet(pAdapter, NdisRequest);
+            break;
+
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            Status = vboxNetAdpWinOidRqQuery(pAdapter, NdisRequest);
+            break;
+
+        default:
+            Status = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    }
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinSendNetBufferLists(IN NDIS_HANDLE MiniportAdapterContext,
+                                                 IN PNET_BUFFER_LIST NetBufferLists,
+                                                 IN NDIS_PORT_NUMBER PortNumber,
+                                                 IN ULONG SendFlags)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    PNET_BUFFER_LIST pNbl = NetBufferLists;
+    for (pNbl = NetBufferLists; pNbl; pNbl = NET_BUFFER_LIST_NEXT_NBL(pNbl))
+        NET_BUFFER_LIST_STATUS(pNbl) = NDIS_STATUS_SUCCESS;
+    NdisMSendNetBufferListsComplete(pAdapter->hAdapter, NetBufferLists,
+                                    (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL) ?
+                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinReturnNetBufferLists(IN NDIS_HANDLE MiniportAdapterContext,
+                                                   IN PNET_BUFFER_LIST NetBufferLists,
+                                                   IN ULONG ReturnFlags)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    Log((__FUNCTION__": We should not be here!\n"));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinCancelSend(IN NDIS_HANDLE MiniportAdapterContext,
+                                         IN PVOID CancelId)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    Log((__FUNCTION__": We should not be here!\n"));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+
+DECLHIDDEN(BOOLEAN) vboxNetAdpWinCheckForHangEx(IN NDIS_HANDLE MiniportAdapterContext)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    LogFlow(("<=="__FUNCTION__" return false\n"));
+    return FALSE;
+}
+
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinResetEx(IN NDIS_HANDLE MiniportAdapterContext,
+                                             OUT PBOOLEAN AddressingReset)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinDevicePnPEventNotify(IN NDIS_HANDLE MiniportAdapterContext,
+                                                   IN PNET_DEVICE_PNP_EVENT NetDevicePnPEvent)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    Log((__FUNCTION__": PnP event=%d\n", NetDevicePnPEvent->DevicePnPEvent));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+
+DECLHIDDEN(VOID) vboxNetAdpWinShutdownEx(IN NDIS_HANDLE MiniportAdapterContext,
+                                         IN NDIS_SHUTDOWN_ACTION ShutdownAction)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    Log((__FUNCTION__": action=%d\n", ShutdownAction));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+DECLHIDDEN(VOID) vboxNetAdpWinCancelOidRequest(IN NDIS_HANDLE MiniportAdapterContext,
+                                               IN PVOID RequestId)
+{
+    PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
+    LogFlow(("==>"__FUNCTION__"\n"));
+    Log((__FUNCTION__": req id=%p\n", RequestId));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+
+
+DECLHIDDEN(VOID) vboxNetAdpWinUnload(IN PDRIVER_OBJECT DriverObject)
+{
+    LogFlow(("==>"__FUNCTION__"\n"));
+    //vboxNetAdpWinDevDestroy(&g_VBoxNetAdpGlobals);
+    if (g_VBoxNetAdpGlobals.hMiniportDriver)
+        NdisMDeregisterMiniportDriver(g_VBoxNetAdpGlobals.hMiniportDriver);
+    //NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
+    LogFlow(("<=="__FUNCTION__"\n"));
+    RTR0Term();
+}
+
+
+/**
+ * register the miniport driver
+ */
+DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinRegister(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPathStr)
+{
+    NDIS_MINIPORT_DRIVER_CHARACTERISTICS MChars;
+
+    NdisZeroMemory(&MChars, sizeof (MChars));
+
+    MChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
+    MChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
+    MChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
+
+    MChars.MajorNdisVersion = VBOXNETADP_VERSION_NDIS_MAJOR;
+    MChars.MinorNdisVersion = VBOXNETADP_VERSION_NDIS_MINOR;
+
+    MChars.MajorDriverVersion = VBOXNETADP_VERSION_MAJOR;
+    MChars.MinorDriverVersion = VBOXNETADP_VERSION_MINOR;
+
+    MChars.InitializeHandlerEx         = vboxNetAdpWinInitializeEx;
+    MChars.HaltHandlerEx               = vboxNetAdpWinHaltEx;
+    MChars.UnloadHandler               = vboxNetAdpWinUnload;
+    MChars.PauseHandler                = vboxNetAdpWinPause;
+    MChars.RestartHandler              = vboxNetAdpWinRestart;
+    MChars.OidRequestHandler           = vboxNetAdpWinOidRequest;
+    MChars.SendNetBufferListsHandler   = vboxNetAdpWinSendNetBufferLists;
+    MChars.ReturnNetBufferListsHandler = vboxNetAdpWinReturnNetBufferLists;
+    MChars.CancelSendHandler           = vboxNetAdpWinCancelSend;
+    MChars.CheckForHangHandlerEx       = vboxNetAdpWinCheckForHangEx;
+    MChars.ResetHandlerEx              = vboxNetAdpWinResetEx;
+    MChars.DevicePnPEventNotifyHandler = vboxNetAdpWinDevicePnPEventNotify;
+    MChars.ShutdownHandlerEx           = vboxNetAdpWinShutdownEx;
+    MChars.CancelOidRequestHandler     = vboxNetAdpWinCancelOidRequest;
+
+    NDIS_STATUS Status;
+    g_VBoxNetAdpGlobals.hMiniportDriver = NULL;
+    Log(("vboxNetAdpWinRegister: registering miniport driver...\n"));
+    Status = NdisMRegisterMiniportDriver(pDriverObject,
+                                         pRegistryPathStr,
+                                         (NDIS_HANDLE)&g_VBoxNetAdpGlobals,
+                                         &MChars,
+                                         &g_VBoxNetAdpGlobals.hMiniportDriver);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Log(("vboxNetAdpWinRegister: successfully registered miniport driver; registering device...\n"));
+        //Status = vboxNetAdpWinDevCreate(&g_VBoxNetAdpGlobals);
+        //Assert(Status == STATUS_SUCCESS);
+        //Log(("vboxNetAdpWinRegister: vboxNetAdpWinDevCreate() returned 0x%x\n", Status));
+    }
+    else
+    {
+        Log(("ERROR! vboxNetAdpWinRegister: failed to register miniport driver, status=0x%x", Status));
+    }
+    return Status;
+}
+
+
+RT_C_DECLS_BEGIN
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath);
+
+RT_C_DECLS_END
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    int rc;
+
+
+    rc = RTR0Init(0);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        NdisZeroMemory(&g_VBoxNetAdpGlobals, sizeof (g_VBoxNetAdpGlobals));
+        //NdisAllocateSpinLock(&g_VBoxNetAdpGlobals.Lock);
+        //g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
+        g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
+        g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
+
+        Status = vboxNetAdpWinRegister(pDriverObject, pRegistryPath);
+        Assert(Status == STATUS_SUCCESS);
+        if (Status == NDIS_STATUS_SUCCESS)
+        {
+            Log(("NETADP: started successfully\n"));
+            return STATUS_SUCCESS;
+        }
+        //NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
+        RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+        RTLogDestroy(RTLogSetDefaultInstance(NULL));
+
+        RTR0Term();
+    }
+    else
+    {
+        Status = NDIS_STATUS_FAILURE;
+    }
+
+    return Status;
+}
+
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.h	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.h	(revision 52630)
@@ -0,0 +1,47 @@
+/* $Id$ */
+/** @file
+ * VBoxNetAdp-win.h - Host-only Miniport Driver, Windows-specific code.
+ */
+/*
+ * Copyright (C) 2014 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 ___VBoxNetAdp_win_h___
+#define ___VBoxNetAdp_win_h___
+
+#define VBOXNETADP_VERSION_NDIS_MAJOR        6
+#define VBOXNETADP_VERSION_NDIS_MINOR        0
+
+#define VBOXNETADP_VERSION_MAJOR             1
+#define VBOXNETADP_VERSION_MINOR             0
+
+#define VBOXNETADP_VENDOR_ID                 0xFFFFFF
+#define VBOXNETADP_MCAST_LIST_SIZE           32
+#define VBOXNETADP_MAX_FRAME_SIZE            1518 // TODO: 14+4+1500
+
+//#define VBOXNETADP_NAME_UNIQUE               L"{7af6b074-048d-4444-bfce-1ecc8bc5cb76}"
+#define VBOXNETADP_NAME_SERVICE              L"VBoxNetAdp"
+
+#define VBOXNETADP_NAME_LINK                 L"\\DosDevices\\Global\\VBoxNetAdp"
+#define VBOXNETADP_NAME_DEVICE               L"\\Device\\VBoxNetAdp"
+
+#define VBOXNETADPWIN_TAG                    'ANBV'
+
+#define VBOXNETADPWIN_ATTR_FLAGS             NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM
+#define VBOXNETADP_MAC_OPTIONS               NDIS_MAC_OPTION_NO_LOOPBACK
+#define VBOXNETADP_SUPPORTED_FILTERS         (NDIS_PACKET_TYPE_DIRECTED | \
+                                              NDIS_PACKET_TYPE_MULTICAST | \
+                                              NDIS_PACKET_TYPE_BROADCAST | \
+                                              NDIS_PACKET_TYPE_PROMISCUOUS | \
+                                              NDIS_PACKET_TYPE_ALL_MULTICAST)
+#define VBOXNETADPWIN_SUPPORTED_STATISTICS   0 //TODO!
+#define VBOXNETADPWIN_HANG_CHECK_TIME        4
+
+#endif /* #ifndef ___VBoxNetAdp_win_h___ */
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.rc
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.rc	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp-win.rc	(revision 52630)
@@ -0,0 +1,52 @@
+/* $Id$ */
+/** @file
+ * VBoxNetFlt - Resource file containing version info and icon.
+ */
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+#define DESCRIPTION_STR    "VirtualBox NDIS 6.0 Host-Only Network Adapter Driver\0"
+#define FILENAME_STR       "VBoxNetAdp6.sys\0"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+   FILEVERSION          VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   PRODUCTVERSION       VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   FILEFLAGSMASK        VS_FFI_FILEFLAGSMASK
+   FILEFLAGS            0x0L
+   FILEOS               VOS_NT_WINDOWS32
+   FILETYPE             VFT_DRV
+   FILESUBTYPE          VFT2_DRV_NETWORK
+BEGIN
+   BLOCK "StringFileInfo"
+   BEGIN
+      BLOCK "040904b0"
+      BEGIN
+         VALUE "CompanyName",      VBOX_RC_COMPANY_NAME
+         VALUE "FileDescription",  DESCRIPTION_STR
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     FILENAME_STR
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", FILENAME_STR
+         VALUE "ProductName",      VBOX_PRODUCT "\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp6.inf
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp6.inf	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetAdp6.inf	(revision 52630)
@@ -0,0 +1,89 @@
+; $Id$
+; @file
+; VBoxNetAdp6.inf - VirtualBox NDIS6 Miniport Driver inf file
+;
+; Note: We use the same component id as the old NetAdp implementation ?
+;
+;
+; Copyright (C) 2014 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.
+;
+
+[Version]
+Signature   = "$Windows NT$"
+CatalogFile = VBoxNetAdp6.cat
+Class       = Net
+ClassGUID   = {4D36E972-E325-11CE-BFC1-08002BE10318}
+Provider    = %Provider%
+DriverVer   = 07/18/2014,1.0.1.0
+
+
+[Manufacturer]
+%Provider% = VBox,NTx86,NTamd64
+
+[ControlFlags]
+
+[VBox]
+%VBoxNetAdp6_Desc% = VBoxNetAdp6.ndi, sun_VBoxNetAdp6
+
+[VBox.NTx86]
+%VBoxNetAdp6_Desc% = VBoxNetAdp6.ndi, sun_VBoxNetAdp6
+
+[VBox.NTamd64]
+%VBoxNetAdp6_Desc% = VBoxNetAdp6.ndi, sun_VBoxNetAdp6
+
+[VBoxNetAdp6.ndi]
+AddReg             = VBoxNetAdp6.ndi.AddReg
+Characteristics    = 0x1 ; NCF_VIRTUAL
+*IfType            = 0x6 ; IF_TYPE_ETHERNET_CSMACD
+*MediaType         = 0x0 ; NdisMedium802_3
+*PhysicalMediaType = 14  ; NdisPhysicalMedium802_3
+CopyFiles          = VBoxNetAdp6.Files.Sys
+
+[VBoxNetAdp6.ndi.Remove.Services]
+DelService       = VBoxNetAdp,0x200 ; Stop the service before uninstalling
+
+[VBoxNetAdp6.ndi.Services]
+AddService = VBoxNetAdp, 2, VBoxNetAdp6.AddService
+
+[VBoxNetAdp6.AddService]
+DisplayName    = %VBoxNetAdp6Service_Desc%
+ServiceType    = 1 ;SERVICE_KERNEL_DRIVER
+StartType      = 1 ;SERVICE_SYSTEM_START
+ErrorControl   = 1 ;SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\VBoxNetAdp6.sys
+LoadOrderGroup = NDIS
+
+[SourceDisksNames]
+1=%DiskDescription%,"",,
+
+[SourceDisksFiles]
+VBoxNetAdp6.sys=1
+
+[DestinationDirs]
+DefaultDestDir = 12
+VBoxNetAdp6.Files.Sys   = 12   ; %windir%\System32\drivers
+
+[VBoxNetAdp6.Files.Sys]
+VBoxNetAdp6.sys,,,2
+
+[VBoxNetAdp6.ndi.AddReg]
+HKR,    ,            BusNumber,  0, "0"
+HKR, Ndi,            Service,    0, VBoxNetAdp
+HKR, Ndi,            HelpText,    , %VBoxNetAdp6_HELP%
+HKR, Ndi\Interfaces, UpperRange, 0, ndis5
+HKR, Ndi\Interfaces, LowerRange, 0, ethernet
+
+[Strings]
+Provider = "Oracle Corporation"
+DiskDescription = "VirtualBox NDIS 6.0 Miniport Driver"
+VBoxNetAdp6_Desc = "VirtualBox Host-Only Ethernet Adapter"
+VBoxNetAdp6_HELP = "VirtualBox NDIS 6.0 Miniport Driver"
+VBoxNetAdp6Service_Desc = "VirtualBox NDIS 6.0 Miniport Service"
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetCmn-win.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetCmn-win.h	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetCmn-win.h	(revision 52630)
@@ -0,0 +1,127 @@
+/* $Id$ */
+/** @file
+ * VBoxNetCmn-win.h - NDIS6 Networking Driver Common Definitions, Windows-specific code.
+ */
+/*
+ * Copyright (C) 2014 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.
+ */
+
+DECLHIDDEN(void) vboxNetCmnWinDumpOidRequest(const char *pcszFunction, PNDIS_OID_REQUEST pRequest)
+{
+    char *pszType = "unknown";
+    char *pszOid  = "unknown";
+
+    switch (pRequest->RequestType)
+    {
+        case NdisRequestSetInformation: pszType = "set"; break;
+        case NdisRequestMethod: pszType = "method"; break;
+        case NdisRequestQueryInformation: pszType = "query info"; break;
+        case NdisRequestQueryStatistics: pszType = "query stats"; break;
+    }
+    switch (pRequest->DATA.SET_INFORMATION.Oid)
+    {
+        case OID_GEN_MAX_LINK_SPEED: pszOid = "OID_GEN_MAX_LINK_SPEED"; break;
+        case OID_GEN_LINK_STATE: pszOid = "OID_GEN_LINK_STATE"; break;
+        case OID_GEN_LINK_PARAMETERS: pszOid = "OID_GEN_LINK_PARAMETERS"; break;
+        case OID_GEN_MINIPORT_RESTART_ATTRIBUTES: pszOid = "OID_GEN_MINIPORT_RESTART_ATTRIBUTES"; break;
+        case OID_GEN_ENUMERATE_PORTS: pszOid = "OID_GEN_ENUMERATE_PORTS"; break;
+        case OID_GEN_PORT_STATE: pszOid = "OID_GEN_PORT_STATE"; break;
+        case OID_GEN_PORT_AUTHENTICATION_PARAMETERS: pszOid = "OID_GEN_PORT_AUTHENTICATION_PARAMETERS"; break;
+        case OID_GEN_INTERRUPT_MODERATION: pszOid = "OID_GEN_INTERRUPT_MODERATION"; break;
+        case OID_GEN_PHYSICAL_MEDIUM_EX: pszOid = "OID_GEN_PHYSICAL_MEDIUM_EX"; break;
+        case OID_GEN_SUPPORTED_LIST: pszOid = "OID_GEN_SUPPORTED_LIST"; break;
+        case OID_GEN_HARDWARE_STATUS: pszOid = "OID_GEN_HARDWARE_STATUS"; break;
+        case OID_GEN_MEDIA_SUPPORTED: pszOid = "OID_GEN_MEDIA_SUPPORTED"; break;
+        case OID_GEN_MEDIA_IN_USE: pszOid = "OID_GEN_MEDIA_IN_USE"; break;
+        case OID_GEN_MAXIMUM_LOOKAHEAD: pszOid = "OID_GEN_MAXIMUM_LOOKAHEAD"; break;
+        case OID_GEN_MAXIMUM_FRAME_SIZE: pszOid = "OID_GEN_MAXIMUM_FRAME_SIZE"; break;
+        case OID_GEN_LINK_SPEED: pszOid = "OID_GEN_LINK_SPEED"; break;
+        case OID_GEN_TRANSMIT_BUFFER_SPACE: pszOid = "OID_GEN_TRANSMIT_BUFFER_SPACE"; break;
+        case OID_GEN_RECEIVE_BUFFER_SPACE: pszOid = "OID_GEN_RECEIVE_BUFFER_SPACE"; break;
+        case OID_GEN_TRANSMIT_BLOCK_SIZE: pszOid = "OID_GEN_TRANSMIT_BLOCK_SIZE"; break;
+        case OID_GEN_RECEIVE_BLOCK_SIZE: pszOid = "OID_GEN_RECEIVE_BLOCK_SIZE"; break;
+        case OID_GEN_VENDOR_ID: pszOid = "OID_GEN_VENDOR_ID"; break;
+        case OID_GEN_VENDOR_DESCRIPTION: pszOid = "OID_GEN_VENDOR_DESCRIPTION"; break;
+        case OID_GEN_VENDOR_DRIVER_VERSION: pszOid = "OID_GEN_VENDOR_DRIVER_VERSION"; break;
+        case OID_GEN_CURRENT_PACKET_FILTER: pszOid = "OID_GEN_CURRENT_PACKET_FILTER"; break;
+        case OID_GEN_CURRENT_LOOKAHEAD: pszOid = "OID_GEN_CURRENT_LOOKAHEAD"; break;
+        case OID_GEN_DRIVER_VERSION: pszOid = "OID_GEN_DRIVER_VERSION"; break;
+        case OID_GEN_MAXIMUM_TOTAL_SIZE: pszOid = "OID_GEN_MAXIMUM_TOTAL_SIZE"; break;
+        case OID_GEN_PROTOCOL_OPTIONS: pszOid = "OID_GEN_PROTOCOL_OPTIONS"; break;
+        case OID_GEN_MAC_OPTIONS: pszOid = "OID_GEN_MAC_OPTIONS"; break;
+        case OID_GEN_MEDIA_CONNECT_STATUS: pszOid = "OID_GEN_MEDIA_CONNECT_STATUS"; break;
+        case OID_GEN_MAXIMUM_SEND_PACKETS: pszOid = "OID_GEN_MAXIMUM_SEND_PACKETS"; break;
+        case OID_GEN_SUPPORTED_GUIDS: pszOid = "OID_GEN_SUPPORTED_GUIDS"; break;
+        case OID_GEN_NETWORK_LAYER_ADDRESSES: pszOid = "OID_GEN_NETWORK_LAYER_ADDRESSES"; break;
+        case OID_GEN_TRANSPORT_HEADER_OFFSET: pszOid = "OID_GEN_TRANSPORT_HEADER_OFFSET"; break;
+        case OID_GEN_PHYSICAL_MEDIUM: pszOid = "OID_GEN_PHYSICAL_MEDIUM"; break;
+        case OID_GEN_MACHINE_NAME: pszOid = "OID_GEN_MACHINE_NAME"; break;
+        case OID_GEN_VLAN_ID: pszOid = "OID_GEN_VLAN_ID"; break;
+        case OID_GEN_RNDIS_CONFIG_PARAMETER: pszOid = "OID_GEN_RNDIS_CONFIG_PARAMETER"; break;
+        case OID_GEN_NDIS_RESERVED_1: pszOid = "OID_GEN_NDIS_RESERVED_1"; break;
+        case OID_GEN_NDIS_RESERVED_2: pszOid = "OID_GEN_NDIS_RESERVED_2"; break;
+        case OID_GEN_NDIS_RESERVED_5: pszOid = "OID_GEN_NDIS_RESERVED_5"; break;
+        case OID_GEN_MEDIA_CAPABILITIES: pszOid = "OID_GEN_MEDIA_CAPABILITIES"; break;
+        case OID_GEN_DEVICE_PROFILE: pszOid = "OID_GEN_DEVICE_PROFILE"; break;
+        case OID_GEN_FRIENDLY_NAME: pszOid = "OID_GEN_FRIENDLY_NAME"; break;
+        case OID_802_3_ADD_MULTICAST_ADDRESS: pszOid = "OID_802_3_ADD_MULTICAST_ADDRESS"; break;
+        case OID_802_3_DELETE_MULTICAST_ADDRESS: pszOid = "OID_802_3_DELETE_MULTICAST_ADDRESS"; break;
+        case OID_802_3_PERMANENT_ADDRESS: pszOid = "OID_802_3_PERMANENT_ADDRESS"; break;
+        case OID_802_3_CURRENT_ADDRESS: pszOid = "OID_802_3_CURRENT_ADDRESS"; break;
+        case OID_802_3_MULTICAST_LIST: pszOid = "OID_802_3_MULTICAST_LIST"; break;
+        case OID_802_3_MAXIMUM_LIST_SIZE: pszOid = "OID_802_3_MAXIMUM_LIST_SIZE"; break;
+        case OID_802_3_MAC_OPTIONS: pszOid = "OID_802_3_MAC_OPTIONS"; break;
+        case OID_TCP_TASK_OFFLOAD: pszOid = "OID_TCP_TASK_OFFLOAD"; break;
+        case OID_TCP_TASK_IPSEC_ADD_SA: pszOid = "OID_TCP_TASK_IPSEC_ADD_SA"; break;
+        case OID_TCP_TASK_IPSEC_ADD_UDPESP_SA: pszOid = "OID_TCP_TASK_IPSEC_ADD_UDPESP_SA"; break;
+        case OID_TCP_TASK_IPSEC_DELETE_SA: pszOid = "OID_TCP_TASK_IPSEC_DELETE_SA"; break;
+        case OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA: pszOid = "OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA"; break;
+
+        case OID_GEN_STATISTICS: pszOid = "OID_GEN_STATISTICS"; break;
+        case OID_GEN_BYTES_RCV: pszOid = "OID_GEN_BYTES_RCV"; break;
+        case OID_GEN_BYTES_XMIT: pszOid = "OID_GEN_BYTES_XMIT"; break;
+        case OID_GEN_RCV_DISCARDS: pszOid = "OID_GEN_RCV_DISCARDS"; break;
+        case OID_GEN_XMIT_DISCARDS: pszOid = "OID_GEN_XMIT_DISCARDS"; break;
+        case OID_GEN_XMIT_OK: pszOid = "OID_GEN_XMIT_OK"; break;
+        case OID_GEN_RCV_OK: pszOid = "OID_GEN_RCV_OK"; break;
+        case OID_GEN_XMIT_ERROR: pszOid = "OID_GEN_XMIT_ERROR"; break;
+        case OID_GEN_RCV_ERROR: pszOid = "OID_GEN_RCV_ERROR"; break;
+        case OID_GEN_RCV_NO_BUFFER: pszOid = "OID_GEN_RCV_NO_BUFFER"; break;
+        case OID_GEN_DIRECTED_BYTES_XMIT: pszOid = "OID_GEN_DIRECTED_BYTES_XMIT"; break;
+        case OID_GEN_DIRECTED_FRAMES_XMIT: pszOid = "OID_GEN_DIRECTED_FRAMES_XMIT"; break;
+        case OID_GEN_MULTICAST_BYTES_XMIT: pszOid = "OID_GEN_MULTICAST_BYTES_XMIT"; break;
+        case OID_GEN_MULTICAST_FRAMES_XMIT: pszOid = "OID_GEN_MULTICAST_FRAMES_XMIT"; break;
+        case OID_GEN_BROADCAST_BYTES_XMIT: pszOid = "OID_GEN_BROADCAST_BYTES_XMIT"; break;
+        case OID_GEN_BROADCAST_FRAMES_XMIT: pszOid = "OID_GEN_BROADCAST_FRAMES_XMIT"; break;
+        case OID_GEN_DIRECTED_BYTES_RCV: pszOid = "OID_GEN_DIRECTED_BYTES_RCV"; break;
+        case OID_GEN_DIRECTED_FRAMES_RCV: pszOid = "OID_GEN_DIRECTED_FRAMES_RCV"; break;
+        case OID_GEN_MULTICAST_BYTES_RCV: pszOid = "OID_GEN_MULTICAST_BYTES_RCV"; break;
+        case OID_GEN_MULTICAST_FRAMES_RCV: pszOid = "OID_GEN_MULTICAST_FRAMES_RCV"; break;
+        case OID_GEN_BROADCAST_BYTES_RCV: pszOid = "OID_GEN_BROADCAST_BYTES_RCV"; break;
+        case OID_GEN_BROADCAST_FRAMES_RCV: pszOid = "OID_GEN_BROADCAST_FRAMES_RCV"; break;
+        case OID_GEN_RCV_CRC_ERROR: pszOid = "OID_GEN_RCV_CRC_ERROR"; break;
+        case OID_GEN_TRANSMIT_QUEUE_LENGTH: pszOid = "OID_GEN_TRANSMIT_QUEUE_LENGTH"; break;
+        case OID_GEN_INIT_TIME_MS: pszOid = "OID_GEN_INIT_TIME_MS"; break;
+        case OID_GEN_RESET_COUNTS: pszOid = "OID_GEN_RESET_COUNTS"; break;
+        case OID_GEN_MEDIA_SENSE_COUNTS: pszOid = "OID_GEN_MEDIA_SENSE_COUNTS"; break;
+
+        case OID_PNP_CAPABILITIES: pszOid = "OID_PNP_CAPABILITIES"; break;
+        case OID_PNP_SET_POWER: pszOid = "OID_PNP_SET_POWER"; break;
+        case OID_PNP_QUERY_POWER: pszOid = "OID_PNP_QUERY_POWER"; break;
+        case OID_PNP_ADD_WAKE_UP_PATTERN: pszOid = "OID_PNP_ADD_WAKE_UP_PATTERN"; break;
+        case OID_PNP_REMOVE_WAKE_UP_PATTERN: pszOid = "OID_PNP_REMOVE_WAKE_UP_PATTERN"; break;
+        case OID_PNP_WAKE_UP_PATTERN_LIST: pszOid = "OID_PNP_WAKE_UP_PATTERN_LIST"; break;
+        case OID_PNP_ENABLE_WAKE_UP: pszOid = "OID_PNP_ENABLE_WAKE_UP"; break;
+        case OID_PNP_WAKE_UP_OK: pszOid = "OID_PNP_WAKE_UP_OK"; break;
+        case OID_PNP_WAKE_UP_ERROR: pszOid = "OID_PNP_WAKE_UP_ERROR"; break;
+    }
+    Log(("%s: %s(0x%x) %s(0x%x)\n", pcszFunction, pszType, pRequest->RequestType, pszOid, pRequest->DATA.SET_INFORMATION.Oid));
+}
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.cpp	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.cpp	(revision 52630)
@@ -0,0 +1,2167 @@
+/* $Id$ */
+/** @file
+ * VBoxNetLwf-win.cpp - NDIS6 Bridged Networking Driver, Windows-specific code.
+ */
+/*
+ * Copyright (C) 2014 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.
+ */
+#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
+
+//#define VBOXNETLWF_SYNC_SEND
+
+#include <VBox/version.h>
+#include <VBox/err.h>
+#include <iprt/initterm.h>
+#include <iprt/net.h>
+#include <iprt/list.h>
+#include <VBox/intnetinline.h>
+
+/// @todo Not sure why, but can it help with build errors?
+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
+
+#if 0
+#undef Log
+#define Log(x) DbgPrint x
+#undef LogFlow
+#define LogFlow(x) DbgPrint x
+#endif
+
+/** We have an entirely different structure than the one defined in VBoxNetFltCmn-win.h */
+typedef struct VBOXNETFLTWIN
+{
+    /** filter module context handle */
+    NDIS_HANDLE hModuleCtx;
+} VBOXNETFLTWIN, *PVBOXNETFLTWIN;
+#define VBOXNETFLT_NO_PACKET_QUEUE
+#define VBOXNETFLT_OS_SPECFIC 1
+#include "VBoxNetFltInternal.h"
+
+#include "VBoxNetLwf-win.h"
+#include "VBoxNetCmn-win.h"
+
+/* Forward declarations */
+FILTER_ATTACH vboxNetLwfWinAttach;
+FILTER_DETACH vboxNetLwfWinDetach;
+FILTER_RESTART vboxNetLwfWinRestart;
+FILTER_PAUSE vboxNetLwfWinPause;
+FILTER_OID_REQUEST vboxNetLwfWinOidRequest;
+FILTER_OID_REQUEST_COMPLETE vboxNetLwfWinOidRequestComplete;
+//FILTER_CANCEL_OID_REQUEST vboxNetLwfWinCancelOidRequest;
+FILTER_STATUS vboxNetLwfWinStatus;
+FILTER_SET_MODULE_OPTIONS vboxNetLwfWinSetModuleOptions;
+//FILTER_NET_PNP_EVENT vboxNetLwfWinPnPEvent;
+FILTER_SEND_NET_BUFFER_LISTS vboxNetLwfWinSendNetBufferLists;
+FILTER_SEND_NET_BUFFER_LISTS_COMPLETE vboxNetLwfWinSendNetBufferListsComplete;
+FILTER_RECEIVE_NET_BUFFER_LISTS vboxNetLwfWinReceiveNetBufferLists;
+FILTER_RETURN_NET_BUFFER_LISTS vboxNetLwfWinReturnNetBufferLists;
+KSTART_ROUTINE vboxNetLwfWinInitIdcWorker;
+
+typedef enum {
+    LwfState_Detached = 0,
+    LwfState_Attaching,
+    LwfState_Paused,
+    LwfState_Restarting,
+    LwfState_Running,
+    LwfState_Pausing,
+    LwfState_32BitHack = 0x7fffffff
+} VBOXNETLWFSTATE;
+
+/*
+ * Valid state transitions are:
+ * 1) Disconnected -> Connecting   : start the worker thread, attempting to init IDC;
+ * 2) Connecting   -> Disconnected : failed to start IDC init worker thread;
+ * 3) Connecting   -> Connected    : IDC init successful, terminate the worker;
+ * 4) Connecting   -> Stopping     : IDC init incomplete, but the driver is being unloaded, terminate the worker;
+ * 5) Connected    -> Stopping     : IDC init was successful, no worker, the driver is being unloaded;
+ *
+ * Driver terminates in Stopping state.
+ */
+typedef enum {
+    LwfIdcState_Disconnected = 0, /* Initial state */
+    LwfIdcState_Connecting,       /* Attemping to init IDC, worker thread running */
+    LwfIdcState_Connected,        /* Successfully connected to IDC, worker thread terminated */
+    LwfIdcState_Stopping          /* Terminating the worker thread and disconnecting IDC */
+} VBOXNETLWFIDCSTATE;
+
+struct _VBOXNETLWF_MODULE;
+
+typedef struct VBOXNETLWFGLOBALS
+{
+    /** synch event used for device creation synchronization */
+    //KEVENT SynchEvent;
+    /** Device reference count */
+    //int cDeviceRefs;
+    /** ndis device */
+    NDIS_HANDLE hDevice;
+    /** device object */
+    PDEVICE_OBJECT pDevObj;
+    /** our filter driver handle */
+    NDIS_HANDLE hFilterDriver;
+    /** lock protecting the module list */
+    NDIS_SPIN_LOCK Lock;
+    /** the head of module list */
+    RTLISTANCHOR listModules;
+    /** IDC initialization state */
+    volatile uint32_t enmIdcState;
+    /** IDC init thread handle */
+    HANDLE hInitIdcThread;
+} VBOXNETLWFGLOBALS, *PVBOXNETLWFGLOBALS;
+
+/**
+ * The (common) global data.
+ */
+static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals;
+/* win-specific global data */
+VBOXNETLWFGLOBALS g_VBoxNetLwfGlobals;
+
+typedef struct _VBOXNETLWF_MODULE {
+    RTLISTNODE node;
+
+    NDIS_HANDLE hFilter;
+    NDIS_HANDLE hPool;
+    PVBOXNETLWFGLOBALS pGlobals;
+    /** Associated instance of NetFlt, one-to-one relationship */
+    PVBOXNETFLTINS pNetFlt; /// @todo Consider automic access!
+    /** Module state as described in http://msdn.microsoft.com/en-us/library/windows/hardware/ff550017(v=vs.85).aspx */
+    volatile uint32_t enmState; /* No lock needed yet, atomic should suffice. */
+    /** Mutex to prevent pausing while transmitting on behalf of NetFlt */
+    NDIS_MUTEX InTransmit;
+#ifdef VBOXNETLWF_SYNC_SEND
+    /** Event signalled when sending to the wire is complete */
+    KEVENT EventWire;
+    /** Event signalled when NDIS returns our receive notification */
+    KEVENT EventHost;
+#else /* !VBOXNETLWF_SYNC_SEND */
+    /** Event signalled when all pending sends (both to wire and host) have completed */
+    NDIS_EVENT EventSendComplete;
+    /** Counter for pending sends (both to wire and host) */
+    int32_t cPendingBuffers;
+#endif /* !VBOXNETLWF_SYNC_SEND */
+    /** Name of underlying adapter */
+    ANSI_STRING strMiniportName;
+    /** MAC address of underlying adapter */
+    RTMAC MacAddr;
+    /** Packet filter of underlying miniport */
+    ULONG uPacketFilter;
+    /** Saved offload configuration */
+    NDIS_OFFLOAD SavedOffloadConfig;
+    /** the cloned request we have passed down */
+    PNDIS_OID_REQUEST pPendingRequest;
+    /** true if the underlying miniport supplied offloading config */
+    bool fOffloadConfigValid;
+    /** true if the trunk expects data from us */
+    bool fActive;
+} VBOXNETLWF_MODULE;
+typedef VBOXNETLWF_MODULE *PVBOXNETLWF_MODULE;
+
+/*
+ * A structure to wrap OID requests in.
+ */
+typedef struct _VBOXNETLWF_OIDREQ {
+    NDIS_OID_REQUEST Request;
+    NDIS_STATUS Status;
+    NDIS_EVENT Event;
+} VBOXNETLWF_OIDREQ;
+typedef VBOXNETLWF_OIDREQ *PVBOXNETLWF_OIDREQ;
+
+/* Forward declarations */
+static VOID vboxNetLwfWinUnloadDriver(IN PDRIVER_OBJECT pDriver);
+static int vboxNetLwfWinInitBase();
+static int vboxNetLwfWinFini();
+
+#ifdef DEBUG
+static const char *vboxNetLwfWinStatusToText(NDIS_STATUS code)
+{
+    switch (code)
+    {
+        case NDIS_STATUS_MEDIA_CONNECT: return "NDIS_STATUS_MEDIA_CONNECT";
+        case NDIS_STATUS_MEDIA_DISCONNECT: return "NDIS_STATUS_MEDIA_DISCONNECT";
+        case NDIS_STATUS_RESET_START: return "NDIS_STATUS_RESET_START";
+        case NDIS_STATUS_RESET_END: return "NDIS_STATUS_RESET_END";
+        case NDIS_STATUS_MEDIA_BUSY: return "NDIS_STATUS_MEDIA_BUSY";
+        case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION: return "NDIS_STATUS_MEDIA_SPECIFIC_INDICATION";
+        case NDIS_STATUS_LINK_SPEED_CHANGE: return "NDIS_STATUS_LINK_SPEED_CHANGE";
+        case NDIS_STATUS_LINK_STATE: return "NDIS_STATUS_LINK_STATE";
+        case NDIS_STATUS_PORT_STATE: return "NDIS_STATUS_PORT_STATE";
+        case NDIS_STATUS_OPER_STATUS: return "NDIS_STATUS_OPER_STATUS";
+        case NDIS_STATUS_NETWORK_CHANGE: return "NDIS_STATUS_NETWORK_CHANGE";
+        case NDIS_STATUS_PACKET_FILTER: return "NDIS_STATUS_PACKET_FILTER";
+        case NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: return "NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG";
+        case NDIS_STATUS_TASK_OFFLOAD_HARDWARE_CAPABILITIES: return "NDIS_STATUS_TASK_OFFLOAD_HARDWARE_CAPABILITIES";
+        case NDIS_STATUS_OFFLOAD_ENCASPULATION_CHANGE: return "NDIS_STATUS_OFFLOAD_ENCASPULATION_CHANGE";
+        case NDIS_STATUS_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES: return "NDIS_STATUS_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES";
+    }
+    return "unknown";
+}
+
+static void vboxNetLwfWinDumpFilterTypes(ULONG uFlags)
+{
+    if (uFlags & NDIS_PACKET_TYPE_DIRECTED) Log5(("   NDIS_PACKET_TYPE_DIRECTED\n"));
+    if (uFlags & NDIS_PACKET_TYPE_MULTICAST) Log5(("   NDIS_PACKET_TYPE_MULTICAST\n"));
+    if (uFlags & NDIS_PACKET_TYPE_ALL_MULTICAST) Log5(("   NDIS_PACKET_TYPE_ALL_MULTICAST\n"));
+    if (uFlags & NDIS_PACKET_TYPE_BROADCAST) Log5(("   NDIS_PACKET_TYPE_BROADCAST\n"));
+    if (uFlags & NDIS_PACKET_TYPE_PROMISCUOUS) Log5(("   NDIS_PACKET_TYPE_PROMISCUOUS\n"));
+    if (uFlags & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) Log5(("   NDIS_PACKET_TYPE_ALL_FUNCTIONAL\n"));
+    if (uFlags & NDIS_PACKET_TYPE_ALL_LOCAL) Log5(("   NDIS_PACKET_TYPE_ALL_LOCAL\n"));
+    if (uFlags & NDIS_PACKET_TYPE_FUNCTIONAL) Log5(("   NDIS_PACKET_TYPE_FUNCTIONAL\n"));
+    if (uFlags & NDIS_PACKET_TYPE_GROUP) Log5(("   NDIS_PACKET_TYPE_GROUP\n"));
+    if (uFlags & NDIS_PACKET_TYPE_MAC_FRAME) Log5(("   NDIS_PACKET_TYPE_MAC_FRAME\n"));
+    if (uFlags & NDIS_PACKET_TYPE_SMT) Log5(("   NDIS_PACKET_TYPE_SMT\n"));
+    if (uFlags & NDIS_PACKET_TYPE_SOURCE_ROUTING) Log5(("   NDIS_PACKET_TYPE_SOURCE_ROUTING\n"));
+    if (uFlags == 0) Log5(("   NONE\n"));
+}
+
+DECLINLINE(void) vboxNetLwfWinDumpEncapsulation(const char *pcszText, ULONG uEncapsulation)
+{
+    if (uEncapsulation == NDIS_ENCAPSULATION_NOT_SUPPORTED)
+        Log5(("%s not supported\n", pcszText));
+    else
+    {
+        Log5(("%s", pcszText));
+        if (uEncapsulation & NDIS_ENCAPSULATION_NULL)
+            Log5((" null"));
+        if (uEncapsulation & NDIS_ENCAPSULATION_IEEE_802_3)
+            Log5((" 802.3"));
+        if (uEncapsulation & NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q)
+            Log5((" 802.3pq"));
+        if (uEncapsulation & NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q_IN_OOB)
+            Log5((" 802.3pq(oob)"));
+        if (uEncapsulation & NDIS_ENCAPSULATION_IEEE_LLC_SNAP_ROUTED)
+            Log5((" LLC"));
+        Log5(("\n"));
+    }
+}
+
+DECLINLINE(const char *) vboxNetLwfWinSetOnOffText(ULONG uOnOff)
+{
+    switch (uOnOff)
+    {
+        case NDIS_OFFLOAD_SET_NO_CHANGE: return "no change";
+        case NDIS_OFFLOAD_SET_ON: return "on";
+        case NDIS_OFFLOAD_SET_OFF: return "off";
+    }
+    return "unknown";
+}
+
+DECLINLINE(const char *) vboxNetLwfWinOnOffText(ULONG uOnOff)
+{
+    switch (uOnOff)
+    {
+        case NDIS_OFFLOAD_NOT_SUPPORTED: return "off";
+        case NDIS_OFFLOAD_SUPPORTED: return "on";
+    }
+    return "unknown";
+}
+
+DECLINLINE(const char *) vboxNetLwfWinSupportedText(ULONG uSupported)
+{
+    switch (uSupported)
+    {
+        case NDIS_OFFLOAD_NOT_SUPPORTED: return "not supported";
+        case NDIS_OFFLOAD_SUPPORTED: return "supported";
+    }
+    return "unknown";
+}
+
+static void vboxNetLwfWinDumpSetOffloadSettings(PNDIS_OFFLOAD pOffloadConfig)
+{
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv4Transmit.Encapsulation               =", pOffloadConfig->Checksum.IPv4Transmit.Encapsulation);
+    Log5(("   Checksum.IPv4Transmit.IpOptionsSupported          = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Transmit.IpOptionsSupported)));
+    Log5(("   Checksum.IPv4Transmit.TcpOptionsSupported         = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Transmit.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv4Transmit.TcpChecksum                 = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Transmit.TcpChecksum)));
+    Log5(("   Checksum.IPv4Transmit.UdpChecksum                 = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Transmit.UdpChecksum)));
+    Log5(("   Checksum.IPv4Transmit.IpChecksum                  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Transmit.IpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv4Receive.Encapsulation                =", pOffloadConfig->Checksum.IPv4Receive.Encapsulation);
+    Log5(("   Checksum.IPv4Receive.IpOptionsSupported           = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Receive.IpOptionsSupported)));
+    Log5(("   Checksum.IPv4Receive.TcpOptionsSupported          = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Receive.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv4Receive.TcpChecksum                  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Receive.TcpChecksum)));
+    Log5(("   Checksum.IPv4Receive.UdpChecksum                  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Receive.UdpChecksum)));
+    Log5(("   Checksum.IPv4Receive.IpChecksum                   = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv4Receive.IpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv6Transmit.Encapsulation               =", pOffloadConfig->Checksum.IPv6Transmit.Encapsulation);
+    Log5(("   Checksum.IPv6Transmit.IpExtensionHeadersSupported = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Transmit.IpExtensionHeadersSupported)));
+    Log5(("   Checksum.IPv6Transmit.TcpOptionsSupported         = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Transmit.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv6Transmit.TcpChecksum                 = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Transmit.TcpChecksum)));
+    Log5(("   Checksum.IPv6Transmit.UdpChecksum                 = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Transmit.UdpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv6Receive.Encapsulation                =", pOffloadConfig->Checksum.IPv6Receive.Encapsulation);
+    Log5(("   Checksum.IPv6Receive.IpExtensionHeadersSupported  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Receive.IpExtensionHeadersSupported)));
+    Log5(("   Checksum.IPv6Receive.TcpOptionsSupported          = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Receive.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv6Receive.TcpChecksum                  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Receive.TcpChecksum)));
+    Log5(("   Checksum.IPv6Receive.UdpChecksum                  = %s\n", vboxNetLwfWinSetOnOffText(pOffloadConfig->Checksum.IPv6Receive.UdpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   LsoV1.IPv4.Encapsulation                          =", pOffloadConfig->LsoV1.IPv4.Encapsulation);
+    Log5(("   LsoV1.IPv4.TcpOptions                             = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV1.IPv4.TcpOptions)));
+    Log5(("   LsoV1.IPv4.IpOptions                              = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV1.IPv4.IpOptions)));
+    vboxNetLwfWinDumpEncapsulation("   LsoV2.IPv4.Encapsulation                          =", pOffloadConfig->LsoV2.IPv4.Encapsulation);
+    vboxNetLwfWinDumpEncapsulation("   LsoV2.IPv6.Encapsulation                          =", pOffloadConfig->LsoV2.IPv6.Encapsulation);
+    Log5(("   LsoV2.IPv6.IpExtensionHeadersSupported            = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV2.IPv6.IpExtensionHeadersSupported)));
+    Log5(("   LsoV2.IPv6.TcpOptionsSupported                    = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV2.IPv6.TcpOptionsSupported)));
+}
+
+static void vboxNetLwfWinDumpOffloadSettings(PNDIS_OFFLOAD pOffloadConfig)
+{
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv4Transmit.Encapsulation               =", pOffloadConfig->Checksum.IPv4Transmit.Encapsulation);
+    Log5(("   Checksum.IPv4Transmit.IpOptionsSupported          = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Transmit.IpOptionsSupported)));
+    Log5(("   Checksum.IPv4Transmit.TcpOptionsSupported         = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Transmit.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv4Transmit.TcpChecksum                 = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Transmit.TcpChecksum)));
+    Log5(("   Checksum.IPv4Transmit.UdpChecksum                 = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Transmit.UdpChecksum)));
+    Log5(("   Checksum.IPv4Transmit.IpChecksum                  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Transmit.IpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv4Receive.Encapsulation                =", pOffloadConfig->Checksum.IPv4Receive.Encapsulation);
+    Log5(("   Checksum.IPv4Receive.IpOptionsSupported           = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Receive.IpOptionsSupported)));
+    Log5(("   Checksum.IPv4Receive.TcpOptionsSupported          = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Receive.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv4Receive.TcpChecksum                  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Receive.TcpChecksum)));
+    Log5(("   Checksum.IPv4Receive.UdpChecksum                  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Receive.UdpChecksum)));
+    Log5(("   Checksum.IPv4Receive.IpChecksum                   = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv4Receive.IpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv6Transmit.Encapsulation               =", pOffloadConfig->Checksum.IPv6Transmit.Encapsulation);
+    Log5(("   Checksum.IPv6Transmit.IpExtensionHeadersSupported = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Transmit.IpExtensionHeadersSupported)));
+    Log5(("   Checksum.IPv6Transmit.TcpOptionsSupported         = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Transmit.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv6Transmit.TcpChecksum                 = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Transmit.TcpChecksum)));
+    Log5(("   Checksum.IPv6Transmit.UdpChecksum                 = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Transmit.UdpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   Checksum.IPv6Receive.Encapsulation                =", pOffloadConfig->Checksum.IPv6Receive.Encapsulation);
+    Log5(("   Checksum.IPv6Receive.IpExtensionHeadersSupported  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Receive.IpExtensionHeadersSupported)));
+    Log5(("   Checksum.IPv6Receive.TcpOptionsSupported          = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Receive.TcpOptionsSupported)));
+    Log5(("   Checksum.IPv6Receive.TcpChecksum                  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Receive.TcpChecksum)));
+    Log5(("   Checksum.IPv6Receive.UdpChecksum                  = %s\n", vboxNetLwfWinOnOffText(pOffloadConfig->Checksum.IPv6Receive.UdpChecksum)));
+    vboxNetLwfWinDumpEncapsulation("   LsoV1.IPv4.Encapsulation                          =", pOffloadConfig->LsoV1.IPv4.Encapsulation);
+    Log5(("   LsoV1.IPv4.TcpOptions                             = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV1.IPv4.TcpOptions)));
+    Log5(("   LsoV1.IPv4.IpOptions                              = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV1.IPv4.IpOptions)));
+    vboxNetLwfWinDumpEncapsulation("   LsoV2.IPv4.Encapsulation                          =", pOffloadConfig->LsoV2.IPv4.Encapsulation);
+    vboxNetLwfWinDumpEncapsulation("   LsoV2.IPv6.Encapsulation                          =", pOffloadConfig->LsoV2.IPv6.Encapsulation);
+    Log5(("   LsoV2.IPv6.IpExtensionHeadersSupported            = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV2.IPv6.IpExtensionHeadersSupported)));
+    Log5(("   LsoV2.IPv6.TcpOptionsSupported                    = %s\n", vboxNetLwfWinSupportedText(pOffloadConfig->LsoV2.IPv6.TcpOptionsSupported)));
+}
+
+static const char *vboxNetLwfWinStateToText(uint32_t enmState)
+{
+    switch (enmState)
+    {
+        case LwfState_Detached: return "Detached";
+        case LwfState_Attaching: return "Attaching";
+        case LwfState_Paused: return "Paused";
+        case LwfState_Restarting: return "Restarting";
+        case LwfState_Running: return "Running";
+        case LwfState_Pausing: return "Pausing";
+    }
+    return "invalid";
+}
+
+#else /* !DEBUG */
+#define vboxNetLwfWinDumpFilterTypes(uFlags)
+#define vboxNetLwfWinDumpOffloadSettings(p)
+#define vboxNetLwfWinDumpSetOffloadSettings(p)
+#endif /* DEBUG */
+
+DECLINLINE(bool) vboxNetLwfWinChangeState(PVBOXNETLWF_MODULE pModuleCtx, uint32_t enmNew, uint32_t enmOld = LwfState_32BitHack)
+{
+    AssertReturn(pModuleCtx, false);
+
+    bool fSuccess = true;
+    if (enmOld != LwfState_32BitHack)
+    {
+        fSuccess = ASMAtomicCmpXchgU32(&pModuleCtx->enmState, enmNew, enmOld);
+        if (fSuccess)
+            Log((__FUNCTION__": state change %s -> %s\n",
+                 vboxNetLwfWinStateToText(enmOld),
+                 vboxNetLwfWinStateToText(enmNew)));
+        else
+            Log((__FUNCTION__": failed state change %s (actual=%s) -> %s\n",
+                 vboxNetLwfWinStateToText(enmOld),
+                 vboxNetLwfWinStateToText(ASMAtomicReadU32(&pModuleCtx->enmState)),
+                 vboxNetLwfWinStateToText(enmNew)));
+        Assert(fSuccess);
+    }
+    else
+    {
+        uint32_t enmPrevState = ASMAtomicXchgU32(&pModuleCtx->enmState, enmNew);
+        Log((__FUNCTION__": state change %s -> %s\n",
+             vboxNetLwfWinStateToText(enmPrevState),
+             vboxNetLwfWinStateToText(enmNew)));
+    }
+    return fSuccess;
+}
+
+DECLINLINE(void) vboxNetLwfWinInitOidRequest(PVBOXNETLWF_OIDREQ pRequest)
+{
+    NdisZeroMemory(pRequest, sizeof(VBOXNETLWF_OIDREQ));
+
+    NdisInitializeEvent(&pRequest->Event);
+
+    pRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
+    pRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1;
+    pRequest->Request.Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
+
+    pRequest->Request.RequestId = (PVOID)VBOXNETLWF_REQ_ID;
+}
+
+static NDIS_STATUS vboxNetLwfWinSyncOidRequest(PVBOXNETLWF_MODULE pModuleCtx, PVBOXNETLWF_OIDREQ pRequest)
+{
+    NDIS_STATUS Status = NdisFOidRequest(pModuleCtx->hFilter, &pRequest->Request);
+    if (Status == NDIS_STATUS_PENDING)
+    {
+        NdisWaitEvent(&pRequest->Event, 0);
+        Status = pRequest->Status;
+    }
+    return Status;
+}
+
+DECLINLINE(void) vboxNetLwfWinCopyOidRequestResults(PNDIS_OID_REQUEST pFrom, PNDIS_OID_REQUEST pTo)
+{
+    switch (pFrom->RequestType)
+    {
+        case NdisRequestSetInformation:
+            pTo->DATA.SET_INFORMATION.BytesRead   = pFrom->DATA.SET_INFORMATION.BytesRead;
+            pTo->DATA.SET_INFORMATION.BytesNeeded = pFrom->DATA.SET_INFORMATION.BytesNeeded;
+            break;
+        case NdisRequestMethod:
+            pTo->DATA.METHOD_INFORMATION.OutputBufferLength = pFrom->DATA.METHOD_INFORMATION.OutputBufferLength;
+            pTo->DATA.METHOD_INFORMATION.BytesWritten       = pFrom->DATA.METHOD_INFORMATION.BytesWritten;
+            pTo->DATA.METHOD_INFORMATION.BytesRead          = pFrom->DATA.METHOD_INFORMATION.BytesRead;
+            pTo->DATA.METHOD_INFORMATION.BytesNeeded        = pFrom->DATA.METHOD_INFORMATION.BytesNeeded;
+            break;
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+        default:
+            pTo->DATA.QUERY_INFORMATION.BytesWritten = pFrom->DATA.QUERY_INFORMATION.BytesWritten;
+            pTo->DATA.QUERY_INFORMATION.BytesNeeded  = pFrom->DATA.QUERY_INFORMATION.BytesNeeded;
+    }
+}
+
+NDIS_STATUS vboxNetLwfWinOidRequest(IN NDIS_HANDLE hModuleCtx,
+                                    IN PNDIS_OID_REQUEST pOidRequest)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    vboxNetCmnWinDumpOidRequest(__FUNCTION__, pOidRequest);
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    PNDIS_OID_REQUEST pClone = NULL;
+    NDIS_STATUS Status = NdisAllocateCloneOidRequest(pModuleCtx->hFilter,
+                                                     pOidRequest,
+                                                     VBOXNETLWF_MEM_TAG,
+                                                     &pClone);
+    if (Status == NDIS_STATUS_SUCCESS)
+    {
+        /* Save the pointer to the original */
+        *((PNDIS_OID_REQUEST*)(pClone->SourceReserved)) = pOidRequest;
+
+        pClone->RequestId = pOidRequest->RequestId;
+        /* We are not supposed to get another request until we are through with the one we "postponed" */
+        PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, pClone, PNDIS_OID_REQUEST);
+        Assert(pPrev == NULL);
+        pModuleCtx->pPendingRequest = pClone;
+        if (pOidRequest->RequestType == NdisRequestSetInformation
+            && pOidRequest->DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
+        {
+            ASMAtomicWriteU32((uint32_t*)&pModuleCtx->uPacketFilter, *(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
+            Log((__FUNCTION__": updated cached packet filter value to:\n"));
+            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
+        }
+        if (pOidRequest->RequestType == NdisRequestSetInformation
+            && pOidRequest->DATA.SET_INFORMATION.Oid == OID_TCP_OFFLOAD_CURRENT_CONFIG)
+        {
+            Log5((__FUNCTION__": offloading set to:\n"));
+            vboxNetLwfWinDumpSetOffloadSettings((PNDIS_OFFLOAD)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
+        }
+
+        /* Forward the clone to underlying filters/miniport */
+        Status = NdisFOidRequest(pModuleCtx->hFilter, pClone);
+        if (Status != NDIS_STATUS_PENDING)
+        {
+            /* Synchronous completion */
+            pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
+            Assert(pPrev == pClone);
+            vboxNetLwfWinCopyOidRequestResults(pClone, pOidRequest);
+            NdisFreeCloneOidRequest(pModuleCtx->hFilter, pClone);
+        }
+        /* In case of async completion we do the rest in vboxNetLwfWinOidRequestComplete() */
+    }
+    else
+    {
+        Log((__FUNCTION__": NdisAllocateCloneOidRequest failed with 0x%x\n", Status));
+    }
+    LogFlow(("<=="__FUNCTION__": Status=0x%x\n", Status));
+    return Status;
+}
+
+VOID vboxNetLwfWinOidRequestComplete(IN NDIS_HANDLE hModuleCtx,
+                                     IN PNDIS_OID_REQUEST pRequest,
+                                     IN NDIS_STATUS Status)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p req=%p status=0x%x\n", hModuleCtx, pRequest, Status));
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    PNDIS_OID_REQUEST pOriginal = *((PNDIS_OID_REQUEST*)(pRequest->SourceReserved));
+    if (pOriginal)
+    {
+        /* NDIS is supposed to serialize requests */
+        PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
+        Assert(pPrev == pRequest);
+
+        vboxNetLwfWinCopyOidRequestResults(pRequest, pOriginal);
+        NdisFreeCloneOidRequest(pModuleCtx->hFilter, pRequest);
+        NdisFOidRequestComplete(pModuleCtx->hFilter, pOriginal, Status);
+    }
+    else
+    {
+        /* This is not a clone, we originated it */
+        Log((__FUNCTION__": locally originated request (%p) completed, status=0x%x\n", pRequest, Status));
+        PVBOXNETLWF_OIDREQ pRqWrapper = RT_FROM_MEMBER(pRequest, VBOXNETLWF_OIDREQ, Request);
+        pRqWrapper->Status = Status;
+        NdisSetEvent(&pRqWrapper->Event);
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+
+static bool vboxNetLwfWinIsPromiscuous(PVBOXNETLWF_MODULE pModuleCtx)
+{
+    return !!(pModuleCtx->uPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS);
+}
+
+#if 0
+static NDIS_STATUS vboxNetLwfWinGetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx)
+{
+    LogFlow(("==>"__FUNCTION__"\n"));
+    VBOXNETLWF_OIDREQ Rq;
+    vboxNetLwfWinInitOidRequest(&Rq);
+    Rq.Request.RequestType = NdisRequestQueryInformation;
+    Rq.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
+    Rq.Request.DATA.QUERY_INFORMATION.InformationBuffer = &pModuleCtx->uPacketFilter;
+    Rq.Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pModuleCtx->uPacketFilter);
+    NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
+    if (Status != NDIS_STATUS_SUCCESS)
+    {
+        Log((__FUNCTION__": vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed with 0x%x\n", Status));
+        return FALSE;
+    }
+    if (Rq.Request.DATA.QUERY_INFORMATION.BytesWritten != sizeof(pModuleCtx->uPacketFilter))
+    {
+        Log((__FUNCTION__": vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed to write neccessary amount (%d bytes), actually written %d bytes\n", sizeof(pModuleCtx->uPacketFilter), Rq.Request.DATA.QUERY_INFORMATION.BytesWritten));
+    }
+    
+    Log5((__FUNCTION__": OID_GEN_CURRENT_PACKET_FILTER query returned the following filters:\n"));
+    vboxNetLwfWinDumpFilterTypes(pModuleCtx->uPacketFilter);
+
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+#endif
+
+static NDIS_STATUS vboxNetLwfWinSetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx, bool fPromisc)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p %s\n", pModuleCtx, fPromisc ? "promiscuous" : "normal"));
+    VBOXNETLWF_OIDREQ Rq;
+    vboxNetLwfWinInitOidRequest(&Rq);
+    ULONG uFilter = ASMAtomicReadU32((uint32_t*)&pModuleCtx->uPacketFilter);
+    if (fPromisc)
+        uFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+    Rq.Request.RequestType = NdisRequestSetInformation;
+    Rq.Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
+    Rq.Request.DATA.SET_INFORMATION.InformationBuffer = &uFilter;
+    Rq.Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(uFilter);
+    NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
+    if (Status != NDIS_STATUS_SUCCESS)
+    {
+        Log((__FUNCTION__": vboxNetLwfWinSyncOidRequest(set, OID_GEN_CURRENT_PACKET_FILTER, vvv below vvv) failed with 0x%x\n", Status));
+        vboxNetLwfWinDumpFilterTypes(uFilter);
+    }
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+
+static NTSTATUS vboxNetLwfWinDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
+{
+    PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    switch (pIrpSl->MajorFunction)
+    {
+        case IRP_MJ_DEVICE_CONTROL:
+            Status = STATUS_NOT_SUPPORTED;
+            break;
+        case IRP_MJ_CREATE:
+        case IRP_MJ_CLEANUP:
+        case IRP_MJ_CLOSE:
+            break;
+        default:
+            Assert(0);
+            break;
+    }
+
+    pIrp->IoStatus.Status = Status;
+    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+/** @todo So far we had no use for device, should we even bother to create it? */
+static NDIS_STATUS vboxNetLwfWinDevCreate(PVBOXNETLWFGLOBALS pGlobals)
+{
+    NDIS_STRING DevName, LinkName;
+    PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
+    NdisInitUnicodeString(&DevName, VBOXNETLWF_NAME_DEVICE);
+    NdisInitUnicodeString(&LinkName, VBOXNETLWF_NAME_LINK);
+
+    Assert(!pGlobals->hDevice);
+    Assert(!pGlobals->pDevObj);
+    NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
+    aMajorFunctions[IRP_MJ_CREATE] = vboxNetLwfWinDevDispatch;
+    aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetLwfWinDevDispatch;
+    aMajorFunctions[IRP_MJ_CLOSE] = vboxNetLwfWinDevDispatch;
+    aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetLwfWinDevDispatch;
+
+    NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttributes;
+    NdisZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
+    DeviceAttributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
+    DeviceAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
+    DeviceAttributes.Header.Size = sizeof(DeviceAttributes);
+    DeviceAttributes.DeviceName = &DevName;
+    DeviceAttributes.SymbolicName = &LinkName;
+    DeviceAttributes.MajorFunctions = aMajorFunctions;
+    //DeviceAttributes.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION);
+
+    NDIS_STATUS Status = NdisRegisterDeviceEx(pGlobals->hFilterDriver,
+                                              &DeviceAttributes,
+                                              &pGlobals->pDevObj,
+                                              &pGlobals->hDevice);
+    Log(("vboxNetLwfWinDevCreate: NdisRegisterDeviceEx returned 0x%x\n", Status));
+    Assert(Status == NDIS_STATUS_SUCCESS);
+#if 0
+    if (Status == NDIS_STATUS_SUCCESS)
+    {
+        PFILTER_DEVICE_EXTENSION pExtension;
+        pExtension = NdisGetDeviceReservedExtension(pGlobals->pDevObj);
+        pExtension->Signature = VBOXNETLWF_MEM_TAG;
+        pExtension->Handle = pGlobals->hFilterDriver;
+    }
+#endif
+    return Status;
+}
+
+static void vboxNetLwfWinDevDestroy(PVBOXNETLWFGLOBALS pGlobals)
+{
+    Assert(pGlobals->hDevice);
+    Assert(pGlobals->pDevObj);
+    NdisDeregisterDeviceEx(pGlobals->hDevice);
+    pGlobals->hDevice = NULL;
+    pGlobals->pDevObj = NULL;
+}
+
+
+static NDIS_STATUS vboxNetLwfWinAttach(IN NDIS_HANDLE hFilter, IN NDIS_HANDLE hDriverCtx,
+                                       IN PNDIS_FILTER_ATTACH_PARAMETERS pParameters)
+{
+    LogFlow(("==>"__FUNCTION__": filter=%p\n", hFilter));
+
+    PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)hDriverCtx;
+    AssertReturn(pGlobals, NDIS_STATUS_FAILURE);
+
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)NdisAllocateMemoryWithTagPriority(hFilter,
+                                                                      sizeof(VBOXNETLWF_MODULE),
+                                                                      VBOXNETLWF_MEM_TAG,
+                                                                      LowPoolPriority);
+    if (!pModuleCtx)
+        return NDIS_STATUS_RESOURCES;
+    Log4((__FUNCTION__ ": allocated module context 0x%p\n", pModuleCtx));
+
+    NdisZeroMemory(pModuleCtx, sizeof(VBOXNETLWF_MODULE));
+
+    /* We use the miniport name to associate this filter module with the netflt instance */
+    NTSTATUS rc = RtlUnicodeStringToAnsiString(&pModuleCtx->strMiniportName,
+                                               pParameters->BaseMiniportName,
+                                               TRUE);
+    if (rc != STATUS_SUCCESS)
+    {
+        Log(("ERROR! vboxNetLwfWinAttach: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",
+             pParameters->BaseMiniportName, rc));
+        NdisFreeMemory(pModuleCtx, 0, 0);
+        return NDIS_STATUS_FAILURE;
+    }
+    Assert(pParameters->MacAddressLength == sizeof(RTMAC));
+    NdisMoveMemory(&pModuleCtx->MacAddr, pParameters->CurrentMacAddress, RT_MIN(sizeof(RTMAC), pParameters->MacAddressLength));
+    if (pParameters->DefaultOffloadConfiguration)
+    {
+        pModuleCtx->SavedOffloadConfig = *pParameters->DefaultOffloadConfiguration;
+        pModuleCtx->fOffloadConfigValid = true;
+    }
+
+    pModuleCtx->pGlobals = pGlobals;
+    pModuleCtx->hFilter  = hFilter;
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Attaching);
+    /* Insert into module chain */
+    NdisAcquireSpinLock(&pGlobals->Lock);
+    RTListPrepend(&pGlobals->listModules, &pModuleCtx->node);
+    NdisReleaseSpinLock(&pGlobals->Lock);
+    /* Initialize transmission mutex and events */
+    NDIS_INIT_MUTEX(&pModuleCtx->InTransmit);
+#ifdef VBOXNETLWF_SYNC_SEND
+    KeInitializeEvent(&pModuleCtx->EventWire, SynchronizationEvent, FALSE);
+    KeInitializeEvent(&pModuleCtx->EventHost, SynchronizationEvent, FALSE);
+#else /* !VBOXNETLWF_SYNC_SEND */
+    NdisInitializeEvent(&pModuleCtx->EventSendComplete);
+    pModuleCtx->cPendingBuffers = 0;
+#endif /* !VBOXNETLWF_SYNC_SEND */
+    /* Allocate buffer pools */
+    NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
+    NdisZeroMemory(&PoolParams, sizeof(PoolParams));
+    PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    PoolParams.Header.Size = sizeof(PoolParams);
+    PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+    PoolParams.fAllocateNetBuffer = TRUE;
+    PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */
+    PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;
+#ifndef VBOXNETLWF_SYNC_SEND
+    PoolParams.DataSize = 2048; /** @todo figure out the optimal size, use several pools if necessary, make configurable, etc */
+#endif /* !VBOXNETLWF_SYNC_SEND */
+
+    pModuleCtx->hPool = NdisAllocateNetBufferListPool(hFilter, &PoolParams);
+    if (!pModuleCtx->hPool)
+    {
+        Log(("ERROR! "__FUNCTION__": NdisAllocateNetBufferListPool failed\n"));
+        RtlFreeAnsiString(&pModuleCtx->strMiniportName);
+        NdisFreeMemory(pModuleCtx, 0, 0);
+        return NDIS_STATUS_RESOURCES;
+    }
+    Log4((__FUNCTION__ ": allocated NBL+NB pool 0x%p\n", pModuleCtx->hPool));
+
+    NDIS_FILTER_ATTRIBUTES Attributes;
+    NdisZeroMemory(&Attributes, sizeof(Attributes));
+    Attributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
+    Attributes.Header.Size = sizeof(Attributes);
+    Attributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
+    Attributes.Flags = 0;
+    NDIS_STATUS Status = NdisFSetAttributes(hFilter, pModuleCtx, &Attributes);
+    if (Status != NDIS_STATUS_SUCCESS)
+    {
+        Log(("ERROR! vboxNetLwfWinAttach: NdisFSetAttributes failed with 0x%x\n", Status));
+        NdisFreeNetBufferListPool(pModuleCtx->hPool);
+        Log4((__FUNCTION__ ": freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
+        RtlFreeAnsiString(&pModuleCtx->strMiniportName);
+        NdisFreeMemory(pModuleCtx, 0, 0);
+        return NDIS_STATUS_RESOURCES;
+    }
+
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused);
+
+    /// @todo Somehow the packet filter is 0 at this point: Status = vboxNetLwfWinGetPacketFilter(pModuleCtx);
+    /// @todo We actually update it later in status handler, perhaps we should not do anything here.
+
+    LogFlow(("<=="__FUNCTION__": Status = 0x%x\n", Status));
+    return Status;
+}
+
+static VOID vboxNetLwfWinDetach(IN NDIS_HANDLE hModuleCtx)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Detached, LwfState_Paused);
+
+    /* Remove from module chain */
+    NdisAcquireSpinLock(&pModuleCtx->pGlobals->Lock);
+    RTListNodeRemove(&pModuleCtx->node);
+    NdisReleaseSpinLock(&pModuleCtx->pGlobals->Lock);
+
+    PVBOXNETFLTINS pNetFltIns = pModuleCtx->pNetFlt; /// @todo Atomic?
+    if (pNetFltIns && vboxNetFltTryRetainBusyNotDisconnected(pNetFltIns))
+    {
+        /*
+         * Set hModuleCtx to null now in order to prevent filter restart,
+         * OID requests and other stuff associated with NetFlt deactivation.
+         */
+        pNetFltIns->u.s.WinIf.hModuleCtx = NULL;
+        /* Notify NetFlt that we are going down */
+        pNetFltIns->pSwitchPort->pfnDisconnect(pNetFltIns->pSwitchPort, &pNetFltIns->MyPort, vboxNetFltPortReleaseBusy);
+        /* We do not 'release' netflt instance since it has been done by pfnDisconnect */
+    }
+    pModuleCtx->pNetFlt = NULL;
+        
+    /*
+     * We have to make sure that all NET_BUFFER_LIST structures have been freed by now, but
+     * it does not require us to do anything here since it has already been taken care of
+     * by vboxNetLwfWinPause().
+     */
+    if (pModuleCtx->hPool)
+    {
+        NdisFreeNetBufferListPool(pModuleCtx->hPool);
+        Log4((__FUNCTION__ ": freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
+    }
+    RtlFreeAnsiString(&pModuleCtx->strMiniportName);
+    NdisFreeMemory(hModuleCtx, 0, 0);
+    Log4((__FUNCTION__ ": freed module context 0x%p\n", pModuleCtx));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+
+static NDIS_STATUS vboxNetLwfWinPause(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_PAUSE_PARAMETERS pParameters)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Pausing, LwfState_Running);
+    /* Wait for pending send/indication operations to complete. */
+    NDIS_WAIT_FOR_MUTEX(&pModuleCtx->InTransmit);
+#ifndef VBOXNETLWF_SYNC_SEND
+    NdisWaitEvent(&pModuleCtx->EventSendComplete, 1000 /* ms */);
+#endif /* !VBOXNETLWF_SYNC_SEND */
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused, LwfState_Pausing);
+    NDIS_RELEASE_MUTEX(&pModuleCtx->InTransmit);
+    LogFlow(("<=="__FUNCTION__"\n"));
+    return NDIS_STATUS_SUCCESS; /* Failure is not an option */
+}
+
+
+static void vboxNetLwfWinIndicateOffload(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)
+{
+    Log5((__FUNCTION__": offload config changed to:\n"));
+    vboxNetLwfWinDumpOffloadSettings(pOffload);
+    NDIS_STATUS_INDICATION OffloadingIndication;
+    NdisZeroMemory(&OffloadingIndication, sizeof(OffloadingIndication));
+    OffloadingIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    OffloadingIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    OffloadingIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
+    OffloadingIndication.SourceHandle = pModuleCtx->hFilter;
+    OffloadingIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    OffloadingIndication.StatusBuffer = pOffload;
+    OffloadingIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD);
+    NdisFIndicateStatus(pModuleCtx->hFilter, &OffloadingIndication);
+}
+
+
+static NDIS_STATUS vboxNetLwfWinRestart(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_RESTART_PARAMETERS pParameters)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Restarting, LwfState_Paused);
+#if 1
+    if (pModuleCtx->fOffloadConfigValid)
+    {
+        if (ASMAtomicReadBool(&pModuleCtx->fActive))
+        {
+            /* Disable offloading temporarily by indicating offload config change. */
+            /** @todo Be sure to revise this when implementing offloading support! */
+            NDIS_OFFLOAD OffloadConfig;
+            OffloadConfig = pModuleCtx->SavedOffloadConfig;
+            OffloadConfig.Checksum.IPv4Transmit.Encapsulation               = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Transmit.IpOptionsSupported          = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Transmit.TcpOptionsSupported         = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Transmit.TcpChecksum                 = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Transmit.UdpChecksum                 = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Transmit.IpChecksum                  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.Encapsulation                = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.IpOptionsSupported           = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.TcpOptionsSupported          = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.TcpChecksum                  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.UdpChecksum                  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv4Receive.IpChecksum                   = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Transmit.Encapsulation               = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Transmit.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Transmit.TcpOptionsSupported         = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Transmit.TcpChecksum                 = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Transmit.UdpChecksum                 = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Receive.Encapsulation                = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Receive.IpExtensionHeadersSupported  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Receive.TcpOptionsSupported          = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Receive.TcpChecksum                  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.Checksum.IPv6Receive.UdpChecksum                  = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.LsoV1.IPv4.Encapsulation                          = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.LsoV1.IPv4.TcpOptions                             = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.LsoV1.IPv4.IpOptions                              = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.LsoV2.IPv4.Encapsulation                          = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.LsoV2.IPv6.Encapsulation                          = NDIS_ENCAPSULATION_NOT_SUPPORTED;
+            OffloadConfig.LsoV2.IPv6.IpExtensionHeadersSupported            = NDIS_OFFLOAD_NOT_SUPPORTED;
+            OffloadConfig.LsoV2.IPv6.TcpOptionsSupported                    = NDIS_OFFLOAD_NOT_SUPPORTED;
+            vboxNetLwfWinIndicateOffload(pModuleCtx, &OffloadConfig);
+            Log((__FUNCTION__": set offloading off\n"));
+        }
+        else
+        {
+            /* The filter is inactive -- restore offloading configuration. */
+            vboxNetLwfWinIndicateOffload(pModuleCtx, &pModuleCtx->SavedOffloadConfig);
+            Log((__FUNCTION__": restored offloading config\n"));
+        }
+    }
+#endif
+
+    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Running, LwfState_Restarting);
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    LogFlow(("<=="__FUNCTION__": Status = 0x%x\n", Status));
+    return Status;
+}
+
+
+static void vboxNetLwfWinDumpPackets(const char *pszMsg, PNET_BUFFER_LIST pBufLists)
+{
+    for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
+    {
+        for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
+        {
+            Log(("%s packet: cb=%d\n", pszMsg, NET_BUFFER_DATA_LENGTH(pBuf)));
+        }
+    }
+}
+
+DECLINLINE(const char *) vboxNetLwfWinEthTypeStr(uint16_t uType)
+{
+    switch (uType)
+    {
+        case RTNET_ETHERTYPE_IPV4: return "IP";
+        case RTNET_ETHERTYPE_IPV6: return "IPv6";
+        case RTNET_ETHERTYPE_ARP:  return "ARP";
+    }
+    return "unknown";
+}
+
+#define VBOXNETLWF_PKTDMPSIZE 0x50
+
+/**
+ * Dump a packet to debug log.
+ *
+ * @param   cpPacket    The packet.
+ * @param   cb          The size of the packet.
+ * @param   cszText     A string denoting direction of packet transfer.
+ */
+DECLINLINE(void) vboxNetLwfWinDumpPacket(PCINTNETSG pSG, const char *cszText)
+{
+    uint8_t bPacket[VBOXNETLWF_PKTDMPSIZE];
+
+    uint32_t cb = pSG->cbTotal < VBOXNETLWF_PKTDMPSIZE ? pSG->cbTotal : VBOXNETLWF_PKTDMPSIZE;
+    IntNetSgReadEx(pSG, 0, cb, bPacket);
+
+    AssertReturnVoid(cb >= 14);
+
+    uint8_t *pHdr = bPacket;
+    uint8_t *pEnd = bPacket + cb;
+    AssertReturnVoid(pEnd - pHdr >= 14);
+    uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+12));
+    Log2(("NetLWF: %s (%d bytes), %RTmac => %RTmac, EthType=%s(0x%x)\n",
+          cszText, cb, pHdr+6, pHdr, vboxNetLwfWinEthTypeStr(uEthType), uEthType));
+    pHdr += sizeof(RTNETETHERHDR);
+    if (uEthType == RTNET_ETHERTYPE_VLAN)
+    {
+        AssertReturnVoid(pEnd - pHdr >= 4);
+        uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+2));
+        Log2((" + VLAN: id=%d EthType=%s(0x%x)\n", RT_N2H_U16(*(uint16_t*)(pHdr)) & 0xFFF,
+              vboxNetLwfWinEthTypeStr(uEthType), uEthType));
+        pHdr += 2 * sizeof(uint16_t);
+    }
+    uint8_t uProto = 0xFF;
+    switch (uEthType)
+    {
+        case RTNET_ETHERTYPE_IPV6:
+            AssertReturnVoid(pEnd - pHdr >= 40);
+            uProto = pHdr[6];
+            Log2((" + IPv6: %RTnaipv6 => %RTnaipv6\n", pHdr+8, pHdr+24));
+            pHdr += 40;
+            break;
+        case RTNET_ETHERTYPE_IPV4:
+            AssertReturnVoid(pEnd - pHdr >= 20);
+            uProto = pHdr[9];
+            Log2((" + IP: %RTnaipv4 => %RTnaipv4\n", *(uint32_t*)(pHdr+12), *(uint32_t*)(pHdr+16)));
+            pHdr += (pHdr[0] & 0xF) * 4;
+            break;
+        case RTNET_ETHERTYPE_ARP:
+            AssertReturnVoid(pEnd - pHdr >= 28);
+            AssertReturnVoid(RT_N2H_U16(*(uint16_t*)(pHdr+2)) == RTNET_ETHERTYPE_IPV4);
+            switch (RT_N2H_U16(*(uint16_t*)(pHdr+6)))
+            {
+                case 1: /* ARP request */
+                    Log2((" + ARP-REQ: who-has %RTnaipv4 tell %RTnaipv4\n",
+                          *(uint32_t*)(pHdr+24), *(uint32_t*)(pHdr+14)));
+                    break;
+                case 2: /* ARP reply */
+                    Log2((" + ARP-RPL: %RTnaipv4 is-at %RTmac\n",
+                          *(uint32_t*)(pHdr+14), pHdr+8));
+                    break;
+                default:
+                    Log2((" + ARP: unknown op %d\n", RT_N2H_U16(*(uint16_t*)(pHdr+6))));
+                    break;
+            }
+            break;
+        /* There is no default case as uProto is initialized with 0xFF */
+    }
+    while (uProto != 0xFF)
+    {
+        switch (uProto)
+        {
+            case 0:  /* IPv6 Hop-by-Hop option*/
+            case 60: /* IPv6 Destination option*/
+            case 43: /* IPv6 Routing option */
+            case 44: /* IPv6 Fragment option */
+                Log2((" + IPv6 option (%d): <not implemented>\n", uProto));
+                uProto = pHdr[0];
+                pHdr += pHdr[1] * 8 + 8; /* Skip to the next extension/protocol */
+                break;
+            case 51: /* IPv6 IPsec AH */
+                Log2((" + IPv6 IPsec AH: <not implemented>\n"));
+                uProto = pHdr[0];
+                pHdr += (pHdr[1] + 2) * 4; /* Skip to the next extension/protocol */
+                break;
+            case 50: /* IPv6 IPsec ESP */
+                /* Cannot decode IPsec, fall through */
+                Log2((" + IPv6 IPsec ESP: <not implemented>\n"));
+                uProto = 0xFF;
+                break;
+            case 59: /* No Next Header */
+                Log2((" + IPv6 No Next Header\n"));
+                uProto = 0xFF;
+                break;
+            case 58: /* IPv6-ICMP */
+                switch (pHdr[0])
+                {
+                    case 1:   Log2((" + IPv6-ICMP: destination unreachable, code %d\n", pHdr[1])); break;
+                    case 128: Log2((" + IPv6-ICMP: echo request\n")); break;
+                    case 129: Log2((" + IPv6-ICMP: echo reply\n")); break;
+                    default:  Log2((" + IPv6-ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
+                }
+                uProto = 0xFF;
+                break;
+            case 1: /* ICMP */
+                switch (pHdr[0])
+                {
+                    case 0:  Log2((" + ICMP: echo reply\n")); break;
+                    case 8:  Log2((" + ICMP: echo request\n")); break;
+                    case 3:  Log2((" + ICMP: destination unreachable, code %d\n", pHdr[1])); break;
+                    default: Log2((" + ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
+                }
+                uProto = 0xFF;
+                break;
+            case 6: /* TCP */
+                Log2((" + TCP: src=%d dst=%d seq=%x ack=%x\n",
+                      RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2)),
+                      RT_N2H_U32(*(uint32_t*)(pHdr+4)), RT_N2H_U32(*(uint32_t*)(pHdr+8))));
+                uProto = 0xFF;
+                break;
+            case 17: /* UDP */
+                Log2((" + UDP: src=%d dst=%d\n",
+                      RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2))));
+                uProto = 0xFF;
+                break;
+            default:
+                Log2((" + Unknown: proto=0x%x\n", uProto));
+                uProto = 0xFF;
+                break;
+        }
+    }
+    Log3(("%.*Rhxd\n", cb, bPacket));
+}
+
+static void vboxNetLwfWinDestroySG(PINTNETSG pSG)
+{
+    NdisFreeMemory(pSG, 0, 0);
+    Log4((__FUNCTION__ ": freed SG 0x%p\n", pSG));
+}
+
+DECLINLINE(ULONG) vboxNetLwfWinCalcSegments(PNET_BUFFER pNetBuf)
+{
+    ULONG cSegs = 0;
+    for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); pMdl; pMdl = NDIS_MDL_LINKAGE(pMdl))
+        cSegs++;
+    return cSegs;
+}
+
+DECLINLINE(void) vboxNetLwfWinFreeMdlChain(PMDL pMdl)
+{
+#ifdef VBOXNETLWF_SYNC_SEND
+    PMDL pMdlNext;
+    while (pMdl)
+    {
+        pMdlNext = pMdl->Next;
+        NdisFreeMdl(pMdl);
+        Log4((__FUNCTION__ ": freed MDL 0x%p\n", pMdl));
+        pMdl = pMdlNext;
+    }
+#endif /* VBOXNETLWF_SYNC_SEND */
+}
+
+/** @todo
+ * 1) Copy data from SG to MDL (if we decide to complete asynchronously).
+ * 2) Provide context/backfill space. Nobody does it, should we?
+ * 3) We always get a single segment from intnet. Simplify?
+ */
+static PNET_BUFFER_LIST vboxNetLwfWinSGtoNB(PVBOXNETLWF_MODULE pModule, PINTNETSG pSG)
+{
+    AssertReturn(pSG->cSegsUsed >= 1, NULL);
+    LogFlow(("==>"__FUNCTION__": segments=%d\n", pSG->cSegsUsed));
+
+#ifdef VBOXNETLWF_SYNC_SEND
+    PINTNETSEG pSeg = pSG->aSegs;
+    PMDL pMdl = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb);
+    if (!pMdl)
+    {
+        Log(("ERROR! "__FUNCTION__": failed to allocate an MDL\n"));
+        LogFlow(("<=="__FUNCTION__": return NULL\n"));
+        return NULL;
+    }
+    Log4((__FUNCTION__ ": allocated Mdl 0x%p\n", pMdl));
+    PMDL pMdlCurr = pMdl;
+    for (int i = 1; i < pSG->cSegsUsed; i++)
+    {
+        pSeg = &pSG->aSegs[i];
+        pMdlCurr->Next = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb);
+        if (!pMdlCurr->Next)
+        {
+            Log(("ERROR! "__FUNCTION__": failed to allocate an MDL\n"));
+            /* Tear down all MDL we chained so far */
+            vboxNetLwfWinFreeMdlChain(pMdl);
+            return NULL;
+        }
+        pMdlCurr = pMdlCurr->Next;
+        Log4((__FUNCTION__ ": allocated Mdl 0x%p\n", pMdlCurr));
+    }
+    PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferAndNetBufferList(pModule->hPool,
+                                                                      0 /* ContextSize */,
+                                                                      0 /* ContextBackFill */,
+                                                                      pMdl,
+                                                                      0 /* DataOffset */,
+                                                                      pSG->cbTotal);
+    if (pBufList)
+    {
+        Log4((__FUNCTION__ ": allocated NBL+NB 0x%p\n", pBufList));
+        pBufList->SourceHandle = pModule->hFilter;
+        /** @todo Do we need to initialize anything else? */
+    }
+    else
+    {
+        Log(("ERROR! "__FUNCTION__": failed to allocate an NBL+NB\n"));
+        vboxNetLwfWinFreeMdlChain(pMdl);
+    }
+#else /* !VBOXNETLWF_SYNC_SEND */
+    AssertReturn(pSG->cbTotal < 2048, NULL);
+    PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferList(pModule->hPool,
+                                                          0 /** @todo ContextSize */,
+                                                          0 /** @todo ContextBackFill */);
+    NET_BUFFER_LIST_NEXT_NBL(pBufList) = NULL; /** @todo Is it even needed? */
+    NET_BUFFER *pBuffer = NET_BUFFER_LIST_FIRST_NB(pBufList);
+    NDIS_STATUS Status = NdisRetreatNetBufferDataStart(pBuffer, pSG->cbTotal, 0 /** @todo DataBackfill */, NULL);
+    if (Status == NDIS_STATUS_SUCCESS)
+    {
+        uint8_t *pDst = (uint8_t*)NdisGetDataBuffer(pBuffer, pSG->cbTotal, NULL, 1, 0);
+        if (pDst)
+        {
+            for (int i = 0; i < pSG->cSegsUsed; i++)
+            {
+                NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb);
+                pDst += pSG->aSegs[i].cb;
+            }
+            Log4((__FUNCTION__ ": allocated NBL+NB+MDL+Data 0x%p\n", pBufList));
+            pBufList->SourceHandle = pModule->hFilter;
+            /** @todo Do we need to initialize anything else? */
+        }
+        else
+        {
+            Log((__FUNCTION__": failed to obtain the buffer pointer (size=%u)\n", pSG->cbTotal));
+            NdisAdvanceNetBufferDataStart(pBuffer, pSG->cbTotal, false, NULL); /** @todo why bother? */
+            NdisFreeNetBufferList(pBufList);
+            pBufList = NULL;
+        }
+    }
+    else
+    {
+        Log((__FUNCTION__": NdisRetreatNetBufferDataStart failed with 0x%x (size=%u)\n", Status, pSG->cbTotal));
+        NdisFreeNetBufferList(pBufList);
+        pBufList = NULL;
+    }
+#endif /* !VBOXNETLWF_SYNC_SEND */
+    LogFlow(("<=="__FUNCTION__": return %p\n", pBufList));
+    return pBufList;
+}
+
+static PINTNETSG vboxNetLwfWinNBtoSG(PVBOXNETLWF_MODULE pModule, PNET_BUFFER pNetBuf)
+{
+    ULONG cbPacket = NET_BUFFER_DATA_LENGTH(pNetBuf);
+    UINT cSegs = vboxNetLwfWinCalcSegments(pNetBuf);
+    /* Allocate and initialize SG */
+    PINTNETSG pSG = (PINTNETSG)NdisAllocateMemoryWithTagPriority(pModule->hFilter,
+                                                                 RT_OFFSETOF(INTNETSG, aSegs[cSegs]),
+                                                                 VBOXNETLWF_MEM_TAG,
+                                                                 NormalPoolPriority);
+    AssertReturn(pSG, pSG);
+    Log4((__FUNCTION__ ": allocated SG 0x%p\n", pSG));
+    IntNetSgInitTempSegs(pSG, cbPacket /*cbTotal*/, cSegs, cSegs /*cSegsUsed*/);
+
+    int rc = NDIS_STATUS_SUCCESS;
+    ULONG uOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuf);
+    cSegs = 0;
+    for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf);
+         pMdl != NULL && cbPacket > 0;
+         pMdl = NDIS_MDL_LINKAGE(pMdl))
+    {
+        PUCHAR pSrc = (PUCHAR)MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);
+        if (!pSrc)
+        {
+            rc = NDIS_STATUS_RESOURCES;
+            break;
+        }
+        ULONG cbSrc = MmGetMdlByteCount(pMdl);
+        if (uOffset)
+        {
+            Assert(uOffset < cbSrc);
+            pSrc  += uOffset;
+            cbSrc -= uOffset;
+            uOffset = 0;
+        }
+
+        if (cbSrc > cbPacket)
+            cbSrc = cbPacket;
+
+        pSG->aSegs[cSegs].pv = pSrc;
+        pSG->aSegs[cSegs].cb = cbSrc;
+        pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS;
+        cSegs++;
+        cbPacket -= cbSrc;
+    }
+
+    Assert(cSegs <= pSG->cSegsAlloc);
+
+    if (RT_FAILURE(rc))
+    {
+        vboxNetLwfWinDestroySG(pSG);
+        pSG = NULL;
+    }
+    else
+    {
+        Assert(cbPacket == 0);
+        Assert(pSG->cSegsUsed == cSegs);
+    }
+    return pSG;
+}
+
+VOID vboxNetLwfWinStatus(IN NDIS_HANDLE hModuleCtx, IN PNDIS_STATUS_INDICATION pIndication)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)hModuleCtx;
+    Log((__FUNCTION__"Status indication: %s\n", vboxNetLwfWinStatusToText(pIndication->StatusCode)));
+    switch (pIndication->StatusCode)
+    {
+        case NDIS_STATUS_PACKET_FILTER:
+            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pIndication->StatusBuffer);
+            break;
+        case NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG:
+            Log5((__FUNCTION__": offloading currently set to:\n"));
+            vboxNetLwfWinDumpOffloadSettings((PNDIS_OFFLOAD)pIndication->StatusBuffer);
+            break;
+    }
+    NdisFIndicateStatus(pModule->hFilter, pIndication);
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+static bool vboxNetLwfWinForwardToIntNet(PVBOXNETLWF_MODULE pModuleCtx, PNET_BUFFER_LIST pBufLists, uint32_t fSrc)
+{
+    /* We must not forward anything to the trunk unless it is ready to receive. */
+    if (!ASMAtomicReadBool(&pModuleCtx->fActive))
+    {
+        Log((__FUNCTION__": trunk is inactive, won't forward\n"));
+        return false;
+    }
+
+    AssertReturn(pModuleCtx->pNetFlt, false);
+    AssertReturn(pModuleCtx->pNetFlt->pSwitchPort, false);
+    AssertReturn(pModuleCtx->pNetFlt->pSwitchPort->pfnRecv, false);
+    LogFlow(("==>"__FUNCTION__": module=%p\n", pModuleCtx));
+    Assert(pBufLists);                                                   /* The chain must contain at least one list */
+    Assert(NET_BUFFER_LIST_NEXT_NBL(pBufLists) == NULL); /* The caller is supposed to unlink the list from the chain */
+    /*
+     * Even if NBL contains more than one buffer we are prepared to deal with it.
+     * When any of buffers should not be dropped we keep the whole list. It is
+     * better to leak some "unexpected" packets to the wire/host than to loose any.
+     */
+    bool fDropIt   = false;
+    bool fDontDrop = false;
+    int nLists = 0;
+    for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
+    {
+        int nBuffers = 0;
+        nLists++;
+        for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
+        {
+            nBuffers++;
+            PINTNETSG pSG = vboxNetLwfWinNBtoSG(pModuleCtx, pBuf);
+            if (pSG)
+            {
+                vboxNetLwfWinDumpPacket(pSG, (fSrc & INTNETTRUNKDIR_WIRE)?"intnet <-- wire":"intnet <-- host");
+                /* A bit paranoid, but we do not use any locks, so... */
+                if (ASMAtomicReadBool(&pModuleCtx->fActive))
+                    if (pModuleCtx->pNetFlt->pSwitchPort->pfnRecv(pModuleCtx->pNetFlt->pSwitchPort, NULL, pSG, fSrc))
+                        fDropIt = true;
+                    else
+                        fDontDrop = true;
+                vboxNetLwfWinDestroySG(pSG);
+            }
+        }
+        Log((__FUNCTION__": list=%d buffers=%d\n", nLists, nBuffers));
+    }
+    Log((__FUNCTION__": lists=%d drop=%s don't=%s\n", nLists, fDropIt ? "true":"false", fDontDrop ? "true":"false"));
+    LogFlow(("<=="__FUNCTION__": return '%s'\n",
+             fDropIt ? (fDontDrop ? "do not drop (some)" : "drop it") : "do not drop (any)"));
+    return fDropIt && !fDontDrop; /* Drop the list if ALL its buffers are being dropped! */
+}
+
+DECLINLINE(bool) vboxNetLwfWinIsRunning(PVBOXNETLWF_MODULE pModule)
+{
+    Log((__FUNCTION__": state=%d\n", ASMAtomicReadU32(&pModule->enmState)));
+    return ASMAtomicReadU32(&pModule->enmState) == LwfState_Running;
+}
+
+VOID vboxNetLwfWinSendNetBufferLists(IN NDIS_HANDLE hModuleCtx, IN PNET_BUFFER_LIST pBufLists, IN NDIS_PORT_NUMBER nPort, IN ULONG fFlags)
+{
+    size_t cb = 0;
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)hModuleCtx;
+    if (vboxNetLwfWinIsRunning(pModule))
+    {
+        PNET_BUFFER_LIST pNext     = NULL;
+        PNET_BUFFER_LIST pDropHead = NULL;
+        PNET_BUFFER_LIST pDropTail = NULL;
+        PNET_BUFFER_LIST pPassHead = NULL;
+        PNET_BUFFER_LIST pPassTail = NULL;
+        for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = pNext)
+        {
+            pNext = NET_BUFFER_LIST_NEXT_NBL(pList);
+            NET_BUFFER_LIST_NEXT_NBL(pList) = NULL; /* Unlink */
+            if (vboxNetLwfWinForwardToIntNet(pModule, pList, INTNETTRUNKDIR_HOST))
+            {
+                NET_BUFFER_LIST_STATUS(pList) = NDIS_STATUS_SUCCESS;
+                if (pDropHead)
+                {
+                    NET_BUFFER_LIST_NEXT_NBL(pDropTail) = pList;
+                    pDropTail = pList;
+                }
+                else
+                    pDropHead = pDropTail = pList;
+            }
+            else
+            {
+                if (pPassHead)
+                {
+                    NET_BUFFER_LIST_NEXT_NBL(pPassTail) = pList;
+                    pPassTail = pList;
+                }
+                else
+                    pPassHead = pPassTail = pList;
+            }
+        }
+        Assert((pBufLists == pPassHead) || (pBufLists == pDropHead));
+        if (pPassHead)
+        {
+            vboxNetLwfWinDumpPackets(__FUNCTION__": passing down", pPassHead);
+            NdisFSendNetBufferLists(pModule->hFilter, pBufLists, nPort, fFlags);
+        }
+        if (pDropHead)
+        {
+            vboxNetLwfWinDumpPackets(__FUNCTION__": consumed", pDropHead);
+            NdisFSendNetBufferListsComplete(pModule->hFilter, pDropHead,
+                                            fFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
+        }
+    }
+    else
+    {
+        for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
+        {
+            NET_BUFFER_LIST_STATUS(pList) = NDIS_STATUS_PAUSED;
+        }
+        vboxNetLwfWinDumpPackets(__FUNCTION__": consumed", pBufLists);
+        NdisFSendNetBufferListsComplete(pModule->hFilter, pBufLists,
+                                        fFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
+        
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+VOID vboxNetLwfWinSendNetBufferListsComplete(IN NDIS_HANDLE hModuleCtx, IN PNET_BUFFER_LIST pBufLists, IN ULONG fFlags)
+{
+    size_t cb = 0;
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)hModuleCtx;
+    PNET_BUFFER_LIST pList = pBufLists;
+    PNET_BUFFER_LIST pNextList;
+    PNET_BUFFER_LIST pPrevList = NULL;
+    while (pList)
+    {
+        pNextList = NET_BUFFER_LIST_NEXT_NBL(pList);
+        if (pList->SourceHandle == pModule->hFilter)
+        {
+            /* We allocated this NET_BUFFER_LIST, let's free it up */
+            Assert(NET_BUFFER_LIST_FIRST_NB(pList));
+            Assert(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
+            /*
+             * All our NBLs hold a single NB each, no need to iterate over a list.
+             * There is no need to free an associated NB explicitly either, as it was
+             * preallocated with NBL structure.
+             */
+            Assert(!NET_BUFFER_NEXT_NB(NET_BUFFER_LIST_FIRST_NB(pList)));
+            vboxNetLwfWinFreeMdlChain(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
+            /* Unlink this list from the chain */
+            if (pPrevList)
+                NET_BUFFER_LIST_NEXT_NBL(pPrevList) = pNextList;
+            else
+                pBufLists = pNextList;
+            Log((__FUNCTION__": our list %p, next=%p, previous=%p, head=%p\n", pList, pNextList, pPrevList, pBufLists));
+            NdisFreeNetBufferList(pList);
+#ifdef VBOXNETLWF_SYNC_SEND
+            Log4((__FUNCTION__ ": freed NBL+NB 0x%p\n", pList));
+            KeSetEvent(&pModule->EventWire, 0, FALSE);
+#else /* !VBOXNETLWF_SYNC_SEND */
+            Log4((__FUNCTION__ ": freed NBL+NB+MDL+Data 0x%p\n", pList));
+            Assert(ASMAtomicReadS32(&pModule->cPendingBuffers) > 0);
+            if (ASMAtomicDecS32(&pModule->cPendingBuffers) == 0)
+                NdisSetEvent(&pModule->EventSendComplete);
+#endif /* !VBOXNETLWF_SYNC_SEND */
+        }
+        else
+        {
+            pPrevList = pList;
+            Log((__FUNCTION__": passing list %p, next=%p, previous=%p, head=%p\n", pList, pNextList, pPrevList, pBufLists));
+        }
+        pList = pNextList;
+    }
+    if (pBufLists)
+    {
+        /* There are still lists remaining in the chain, pass'em up */
+        NdisFSendNetBufferListsComplete(pModule->hFilter, pBufLists, fFlags);
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+VOID vboxNetLwfWinReceiveNetBufferLists(IN NDIS_HANDLE hModuleCtx,
+                                        IN PNET_BUFFER_LIST pBufLists,
+                                        IN NDIS_PORT_NUMBER nPort,
+                                        IN ULONG nBufLists,
+                                        IN ULONG fFlags)
+{
+    /// @todo Do we need loopback handling?
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)hModuleCtx;
+    if (vboxNetLwfWinIsRunning(pModule))
+    {
+        if (NDIS_TEST_RECEIVE_CANNOT_PEND(fFlags))
+        {
+            /* We do not own NBLs so we do not need to return them */
+            /* First we need to scan through the list to see if some packets must be dropped */
+            bool bDropIt = false;
+            for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
+            {
+                PNET_BUFFER_LIST pNext = NET_BUFFER_LIST_NEXT_NBL(pList);
+                NET_BUFFER_LIST_NEXT_NBL(pList) = NULL; /* Unlink temporarily */
+                if (vboxNetLwfWinForwardToIntNet(pModule, pList, INTNETTRUNKDIR_WIRE))
+                    bDropIt = true;
+                NET_BUFFER_LIST_NEXT_NBL(pList) = pNext; /* Restore the link */
+            }
+            if (bDropIt)
+            {
+                /* Some NBLs must be dropped, indicate selectively one by one */
+                for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
+                {
+                    PNET_BUFFER_LIST pNext = NET_BUFFER_LIST_NEXT_NBL(pList);
+                    NET_BUFFER_LIST_NEXT_NBL(pList) = NULL; /* Unlink temporarily */
+                    vboxNetLwfWinDumpPackets(__FUNCTION__": passing up", pList);
+                    NdisFIndicateReceiveNetBufferLists(pModule->hFilter, pList, nPort, nBufLists, fFlags);
+                    NET_BUFFER_LIST_NEXT_NBL(pList) = pNext; /* Restore the link */
+                }
+            }
+            else
+            {
+                /* All NBLs must be indicated, do it in bulk. */
+                vboxNetLwfWinDumpPackets(__FUNCTION__": passing up", pBufLists);
+                NdisFIndicateReceiveNetBufferLists(pModule->hFilter, pBufLists, nPort, nBufLists, fFlags);
+            }
+        }
+        else
+        {
+            /* We collect dropped NBLs in a separate list in order to "return" them. */
+            PNET_BUFFER_LIST pNext     = NULL;
+            PNET_BUFFER_LIST pDropHead = NULL;
+            PNET_BUFFER_LIST pDropTail = NULL;
+            PNET_BUFFER_LIST pPassHead = NULL;
+            PNET_BUFFER_LIST pPassTail = NULL;
+            ULONG nDrop = 0, nPass = 0;
+            for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = pNext)
+            {
+                pNext = NET_BUFFER_LIST_NEXT_NBL(pList);
+                NET_BUFFER_LIST_NEXT_NBL(pList) = NULL; /* Unlink */
+                if (vboxNetLwfWinForwardToIntNet(pModule, pList, INTNETTRUNKDIR_WIRE))
+                {
+                    if (nDrop++)
+                    {
+                        NET_BUFFER_LIST_NEXT_NBL(pDropTail) = pList;
+                        pDropTail = pList;
+                    }
+                    else
+                        pDropHead = pDropTail = pList;
+                }
+                else
+                {
+                    if (nPass++)
+                    {
+                        NET_BUFFER_LIST_NEXT_NBL(pPassTail) = pList;
+                        pPassTail = pList;
+                    }
+                    else
+                        pPassHead = pPassTail = pList;
+                }
+            }
+            Assert((pBufLists == pPassHead) || (pBufLists == pDropHead));
+            Assert(nDrop + nPass == nBufLists);
+            if (pPassHead)
+            {
+                vboxNetLwfWinDumpPackets(__FUNCTION__": passing up", pPassHead);
+                NdisFIndicateReceiveNetBufferLists(pModule->hFilter, pPassHead, nPort, nPass, fFlags);
+            }
+            if (pDropHead)
+            {
+                vboxNetLwfWinDumpPackets(__FUNCTION__": consumed", pDropHead);
+                NdisFReturnNetBufferLists(pModule->hFilter, pDropHead,
+                                          fFlags & NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0);
+            }
+        }
+
+    }
+    else
+    {
+        vboxNetLwfWinDumpPackets(__FUNCTION__": consumed", pBufLists);
+        if ((fFlags & NDIS_RECEIVE_FLAGS_RESOURCES) == 0)
+            NdisFReturnNetBufferLists(pModule->hFilter, pBufLists,
+                                      fFlags & NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0);
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+VOID vboxNetLwfWinReturnNetBufferLists(IN NDIS_HANDLE hModuleCtx, IN PNET_BUFFER_LIST pBufLists, IN ULONG fFlags)
+{
+    size_t cb = 0;
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)hModuleCtx;
+    PNET_BUFFER_LIST pList = pBufLists;
+    PNET_BUFFER_LIST pNextList;
+    PNET_BUFFER_LIST pPrevList = NULL;
+    /** @todo Move common part into a separate function to be used by vboxNetLwfWinSendNetBufferListsComplete() as well */
+    while (pList)
+    {
+        pNextList = NET_BUFFER_LIST_NEXT_NBL(pList);
+        if (pList->SourceHandle == pModule->hFilter)
+        {
+            /* We allocated this NET_BUFFER_LIST, let's free it up */
+            Assert(NET_BUFFER_LIST_FIRST_NB(pList));
+            Assert(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
+            /*
+             * All our NBLs hold a single NB each, no need to iterate over a list.
+             * There is no need to free an associated NB explicitly either, as it was
+             * preallocated with NBL structure.
+             */
+            vboxNetLwfWinFreeMdlChain(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
+            /* Unlink this list from the chain */
+            if (pPrevList)
+                NET_BUFFER_LIST_NEXT_NBL(pPrevList) = pNextList;
+            else
+                pBufLists = pNextList;
+            NdisFreeNetBufferList(pList);
+#ifdef VBOXNETLWF_SYNC_SEND
+            Log4((__FUNCTION__ ": freed NBL+NB 0x%p\n", pList));
+            KeSetEvent(&pModule->EventHost, 0, FALSE);
+#else /* !VBOXNETLWF_SYNC_SEND */
+            Log4((__FUNCTION__ ": freed NBL+NB+MDL+Data 0x%p\n", pList));
+            Assert(ASMAtomicReadS32(&pModule->cPendingBuffers) > 0);
+            if (ASMAtomicDecS32(&pModule->cPendingBuffers) == 0)
+                NdisSetEvent(&pModule->EventSendComplete);
+#endif /* !VBOXNETLWF_SYNC_SEND */
+        }
+        else
+            pPrevList = pList;
+        pList = pNextList;
+    }
+    if (pBufLists)
+    {
+        /* There are still lists remaining in the chain, pass'em up */
+        NdisFReturnNetBufferLists(pModule->hFilter, pBufLists, fFlags);
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+NDIS_STATUS vboxNetLwfWinSetModuleOptions(IN NDIS_HANDLE hModuleCtx)
+{
+    LogFlow(("==>"__FUNCTION__": module=%p\n", hModuleCtx));
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
+    NDIS_FILTER_PARTIAL_CHARACTERISTICS PChars;
+
+    NdisZeroMemory(&PChars, sizeof(PChars));
+
+    PChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_PARTIAL_CHARACTERISTICS;
+    PChars.Header.Size = NDIS_SIZEOF_FILTER_PARTIAL_CHARACTERISTICS_REVISION_1;
+    PChars.Header.Revision = NDIS_FILTER_PARTIAL_CHARACTERISTICS_REVISION_1;
+
+    if (ASMAtomicReadBool(&pModuleCtx->fActive))
+    {
+        Log((__FUNCTION__": active mode\n"));
+        PChars.SendNetBufferListsHandler = vboxNetLwfWinSendNetBufferLists;
+        PChars.SendNetBufferListsCompleteHandler = vboxNetLwfWinSendNetBufferListsComplete;
+        PChars.ReceiveNetBufferListsHandler = vboxNetLwfWinReceiveNetBufferLists;
+        PChars.ReturnNetBufferListsHandler = vboxNetLwfWinReturnNetBufferLists;
+    }
+    else
+    {
+        Log((__FUNCTION__": bypass mode\n"));
+    }
+    NDIS_STATUS Status = NdisSetOptionalHandlers(pModuleCtx->hFilter,
+                                                 (PNDIS_DRIVER_OPTIONAL_HANDLERS)&PChars);
+    LogFlow(("<=="__FUNCTION__": status=0x%x\n", Status));
+    return Status;
+}
+
+/**
+ * register the filter driver
+ */
+DECLHIDDEN(NDIS_STATUS) vboxNetLwfWinRegister(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPathStr)
+{
+    NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
+    NDIS_STRING FriendlyName;
+    NDIS_STRING UniqueName;
+    NDIS_STRING ServiceName;
+
+    NdisInitUnicodeString(&FriendlyName, VBOXNETLWF_NAME_FRIENDLY);
+    NdisInitUnicodeString(&UniqueName, VBOXNETLWF_NAME_UNIQUE);
+    NdisInitUnicodeString(&ServiceName, VBOXNETLWF_NAME_SERVICE);
+
+    NdisZeroMemory(&FChars, sizeof (FChars));
+
+    FChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
+    FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
+    FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;
+
+    FChars.MajorNdisVersion = VBOXNETLWF_VERSION_NDIS_MAJOR;
+    FChars.MinorNdisVersion = VBOXNETLWF_VERSION_NDIS_MINOR;
+
+    FChars.FriendlyName = FriendlyName;
+    FChars.UniqueName = UniqueName;
+    FChars.ServiceName = ServiceName;
+
+    /* Mandatory functions */
+    FChars.AttachHandler = vboxNetLwfWinAttach;
+    FChars.DetachHandler = vboxNetLwfWinDetach;
+    FChars.RestartHandler = vboxNetLwfWinRestart;
+    FChars.PauseHandler = vboxNetLwfWinPause;
+
+    /* Optional functions, non changeble at run-time */
+    FChars.OidRequestHandler = vboxNetLwfWinOidRequest;
+    FChars.OidRequestCompleteHandler = vboxNetLwfWinOidRequestComplete;
+    //FChars.CancelOidRequestHandler = vboxNetLwfWinCancelOidRequest;
+    FChars.StatusHandler = vboxNetLwfWinStatus;
+    //FChars.NetPnPEventHandler = vboxNetLwfWinPnPEvent;
+    FChars.SetFilterModuleOptionsHandler = vboxNetLwfWinSetModuleOptions;
+
+    /* Optional functions */
+    FChars.SendNetBufferListsHandler = vboxNetLwfWinSendNetBufferLists;
+    FChars.SendNetBufferListsCompleteHandler = vboxNetLwfWinSendNetBufferListsComplete;
+    FChars.ReceiveNetBufferListsHandler = vboxNetLwfWinReceiveNetBufferLists;
+    FChars.ReturnNetBufferListsHandler = vboxNetLwfWinReturnNetBufferLists;
+
+    pDriverObject->DriverUnload = vboxNetLwfWinUnloadDriver;
+
+    NDIS_STATUS Status;
+    g_VBoxNetLwfGlobals.hFilterDriver = NULL;
+    Log(("vboxNetLwfWinRegister: registering filter driver...\n"));
+    Status = NdisFRegisterFilterDriver(pDriverObject,
+                                       (NDIS_HANDLE)&g_VBoxNetLwfGlobals,
+                                       &FChars,
+                                       &g_VBoxNetLwfGlobals.hFilterDriver);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Log(("vboxNetLwfWinRegister: successfully registered filter driver; registering device...\n"));
+        Status = vboxNetLwfWinDevCreate(&g_VBoxNetLwfGlobals);
+        Assert(Status == STATUS_SUCCESS);
+        Log(("vboxNetLwfWinRegister: vboxNetLwfWinDevCreate() returned 0x%x\n", Status));
+    }
+    else
+    {
+        Log(("ERROR! vboxNetLwfWinRegister: failed to register filter driver, status=0x%x", Status));
+    }
+    return Status;
+}
+
+static int vboxNetLwfWinStartInitIdcThread()
+{
+    int rc = VERR_INVALID_STATE;
+
+    if (ASMAtomicCmpXchgU32(&g_VBoxNetLwfGlobals.enmIdcState, LwfIdcState_Connecting, LwfIdcState_Disconnected))
+    {
+        Log((__FUNCTION__": IDC state change Diconnected -> Connecting\n"));
+
+        NTSTATUS Status = PsCreateSystemThread(&g_VBoxNetLwfGlobals.hInitIdcThread,
+                                               THREAD_ALL_ACCESS,
+                                               NULL,
+                                               NULL,
+                                               NULL,
+                                               vboxNetLwfWinInitIdcWorker,
+                                               &g_VBoxNetLwfGlobals);
+        Log((__FUNCTION__": create IDC initialization thread, status=0x%x\n", Status));
+        if (Status != STATUS_SUCCESS)
+        {
+            LogRel(("NETLWF: IDC initialization failed (system thread creation, status=0x%x)\n", Status));
+            /*
+             * We failed to init IDC and there will be no second chance.
+             */
+            Log((__FUNCTION__": IDC state change Connecting -> Diconnected\n"));
+            ASMAtomicWriteU32(&g_VBoxNetLwfGlobals.enmIdcState, LwfIdcState_Disconnected);
+        }
+        rc = RTErrConvertFromNtStatus(Status);
+    }
+    return rc;
+}
+
+static void vboxNetLwfWinStopInitIdcThread()
+{
+}
+
+
+RT_C_DECLS_BEGIN
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath);
+
+RT_C_DECLS_END
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
+{
+    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+    int rc;
+
+    /* the idc registration is initiated via IOCTL since our driver
+     * can be loaded when the VBoxDrv is not in case we are a Ndis IM driver */
+    rc = vboxNetLwfWinInitBase();
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        NdisZeroMemory(&g_VBoxNetLwfGlobals, sizeof (g_VBoxNetLwfGlobals));
+        RTListInit(&g_VBoxNetLwfGlobals.listModules);
+        NdisAllocateSpinLock(&g_VBoxNetLwfGlobals.Lock);
+        /*
+         * We choose to ignore IDC initialization errors here because if we fail to load
+         * our filter the upper protocols won't bind to the associated adapter, causing
+         * network failure at the host. Better to have non-working filter than broken
+         * networking on the host.
+         */
+        rc = vboxNetLwfWinStartInitIdcThread();
+        AssertRC(rc);
+
+        Status = vboxNetLwfWinRegister(pDriverObject, pRegistryPath);
+        Assert(Status == STATUS_SUCCESS);
+        if (Status == NDIS_STATUS_SUCCESS)
+        {
+            Log(("NETLWF: started successfully\n"));
+            return STATUS_SUCCESS;
+        }
+        NdisFreeSpinLock(&g_VBoxNetLwfGlobals.Lock);
+        vboxNetLwfWinFini();
+    }
+    else
+    {
+        Status = NDIS_STATUS_FAILURE;
+    }
+
+    return Status;
+}
+
+
+static VOID vboxNetLwfWinUnloadDriver(IN PDRIVER_OBJECT pDriver)
+{
+    LogFlow(("==>"__FUNCTION__": driver=%p\n", pDriver));
+    vboxNetLwfWinDevDestroy(&g_VBoxNetLwfGlobals);
+    NdisFDeregisterFilterDriver(g_VBoxNetLwfGlobals.hFilterDriver);
+    NdisFreeSpinLock(&g_VBoxNetLwfGlobals.Lock);
+    LogFlow(("<=="__FUNCTION__"\n"));
+    vboxNetLwfWinFini();
+}
+
+static const char *vboxNetLwfWinIdcStateToText(uint32_t enmState)
+{
+    switch (enmState)
+    {
+        case LwfIdcState_Disconnected: return "Disconnected";
+        case LwfIdcState_Connecting: return "Connecting";
+        case LwfIdcState_Connected: return "Connected";
+        case LwfIdcState_Stopping: return "Stopping";
+    }
+    return "Unknown";
+}
+
+static VOID vboxNetLwfWinInitIdcWorker(PVOID pvContext)
+{
+    int rc;
+    PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)pvContext;
+
+    while (ASMAtomicReadU32(&pGlobals->enmIdcState) == LwfIdcState_Connecting)
+    {
+        rc = vboxNetFltInitIdc(&g_VBoxNetFltGlobals);
+        if (RT_SUCCESS(rc))
+        {
+            if (!ASMAtomicCmpXchgU32(&pGlobals->enmIdcState, LwfIdcState_Connected, LwfIdcState_Connecting))
+            {
+                /* The state has been changed (the only valid transition is to "Stopping"), undo init */
+                rc = vboxNetFltTryDeleteIdc(&g_VBoxNetFltGlobals);
+                Log((__FUNCTION__": state change (Connecting -> %s) while initializing IDC, deleted IDC, rc=0x%x\n",
+                     vboxNetLwfWinIdcStateToText(ASMAtomicReadU32(&pGlobals->enmIdcState)), rc));
+            }
+            else
+            {
+                Log((__FUNCTION__": IDC state change Connecting -> Connected\n"));
+            }
+        }
+        else
+        {
+            LARGE_INTEGER WaitIn100nsUnits;
+            WaitIn100nsUnits.QuadPart = -(LONGLONG)10000000; /* 1 sec */
+            KeDelayExecutionThread(KernelMode, FALSE /* non-alertable */, &WaitIn100nsUnits);
+        }
+    }
+    PsTerminateSystemThread(STATUS_SUCCESS);
+}
+
+static int vboxNetLwfWinTryFiniIdc()
+{
+    int rc = VINF_SUCCESS;
+    NTSTATUS Status;
+    PKTHREAD pThread = NULL;
+    uint32_t enmPrevState = ASMAtomicXchgU32(&g_VBoxNetLwfGlobals.enmIdcState, LwfIdcState_Stopping);
+
+    Log((__FUNCTION__": IDC state change %s -> Stopping\n", vboxNetLwfWinIdcStateToText(enmPrevState)));
+
+    switch (enmPrevState)
+    {
+        case LwfIdcState_Disconnected:
+            /* Have not even attempted to connect -- nothing to do. */
+            break;
+        case LwfIdcState_Stopping:
+            /* Impossible, but another thread is alreading doing FiniIdc, bail out */
+            Log(("ERROR: "__FUNCTION__"() called in 'Stopping' state\n"));
+            rc = VERR_INVALID_STATE;
+            break;
+        case LwfIdcState_Connecting:
+            /* the worker thread is running, let's wait for it to stop */
+            Status = ObReferenceObjectByHandle(g_VBoxNetLwfGlobals.hInitIdcThread,
+                                               THREAD_ALL_ACCESS, NULL, KernelMode,
+                                               (PVOID*)&pThread, NULL);
+            if (Status == STATUS_SUCCESS)
+            {
+                KeWaitForSingleObject(pThread, Executive, KernelMode, FALSE, NULL);
+                ObDereferenceObject(pThread);
+            }
+            else
+            {
+                Log(("ERROR in "__FUNCTION__": ObReferenceObjectByHandle(%p) failed with 0x%x\n",
+                     g_VBoxNetLwfGlobals.hInitIdcThread, Status));
+            }
+            rc = RTErrConvertFromNtStatus(Status);
+            break;
+        case LwfIdcState_Connected:
+            /* the worker succeeded in IDC init and terminated */
+            rc = vboxNetFltTryDeleteIdc(&g_VBoxNetFltGlobals);
+            Log((__FUNCTION__": deleted IDC, rc=0x%x\n", rc));
+            break;
+    }
+    return rc;
+}
+
+static void vboxNetLwfWinFiniBase()
+{
+    vboxNetFltDeleteGlobals(&g_VBoxNetFltGlobals);
+
+    /*
+     * Undo the work done during start (in reverse order).
+     */
+    memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
+
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+
+    RTR0Term();
+}
+
+static int vboxNetLwfWinInitBase()
+{
+    int rc = RTR0Init(0);
+    if (!RT_SUCCESS(rc))
+        return rc;
+
+    memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
+    rc = vboxNetFltInitGlobals(&g_VBoxNetFltGlobals);
+    if (!RT_SUCCESS(rc))
+        RTR0Term();
+
+    return rc;
+}
+
+static int vboxNetLwfWinFini()
+{
+    int rc = vboxNetLwfWinTryFiniIdc();
+    if (RT_SUCCESS(rc))
+    {
+        vboxNetLwfWinFiniBase();
+    }
+    return rc;
+}
+
+
+/*
+ *
+ * The OS specific interface definition
+ *
+ */
+
+
+bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p\n", pThis));
+    LogFlow(("<=="__FUNCTION__": return %RTbool\n", !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)));
+    /* AttachToInterface true if disconnected */
+    return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+}
+
+int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
+{
+    int rc = VINF_SUCCESS;
+
+    PVBOXNETLWF_MODULE pModule = (PVBOXNETLWF_MODULE)pThis->u.s.WinIf.hModuleCtx;
+    LogFlow(("==>"__FUNCTION__": instance=%p module=%p\n", pThis, pModule));
+    if (!pModule)
+    {
+        LogFlow(("<=="__FUNCTION__": pModule is null, return %d\n", VERR_INTERNAL_ERROR));
+        return VERR_INTERNAL_ERROR;
+    }
+    /* Prevent going into "paused" state until all transmissions have been completed. */
+    NDIS_WAIT_FOR_MUTEX(&pModule->InTransmit);
+    /* Ignore all sends if the stack is paused or being paused, etc... */
+    if (!vboxNetLwfWinIsRunning(pModule))
+    {
+        NDIS_RELEASE_MUTEX(&pModule->InTransmit);
+        return VINF_SUCCESS;
+    }
+
+    const char *pszDir = (fDst & INTNETTRUNKDIR_WIRE) ?
+        ( (fDst & INTNETTRUNKDIR_HOST) ? "intnet --> all" : "intnet --> wire" ) : "intnet --> host";
+    vboxNetLwfWinDumpPacket(pSG, pszDir);
+    /*
+     * There are two possible strategies to deal with incoming SGs:
+     * 1) make a copy of data and complete asynchronously;
+     * 2) complete synchronously using the original data buffers.
+     * Before we consider implementing (1) it is quite interesting to see
+     * how well (2) performs. So we block until our requests are complete.
+     * Actually there is third possibility -- to use SG retain/release
+     * callbacks, but those seem not be fully implemented yet.
+     * Note that ansynchronous completion will require different implementation
+     * of vboxNetLwfWinPause(), not relying on InTransmit mutex.
+     */
+#ifdef VBOXNETLWF_SYNC_SEND
+    PVOID aEvents[2]; /* To wire and to host */
+    ULONG nEvents = 0;
+    LARGE_INTEGER timeout;
+    timeout.QuadPart = -(LONGLONG)10000000; /* 1 sec */
+#endif /* VBOXNETLWF_SYNC_SEND */
+    if (fDst & INTNETTRUNKDIR_WIRE)
+    {
+        PNET_BUFFER_LIST pBufList = vboxNetLwfWinSGtoNB(pModule, pSG);
+        if (pBufList)
+        {
+#ifdef VBOXNETLWF_SYNC_SEND
+            aEvents[nEvents++] = &pModule->EventWire;
+#else /* !VBOXNETLWF_SYNC_SEND */
+            if (ASMAtomicIncS32(&pModule->cPendingBuffers) == 1)
+                NdisResetEvent(&pModule->EventSendComplete);
+#endif /* !VBOXNETLWF_SYNC_SEND */
+            NdisFSendNetBufferLists(pModule->hFilter, pBufList, NDIS_DEFAULT_PORT_NUMBER, 0); /** @todo sendFlags! */
+        }
+    }
+    if (fDst & INTNETTRUNKDIR_HOST)
+    {
+        PNET_BUFFER_LIST pBufList = vboxNetLwfWinSGtoNB(pModule, pSG);
+        if (pBufList)
+        {
+#ifdef VBOXNETLWF_SYNC_SEND
+            aEvents[nEvents++] = &pModule->EventHost;
+#else /* !VBOXNETLWF_SYNC_SEND */
+            if (ASMAtomicIncS32(&pModule->cPendingBuffers) == 1)
+                NdisResetEvent(&pModule->EventSendComplete);
+#endif /* !VBOXNETLWF_SYNC_SEND */
+            NdisFIndicateReceiveNetBufferLists(pModule->hFilter, pBufList, NDIS_DEFAULT_PORT_NUMBER, 1, 0);
+        }
+    }
+#ifdef VBOXNETLWF_SYNC_SEND
+    if (nEvents)
+    {
+        NTSTATUS Status = KeWaitForMultipleObjects(nEvents, aEvents, WaitAll, Executive, KernelMode, FALSE, &timeout, NULL);
+        if (Status != STATUS_SUCCESS)
+        {
+            Log(("ERROR! "__FUNCTION__": KeWaitForMultipleObjects() failed with 0x%x\n", Status));
+            if (Status == STATUS_TIMEOUT)
+                rc = VERR_TIMEOUT;
+            else
+                rc = RTErrConvertFromNtStatus(Status);
+        }
+    }
+#endif /* VBOXNETLWF_SYNC_SEND */
+    NDIS_RELEASE_MUTEX(&pModule->InTransmit);
+
+    LogFlow(("<=="__FUNCTION__": return %d\n", rc));
+    return rc;
+}
+
+void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
+{
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)pThis->u.s.WinIf.hModuleCtx;
+    LogFlow(("==>"__FUNCTION__": instance=%p module=%p fActive=%RTbool\n", pThis, pModuleCtx, fActive));
+    if (!pModuleCtx)
+    {
+        LogFlow(("<=="__FUNCTION__": pModuleCtx is null\n"));
+        return;
+    }
+
+    NDIS_STATUS Status = STATUS_SUCCESS;
+    bool fOldActive = ASMAtomicXchgBool(&pModuleCtx->fActive, fActive);
+    if (fOldActive != fActive)
+    {
+        /// @todo Shouldn't we wait for traffic to cease here? Probably not.
+        /* Schedule restart to enable/disable bypass mode */
+        NdisFRestartFilter(pModuleCtx->hFilter);
+        Status = vboxNetLwfWinSetPacketFilter(pModuleCtx, fActive);
+        LogFlow(("<=="__FUNCTION__": vboxNetLwfWinSetPacketFilter() returned 0x%x\n", Status));
+    }
+    else
+        LogFlow(("<=="__FUNCTION__": no change, remain %sactive\n", fActive ? "":"in"));
+}
+
+int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p\n", pThis));
+    LogFlow(("<=="__FUNCTION__": return 0\n"));
+    return VINF_SUCCESS;
+}
+
+int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p\n", pThis));
+    LogFlow(("<=="__FUNCTION__": return 0\n"));
+    return VINF_SUCCESS;
+}
+
+void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
+{
+    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)pThis->u.s.WinIf.hModuleCtx;
+    LogFlow(("==>"__FUNCTION__": instance=%p module=%p\n", pThis, pModuleCtx));
+    /* Technically it is possible that the module has already been gone by now. */
+    if (pModuleCtx)
+    {
+        Assert(!pModuleCtx->fActive); /* Deactivation ensures bypass mode */
+        pModuleCtx->pNetFlt = NULL;
+        pThis->u.s.WinIf.hModuleCtx = NULL;
+    }
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+static void vboxNetLwfWinReportCapabilities(PVBOXNETFLTINS pThis, PVBOXNETLWF_MODULE pModuleCtx)
+{
+    if (pThis->pSwitchPort
+        && vboxNetFltTryRetainBusyNotDisconnected(pThis))
+    {
+        pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pModuleCtx->MacAddr);
+        pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort,
+                                                     vboxNetLwfWinIsPromiscuous(pModuleCtx));
+        pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0,
+                                                     INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
+        pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
+        vboxNetFltRelease(pThis, true /*fBusy*/);
+    }
+}
+
+int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p context=%p\n", pThis, pvContext));
+    AssertReturn(pThis, VERR_INVALID_PARAMETER);
+    Log((__FUNCTION__": trunk name=%s\n", pThis->szName));
+    ANSI_STRING strInst;
+    RtlInitAnsiString(&strInst, pThis->szName);
+    PVBOXNETLWF_MODULE pModuleCtx = NULL;
+    RTListForEach(&g_VBoxNetLwfGlobals.listModules, pModuleCtx, VBOXNETLWF_MODULE, node)
+    {
+        DbgPrint(__FUNCTION__": evaluating module, name=%Z\n", pModuleCtx->strMiniportName);
+        if (RtlEqualString(&strInst, &pModuleCtx->strMiniportName, TRUE))
+        {
+            Log((__FUNCTION__": found matching module, name=%s\n", pThis->szName));
+            pThis->u.s.WinIf.hModuleCtx = pModuleCtx;
+            pModuleCtx->pNetFlt = pThis;
+            vboxNetLwfWinReportCapabilities(pThis, pModuleCtx);
+            LogFlow(("<=="__FUNCTION__": return 0\n"));
+            return VINF_SUCCESS;
+        }
+    }
+    LogFlow(("<=="__FUNCTION__": return VERR_INTNET_FLT_IF_NOT_FOUND\n"));
+    return VERR_INTNET_FLT_IF_NOT_FOUND;
+}
+
+int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p\n", pThis));
+    pThis->u.s.WinIf.hModuleCtx = 0;
+    LogFlow(("<=="__FUNCTION__": return 0\n"));
+    return VINF_SUCCESS;
+}
+
+void vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p data=%p mac=%RTmac\n", pThis, pvIfData, pMac));
+    LogFlow(("<=="__FUNCTION__"\n"));
+}
+
+int vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p if=%p data=%p\n", pThis, pvIf, ppvIfData));
+    LogFlow(("<=="__FUNCTION__": return 0\n"));
+    /* Nothing to do */
+    return VINF_SUCCESS;
+}
+
+int vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)
+{
+    LogFlow(("==>"__FUNCTION__": instance=%p data=%p\n", pThis, pvIfData));
+    LogFlow(("<=="__FUNCTION__": return 0\n"));
+    /* Nothing to do */
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.h	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf-win.h	(revision 52630)
@@ -0,0 +1,32 @@
+/* $Id$ */
+/** @file
+ * VBoxNetLwf-win.h - Bridged Networking Driver, Windows-specific code.
+ */
+/*
+ * Copyright (C) 2014 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 ___VBoxNetLwf_win_h___
+#define ___VBoxNetLwf_win_h___
+
+#define VBOXNETLWF_VERSION_NDIS_MAJOR        6
+#define VBOXNETLWF_VERSION_NDIS_MINOR        0
+
+#define VBOXNETLWF_NAME_FRIENDLY             L"VirtualBox NDIS Light-Weight Filter"
+#define VBOXNETLWF_NAME_UNIQUE               L"{7af6b074-048d-4444-bfce-1ecc8bc5cb76}"
+#define VBOXNETLWF_NAME_SERVICE              L"VBoxNetLwf"
+
+#define VBOXNETLWF_NAME_LINK                 L"\\DosDevices\\Global\\VBoxNetLwf"
+#define VBOXNETLWF_NAME_DEVICE               L"\\Device\\VBoxNetLwf"
+
+#define VBOXNETLWF_MEM_TAG                   'FLBV'
+#define VBOXNETLWF_REQ_ID                    'fLBV'
+
+#endif /* #ifndef ___VBoxNetLwf_win_h___ */
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf.inf
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf.inf	(revision 52630)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/win/ndis6/VBoxNetLwf.inf	(revision 52630)
@@ -0,0 +1,100 @@
+; $Id$
+; @file
+; VBoxNetLwf.inf - VirtualBox Bridged Networking Driver inf file
+;
+; Note: We use the same component id as the old NetFlt implementation 
+;
+;
+; Copyright (C) 2014 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.
+;
+
+[Version]
+Signature   = "$Windows NT$"
+CatalogFile = VBoxNetLwf.cat
+Class       = NetService
+ClassGUID   = {4D36E974-E325-11CE-BFC1-08002BE10318}
+Provider    = %Provider%
+DriverVer   = 05/31/2014,1.0.1.0
+
+
+[Manufacturer]
+%Provider% = VBox,NTx86,NTamd64
+
+[ControlFlags]
+
+[VBox]
+%VBoxNetLwf_Desc% = VBoxNetLwf.ndi, sun_VBoxNetFlt
+
+[VBox.NTx86]
+%VBoxNetLwf_Desc% = VBoxNetLwf.ndi, sun_VBoxNetFlt
+
+[VBox.NTamd64]
+%VBoxNetLwf_Desc% = VBoxNetLwf.ndi, sun_VBoxNetFlt
+
+[VBoxNetLwf.ndi]
+AddReg           = VBoxNetLwf.ndi.AddReg, VBoxNetLwf.AddReg
+Characteristics  = 0x40000 ;  NCF_LW_FILTER
+CopyFiles        = VBoxNetLwf.Files.Sys
+NetCfgInstanceId = "{7af6b074-048d-4444-bfce-1ecc8bc5cb76}"
+
+[VBoxNetLwf.ndi.Remove.Services]
+DelService       = VBoxNetLwf,0x200 ; Stop the service before uninstalling
+
+[VBoxNetLwf.ndi.Services]
+AddService = VBoxNetLwf,, VBoxNetLwf.AddService
+
+[VBoxNetLwf.AddService]
+DisplayName    = %VBoxNetLwfService_Desc%
+ServiceType    = 1 ;SERVICE_KERNEL_DRIVER
+StartType      = 1 ;SERVICE_SYSTEM_START
+ErrorControl   = 1 ;SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\VBoxNetLwf.sys
+LoadOrderGroup = NDIS
+AddReg         = VBoxNetLwf.AddService.AddReg
+
+[VBoxNetLwf.AddService.AddReg]
+
+[SourceDisksNames]
+1=%DiskDescription%,"",,
+
+[SourceDisksFiles]
+VBoxNetLwf.sys=1
+
+[DestinationDirs]
+DefaultDestDir = 12
+VBoxNetLwf.Files.Sys   = 12   ; %windir%\System32\drivers
+
+[VBoxNetLwf.Files.Sys]
+VBoxNetLwf.sys,,,2
+
+
+[VBoxNetLwf.ndi.AddReg]
+HKR, Ndi, HelpText, , %VBoxNetLwf_HELP%
+HKR, Ndi,            ClsID,              0, {f374d1a0-bf08-4bdc-9cb2-c15ddaeef955}
+;HKR, Ndi,            ComponentDll,        , VBoxNetLwfNobj.dll
+HKR, Ndi,            FilterClass,         , compression
+HKR, Ndi,            FilterType,   0x10001, 0x2
+HKR, Ndi,            FilterRunType,0x10001, 1
+HKR, Ndi,            Service,             , VBoxNetLwf
+HKR, Ndi,            CoServices,   0x10000, VBoxNetLwf
+HKR, Ndi\Interfaces, UpperRange,          , noupper
+HKR, Ndi\Interfaces, LowerRange,          , nolower
+HKR, Ndi\Interfaces, FilterMediaTypes,    , ethernet
+
+[VBoxNetLwf.AddReg]
+;HKR, Parameters, Param1, 0, 4
+
+[Strings]
+Provider = "Oracle Corporation"
+DiskDescription = "VirtualBox NDIS6 Bridged Networking Driver"
+VBoxNetLwf_Desc = "VirtualBox NDIS6 Bridged Networking Driver"
+VBoxNetLwf_HELP = "VirtualBox NDIS6 Bridged Networking Driver"
+VBoxNetLwfService_Desc = "VirtualBox NDIS6 Bridged Networking Service"
