VirtualBox

vbox的更動 65698 路徑 trunk/src/VBox/HostDrivers


忽略:
時間撮記:
2017-2-9 下午12:28:01 (8 年 以前)
作者:
vboxsync
訊息:

NetAdp/win (bugref:8488) standalone implementation, does not require NetLwf to be installed.

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/HostDrivers/VBoxNetAdp/win/VBoxNetAdp-win.cpp

    r63564 r65698  
    2020#include <VBox/version.h>
    2121#include <VBox/err.h>
     22#include <VBox/sup.h>
     23#include <VBox/intnet.h>
     24#include <VBox/intnetinline.h>
     25#include <iprt/assert.h>
    2226#include <iprt/initterm.h>
    23 #include <iprt/assert.h>
     27#include <iprt/list.h>
     28#include <iprt/net.h>
     29#include <iprt/semaphore.h>
     30#include <iprt/string.h>
     31#include <iprt/uuid.h>
    2432
    2533#include <iprt/nt/ndis.h>
     
    2735#include "VBoxNetAdp-win.h"
    2836#include "VBox/VBoxNetCmn-win.h"
     37
     38#define VBOXNETADP_MEM_TAG                   'OHBV'
    2939
    3040/*
     
    3444 */
    3545#define VBOXNETADPWIN_LINK_SPEED 1000000000ULL
     46
     47#define LogError LogRel
    3648
    3749/* Forward declarations */
     
    5264
    5365
     66/* Packet types by destination address; used in statistics. */
     67typedef enum {
     68    kVBoxNetAdpWinPacketType_Unicast,
     69    kVBoxNetAdpWinPacketType_Multicast,
     70    kVBoxNetAdpWinPacketType_Broadcast,
     71    kVBoxNetAdpWinPacketType_ArraySize /* Must be the last one */
     72} VBOXNETADPWIN_PACKET_TYPE;
     73
     74
     75/* Miniport states as defined by NDIS. */
     76typedef enum {
     77    kVBoxNetAdpWinState_Initializing,
     78    kVBoxNetAdpWinState_Paused,
     79    kVBoxNetAdpWinState_Restarting,
     80    kVBoxNetAdpWinState_Running,
     81    kVBoxNetAdpWinState_Pausing,
     82    kVBoxNetAdpWinState_32BitHack = 0x7fffffff
     83} VBOXNETADPWIN_ADAPTER_STATE;
     84
     85
     86/*
     87 * Valid state transitions are:
     88 * 1) Disconnected -> Connecting   : start the worker thread, attempting to init IDC;
     89 * 2) Connecting   -> Disconnected : failed to start IDC init worker thread;
     90 * 3) Connecting   -> Connected    : IDC init successful, terminate the worker;
     91 * 4) Connecting   -> Stopping     : IDC init incomplete, but the driver is being unloaded, terminate the worker;
     92 * 5) Connected    -> Stopping     : IDC init was successful, no worker, the driver is being unloaded;
     93 *
     94 * Driver terminates in either in Disconnected or in Stopping state.
     95 */
     96typedef enum {
     97    kVBoxNetAdpWinIdcState_Disconnected = 0, /* Initial state */
     98    kVBoxNetAdpWinIdcState_Connecting,       /* Attemping to init IDC, worker thread running */
     99    kVBoxNetAdpWinIdcState_Connected,        /* Successfully connected to IDC, worker thread terminated */
     100    kVBoxNetAdpWinIdcState_Stopping          /* Terminating the worker thread and disconnecting IDC */
     101} VBOXNETADPWIN_IDC_STATE;
     102
    54103typedef struct _VBOXNETADPGLOBALS
    55104{
    56     /** ndis device */
    57     NDIS_HANDLE hDevice;
    58     /** device object */
    59     PDEVICE_OBJECT pDevObj;
    60     /** our miniport driver handle */
     105    /** Miniport driver handle. */
    61106    NDIS_HANDLE hMiniportDriver;
    62     /** power management capabilities, shared by all instances, do not change after init */
     107    /** Power management capabilities, shared by all instances, do not change after init. */
    63108    NDIS_PNP_CAPABILITIES PMCaps;
     109    /** The INTNET trunk network interface factory. */
     110    INTNETTRUNKFACTORY TrunkFactory;
     111    /** The SUPDRV component factory registration. */
     112    SUPDRVFACTORY SupDrvFactory;
     113    /** The SUPDRV IDC handle (opaque struct). */
     114    SUPDRVIDCHANDLE SupDrvIDC;
     115    /** IDC init thread handle. */
     116    HANDLE hInitIdcThread;
     117    /** Lock protecting the following members. */
     118    NDIS_SPIN_LOCK Lock;
     119    /** Lock-protected: the head of module list. */
     120    RTLISTANCHOR ListOfAdapters;
     121    /** Lock-protected: The number of current factory references. */
     122    int32_t volatile cFactoryRefs;
     123    /** Lock-protected: IDC initialization state. */
     124    volatile uint32_t enmIdcState;
     125    /** Lock-protected: event signaled when trunk factory is not in use. */
     126    NDIS_EVENT EventUnloadAllowed;
    64127} VBOXNETADPGLOBALS, *PVBOXNETADPGLOBALS;
    65128
     
    69132
    70133typedef struct _VBOXNETADP_ADAPTER {
     134    /** Auxiliary member to link adapters into a list. */
     135    RTLISTNODE node;
     136    /** Adapter handle for NDIS. */
    71137    NDIS_HANDLE hAdapter;
     138    /** Memory pool network buffers are allocated from. */
     139    NDIS_HANDLE hPool;
     140    /** Our RJ-45 port.
     141     * This is what the internal network plugs into. */
     142    INTNETTRUNKIFPORT MyPort;
     143    /** The RJ-45 port on the INTNET "switch".
     144     * This is what we're connected to. */
     145    PINTNETTRUNKSWPORT pSwitchPort;
     146    /** Pointer to global data */
    72147    PVBOXNETADPGLOBALS pGlobals;
     148    /** Adapter state in NDIS, used for assertions only */
     149    VBOXNETADPWIN_ADAPTER_STATE volatile enmAdapterState; // @todo do we need it really?
     150    /** The trunk state. */
     151    INTNETTRUNKIFSTATE volatile enmTrunkState;
     152    /** Number of pending operations, when it reaches zero we signal EventIdle. */
     153    int32_t volatile cBusy;
     154    /** The event that is signaled when we go idle and that pfnWaitForIdle blocks on. */
     155    NDIS_EVENT EventIdle;
     156    /** MAC address of adapter. */
    73157    RTMAC MacAddr;
     158    /** Statistics: bytes received from internal network. */
     159    uint64_t au64StatsInOctets[kVBoxNetAdpWinPacketType_ArraySize];
     160    /** Statistics: packets received from internal network. */
     161    uint64_t au64StatsInPackets[kVBoxNetAdpWinPacketType_ArraySize];
     162    /** Statistics: bytes sent to internal network. */
     163    uint64_t au64StatsOutOctets[kVBoxNetAdpWinPacketType_ArraySize];
     164    /** Statistics: packets sent to internal network. */
     165    uint64_t au64StatsOutPackets[kVBoxNetAdpWinPacketType_ArraySize];
     166    /** Adapter friendly name. */
     167    char szName[1];
    74168} VBOXNETADP_ADAPTER;
    75169typedef VBOXNETADP_ADAPTER *PVBOXNETADP_ADAPTER;
    76170
    77171
    78 static NTSTATUS vboxNetAdpWinDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
    79 {
    80     RT_NOREF1(pDevObj);
    81     PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);
    82     NTSTATUS Status = STATUS_SUCCESS;
    83 
    84     switch (pIrpSl->MajorFunction)
    85     {
    86         case IRP_MJ_DEVICE_CONTROL:
    87             Status = STATUS_NOT_SUPPORTED; /// @todo add/remove ioctls
    88             break;
    89         case IRP_MJ_CREATE:
    90         case IRP_MJ_CLEANUP:
    91         case IRP_MJ_CLOSE:
    92             break;
    93         default:
    94             AssertFailed();
    95             break;
    96     }
    97 
    98     pIrp->IoStatus.Status = Status;
    99     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    100 
    101     return Status;
    102 }
    103 
    104 static NDIS_STATUS vboxNetAdpWinDevCreate(PVBOXNETADPGLOBALS pGlobals)
    105 {
    106     NDIS_STRING DevName, LinkName;
    107     PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
    108     NdisInitUnicodeString(&DevName, VBOXNETADP_NAME_DEVICE);
    109     NdisInitUnicodeString(&LinkName, VBOXNETADP_NAME_LINK);
    110 
    111     Assert(!pGlobals->hDevice);
    112     Assert(!pGlobals->pDevObj);
    113     NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
    114     aMajorFunctions[IRP_MJ_CREATE] = vboxNetAdpWinDevDispatch;
    115     aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetAdpWinDevDispatch;
    116     aMajorFunctions[IRP_MJ_CLOSE] = vboxNetAdpWinDevDispatch;
    117     aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetAdpWinDevDispatch;
    118 
    119     NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttributes;
    120     NdisZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
    121     DeviceAttributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
    122     DeviceAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
    123     DeviceAttributes.Header.Size = sizeof(DeviceAttributes);
    124     DeviceAttributes.DeviceName = &DevName;
    125     DeviceAttributes.SymbolicName = &LinkName;
    126     DeviceAttributes.MajorFunctions = aMajorFunctions;
    127 
    128     NDIS_STATUS Status = NdisRegisterDeviceEx(pGlobals->hMiniportDriver,
    129                                               &DeviceAttributes,
    130                                               &pGlobals->pDevObj,
    131                                               &pGlobals->hDevice);
    132     Log(("vboxNetAdpWinDevCreate: NdisRegisterDeviceEx returned 0x%x\n", Status));
    133     Assert(Status == NDIS_STATUS_SUCCESS);
    134     return Status;
    135 }
    136 
    137 static void vboxNetAdpWinDevDestroy(PVBOXNETADPGLOBALS pGlobals)
    138 {
    139     Assert(pGlobals->hDevice);
    140     Assert(pGlobals->pDevObj);
    141     NdisDeregisterDeviceEx(pGlobals->hDevice);
    142     pGlobals->hDevice = NULL;
    143     pGlobals->pDevObj = NULL;
    144 }
    145 
    146 
    147 
     172/* Port */
     173
     174#define IFPORT_2_VBOXNETADP_ADAPTER(pIfPort) \
     175    ( (PVBOXNETADP_ADAPTER)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETADP_ADAPTER, MyPort)) )
     176
     177DECLINLINE(VBOXNETADPWIN_ADAPTER_STATE) vboxNetAdpWinGetState(PVBOXNETADP_ADAPTER pThis)
     178{
     179    return (VBOXNETADPWIN_ADAPTER_STATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmAdapterState);
     180}
     181
     182DECLINLINE(VBOXNETADPWIN_ADAPTER_STATE) vboxNetAdpWinSetState(PVBOXNETADP_ADAPTER pThis, VBOXNETADPWIN_ADAPTER_STATE enmNewState)
     183{
     184    return (VBOXNETADPWIN_ADAPTER_STATE)ASMAtomicXchgU32((uint32_t volatile *)&pThis->enmAdapterState, enmNewState);
     185}
     186
     187DECLINLINE(bool) vboxNetAdpWinSetState(PVBOXNETADP_ADAPTER pThis, VBOXNETADPWIN_ADAPTER_STATE enmNewState,
     188                                                              VBOXNETADPWIN_ADAPTER_STATE enmOldState)
     189{
     190    return ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmAdapterState, enmNewState, enmOldState);
     191}
     192
     193#ifdef DEBUG
     194
     195DECLHIDDEN(void) vboxNetAdpWinDumpPackets(const char *pszMsg, PNET_BUFFER_LIST pBufLists)
     196{
     197    for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
     198    {
     199        for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
     200        {
     201            Log6(("%s packet: cb=%d offset=%d", pszMsg, NET_BUFFER_DATA_LENGTH(pBuf), NET_BUFFER_DATA_OFFSET(pBuf)));
     202            for (PMDL pMdl = NET_BUFFER_FIRST_MDL(pBuf);
     203                 pMdl != NULL;
     204                 pMdl = NDIS_MDL_LINKAGE(pMdl))
     205            {
     206                Log6((" MDL: cb=%d", MmGetMdlByteCount(pMdl)));
     207            }
     208            Log6(("\n"));
     209        }
     210    }
     211}
     212
     213DECLINLINE(const char *) vboxNetAdpWinEthTypeStr(uint16_t uType)
     214{
     215    switch (uType)
     216    {
     217        case RTNET_ETHERTYPE_IPV4: return "IP";
     218        case RTNET_ETHERTYPE_IPV6: return "IPv6";
     219        case RTNET_ETHERTYPE_ARP:  return "ARP";
     220    }
     221    return "unknown";
     222}
     223
     224#define VBOXNETADP_PKTDMPSIZE 0x50
     225
     226/**
     227 * Dump a packet to debug log.
     228 *
     229 * @param   cpPacket    The packet.
     230 * @param   cb          The size of the packet.
     231 * @param   cszText     A string denoting direction of packet transfer.
     232 */
     233DECLINLINE(void) vboxNetAdpWinDumpPacket(PCINTNETSG pSG, const char *cszText)
     234{
     235    uint8_t bPacket[VBOXNETADP_PKTDMPSIZE];
     236
     237    uint32_t cb = pSG->cbTotal < VBOXNETADP_PKTDMPSIZE ? pSG->cbTotal : VBOXNETADP_PKTDMPSIZE;
     238    IntNetSgReadEx(pSG, 0, cb, bPacket);
     239
     240    AssertReturnVoid(cb >= 14);
     241
     242    uint8_t *pHdr = bPacket;
     243    uint8_t *pEnd = bPacket + cb;
     244    AssertReturnVoid(pEnd - pHdr >= 14);
     245    uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+12));
     246    Log2(("NetADP: %s (%d bytes), %RTmac => %RTmac, EthType=%s(0x%x)\n",
     247          cszText, pSG->cbTotal, pHdr+6, pHdr, vboxNetAdpWinEthTypeStr(uEthType), uEthType));
     248    pHdr += sizeof(RTNETETHERHDR);
     249    if (uEthType == RTNET_ETHERTYPE_VLAN)
     250    {
     251        AssertReturnVoid(pEnd - pHdr >= 4);
     252        uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+2));
     253        Log2((" + VLAN: id=%d EthType=%s(0x%x)\n", RT_N2H_U16(*(uint16_t*)(pHdr)) & 0xFFF,
     254              vboxNetAdpWinEthTypeStr(uEthType), uEthType));
     255        pHdr += 2 * sizeof(uint16_t);
     256    }
     257    uint8_t uProto = 0xFF;
     258    switch (uEthType)
     259    {
     260        case RTNET_ETHERTYPE_IPV6:
     261            AssertReturnVoid(pEnd - pHdr >= 40);
     262            uProto = pHdr[6];
     263            Log2((" + IPv6: %RTnaipv6 => %RTnaipv6\n", pHdr+8, pHdr+24));
     264            pHdr += 40;
     265            break;
     266        case RTNET_ETHERTYPE_IPV4:
     267            AssertReturnVoid(pEnd - pHdr >= 20);
     268            uProto = pHdr[9];
     269            Log2((" + IP: %RTnaipv4 => %RTnaipv4\n", *(uint32_t*)(pHdr+12), *(uint32_t*)(pHdr+16)));
     270            pHdr += (pHdr[0] & 0xF) * 4;
     271            break;
     272        case RTNET_ETHERTYPE_ARP:
     273            AssertReturnVoid(pEnd - pHdr >= 28);
     274            AssertReturnVoid(RT_N2H_U16(*(uint16_t*)(pHdr+2)) == RTNET_ETHERTYPE_IPV4);
     275            switch (RT_N2H_U16(*(uint16_t*)(pHdr+6)))
     276            {
     277                case 1: /* ARP request */
     278                    Log2((" + ARP-REQ: who-has %RTnaipv4 tell %RTnaipv4\n",
     279                          *(uint32_t*)(pHdr+24), *(uint32_t*)(pHdr+14)));
     280                    break;
     281                case 2: /* ARP reply */
     282                    Log2((" + ARP-RPL: %RTnaipv4 is-at %RTmac\n",
     283                          *(uint32_t*)(pHdr+14), pHdr+8));
     284                    break;
     285                default:
     286                    Log2((" + ARP: unknown op %d\n", RT_N2H_U16(*(uint16_t*)(pHdr+6))));
     287                    break;
     288            }
     289            break;
     290        /* There is no default case as uProto is initialized with 0xFF */
     291    }
     292    while (uProto != 0xFF)
     293    {
     294        switch (uProto)
     295        {
     296            case 0:  /* IPv6 Hop-by-Hop option*/
     297            case 60: /* IPv6 Destination option*/
     298            case 43: /* IPv6 Routing option */
     299            case 44: /* IPv6 Fragment option */
     300                Log2((" + IPv6 option (%d): <not implemented>\n", uProto));
     301                uProto = pHdr[0];
     302                pHdr += pHdr[1] * 8 + 8; /* Skip to the next extension/protocol */
     303                break;
     304            case 51: /* IPv6 IPsec AH */
     305                Log2((" + IPv6 IPsec AH: <not implemented>\n"));
     306                uProto = pHdr[0];
     307                pHdr += (pHdr[1] + 2) * 4; /* Skip to the next extension/protocol */
     308                break;
     309            case 50: /* IPv6 IPsec ESP */
     310                /* Cannot decode IPsec, fall through */
     311                Log2((" + IPv6 IPsec ESP: <not implemented>\n"));
     312                uProto = 0xFF;
     313                break;
     314            case 59: /* No Next Header */
     315                Log2((" + IPv6 No Next Header\n"));
     316                uProto = 0xFF;
     317                break;
     318            case 58: /* IPv6-ICMP */
     319                switch (pHdr[0])
     320                {
     321                    case 1:   Log2((" + IPv6-ICMP: destination unreachable, code %d\n", pHdr[1])); break;
     322                    case 128: Log2((" + IPv6-ICMP: echo request\n")); break;
     323                    case 129: Log2((" + IPv6-ICMP: echo reply\n")); break;
     324                    default:  Log2((" + IPv6-ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
     325                }
     326                uProto = 0xFF;
     327                break;
     328            case 1: /* ICMP */
     329                switch (pHdr[0])
     330                {
     331                    case 0:  Log2((" + ICMP: echo reply\n")); break;
     332                    case 8:  Log2((" + ICMP: echo request\n")); break;
     333                    case 3:  Log2((" + ICMP: destination unreachable, code %d\n", pHdr[1])); break;
     334                    default: Log2((" + ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
     335                }
     336                uProto = 0xFF;
     337                break;
     338            case 6: /* TCP */
     339                Log2((" + TCP: src=%d dst=%d seq=%x ack=%x\n",
     340                      RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2)),
     341                      RT_N2H_U32(*(uint32_t*)(pHdr+4)), RT_N2H_U32(*(uint32_t*)(pHdr+8))));
     342                uProto = 0xFF;
     343                break;
     344            case 17: /* UDP */
     345                Log2((" + UDP: src=%d dst=%d\n",
     346                      RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2))));
     347                uProto = 0xFF;
     348                break;
     349            default:
     350                Log2((" + Unknown: proto=0x%x\n", uProto));
     351                uProto = 0xFF;
     352                break;
     353        }
     354    }
     355    Log3(("%.*Rhxd\n", cb, bPacket));
     356}
     357
     358#else /* !DEBUG */
     359//# define vboxNetAdpWinDumpFilterTypes(uFlags)    do { } while (0)
     360//# define vboxNetAdpWinDumpOffloadSettings(p)     do { } while (0)
     361//# define vboxNetAdpWinDumpSetOffloadSettings(p)  do { } while (0)
     362# define vboxNetAdpWinDumpPackets(m,l)           do { } while (0)
     363# define vboxNetAdpWinDumpPacket(p,t)            do { } while (0)
     364#endif /* !DEBUG */
     365
     366
     367DECLHIDDEN(VBOXNETADPWIN_PACKET_TYPE) vboxNetAdpWinPacketType(PINTNETSG pSG)
     368{
     369    static const uint8_t g_abBcastAddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
     370    AssertReturn(pSG->cbTotal >= sizeof(g_abBcastAddr), kVBoxNetAdpWinPacketType_Unicast);
     371    AssertReturn(pSG->cSegsUsed > 0, kVBoxNetAdpWinPacketType_Unicast);
     372    AssertReturn(pSG->aSegs[0].cb >= sizeof(g_abBcastAddr), kVBoxNetAdpWinPacketType_Unicast);
     373    if (!memcmp(pSG->aSegs[0].pv, g_abBcastAddr, sizeof(g_abBcastAddr)))
     374        return kVBoxNetAdpWinPacketType_Broadcast;
     375    if ((*(uint8_t*)pSG->aSegs[0].pv) & 1)
     376        return kVBoxNetAdpWinPacketType_Multicast;
     377    return kVBoxNetAdpWinPacketType_Unicast;
     378}
     379
     380DECLINLINE(void) vboxNetAdpWinUpdateStats(uint64_t *pPacketStats, uint64_t *pOctetStats, PINTNETSG pSG)
     381{
     382    VBOXNETADPWIN_PACKET_TYPE enmPktType = vboxNetAdpWinPacketType(pSG);
     383    ASMAtomicIncU64(&pPacketStats[enmPktType]);
     384    ASMAtomicAddU64(&pOctetStats[enmPktType], pSG->cbTotal);
     385}
     386
     387DECLINLINE(void) vboxNetAdpWinFreeMdlChain(PMDL pMdl)
     388{
     389    PMDL pMdlNext;
     390    while (pMdl)
     391    {
     392        pMdlNext = pMdl->Next;
     393        PUCHAR pDataBuf;
     394        ULONG cb = 0;
     395        NdisQueryMdl(pMdl, &pDataBuf, &cb, NormalPagePriority);
     396        NdisFreeMdl(pMdl);
     397        Log4(("vboxNetAdpWinFreeMdlChain: freed MDL 0x%p\n", pMdl));
     398        NdisFreeMemory(pDataBuf, 0, 0);
     399        Log4(("vboxNetAdpWinFreeMdlChain: freed data buffer 0x%p\n", pDataBuf));
     400        pMdl = pMdlNext;
     401    }
     402}
     403
     404DECLHIDDEN(PNET_BUFFER_LIST) vboxNetAdpWinSGtoNB(PVBOXNETADP_ADAPTER pThis, PINTNETSG pSG)
     405{
     406    AssertReturn(pSG->cSegsUsed >= 1, NULL);
     407    LogFlow(("==>vboxNetAdpWinSGtoNB: segments=%d hPool=%p cb=%u\n", pSG->cSegsUsed,
     408             pThis->hPool, pSG->cbTotal));
     409    AssertReturn(pThis->hPool, NULL);
     410
     411
     412    PNET_BUFFER_LIST pBufList = NULL;
     413    ULONG cbMdl = pSG->cbTotal;
     414    ULONG uDataOffset = cbMdl - pSG->cbTotal;
     415    PUCHAR pDataBuf = (PUCHAR)NdisAllocateMemoryWithTagPriority(pThis->hAdapter, cbMdl,
     416                                                                VBOXNETADP_MEM_TAG, NormalPoolPriority);
     417    if (pDataBuf)
     418    {
     419        Log4(("vboxNetAdpWinSGtoNB: allocated data buffer (cb=%u) 0x%p\n", cbMdl, pDataBuf));
     420        PMDL pMdl = NdisAllocateMdl(pThis->hAdapter, pDataBuf, cbMdl);
     421        if (!pMdl)
     422        {
     423            NdisFreeMemory(pDataBuf, 0, 0);
     424            Log4(("vboxNetAdpWinSGtoNB: freed data buffer 0x%p\n", pDataBuf));
     425            LogError(("vboxNetAdpWinSGtoNB: failed to allocate an MDL (cb=%u)\n", cbMdl));
     426            LogFlow(("<==vboxNetAdpWinSGtoNB: return NULL\n"));
     427            return NULL;
     428        }
     429        PUCHAR pDst = pDataBuf + uDataOffset;
     430        for (int i = 0; i < pSG->cSegsUsed; i++)
     431        {
     432            NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb);
     433            pDst += pSG->aSegs[i].cb;
     434        }
     435        pBufList = NdisAllocateNetBufferAndNetBufferList(pThis->hPool,
     436                                                         0 /* ContextSize */,
     437                                                         0 /* ContextBackFill */,
     438                                                         pMdl,
     439                                                         uDataOffset,
     440                                                         pSG->cbTotal);
     441        if (pBufList)
     442        {
     443            Log4(("vboxNetAdpWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList));
     444            pBufList->SourceHandle = pThis->hAdapter;
     445            /** @todo Do we need to initialize anything else? */
     446        }
     447        else
     448        {
     449            LogError(("vboxNetAdpWinSGtoNB: failed to allocate an NBL+NB\n"));
     450            vboxNetAdpWinFreeMdlChain(pMdl);
     451        }
     452    }
     453    else
     454    {
     455        LogError(("vboxNetAdpWinSGtoNB: failed to allocate data buffer (size=%u)\n", cbMdl));
     456    }
     457
     458    LogFlow(("<==vboxNetAdpWinSGtoNB: return %p\n", pBufList));
     459    return pBufList;
     460}
     461
     462DECLINLINE(void) vboxNetAdpWinDestroySG(PINTNETSG pSG)
     463{
     464    NdisFreeMemory(pSG, 0, 0);
     465    Log4(("vboxNetAdpWinDestroySG: freed SG 0x%p\n", pSG));
     466}
     467
     468DECLINLINE(ULONG) vboxNetAdpWinCalcSegments(PNET_BUFFER pNetBuf)
     469{
     470    ULONG cSegs = 0;
     471    for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); pMdl; pMdl = NDIS_MDL_LINKAGE(pMdl))
     472        cSegs++;
     473    return cSegs;
     474}
     475
     476DECLHIDDEN(PINTNETSG) vboxNetAdpWinNBtoSG(PVBOXNETADP_ADAPTER pThis, PNET_BUFFER pNetBuf)
     477{
     478    ULONG cbPacket = NET_BUFFER_DATA_LENGTH(pNetBuf);
     479    UINT cSegs = vboxNetAdpWinCalcSegments(pNetBuf);
     480    /* Allocate and initialize SG */
     481    PINTNETSG pSG = (PINTNETSG)NdisAllocateMemoryWithTagPriority(pThis->hAdapter,
     482                                                                 RT_OFFSETOF(INTNETSG, aSegs[cSegs]),
     483                                                                 VBOXNETADP_MEM_TAG,
     484                                                                 NormalPoolPriority);
     485    AssertReturn(pSG, pSG);
     486    Log4(("vboxNetAdpWinNBtoSG: allocated SG 0x%p\n", pSG));
     487    IntNetSgInitTempSegs(pSG, cbPacket /*cbTotal*/, cSegs, cSegs /*cSegsUsed*/);
     488
     489    int rc = NDIS_STATUS_SUCCESS;
     490    ULONG uOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuf);
     491    cSegs = 0;
     492    for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf);
     493         pMdl != NULL && cbPacket > 0;
     494         pMdl = NDIS_MDL_LINKAGE(pMdl))
     495    {
     496        PUCHAR pSrc = (PUCHAR)MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);
     497        if (!pSrc)
     498        {
     499            rc = NDIS_STATUS_RESOURCES;
     500            break;
     501        }
     502        ULONG cbSrc = MmGetMdlByteCount(pMdl);
     503        if (uOffset)
     504        {
     505            Assert(uOffset < cbSrc);
     506            pSrc  += uOffset;
     507            cbSrc -= uOffset;
     508            uOffset = 0;
     509        }
     510
     511        if (cbSrc > cbPacket)
     512            cbSrc = cbPacket;
     513
     514        pSG->aSegs[cSegs].pv = pSrc;
     515        pSG->aSegs[cSegs].cb = cbSrc;
     516        pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS;
     517        cSegs++;
     518        cbPacket -= cbSrc;
     519    }
     520
     521    Assert(cSegs <= pSG->cSegsAlloc);
     522
     523    if (RT_FAILURE(rc))
     524    {
     525        vboxNetAdpWinDestroySG(pSG);
     526        pSG = NULL;
     527    }
     528    else
     529    {
     530        Assert(cbPacket == 0);
     531        Assert(pSG->cSegsUsed == cSegs);
     532    }
     533    return pSG;
     534}
     535
     536DECLINLINE(bool) vboxNetAdpWinIsActive(PVBOXNETADP_ADAPTER pThis)
     537{
     538    if (vboxNetAdpWinGetState(pThis) != kVBoxNetAdpWinState_Running)
     539        return false;
     540    if (pThis->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE)
     541        return false;
     542    AssertPtrReturn(pThis->pSwitchPort, false);
     543    return true;
     544}
     545
     546DECLHIDDEN(bool) vboxNetAdpWinForwardToIntNet(PVBOXNETADP_ADAPTER pThis, PNET_BUFFER_LIST pList, uint32_t fSrc)
     547{
     548    if (!vboxNetAdpWinIsActive(pThis))
     549    {
     550        LogFlow(("vboxNetAdpWinForwardToIntNet: not active\n"));
     551        return false;
     552    }
     553    AssertReturn(pThis->pSwitchPort, false);
     554    AssertReturn(pThis->pSwitchPort->pfnRecv, false);
     555    LogFlow(("==>vboxNetAdpWinForwardToIntNet\n"));
     556
     557    if (ASMAtomicIncS32(&pThis->cBusy) == 1)
     558        NdisResetEvent(&pThis->EventIdle);
     559    for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
     560    {
     561        PINTNETSG pSG = vboxNetAdpWinNBtoSG(pThis, pBuf);
     562        if (pSG)
     563        {
     564            vboxNetAdpWinUpdateStats(pThis->au64StatsOutPackets, pThis->au64StatsOutOctets, pSG);
     565            vboxNetAdpWinDumpPacket(pSG, (fSrc & INTNETTRUNKDIR_WIRE)?"intnet <-- wire":"intnet <-- host");
     566            pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL, pSG, fSrc);
     567            vboxNetAdpWinDestroySG(pSG);
     568        }
     569    }
     570    if (ASMAtomicDecS32(&pThis->cBusy) == 0)
     571        NdisSetEvent(&pThis->EventIdle);
     572
     573    return true;
     574}
     575
     576
     577/**
     578 * @copydoc INTNETTRUNKIFPORT::pfnRetain
     579 */
     580static DECLCALLBACK(void) vboxNetAdpWinPortRetain(PINTNETTRUNKIFPORT pIfPort)
     581{
     582    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     583    RT_NOREF1(pThis);
     584    LogFlow(("vboxNetAdpWinPortRetain: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
     585}
     586
     587/**
     588 * @copydoc INTNETTRUNKIFPORT::pfnRelease
     589 */
     590static DECLCALLBACK(void) vboxNetAdpWinPortRelease(PINTNETTRUNKIFPORT pIfPort)
     591{
     592    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     593    RT_NOREF1(pThis);
     594    LogFlow(("vboxNetAdpWinPortRelease: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
     595}
     596
     597/**
     598 * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
     599 */
     600static DECLCALLBACK(void) vboxNetAdpWinPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
     601{
     602    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     603
     604    LogFlow(("vboxNetAdpWinPortDisconnectAndRelease: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
     605    /*
     606     * Serious paranoia.
     607     */
     608    AssertPtr(pThis);
     609    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     610    Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
     611    AssertPtr(pThis->pGlobals);
     612    Assert(pThis->szName[0]);
     613
     614    AssertPtr(pThis->pSwitchPort);
     615    Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING);
     616
     617    pThis->pSwitchPort = NULL;
     618}
     619
     620/**
     621 * @copydoc INTNETTRUNKIFPORT::pfnSetState
     622 */
     623static DECLCALLBACK(INTNETTRUNKIFSTATE) vboxNetAdpWinPortSetState(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState)
     624{
     625    PVBOXNETADP_ADAPTER      pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     626    INTNETTRUNKIFSTATE  enmOldTrunkState;
     627
     628    LogFlow(("vboxNetAdpWinPortSetState: pThis=%p, pIfPort=%p, enmState=%d\n", pThis, pIfPort, enmState));
     629    /*
     630     * Input validation.
     631     */
     632    AssertPtr(pThis);
     633    AssertPtr(pThis->pGlobals);
     634    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     635    AssertPtrReturn(pThis->pSwitchPort, INTNETTRUNKIFSTATE_INVALID);
     636    AssertReturn(enmState > INTNETTRUNKIFSTATE_INVALID && enmState < INTNETTRUNKIFSTATE_END,
     637                 INTNETTRUNKIFSTATE_INVALID);
     638
     639    enmOldTrunkState = pThis->enmTrunkState;
     640    if (enmOldTrunkState != enmState)
     641        ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmTrunkState, enmState);
     642
     643    return enmOldTrunkState;
     644}
     645
     646/**
     647 * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
     648 */
     649static DECLCALLBACK(int) vboxNetAdpWinPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
     650{
     651    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     652    int rc;
     653
     654    LogFlow(("vboxNetAdpWinPortWaitForIdle: pThis=%p, pIfPort=%p, cMillies=%u\n", pThis, pIfPort, cMillies));
     655    /*
     656     * Input validation.
     657     */
     658    AssertPtr(pThis);
     659    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     660    AssertPtrReturn(pThis->pSwitchPort, VERR_INVALID_STATE);
     661    AssertReturn(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING, VERR_INVALID_STATE);
     662
     663    rc = NdisWaitEvent(&pThis->EventIdle, cMillies) ? VINF_SUCCESS : VERR_TIMEOUT;
     664
     665    return rc;
     666}
     667
     668/**
     669 * @copydoc INTNETTRUNKIFPORT::pfnXmit
     670 */
     671static DECLCALLBACK(int) vboxNetAdpWinPortXmit(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
     672{
     673    RT_NOREF1(fDst);
     674    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     675    int rc = VINF_SUCCESS;
     676
     677    LogFlow(("vboxNetAdpWinPortXmit: pThis=%p, pIfPort=%p, pvIfData=%p, pSG=%p, fDst=0x%x\n", pThis, pIfPort, pvIfData, pSG, fDst));
     678    RT_NOREF1(pvIfData);
     679    /*
     680     * Input validation.
     681     */
     682    AssertPtr(pThis);
     683    AssertPtr(pSG);
     684    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     685    AssertPtrReturn(pThis->pSwitchPort, VERR_INVALID_STATE);
     686
     687    vboxNetAdpWinDumpPacket(pSG, "intnet --> host");
     688
     689    /*
     690     * First of all, indicate we are busy. It is possible the trunk or the adapter
     691     * will get paused or even disconnected, so we need to check the state after
     692     * we have marked ourselves busy.
     693     * Later, when NDIS returns all buffers, we will mark ourselves idle.
     694     */
     695    if (ASMAtomicIncS32(&pThis->cBusy) == 1)
     696        NdisResetEvent(&pThis->EventIdle);
     697
     698    if (vboxNetAdpWinIsActive(pThis))
     699    {
     700        PNET_BUFFER_LIST pBufList = vboxNetAdpWinSGtoNB(pThis, pSG);
     701        if (pBufList)
     702        {
     703            NdisMIndicateReceiveNetBufferLists(pThis->hAdapter, pBufList, NDIS_DEFAULT_PORT_NUMBER, 1, 0);
     704            vboxNetAdpWinUpdateStats(pThis->au64StatsInPackets, pThis->au64StatsInOctets, pSG);
     705        }
     706    }
     707
     708    return rc;
     709}
     710
     711/**
     712 * @copydoc INTNETTRUNKIFPORT::pfnNotifyMacAddress
     713 */
     714static DECLCALLBACK(void) vboxNetAdpWinPortNotifyMacAddress(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PCRTMAC pMac)
     715{
     716    PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     717
     718    LogFlow(("vboxNetAdpWinPortNotifyMacAddress: pThis=%p, pIfPort=%p, pvIfData=%p, pMac=%p\n", pThis, pIfPort, pvIfData, pMac));
     719    RT_NOREF3(pThis, pvIfData, pMac);
     720    /*
     721     * Input validation.
     722     */
     723    AssertPtr(pThis);
     724    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     725
     726    // @todo Do we really need to handle this?
     727}
     728
     729
     730/**
     731 * @copydoc INTNETTRUNKIFPORT::pfnConnectInterface
     732 */
     733static DECLCALLBACK(int) vboxNetAdpWinPortConnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIf, void **ppvIfData)
     734{
     735    PVBOXNETADP_ADAPTER  pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     736    int             rc;
     737
     738    LogFlow(("vboxNetAdpWinPortConnectInterface: pThis=%p, pIfPort=%p, pvIf=%p, ppvIfData=%p\n", pThis, pIfPort, pvIf, ppvIfData));
     739    RT_NOREF3(pThis, pvIf, ppvIfData);
     740    /*
     741     * Input validation.
     742     */
     743    AssertPtr(pThis);
     744    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     745
     746    rc = VINF_SUCCESS;
     747
     748    return rc;
     749}
     750
     751
     752/**
     753 * @copydoc INTNETTRUNKIFPORT::pfnDisconnectInterface
     754 */
     755static DECLCALLBACK(void) vboxNetAdpWinPortDisconnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIfData)
     756{
     757    PVBOXNETADP_ADAPTER  pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
     758    int             rc;
     759
     760    LogFlow(("vboxNetAdpWinPortDisconnectInterface: pThis=%p, pIfPort=%p, pvIfData=%p\n", pThis, pIfPort, pvIfData));
     761    RT_NOREF2(pThis, pvIfData);
     762    /*
     763     * Input validation.
     764     */
     765    AssertPtr(pThis);
     766    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
     767
     768    rc = VINF_SUCCESS;
     769    AssertRC(rc);
     770}
     771
     772
     773
     774/**
     775 * Implements the SUPDRV component factor interface query method.
     776 *
     777 * @returns Pointer to an interface. NULL if not supported.
     778 *
     779 * @param   pSupDrvFactory      Pointer to the component factory registration structure.
     780 * @param   pSession            The session - unused.
     781 * @param   pszInterfaceUuid    The factory interface id.
     782 */
     783static DECLCALLBACK(void *) vboxNetAdpWinQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession,
     784                                                            const char *pszInterfaceUuid)
     785{
     786    PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, SupDrvFactory));
     787
     788    /*
     789     * Convert the UUID strings and compare them.
     790     */
     791    RTUUID UuidReq;
     792    int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
     793    if (RT_SUCCESS(rc))
     794    {
     795        if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
     796        {
     797            NdisAcquireSpinLock(&pGlobals->Lock);
     798            if (pGlobals->enmIdcState == kVBoxNetAdpWinIdcState_Connected)
     799            {
     800                pGlobals->cFactoryRefs++;
     801                NdisResetEvent(&pGlobals->EventUnloadAllowed);
     802            }
     803            NdisReleaseSpinLock(&pGlobals->Lock);
     804            return &pGlobals->TrunkFactory;
     805        }
     806#ifdef LOG_ENABLED
     807        else
     808            Log(("VBoxNetFlt: unknown factory interface query (%s)\n", pszInterfaceUuid));
     809#endif
     810    }
     811    else
     812        Log(("VBoxNetFlt: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
     813
     814    RT_NOREF1(pSession);
     815    return NULL;
     816}
     817
     818
     819DECLHIDDEN(void) vboxNetAdpWinReportCapabilities(PVBOXNETADP_ADAPTER pThis)
     820{
     821    if (pThis->pSwitchPort)
     822    {
     823        pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->MacAddr);
     824        /* Promiscuous mode makes no sense for host-only adapters, does it? */
     825        pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0,
     826                                                     INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
     827        pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
     828    }
     829}
     830
     831/**
     832 * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
     833 */
     834static DECLCALLBACK(int) vboxNetAdpWinFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
     835                                                           PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
     836                                                           PINTNETTRUNKIFPORT *ppIfPort)
     837{
     838    PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
     839
     840    LogFlow(("==>vboxNetAdpWinFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
     841    Assert(pGlobals->cFactoryRefs > 0);
     842    AssertMsgReturn(!(fFlags & ~(INTNETTRUNKFACTORY_FLAG_NO_PROMISC)),
     843                    ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     844
     845    PVBOXNETADP_ADAPTER pAdapter = NULL;
     846    NdisAcquireSpinLock(&pGlobals->Lock);
     847    RTListForEach(&g_VBoxNetAdpGlobals.ListOfAdapters, pAdapter, VBOXNETADP_ADAPTER, node)
     848    {
     849        Log(("vboxNetAdpWinFactoryCreateAndConnect: evaluating adapter=%s\n", pAdapter->szName));
     850        if (!RTStrICmp(pszName, pAdapter->szName))
     851        {
     852            pAdapter->pSwitchPort = pSwitchPort;
     853            *ppIfPort = &pAdapter->MyPort;
     854            NdisReleaseSpinLock(&g_VBoxNetAdpGlobals.Lock); // @todo too early? adp should have been connected by the time we do this
     855            Log(("vboxNetAdpWinFactoryCreateAndConnect: found matching adapter, name=%s\n", pszName));
     856            vboxNetAdpWinReportCapabilities(pAdapter);
     857            // @todo I guess there is no need in vboxNetAdpWinRegisterIpAddrNotifier(pThis);
     858            LogFlow(("<==vboxNetAdpWinFactoryCreateAndConnect: return VINF_SUCCESS\n"));
     859            return VINF_SUCCESS;
     860        }
     861    }
     862    NdisReleaseSpinLock(&pGlobals->Lock);
     863    // @todo vboxNetAdpLogErrorEvent(IO_ERR_INTERNAL_ERROR, STATUS_SUCCESS, 6);
     864    LogFlow(("<==vboxNetAdpWinFactoryCreateAndConnect: return VERR_INTNET_FLT_IF_NOT_FOUND\n"));
     865    return VERR_INTNET_FLT_IF_NOT_FOUND;
     866}
     867
     868
     869/**
     870 * @copydoc INTNETTRUNKFACTORY::pfnRelease
     871 */
     872static DECLCALLBACK(void) vboxNetAdpWinFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
     873{
     874    PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
     875
     876    NdisAcquireSpinLock(&pGlobals->Lock);
     877    int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
     878    if (cRefs == 0)
     879        NdisSetEvent(&pGlobals->EventUnloadAllowed);
     880    NdisReleaseSpinLock(&pGlobals->Lock);
     881    Assert(cRefs >= 0); NOREF(cRefs);
     882    LogFlow(("vboxNetAdpWinFactoryRelease: cRefs=%d (new)\n", cRefs));
     883}
     884
     885
     886
     887/* IDC */
     888
     889DECLINLINE(const char *) vboxNetAdpWinIdcStateToText(uint32_t enmState)
     890{
     891    switch (enmState)
     892    {
     893        case kVBoxNetAdpWinIdcState_Disconnected: return "Disconnected";
     894        case kVBoxNetAdpWinIdcState_Connecting: return "Connecting";
     895        case kVBoxNetAdpWinIdcState_Connected: return "Connected";
     896        case kVBoxNetAdpWinIdcState_Stopping: return "Stopping";
     897    }
     898    return "Unknown";
     899}
     900
     901static VOID vboxNetAdpWinInitIdcWorker(PVOID pvContext)
     902{
     903    int rc;
     904    PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)pvContext;
     905
     906    /*
     907     * Note that we break the rules here and access IDC state wihout acquiring
     908     * the lock. This is ok because vboxNetAdpWinUnload will wait for this
     909     * thread to terminate itself and we always use atomic access to IDC state.
     910     * We check the state (while holding the lock) further when we have succeeded
     911     * to connect. We cannot take the lock here and release it later as we will
     912     * be holding it for too long.
     913     */
     914    while (ASMAtomicReadU32(&pGlobals->enmIdcState) == kVBoxNetAdpWinIdcState_Connecting)
     915    {
     916        /*
     917         * Establish a connection to SUPDRV and register our component factory.
     918         */
     919        rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
     920        if (RT_SUCCESS(rc))
     921        {
     922            rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
     923            if (RT_SUCCESS(rc))
     924            {
     925                /*
     926                 * At this point we should take the lock to access IDC state as
     927                 * we technically may now race with factory methods.
     928                 */
     929                NdisAcquireSpinLock(&pGlobals->Lock);
     930                bool fSuccess = ASMAtomicCmpXchgU32(&pGlobals->enmIdcState,
     931                                                    kVBoxNetAdpWinIdcState_Connected,
     932                                                    kVBoxNetAdpWinIdcState_Connecting);
     933                NdisReleaseSpinLock(&pGlobals->Lock);
     934                if (!fSuccess)
     935                {
     936                    /* The state has been changed (the only valid transition is to "Stopping"), undo init */
     937                    rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
     938                    AssertRC(rc);
     939                    SUPR0IdcClose(&pGlobals->SupDrvIDC);
     940                    Log(("vboxNetAdpWinInitIdcWorker: state change (Connecting -> %s) while initializing IDC, closed IDC, rc=0x%x\n",
     941                         vboxNetAdpWinIdcStateToText(ASMAtomicReadU32(&pGlobals->enmIdcState)), rc));
     942                }
     943                else
     944                {
     945                    Log(("vboxNetAdpWinInitIdcWorker: IDC state change Connecting -> Connected\n"));
     946                }
     947            }
     948        }
     949        else
     950        {
     951            LARGE_INTEGER WaitIn100nsUnits;
     952            WaitIn100nsUnits.QuadPart = -(LONGLONG)5000000; /* 0.5 sec */
     953            KeDelayExecutionThread(KernelMode, FALSE /* non-alertable */, &WaitIn100nsUnits);
     954        }
     955    }
     956    PsTerminateSystemThread(STATUS_SUCCESS);
     957}
     958
     959
     960DECLHIDDEN(int) vboxNetAdpWinStartInitIdcThread(PVBOXNETADPGLOBALS pGlobals)
     961{
     962    int rc = VERR_INVALID_STATE;
     963
     964    /* No locking needed yet */
     965    if (ASMAtomicCmpXchgU32(&pGlobals->enmIdcState, kVBoxNetAdpWinIdcState_Connecting, kVBoxNetAdpWinIdcState_Disconnected))
     966    {
     967        Log(("vboxNetAdpWinStartInitIdcThread: IDC state change Diconnected -> Connecting\n"));
     968
     969        NTSTATUS Status = PsCreateSystemThread(&g_VBoxNetAdpGlobals.hInitIdcThread,
     970                                               THREAD_ALL_ACCESS,
     971                                               NULL,
     972                                               NULL,
     973                                               NULL,
     974                                               vboxNetAdpWinInitIdcWorker,
     975                                               &g_VBoxNetAdpGlobals);
     976        Log(("vboxNetAdpWinStartInitIdcThread: create IDC initialization thread, status=0x%x\n", Status));
     977        if (Status != STATUS_SUCCESS)
     978        {
     979            LogError(("vboxNetAdpWinStartInitIdcThread: IDC initialization failed (system thread creation, status=0x%x)\n", Status));
     980            /*
     981             * We failed to init IDC and there will be no second chance.
     982             */
     983            Log(("vboxNetAdpWinStartInitIdcThread: IDC state change Connecting -> Diconnected\n"));
     984            ASMAtomicWriteU32(&g_VBoxNetAdpGlobals.enmIdcState, kVBoxNetAdpWinIdcState_Disconnected);
     985        }
     986        rc = RTErrConvertFromNtStatus(Status);
     987    }
     988    return rc;
     989}
     990
     991
     992
     993/* === !!!! */
    148994
    149995
     
    1781024    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    1791025    PVBOXNETADP_ADAPTER pAdapter = NULL;
     1026    PVBOXNETADPGLOBALS pGlobals = &g_VBoxNetAdpGlobals;
    1801027
    1811028    LogFlow(("==>vboxNetAdpWinAllocAdapter: adapter handle=%p\n", hAdapter));
    1821029
     1030    /* Get the name */
     1031    UNICODE_STRING strUnicodeName;
     1032    Status = NdisMQueryAdapterInstanceName(&strUnicodeName, hAdapter);
     1033    if (Status != NDIS_STATUS_SUCCESS)
     1034    {
     1035        LogError(("vboxNetAdpWinAllocAdapter: NdisMQueryAdapterInstanceName failed with 0x%x\n", Status));
     1036        return Status;
     1037    }
     1038
     1039    ANSI_STRING strAnsiName;
     1040    /* We use the miniport name to associate this filter module with the netflt instance */
     1041    NTSTATUS rc = RtlUnicodeStringToAnsiString(&strAnsiName,
     1042                                               &strUnicodeName,
     1043                                               TRUE);
     1044    if (rc != STATUS_SUCCESS)
     1045    {
     1046        LogError(("vboxNetAdpWinAllocAdapter: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",
     1047                  strUnicodeName, rc));
     1048        //vboxNetAdpLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2);
     1049        NdisFreeMemory(strUnicodeName.Buffer, 0, 0);
     1050        return NDIS_STATUS_FAILURE;
     1051    }
     1052    NdisFreeMemory(strUnicodeName.Buffer, 0, 0);
     1053    DbgPrint("vboxNetAdpWinAllocAdapter: name=%Z\n", &strAnsiName);
     1054
    1831055    *ppAdapter = NULL;
    1841056
    185     pAdapter = (PVBOXNETADP_ADAPTER)NdisAllocateMemoryWithTagPriority(g_VBoxNetAdpGlobals.hMiniportDriver,
    186                                                                          sizeof(VBOXNETADP_ADAPTER),
    187                                                                          VBOXNETADPWIN_TAG,
    188                                                                          NormalPoolPriority);
     1057    UINT cbAdapterWithNameExtra = sizeof(VBOXNETADP_ADAPTER) + strAnsiName.Length;
     1058    pAdapter = (PVBOXNETADP_ADAPTER)NdisAllocateMemoryWithTagPriority(pGlobals->hMiniportDriver,
     1059                                                                      cbAdapterWithNameExtra,
     1060                                                                      VBOXNETADPWIN_TAG,
     1061                                                                      NormalPoolPriority);
    1891062    if (!pAdapter)
    1901063    {
     1064        RtlFreeAnsiString(&strAnsiName);
    1911065        Status = NDIS_STATUS_RESOURCES;
    1921066        Log(("vboxNetAdpWinAllocAdapter: Out of memory while allocating adapter context (size=%d)\n", sizeof(VBOXNETADP_ADAPTER)));
     
    1941068    else
    1951069    {
    196         NdisZeroMemory(pAdapter, sizeof(VBOXNETADP_ADAPTER));
     1070        NdisZeroMemory(pAdapter, cbAdapterWithNameExtra);
     1071        NdisMoveMemory(pAdapter->szName, strAnsiName.Buffer, strAnsiName.Length);
     1072        RtlFreeAnsiString(&strAnsiName);
     1073
     1074        /* Allocate buffer pool */
     1075        NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
     1076        NdisZeroMemory(&PoolParams, sizeof(PoolParams));
     1077        PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
     1078        PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
     1079        PoolParams.Header.Size = sizeof(PoolParams);
     1080        PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
     1081        PoolParams.fAllocateNetBuffer = TRUE;
     1082        PoolParams.ContextSize = 0;
     1083        PoolParams.PoolTag = VBOXNETADP_MEM_TAG;
     1084        pAdapter->hPool = NdisAllocateNetBufferListPool(hAdapter, &PoolParams);
     1085        if (!pAdapter->hPool)
     1086        {
     1087            LogError(("vboxNetAdpWinAllocAdapter: NdisAllocateNetBufferListPool failed\n"));
     1088            NdisFreeMemory(pAdapter, 0, 0);
     1089            return NDIS_STATUS_RESOURCES;
     1090        }
     1091        Log4(("vboxNetAdpWinAllocAdapter: allocated NBL+NB pool 0x%p\n", pAdapter->hPool));
     1092
    1971093        pAdapter->hAdapter = hAdapter;
    198         pAdapter->pGlobals = &g_VBoxNetAdpGlobals;
    199         /// @todo Use netadp structure instead!
    200     /* Use a locally administered version of the OUI we use for the guest NICs. */
    201     pAdapter->MacAddr.au8[0] = 0x08 | 2;
    202     pAdapter->MacAddr.au8[1] = 0x00;
    203     pAdapter->MacAddr.au8[2] = 0x27;
    204 
    205     pAdapter->MacAddr.au8[3] = (uIfIndex >> 16) & 0xFF;
    206     pAdapter->MacAddr.au8[4] = (uIfIndex >> 8) & 0xFF;
    207     pAdapter->MacAddr.au8[5] = uIfIndex & 0xFF;
    208 
    209         /// @todo Statistics?
     1094        pAdapter->MyPort.u32Version              = INTNETTRUNKIFPORT_VERSION;
     1095        pAdapter->MyPort.pfnRetain               = vboxNetAdpWinPortRetain;
     1096        pAdapter->MyPort.pfnRelease              = vboxNetAdpWinPortRelease;
     1097        pAdapter->MyPort.pfnDisconnectAndRelease = vboxNetAdpWinPortDisconnectAndRelease;
     1098        pAdapter->MyPort.pfnSetState             = vboxNetAdpWinPortSetState;
     1099        pAdapter->MyPort.pfnWaitForIdle          = vboxNetAdpWinPortWaitForIdle;
     1100        pAdapter->MyPort.pfnXmit                 = vboxNetAdpWinPortXmit;
     1101        pAdapter->MyPort.pfnNotifyMacAddress     = vboxNetAdpWinPortNotifyMacAddress;
     1102        pAdapter->MyPort.pfnConnectInterface     = vboxNetAdpWinPortConnectInterface;
     1103        pAdapter->MyPort.pfnDisconnectInterface  = vboxNetAdpWinPortDisconnectInterface;
     1104        pAdapter->MyPort.u32VersionEnd           = INTNETTRUNKIFPORT_VERSION;
     1105        pAdapter->pGlobals = pGlobals;
     1106        pAdapter->enmAdapterState = kVBoxNetAdpWinState_Initializing;
     1107        pAdapter->enmTrunkState = INTNETTRUNKIFSTATE_INACTIVE;
     1108        pAdapter->cBusy = 0;
     1109        NdisInitializeEvent(&pAdapter->EventIdle);
     1110        NdisSetEvent(&pAdapter->EventIdle); /* We are idle initially */
     1111
     1112        /* Use a locally administered version of the OUI we use for the guest NICs. */
     1113        pAdapter->MacAddr.au8[0] = 0x08 | 2;
     1114        pAdapter->MacAddr.au8[1] = 0x00;
     1115        pAdapter->MacAddr.au8[2] = 0x27;
     1116
     1117        pAdapter->MacAddr.au8[3] = (uIfIndex >> 16) & 0xFF;
     1118        pAdapter->MacAddr.au8[4] = (uIfIndex >> 8) & 0xFF;
     1119        pAdapter->MacAddr.au8[5] = uIfIndex & 0xFF;
     1120
     1121        NdisAcquireSpinLock(&pGlobals->Lock);
     1122        RTListPrepend(&pGlobals->ListOfAdapters, &pAdapter->node);
     1123        NdisReleaseSpinLock(&pGlobals->Lock);
    2101124
    2111125        *ppAdapter = pAdapter;
     
    2171131DECLHIDDEN(void) vboxNetAdpWinFreeAdapter(PVBOXNETADP_ADAPTER pAdapter)
    2181132{
     1133    /* Remove from adapter chain */
     1134    NdisAcquireSpinLock(&pAdapter->pGlobals->Lock);
     1135    RTListNodeRemove(&pAdapter->node);
     1136    NdisReleaseSpinLock(&pAdapter->pGlobals->Lock);
     1137
    2191138    NdisFreeMemory(pAdapter, 0, 0);
    2201139}
     
    3161235            break;
    3171236        }
     1237
     1238        VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pAdapter, kVBoxNetAdpWinState_Paused);
     1239        RT_NOREF1(enmPrevState);
     1240        Assert(enmPrevState == kVBoxNetAdpWinState_Initializing);
    3181241    } while (false);
    3191242
     
    3321255{
    3331256    RT_NOREF1(HaltAction);
    334     PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
     1257    PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
    3351258    LogFlow(("==>vboxNetAdpWinHaltEx\n"));
    336     /// @todo Stop something?
    337     if (pAdapter)
    338         vboxNetAdpWinFreeAdapter(pAdapter);
     1259    AssertPtr(pThis);
     1260    Assert(vboxNetAdpWinGetState(pThis) == kVBoxNetAdpWinState_Paused);
     1261    /*
     1262     * Check if the trunk is active which means the adapter gets disabled
     1263     * while it is used by VM(s) and we need to disconnect the trunk.
     1264     */
     1265    if (pThis->pSwitchPort && pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE)
     1266        pThis->pSwitchPort->pfnDisconnect(pThis->pSwitchPort, &pThis->MyPort, NULL);
     1267    /*
     1268     * Since we are already in the paused state and we have disconnected
     1269     * the trunk, we can safely destroy this adapter.
     1270     */
     1271    vboxNetAdpWinFreeAdapter(pThis);
    3391272    LogFlow(("<==vboxNetAdpWinHaltEx\n"));
    3401273}
     
    3431276                                           IN PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)
    3441277{
    345     RT_NOREF2(MiniportAdapterContext, MiniportPauseParameters);
     1278    RT_NOREF1(MiniportPauseParameters);
     1279    PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
    3461280    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    3471281    LogFlow(("==>vboxNetAdpWinPause\n"));
     1282    VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Pausing);
     1283    Assert(enmPrevState == kVBoxNetAdpWinState_Running);
     1284    if (!NdisWaitEvent(&pThis->EventIdle, 1000 /* ms */))
     1285    {
     1286        LogError(("vboxNetAdpWinPause: timed out while pausing the adapter\n"));
     1287        // @todo implement NDIS_STATUS_PENDING case? probably not.
     1288    }
     1289    enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Paused);
     1290    Assert(enmPrevState == kVBoxNetAdpWinState_Pausing);
    3481291    LogFlow(("<==vboxNetAdpWinPause: status=0x%x\n", Status));
    3491292    return Status;
     
    3531296                                             IN PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
    3541297{
    355     RT_NOREF2(MiniportAdapterContext, MiniportRestartParameters);
     1298    RT_NOREF1(MiniportRestartParameters);
     1299    PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
    3561300    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    3571301    LogFlow(("==>vboxNetAdpWinRestart\n"));
     1302    VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Restarting);
     1303    Assert(enmPrevState == kVBoxNetAdpWinState_Paused);
     1304    // @todo anything?
     1305    enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Running);
     1306    Assert(enmPrevState == kVBoxNetAdpWinState_Restarting);
    3581307    LogFlow(("<==vboxNetAdpWinRestart: status=0x%x\n", Status));
    3591308    return Status;
    3601309}
    3611310
    362 DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqQuery(PVBOXNETADP_ADAPTER pAdapter,
     1311DECLINLINE(uint64_t) vboxNetAdpWinStatsTotals(uint64_t *pStats)
     1312{
     1313    return pStats[kVBoxNetAdpWinPacketType_Unicast]
     1314        + pStats[kVBoxNetAdpWinPacketType_Multicast]
     1315        + pStats[kVBoxNetAdpWinPacketType_Broadcast];
     1316}
     1317
     1318DECLINLINE(PVOID) vboxNetAdpWinStatsU64(uint64_t *pTmp, ULONG *pcbTmp, uint64_t u64Stat)
     1319{
     1320    *pcbTmp = sizeof(*pTmp);
     1321    *pTmp = u64Stat;
     1322    return pTmp;
     1323}
     1324
     1325DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqQuery(PVBOXNETADP_ADAPTER pThis,
    3631326                                                PNDIS_OID_REQUEST pRequest)
    3641327{
     
    3951358            ulTmp = VBOXNETADP_MAX_FRAME_SIZE;
    3961359            break;
    397         case OID_GEN_RCV_OK:
    398         case OID_GEN_XMIT_OK:
    399             u64Tmp = 0;
    400             pInfo = &u64Tmp;
    401             cbInfo = sizeof(u64Tmp);
    402             break;
    4031360        case OID_GEN_RECEIVE_BUFFER_SPACE:
    4041361        case OID_GEN_TRANSMIT_BUFFER_SPACE:
    4051362            /// @todo Make configurable
    4061363            ulTmp = VBOXNETADP_MAX_FRAME_SIZE * 40;
     1364            break;
     1365        case OID_GEN_RCV_OK:
     1366            pInfo = vboxNetAdpWinStatsU64(&u64Tmp, &cbInfo, vboxNetAdpWinStatsTotals(pThis->au64StatsInPackets));
     1367            break;
     1368        case OID_GEN_XMIT_OK:
     1369            pInfo = vboxNetAdpWinStatsU64(&u64Tmp, &cbInfo, vboxNetAdpWinStatsTotals(pThis->au64StatsOutPackets));
    4071370            break;
    4081371        case OID_GEN_STATISTICS:
     
    4181381            pStats->Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
    4191382            pStats->Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
    420             /// @todo We need some stats, don't we?
     1383            pStats->SupportedStatistics =
     1384                  NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV
     1385                | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV
     1386                | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV
     1387                | NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV
     1388                | NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS
     1389                | NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR
     1390                | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT
     1391                | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT
     1392                | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT
     1393                | NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT
     1394                | NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR
     1395                | NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS
     1396                | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV
     1397                | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV
     1398                | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV
     1399                | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT
     1400                | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT
     1401                | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
     1402
     1403            pStats->ifHCInOctets = vboxNetAdpWinStatsTotals(pThis->au64StatsInOctets);
     1404            pStats->ifHCInUcastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Unicast]);
     1405            pStats->ifHCInMulticastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Multicast]);
     1406            pStats->ifHCInBroadcastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Broadcast]);
     1407            pStats->ifHCOutOctets = vboxNetAdpWinStatsTotals(pThis->au64StatsOutOctets);;
     1408            pStats->ifHCOutUcastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Unicast]);
     1409            pStats->ifHCOutMulticastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Multicast]);
     1410            pStats->ifHCOutBroadcastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Broadcast]);
     1411            pStats->ifHCInUcastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Unicast]);
     1412            pStats->ifHCInMulticastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Multicast]);
     1413            pStats->ifHCInBroadcastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Broadcast]);
     1414            pStats->ifHCOutUcastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Unicast]);
     1415            pStats->ifHCOutMulticastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Multicast]);
     1416            pStats->ifHCOutBroadcastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Broadcast]);
    4211417            break;
    4221418        }
     
    4331429        case OID_802_3_PERMANENT_ADDRESS:
    4341430        case OID_802_3_CURRENT_ADDRESS:
    435             pInfo = &pAdapter->MacAddr;
    436             cbInfo = sizeof(pAdapter->MacAddr);
     1431            pInfo = &pThis->MacAddr;
     1432            cbInfo = sizeof(pThis->MacAddr);
    4371433            break;
    4381434            //case OID_802_3_MULTICAST_LIST:
     
    4411437            break;
    4421438        case OID_PNP_CAPABILITIES:
    443             pInfo = &pAdapter->pGlobals->PMCaps;
    444             cbInfo = sizeof(pAdapter->pGlobals->PMCaps);
     1439            pInfo = &pThis->pGlobals->PMCaps;
     1440            cbInfo = sizeof(pThis->pGlobals->PMCaps);
    4451441            break;
    4461442        case OID_PNP_QUERY_POWER:
     
    5741570    LogFlow(("==>vboxNetAdpWinSendNetBufferLists\n"));
    5751571    PNET_BUFFER_LIST pNbl = NetBufferLists;
     1572    vboxNetAdpWinDumpPackets("vboxNetAdpWinSendNetBufferLists: got", pNbl);
     1573
     1574    /* We alwast complete all send requests. */
    5761575    for (pNbl = NetBufferLists; pNbl; pNbl = NET_BUFFER_LIST_NEXT_NBL(pNbl))
     1576    {
     1577        vboxNetAdpWinForwardToIntNet(pAdapter, pNbl, INTNETTRUNKDIR_HOST);
    5771578        NET_BUFFER_LIST_STATUS(pNbl) = NDIS_STATUS_SUCCESS;
     1579    }
    5781580    NdisMSendNetBufferListsComplete(pAdapter->hAdapter, NetBufferLists,
    5791581                                    (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL) ?
     
    5861588                                                   IN ULONG ReturnFlags)
    5871589{
    588     RT_NOREF3(MiniportAdapterContext, NetBufferLists, ReturnFlags);
    5891590    LogFlow(("==>vboxNetAdpWinReturnNetBufferLists\n"));
    590     Log(("vboxNetAdpWinReturnNetBufferLists: We should not be here!\n"));
     1591    RT_NOREF1(ReturnFlags);
     1592    PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
     1593    PNET_BUFFER_LIST pList = NetBufferLists;
     1594    while (pList)
     1595    {
     1596        Assert(pList->SourceHandle == pThis->hAdapter);
     1597        Assert(NET_BUFFER_LIST_FIRST_NB(pList));
     1598        Assert(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
     1599
     1600        PNET_BUFFER_LIST pNextList = NET_BUFFER_LIST_NEXT_NBL(pList);
     1601
     1602        vboxNetAdpWinFreeMdlChain(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
     1603        NdisFreeNetBufferList(pList);
     1604        Log4(("vboxNetLwfWinReturnNetBufferLists: freed NBL+NB+MDL+Data 0x%p\n", pList));
     1605        Assert(ASMAtomicReadS32(&pThis->cBusy) > 0);
     1606        if (ASMAtomicDecS32(&pThis->cBusy) == 0)
     1607            NdisSetEvent(&pThis->EventIdle);
     1608
     1609        pList = pNextList;
     1610    }
    5911611    LogFlow(("<==vboxNetAdpWinReturnNetBufferLists\n"));
    5921612}
     
    6541674    RT_NOREF1(DriverObject);
    6551675    LogFlow(("==>vboxNetAdpWinUnload\n"));
    656     //vboxNetAdpWinDevDestroy(&g_VBoxNetAdpGlobals);
    657     if (g_VBoxNetAdpGlobals.hMiniportDriver)
    658         NdisMDeregisterMiniportDriver(g_VBoxNetAdpGlobals.hMiniportDriver);
    659     //NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
     1676    PVBOXNETADPGLOBALS pGlobals = &g_VBoxNetAdpGlobals;
     1677    int rc;
     1678    NDIS_STATUS Status;
     1679    PKTHREAD pThread = NULL;
     1680
     1681    /* We are about to disconnect IDC, let's make it clear so the factories will know */
     1682    NdisAcquireSpinLock(&pGlobals->Lock);
     1683    uint32_t enmPrevState = ASMAtomicXchgU32(&g_VBoxNetAdpGlobals.enmIdcState, kVBoxNetAdpWinIdcState_Stopping);
     1684    NdisReleaseSpinLock(&pGlobals->Lock);
     1685    Log(("vboxNetAdpWinUnload: IDC state change %s -> Stopping\n", vboxNetAdpWinIdcStateToText(enmPrevState)));
     1686
     1687    switch (enmPrevState)
     1688    {
     1689        case kVBoxNetAdpWinIdcState_Disconnected:
     1690            /* Have not even attempted to connect -- nothing to do. */
     1691            break;
     1692        case kVBoxNetAdpWinIdcState_Stopping:
     1693            /* Impossible, but another thread is alreading doing StopIdc, bail out */
     1694            LogError(("vboxNetAdpWinUnload: called in 'Stopping' state\n"));
     1695            break;
     1696        case kVBoxNetAdpWinIdcState_Connecting:
     1697            /* the worker thread is running, let's wait for it to stop */
     1698            Status = ObReferenceObjectByHandle(g_VBoxNetAdpGlobals.hInitIdcThread,
     1699                                               THREAD_ALL_ACCESS, NULL, KernelMode,
     1700                                               (PVOID*)&pThread, NULL);
     1701            if (Status == STATUS_SUCCESS)
     1702            {
     1703                KeWaitForSingleObject(pThread, Executive, KernelMode, FALSE, NULL);
     1704                ObDereferenceObject(pThread);
     1705            }
     1706            else
     1707            {
     1708                LogError(("vboxNetAdpWinStopIdc: ObReferenceObjectByHandle(%p) failed with 0x%x\n",
     1709                     g_VBoxNetAdpGlobals.hInitIdcThread, Status));
     1710            }
     1711            break;
     1712        case kVBoxNetAdpWinIdcState_Connected:
     1713            /* the worker succeeded in IDC init and terminated */
     1714            /* Make sure nobody uses the trunk factory. Wait half a second if needed. */
     1715            if (!NdisWaitEvent(&pGlobals->EventUnloadAllowed, 500))
     1716                LogRel(("VBoxNetAdp: unloading driver while trunk factory is in use!\n"));
     1717            rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
     1718            AssertRC(rc);
     1719            SUPR0IdcClose(&pGlobals->SupDrvIDC);
     1720            Log(("vboxNetAdpWinUnload: closed IDC, rc=0x%x\n", rc));
     1721            break;
     1722    }
     1723    if (pGlobals->hMiniportDriver)
     1724        NdisMDeregisterMiniportDriver(pGlobals->hMiniportDriver);
     1725    NdisFreeSpinLock(&pGlobals->Lock);
    6601726    LogFlow(("<==vboxNetAdpWinUnload\n"));
     1727    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
     1728    RTLogDestroy(RTLogSetDefaultInstance(NULL));
    6611729    RTR0Term();
    6621730}
     
    7091777    {
    7101778        Log(("vboxNetAdpWinRegister: successfully registered miniport driver; registering device...\n"));
    711         //Status = vboxNetAdpWinDevCreate(&g_VBoxNetAdpGlobals);
    712         //Assert(Status == STATUS_SUCCESS);
    713         //Log(("vboxNetAdpWinRegister: vboxNetAdpWinDevCreate() returned 0x%x\n", Status));
    7141779    }
    7151780    else
     
    7381803    {
    7391804        NdisZeroMemory(&g_VBoxNetAdpGlobals, sizeof (g_VBoxNetAdpGlobals));
    740         //NdisAllocateSpinLock(&g_VBoxNetAdpGlobals.Lock);
     1805        RTListInit(&g_VBoxNetAdpGlobals.ListOfAdapters);
     1806        NdisAllocateSpinLock(&g_VBoxNetAdpGlobals.Lock);
     1807        NdisInitializeEvent(&g_VBoxNetAdpGlobals.EventUnloadAllowed);
    7411808        //g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
    7421809        g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
    7431810        g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
    7441811
    745         Status = vboxNetAdpWinRegister(pDriverObject, pRegistryPath);
    746         Assert(Status == STATUS_SUCCESS);
    747         if (Status == NDIS_STATUS_SUCCESS)
    748         {
    749             Log(("NETADP: started successfully\n"));
    750             return STATUS_SUCCESS;
    751         }
    752         //NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
     1812        /* Initialize SupDrv interface */
     1813        g_VBoxNetAdpGlobals.SupDrvFactory.pfnQueryFactoryInterface = vboxNetAdpWinQueryFactoryInterface;
     1814        memcpy(g_VBoxNetAdpGlobals.SupDrvFactory.szName, "VBoxNetAdp", sizeof("VBoxNetAdp"));
     1815        /* Initialize trunk factory interface */
     1816        g_VBoxNetAdpGlobals.TrunkFactory.pfnRelease = vboxNetAdpWinFactoryRelease;
     1817        g_VBoxNetAdpGlobals.TrunkFactory.pfnCreateAndConnect = vboxNetAdpWinFactoryCreateAndConnect;
     1818
     1819        rc = vboxNetAdpWinStartInitIdcThread(&g_VBoxNetAdpGlobals);
     1820        if (RT_SUCCESS(rc))
     1821        {
     1822            Status = vboxNetAdpWinRegister(pDriverObject, pRegistryPath);
     1823            Assert(Status == STATUS_SUCCESS);
     1824            if (Status == NDIS_STATUS_SUCCESS)
     1825            {
     1826                Log(("NETADP: started successfully\n"));
     1827                return STATUS_SUCCESS;
     1828            }
     1829        }
     1830        else
     1831            Status = NDIS_STATUS_FAILURE;
     1832        NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
    7531833        RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
    7541834        RTLogDestroy(RTLogSetDefaultInstance(NULL));
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette