VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/win/VBoxNetAdp-win.cpp@ 80651

Last change on this file since 80651 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 73.7 KB
Line 
1/* $Id: VBoxNetAdp-win.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxNetAdp-win.cpp - NDIS6 Host-only Networking Driver, Windows-specific code.
4 */
5/*
6 * Copyright (C) 2014-2019 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
27
28#include <VBox/log.h>
29#include <VBox/version.h>
30#include <VBox/err.h>
31#include <VBox/sup.h>
32#include <VBox/intnet.h>
33#include <VBox/intnetinline.h>
34#include <iprt/assert.h>
35#include <iprt/initterm.h>
36#include <iprt/list.h>
37#include <iprt/net.h>
38#include <iprt/semaphore.h>
39#include <iprt/string.h>
40#include <iprt/uuid.h>
41
42#include <iprt/nt/ntddk.h>
43#include <iprt/nt/ndis.h>
44
45#include "VBoxNetAdp-win.h"
46#include "VBox/VBoxNetCmn-win.h"
47
48#define VBOXNETADP_MEM_TAG 'OHBV'
49
50/*
51 * By default the link speed reported to be 1Gbps. We may wish to lower
52 * it to 100Mbps to work around issues with multi-cast traffic on the host.
53 * See @bugref{6379}.
54 */
55#define VBOXNETADPWIN_LINK_SPEED 1000000000ULL
56
57#define LogError LogRel
58
59/* Forward declarations */
60MINIPORT_INITIALIZE vboxNetAdpWinInitializeEx;
61MINIPORT_HALT vboxNetAdpWinHaltEx;
62MINIPORT_UNLOAD vboxNetAdpWinUnload;
63MINIPORT_PAUSE vboxNetAdpWinPause;
64MINIPORT_RESTART vboxNetAdpWinRestart;
65MINIPORT_OID_REQUEST vboxNetAdpWinOidRequest;
66MINIPORT_SEND_NET_BUFFER_LISTS vboxNetAdpWinSendNetBufferLists;
67MINIPORT_RETURN_NET_BUFFER_LISTS vboxNetAdpWinReturnNetBufferLists;
68MINIPORT_CANCEL_SEND vboxNetAdpWinCancelSend;
69MINIPORT_CHECK_FOR_HANG vboxNetAdpWinCheckForHangEx;
70MINIPORT_RESET vboxNetAdpWinResetEx;
71MINIPORT_DEVICE_PNP_EVENT_NOTIFY vboxNetAdpWinDevicePnPEventNotify;
72MINIPORT_SHUTDOWN vboxNetAdpWinShutdownEx;
73MINIPORT_CANCEL_OID_REQUEST vboxNetAdpWinCancelOidRequest;
74
75
76/* Packet types by destination address; used in statistics. */
77typedef enum {
78 kVBoxNetAdpWinPacketType_Unicast,
79 kVBoxNetAdpWinPacketType_Multicast,
80 kVBoxNetAdpWinPacketType_Broadcast,
81 kVBoxNetAdpWinPacketType_ArraySize /* Must be the last one */
82} VBOXNETADPWIN_PACKET_TYPE;
83
84
85/* Miniport states as defined by NDIS. */
86typedef enum {
87 kVBoxNetAdpWinState_Initializing,
88 kVBoxNetAdpWinState_Paused,
89 kVBoxNetAdpWinState_Restarting,
90 kVBoxNetAdpWinState_Running,
91 kVBoxNetAdpWinState_Pausing,
92 kVBoxNetAdpWinState_32BitHack = 0x7fffffff
93} VBOXNETADPWIN_ADAPTER_STATE;
94
95
96/*
97 * Valid state transitions are:
98 * 1) Disconnected -> Connecting : start the worker thread, attempting to init IDC;
99 * 2) Connecting -> Disconnected : failed to start IDC init worker thread;
100 * 3) Connecting -> Connected : IDC init successful, terminate the worker;
101 * 4) Connecting -> Stopping : IDC init incomplete, but the driver is being unloaded, terminate the worker;
102 * 5) Connected -> Stopping : IDC init was successful, no worker, the driver is being unloaded;
103 *
104 * Driver terminates in either in Disconnected or in Stopping state.
105 */
106typedef enum {
107 kVBoxNetAdpWinIdcState_Disconnected = 0, /* Initial state */
108 kVBoxNetAdpWinIdcState_Connecting, /* Attemping to init IDC, worker thread running */
109 kVBoxNetAdpWinIdcState_Connected, /* Successfully connected to IDC, worker thread terminated */
110 kVBoxNetAdpWinIdcState_Stopping /* Terminating the worker thread and disconnecting IDC */
111} VBOXNETADPWIN_IDC_STATE;
112
113typedef struct _VBOXNETADPGLOBALS
114{
115 /** Miniport driver handle. */
116 NDIS_HANDLE hMiniportDriver;
117 /** Power management capabilities, shared by all instances, do not change after init. */
118 NDIS_PNP_CAPABILITIES PMCaps;
119 /** The INTNET trunk network interface factory. */
120 INTNETTRUNKFACTORY TrunkFactory;
121 /** The SUPDRV component factory registration. */
122 SUPDRVFACTORY SupDrvFactory;
123 /** The SUPDRV IDC handle (opaque struct). */
124 SUPDRVIDCHANDLE SupDrvIDC;
125 /** IDC init thread handle. */
126 HANDLE hInitIdcThread;
127 /** Lock protecting the following members. */
128 NDIS_SPIN_LOCK Lock;
129 /** Lock-protected: the head of module list. */
130 RTLISTANCHOR ListOfAdapters;
131 /** Lock-protected: The number of current factory references. */
132 int32_t volatile cFactoryRefs;
133 /** Lock-protected: IDC initialization state. */
134 volatile uint32_t enmIdcState;
135 /** Lock-protected: event signaled when trunk factory is not in use. */
136 NDIS_EVENT EventUnloadAllowed;
137} VBOXNETADPGLOBALS, *PVBOXNETADPGLOBALS;
138
139/* win-specific global data */
140VBOXNETADPGLOBALS g_VBoxNetAdpGlobals;
141
142
143typedef struct _VBOXNETADP_ADAPTER {
144 /** Auxiliary member to link adapters into a list. */
145 RTLISTNODE node;
146 /** Adapter handle for NDIS. */
147 NDIS_HANDLE hAdapter;
148 /** Memory pool network buffers are allocated from. */
149 NDIS_HANDLE hPool;
150 /** Our RJ-45 port.
151 * This is what the internal network plugs into. */
152 INTNETTRUNKIFPORT MyPort;
153 /** The RJ-45 port on the INTNET "switch".
154 * This is what we're connected to. */
155 PINTNETTRUNKSWPORT pSwitchPort;
156 /** Pointer to global data */
157 PVBOXNETADPGLOBALS pGlobals;
158 /** Adapter state in NDIS, used for assertions only */
159 VBOXNETADPWIN_ADAPTER_STATE volatile enmAdapterState; /// @todo do we need it really?
160 /** The trunk state. */
161 INTNETTRUNKIFSTATE volatile enmTrunkState;
162 /** Number of pending operations, when it reaches zero we signal EventIdle. */
163 int32_t volatile cBusy;
164 /** The event that is signaled when we go idle and that pfnWaitForIdle blocks on. */
165 NDIS_EVENT EventIdle;
166 /** MAC address of adapter. */
167 RTMAC MacAddr;
168 /** Statistics: bytes received from internal network. */
169 uint64_t au64StatsInOctets[kVBoxNetAdpWinPacketType_ArraySize];
170 /** Statistics: packets received from internal network. */
171 uint64_t au64StatsInPackets[kVBoxNetAdpWinPacketType_ArraySize];
172 /** Statistics: bytes sent to internal network. */
173 uint64_t au64StatsOutOctets[kVBoxNetAdpWinPacketType_ArraySize];
174 /** Statistics: packets sent to internal network. */
175 uint64_t au64StatsOutPackets[kVBoxNetAdpWinPacketType_ArraySize];
176 /** Adapter friendly name. */
177 char szName[1];
178} VBOXNETADP_ADAPTER;
179typedef VBOXNETADP_ADAPTER *PVBOXNETADP_ADAPTER;
180
181
182/* Port */
183
184#define IFPORT_2_VBOXNETADP_ADAPTER(pIfPort) \
185 ( (PVBOXNETADP_ADAPTER)((uint8_t *)(pIfPort) - RT_UOFFSETOF(VBOXNETADP_ADAPTER, MyPort)) )
186
187DECLINLINE(VBOXNETADPWIN_ADAPTER_STATE) vboxNetAdpWinGetState(PVBOXNETADP_ADAPTER pThis)
188{
189 return (VBOXNETADPWIN_ADAPTER_STATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmAdapterState);
190}
191
192DECLINLINE(VBOXNETADPWIN_ADAPTER_STATE) vboxNetAdpWinSetState(PVBOXNETADP_ADAPTER pThis, VBOXNETADPWIN_ADAPTER_STATE enmNewState)
193{
194 return (VBOXNETADPWIN_ADAPTER_STATE)ASMAtomicXchgU32((uint32_t volatile *)&pThis->enmAdapterState, enmNewState);
195}
196
197DECLINLINE(bool) vboxNetAdpWinSetState(PVBOXNETADP_ADAPTER pThis, VBOXNETADPWIN_ADAPTER_STATE enmNewState,
198 VBOXNETADPWIN_ADAPTER_STATE enmOldState)
199{
200 return ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmAdapterState, enmNewState, enmOldState);
201}
202
203#ifdef DEBUG
204
205DECLHIDDEN(void) vboxNetAdpWinDumpPackets(const char *pszMsg, PNET_BUFFER_LIST pBufLists)
206{
207 for (PNET_BUFFER_LIST pList = pBufLists; pList; pList = NET_BUFFER_LIST_NEXT_NBL(pList))
208 {
209 for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
210 {
211 Log6(("%s packet: cb=%d offset=%d", pszMsg, NET_BUFFER_DATA_LENGTH(pBuf), NET_BUFFER_DATA_OFFSET(pBuf)));
212 for (PMDL pMdl = NET_BUFFER_FIRST_MDL(pBuf);
213 pMdl != NULL;
214 pMdl = NDIS_MDL_LINKAGE(pMdl))
215 {
216 Log6((" MDL: cb=%d", MmGetMdlByteCount(pMdl)));
217 }
218 Log6(("\n"));
219 }
220 }
221}
222
223DECLINLINE(const char *) vboxNetAdpWinEthTypeStr(uint16_t uType)
224{
225 switch (uType)
226 {
227 case RTNET_ETHERTYPE_IPV4: return "IP";
228 case RTNET_ETHERTYPE_IPV6: return "IPv6";
229 case RTNET_ETHERTYPE_ARP: return "ARP";
230 }
231 return "unknown";
232}
233
234#define VBOXNETADP_PKTDMPSIZE 0x50
235
236/**
237 * Dump a packet to debug log.
238 *
239 * @param cpPacket The packet.
240 * @param cb The size of the packet.
241 * @param cszText A string denoting direction of packet transfer.
242 */
243DECLINLINE(void) vboxNetAdpWinDumpPacket(PCINTNETSG pSG, const char *cszText)
244{
245 uint8_t bPacket[VBOXNETADP_PKTDMPSIZE];
246
247 uint32_t cb = pSG->cbTotal < VBOXNETADP_PKTDMPSIZE ? pSG->cbTotal : VBOXNETADP_PKTDMPSIZE;
248 IntNetSgReadEx(pSG, 0, cb, bPacket);
249
250 AssertReturnVoid(cb >= 14);
251
252 uint8_t *pHdr = bPacket;
253 uint8_t *pEnd = bPacket + cb;
254 AssertReturnVoid(pEnd - pHdr >= 14);
255 uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+12));
256 Log2(("NetADP: %s (%d bytes), %RTmac => %RTmac, EthType=%s(0x%x)\n",
257 cszText, pSG->cbTotal, pHdr+6, pHdr, vboxNetAdpWinEthTypeStr(uEthType), uEthType));
258 pHdr += sizeof(RTNETETHERHDR);
259 if (uEthType == RTNET_ETHERTYPE_VLAN)
260 {
261 AssertReturnVoid(pEnd - pHdr >= 4);
262 uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+2));
263 Log2((" + VLAN: id=%d EthType=%s(0x%x)\n", RT_N2H_U16(*(uint16_t*)(pHdr)) & 0xFFF,
264 vboxNetAdpWinEthTypeStr(uEthType), uEthType));
265 pHdr += 2 * sizeof(uint16_t);
266 }
267 uint8_t uProto = 0xFF;
268 switch (uEthType)
269 {
270 case RTNET_ETHERTYPE_IPV6:
271 AssertReturnVoid(pEnd - pHdr >= 40);
272 uProto = pHdr[6];
273 Log2((" + IPv6: %RTnaipv6 => %RTnaipv6\n", pHdr+8, pHdr+24));
274 pHdr += 40;
275 break;
276 case RTNET_ETHERTYPE_IPV4:
277 AssertReturnVoid(pEnd - pHdr >= 20);
278 uProto = pHdr[9];
279 Log2((" + IP: %RTnaipv4 => %RTnaipv4\n", *(uint32_t*)(pHdr+12), *(uint32_t*)(pHdr+16)));
280 pHdr += (pHdr[0] & 0xF) * 4;
281 break;
282 case RTNET_ETHERTYPE_ARP:
283 AssertReturnVoid(pEnd - pHdr >= 28);
284 AssertReturnVoid(RT_N2H_U16(*(uint16_t*)(pHdr+2)) == RTNET_ETHERTYPE_IPV4);
285 switch (RT_N2H_U16(*(uint16_t*)(pHdr+6)))
286 {
287 case 1: /* ARP request */
288 Log2((" + ARP-REQ: who-has %RTnaipv4 tell %RTnaipv4\n",
289 *(uint32_t*)(pHdr+24), *(uint32_t*)(pHdr+14)));
290 break;
291 case 2: /* ARP reply */
292 Log2((" + ARP-RPL: %RTnaipv4 is-at %RTmac\n",
293 *(uint32_t*)(pHdr+14), pHdr+8));
294 break;
295 default:
296 Log2((" + ARP: unknown op %d\n", RT_N2H_U16(*(uint16_t*)(pHdr+6))));
297 break;
298 }
299 break;
300 /* There is no default case as uProto is initialized with 0xFF */
301 }
302 while (uProto != 0xFF)
303 {
304 switch (uProto)
305 {
306 case 0: /* IPv6 Hop-by-Hop option*/
307 case 60: /* IPv6 Destination option*/
308 case 43: /* IPv6 Routing option */
309 case 44: /* IPv6 Fragment option */
310 Log2((" + IPv6 option (%d): <not implemented>\n", uProto));
311 uProto = pHdr[0];
312 pHdr += pHdr[1] * 8 + 8; /* Skip to the next extension/protocol */
313 break;
314 case 51: /* IPv6 IPsec AH */
315 Log2((" + IPv6 IPsec AH: <not implemented>\n"));
316 uProto = pHdr[0];
317 pHdr += (pHdr[1] + 2) * 4; /* Skip to the next extension/protocol */
318 break;
319 case 50: /* IPv6 IPsec ESP */
320 /* Cannot decode IPsec, fall through */
321 Log2((" + IPv6 IPsec ESP: <not implemented>\n"));
322 uProto = 0xFF;
323 break;
324 case 59: /* No Next Header */
325 Log2((" + IPv6 No Next Header\n"));
326 uProto = 0xFF;
327 break;
328 case 58: /* IPv6-ICMP */
329 switch (pHdr[0])
330 {
331 case 1: Log2((" + IPv6-ICMP: destination unreachable, code %d\n", pHdr[1])); break;
332 case 128: Log2((" + IPv6-ICMP: echo request\n")); break;
333 case 129: Log2((" + IPv6-ICMP: echo reply\n")); break;
334 default: Log2((" + IPv6-ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
335 }
336 uProto = 0xFF;
337 break;
338 case 1: /* ICMP */
339 switch (pHdr[0])
340 {
341 case 0: Log2((" + ICMP: echo reply\n")); break;
342 case 8: Log2((" + ICMP: echo request\n")); break;
343 case 3: Log2((" + ICMP: destination unreachable, code %d\n", pHdr[1])); break;
344 default: Log2((" + ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
345 }
346 uProto = 0xFF;
347 break;
348 case 6: /* TCP */
349 Log2((" + TCP: src=%d dst=%d seq=%x ack=%x\n",
350 RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2)),
351 RT_N2H_U32(*(uint32_t*)(pHdr+4)), RT_N2H_U32(*(uint32_t*)(pHdr+8))));
352 uProto = 0xFF;
353 break;
354 case 17: /* UDP */
355 Log2((" + UDP: src=%d dst=%d\n",
356 RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2))));
357 uProto = 0xFF;
358 break;
359 default:
360 Log2((" + Unknown: proto=0x%x\n", uProto));
361 uProto = 0xFF;
362 break;
363 }
364 }
365 Log3(("%.*Rhxd\n", cb, bPacket));
366}
367
368#else /* !DEBUG */
369//# define vboxNetAdpWinDumpFilterTypes(uFlags) do { } while (0)
370//# define vboxNetAdpWinDumpOffloadSettings(p) do { } while (0)
371//# define vboxNetAdpWinDumpSetOffloadSettings(p) do { } while (0)
372# define vboxNetAdpWinDumpPackets(m,l) do { } while (0)
373# define vboxNetAdpWinDumpPacket(p,t) do { } while (0)
374#endif /* !DEBUG */
375
376
377DECLHIDDEN(VBOXNETADPWIN_PACKET_TYPE) vboxNetAdpWinPacketType(PINTNETSG pSG)
378{
379 static const uint8_t g_abBcastAddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
380 AssertReturn(pSG->cbTotal >= sizeof(g_abBcastAddr), kVBoxNetAdpWinPacketType_Unicast);
381 AssertReturn(pSG->cSegsUsed > 0, kVBoxNetAdpWinPacketType_Unicast);
382 AssertReturn(pSG->aSegs[0].cb >= sizeof(g_abBcastAddr), kVBoxNetAdpWinPacketType_Unicast);
383 if (!memcmp(pSG->aSegs[0].pv, g_abBcastAddr, sizeof(g_abBcastAddr)))
384 return kVBoxNetAdpWinPacketType_Broadcast;
385 if ((*(uint8_t*)pSG->aSegs[0].pv) & 1)
386 return kVBoxNetAdpWinPacketType_Multicast;
387 return kVBoxNetAdpWinPacketType_Unicast;
388}
389
390DECLINLINE(void) vboxNetAdpWinUpdateStats(uint64_t *pPacketStats, uint64_t *pOctetStats, PINTNETSG pSG)
391{
392 VBOXNETADPWIN_PACKET_TYPE enmPktType = vboxNetAdpWinPacketType(pSG);
393 ASMAtomicIncU64(&pPacketStats[enmPktType]);
394 ASMAtomicAddU64(&pOctetStats[enmPktType], pSG->cbTotal);
395}
396
397DECLINLINE(void) vboxNetAdpWinFreeMdlChain(PMDL pMdl)
398{
399 PMDL pMdlNext;
400 while (pMdl)
401 {
402 pMdlNext = pMdl->Next;
403 PUCHAR pDataBuf;
404 ULONG cb = 0;
405 NdisQueryMdl(pMdl, &pDataBuf, &cb, NormalPagePriority);
406 NdisFreeMdl(pMdl);
407 Log4(("vboxNetAdpWinFreeMdlChain: freed MDL 0x%p\n", pMdl));
408 NdisFreeMemory(pDataBuf, 0, 0);
409 Log4(("vboxNetAdpWinFreeMdlChain: freed data buffer 0x%p\n", pDataBuf));
410 pMdl = pMdlNext;
411 }
412}
413
414DECLHIDDEN(PNET_BUFFER_LIST) vboxNetAdpWinSGtoNB(PVBOXNETADP_ADAPTER pThis, PINTNETSG pSG)
415{
416 AssertReturn(pSG->cSegsUsed >= 1, NULL);
417 LogFlow(("==>vboxNetAdpWinSGtoNB: segments=%d hPool=%p cb=%u\n", pSG->cSegsUsed,
418 pThis->hPool, pSG->cbTotal));
419 AssertReturn(pThis->hPool, NULL);
420
421
422 PNET_BUFFER_LIST pBufList = NULL;
423 ULONG cbMdl = pSG->cbTotal;
424 ULONG uDataOffset = cbMdl - pSG->cbTotal;
425 PUCHAR pDataBuf = (PUCHAR)NdisAllocateMemoryWithTagPriority(pThis->hAdapter, cbMdl,
426 VBOXNETADP_MEM_TAG, NormalPoolPriority);
427 if (pDataBuf)
428 {
429 Log4(("vboxNetAdpWinSGtoNB: allocated data buffer (cb=%u) 0x%p\n", cbMdl, pDataBuf));
430 PMDL pMdl = NdisAllocateMdl(pThis->hAdapter, pDataBuf, cbMdl);
431 if (!pMdl)
432 {
433 NdisFreeMemory(pDataBuf, 0, 0);
434 Log4(("vboxNetAdpWinSGtoNB: freed data buffer 0x%p\n", pDataBuf));
435 LogError(("vboxNetAdpWinSGtoNB: failed to allocate an MDL (cb=%u)\n", cbMdl));
436 LogFlow(("<==vboxNetAdpWinSGtoNB: return NULL\n"));
437 return NULL;
438 }
439 PUCHAR pDst = pDataBuf + uDataOffset;
440 for (int i = 0; i < pSG->cSegsUsed; i++)
441 {
442 NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb);
443 pDst += pSG->aSegs[i].cb;
444 }
445 pBufList = NdisAllocateNetBufferAndNetBufferList(pThis->hPool,
446 0 /* ContextSize */,
447 0 /* ContextBackFill */,
448 pMdl,
449 uDataOffset,
450 pSG->cbTotal);
451 if (pBufList)
452 {
453 Log4(("vboxNetAdpWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList));
454 pBufList->SourceHandle = pThis->hAdapter;
455 /** @todo Do we need to initialize anything else? */
456 }
457 else
458 {
459 LogError(("vboxNetAdpWinSGtoNB: failed to allocate an NBL+NB\n"));
460 vboxNetAdpWinFreeMdlChain(pMdl);
461 }
462 }
463 else
464 {
465 LogError(("vboxNetAdpWinSGtoNB: failed to allocate data buffer (size=%u)\n", cbMdl));
466 }
467
468 LogFlow(("<==vboxNetAdpWinSGtoNB: return %p\n", pBufList));
469 return pBufList;
470}
471
472DECLINLINE(void) vboxNetAdpWinDestroySG(PINTNETSG pSG)
473{
474 NdisFreeMemory(pSG, 0, 0);
475 Log4(("vboxNetAdpWinDestroySG: freed SG 0x%p\n", pSG));
476}
477
478/**
479 * Worker for vboxNetAdpWinNBtoSG() that gets the max segment count needed.
480 * @note vboxNetAdpWinNBtoSG may use fewer depending on cbPacket and offset!
481 * @note vboxNetLwfWinCalcSegments() is a copy of this code.
482 */
483DECLINLINE(ULONG) vboxNetAdpWinCalcSegments(PNET_BUFFER pNetBuf)
484{
485 ULONG cSegs = 0;
486 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); pMdl; pMdl = NDIS_MDL_LINKAGE(pMdl))
487 {
488 /* Skip empty MDLs (see @bugref{9233}) */
489 if (MmGetMdlByteCount(pMdl))
490 cSegs++;
491 }
492 return cSegs;
493}
494
495/**
496 * @note vboxNetLwfWinNBtoSG() is a copy of this code.
497 */
498DECLHIDDEN(PINTNETSG) vboxNetAdpWinNBtoSG(PVBOXNETADP_ADAPTER pThis, PNET_BUFFER pNetBuf)
499{
500 ULONG cbPacket = NET_BUFFER_DATA_LENGTH(pNetBuf);
501 ULONG cSegs = vboxNetAdpWinCalcSegments(pNetBuf);
502 /* Allocate and initialize SG */
503 PINTNETSG pSG = (PINTNETSG)NdisAllocateMemoryWithTagPriority(pThis->hAdapter,
504 RT_UOFFSETOF_DYN(INTNETSG, aSegs[cSegs]),
505 VBOXNETADP_MEM_TAG,
506 NormalPoolPriority);
507 AssertReturn(pSG, pSG);
508 Log4(("vboxNetAdpWinNBtoSG: allocated SG 0x%p\n", pSG));
509 IntNetSgInitTempSegs(pSG, cbPacket /*cbTotal*/, cSegs, cSegs /*cSegsUsed*/);
510
511 ULONG uOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuf);
512 cSegs = 0;
513 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf);
514 pMdl != NULL && cbPacket > 0;
515 pMdl = NDIS_MDL_LINKAGE(pMdl))
516 {
517 ULONG cbSrc = MmGetMdlByteCount(pMdl);
518 if (cbSrc == 0)
519 continue; /* Skip empty MDLs (see @bugref{9233}) */
520
521 PUCHAR pSrc = (PUCHAR)MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);
522 if (!pSrc)
523 {
524 vboxNetAdpWinDestroySG(pSG);
525 return NULL;
526 }
527
528 /* Handle the offset in the current (which is the first for us) MDL */
529 if (uOffset)
530 {
531 if (uOffset < cbSrc)
532 {
533 pSrc += uOffset;
534 cbSrc -= uOffset;
535 uOffset = 0;
536 }
537 else
538 {
539 /* This is an invalid MDL chain */
540 vboxNetAdpWinDestroySG(pSG);
541 return NULL;
542 }
543 }
544
545 /* Do not read the last MDL beyond packet's end */
546 if (cbSrc > cbPacket)
547 cbSrc = cbPacket;
548
549 Assert(cSegs < pSG->cSegsAlloc);
550 pSG->aSegs[cSegs].pv = pSrc;
551 pSG->aSegs[cSegs].cb = cbSrc;
552 pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS;
553 cSegs++;
554 cbPacket -= cbSrc;
555 }
556
557 Assert(cbPacket == 0);
558 Assert(cSegs <= pSG->cSegsUsed);
559
560 /* Update actual segment count in case we used fewer than anticipated. */
561 pSG->cSegsUsed = (uint16_t)cSegs;
562
563 return pSG;
564}
565
566DECLINLINE(bool) vboxNetAdpWinIsActive(PVBOXNETADP_ADAPTER pThis)
567{
568 if (vboxNetAdpWinGetState(pThis) != kVBoxNetAdpWinState_Running)
569 return false;
570 if (pThis->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE)
571 return false;
572 AssertPtrReturn(pThis->pSwitchPort, false);
573 return true;
574}
575
576DECLHIDDEN(bool) vboxNetAdpWinForwardToIntNet(PVBOXNETADP_ADAPTER pThis, PNET_BUFFER_LIST pList, uint32_t fSrc)
577{
578 if (!vboxNetAdpWinIsActive(pThis))
579 {
580 LogFlow(("vboxNetAdpWinForwardToIntNet: not active\n"));
581 return false;
582 }
583 AssertReturn(pThis->pSwitchPort, false);
584 AssertReturn(pThis->pSwitchPort->pfnRecv, false);
585 LogFlow(("==>vboxNetAdpWinForwardToIntNet\n"));
586
587 if (ASMAtomicIncS32(&pThis->cBusy) == 1)
588 NdisResetEvent(&pThis->EventIdle);
589 for (PNET_BUFFER pBuf = NET_BUFFER_LIST_FIRST_NB(pList); pBuf; pBuf = NET_BUFFER_NEXT_NB(pBuf))
590 {
591 PINTNETSG pSG = vboxNetAdpWinNBtoSG(pThis, pBuf);
592 if (pSG)
593 {
594 vboxNetAdpWinUpdateStats(pThis->au64StatsOutPackets, pThis->au64StatsOutOctets, pSG);
595 vboxNetAdpWinDumpPacket(pSG, (fSrc & INTNETTRUNKDIR_WIRE)?"intnet <-- wire":"intnet <-- host");
596 pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL, pSG, fSrc);
597 vboxNetAdpWinDestroySG(pSG);
598 }
599 }
600 if (ASMAtomicDecS32(&pThis->cBusy) == 0)
601 NdisSetEvent(&pThis->EventIdle);
602
603 return true;
604}
605
606
607/**
608 * @copydoc INTNETTRUNKIFPORT::pfnRetain
609 */
610static DECLCALLBACK(void) vboxNetAdpWinPortRetain(PINTNETTRUNKIFPORT pIfPort)
611{
612 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
613 RT_NOREF1(pThis);
614 LogFlow(("vboxNetAdpWinPortRetain: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
615}
616
617/**
618 * @copydoc INTNETTRUNKIFPORT::pfnRelease
619 */
620static DECLCALLBACK(void) vboxNetAdpWinPortRelease(PINTNETTRUNKIFPORT pIfPort)
621{
622 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
623 RT_NOREF1(pThis);
624 LogFlow(("vboxNetAdpWinPortRelease: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
625}
626
627/**
628 * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
629 */
630static DECLCALLBACK(void) vboxNetAdpWinPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
631{
632 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
633
634 LogFlow(("vboxNetAdpWinPortDisconnectAndRelease: pThis=%p, pIfPort=%p\n", pThis, pIfPort));
635 /*
636 * Serious paranoia.
637 */
638 AssertPtr(pThis);
639 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
640 Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
641 AssertPtr(pThis->pGlobals);
642 Assert(pThis->szName[0]);
643
644 AssertPtr(pThis->pSwitchPort);
645 Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING);
646
647 pThis->pSwitchPort = NULL;
648}
649
650/**
651 * @copydoc INTNETTRUNKIFPORT::pfnSetState
652 */
653static DECLCALLBACK(INTNETTRUNKIFSTATE) vboxNetAdpWinPortSetState(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState)
654{
655 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
656 INTNETTRUNKIFSTATE enmOldTrunkState;
657
658 LogFlow(("vboxNetAdpWinPortSetState: pThis=%p, pIfPort=%p, enmState=%d\n", pThis, pIfPort, enmState));
659 /*
660 * Input validation.
661 */
662 AssertPtr(pThis);
663 AssertPtr(pThis->pGlobals);
664 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
665 AssertPtrReturn(pThis->pSwitchPort, INTNETTRUNKIFSTATE_INVALID);
666 AssertReturn(enmState > INTNETTRUNKIFSTATE_INVALID && enmState < INTNETTRUNKIFSTATE_END,
667 INTNETTRUNKIFSTATE_INVALID);
668
669 enmOldTrunkState = pThis->enmTrunkState;
670 if (enmOldTrunkState != enmState)
671 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmTrunkState, enmState);
672
673 return enmOldTrunkState;
674}
675
676/**
677 * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
678 */
679static DECLCALLBACK(int) vboxNetAdpWinPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
680{
681 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
682 int rc;
683
684 LogFlow(("vboxNetAdpWinPortWaitForIdle: pThis=%p, pIfPort=%p, cMillies=%u\n", pThis, pIfPort, cMillies));
685 /*
686 * Input validation.
687 */
688 AssertPtr(pThis);
689 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
690 AssertPtrReturn(pThis->pSwitchPort, VERR_INVALID_STATE);
691 AssertReturn(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING, VERR_INVALID_STATE);
692
693 rc = NdisWaitEvent(&pThis->EventIdle, cMillies) ? VINF_SUCCESS : VERR_TIMEOUT;
694
695 return rc;
696}
697
698/**
699 * @copydoc INTNETTRUNKIFPORT::pfnXmit
700 */
701static DECLCALLBACK(int) vboxNetAdpWinPortXmit(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
702{
703 RT_NOREF1(fDst);
704 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
705 int rc = VINF_SUCCESS;
706
707 LogFlow(("vboxNetAdpWinPortXmit: pThis=%p, pIfPort=%p, pvIfData=%p, pSG=%p, fDst=0x%x\n", pThis, pIfPort, pvIfData, pSG, fDst));
708 RT_NOREF1(pvIfData);
709 /*
710 * Input validation.
711 */
712 AssertPtr(pThis);
713 AssertPtr(pSG);
714 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
715 AssertPtrReturn(pThis->pSwitchPort, VERR_INVALID_STATE);
716
717 vboxNetAdpWinDumpPacket(pSG, "intnet --> host");
718
719 /*
720 * First of all, indicate we are busy. It is possible the trunk or the adapter
721 * will get paused or even disconnected, so we need to check the state after
722 * we have marked ourselves busy.
723 * Later, when NDIS returns all buffers, we will mark ourselves idle.
724 */
725 if (ASMAtomicIncS32(&pThis->cBusy) == 1)
726 NdisResetEvent(&pThis->EventIdle);
727
728 if (vboxNetAdpWinIsActive(pThis))
729 {
730 PNET_BUFFER_LIST pBufList = vboxNetAdpWinSGtoNB(pThis, pSG);
731 if (pBufList)
732 {
733 NdisMIndicateReceiveNetBufferLists(pThis->hAdapter, pBufList, NDIS_DEFAULT_PORT_NUMBER, 1, 0);
734 vboxNetAdpWinUpdateStats(pThis->au64StatsInPackets, pThis->au64StatsInOctets, pSG);
735 }
736 }
737
738 return rc;
739}
740
741/**
742 * @copydoc INTNETTRUNKIFPORT::pfnNotifyMacAddress
743 */
744static DECLCALLBACK(void) vboxNetAdpWinPortNotifyMacAddress(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PCRTMAC pMac)
745{
746 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
747
748 LogFlow(("vboxNetAdpWinPortNotifyMacAddress: pThis=%p, pIfPort=%p, pvIfData=%p, pMac=%p\n", pThis, pIfPort, pvIfData, pMac));
749 RT_NOREF3(pThis, pvIfData, pMac);
750 /*
751 * Input validation.
752 */
753 AssertPtr(pThis);
754 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
755
756 /// @todo Do we really need to handle this?
757}
758
759
760/**
761 * @copydoc INTNETTRUNKIFPORT::pfnConnectInterface
762 */
763static DECLCALLBACK(int) vboxNetAdpWinPortConnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIf, void **ppvIfData)
764{
765 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
766 int rc;
767
768 LogFlow(("vboxNetAdpWinPortConnectInterface: pThis=%p, pIfPort=%p, pvIf=%p, ppvIfData=%p\n", pThis, pIfPort, pvIf, ppvIfData));
769 RT_NOREF3(pThis, pvIf, ppvIfData);
770 /*
771 * Input validation.
772 */
773 AssertPtr(pThis);
774 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
775
776 rc = VINF_SUCCESS;
777
778 return rc;
779}
780
781
782/**
783 * @copydoc INTNETTRUNKIFPORT::pfnDisconnectInterface
784 */
785static DECLCALLBACK(void) vboxNetAdpWinPortDisconnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIfData)
786{
787 PVBOXNETADP_ADAPTER pThis = IFPORT_2_VBOXNETADP_ADAPTER(pIfPort);
788 int rc;
789
790 LogFlow(("vboxNetAdpWinPortDisconnectInterface: pThis=%p, pIfPort=%p, pvIfData=%p\n", pThis, pIfPort, pvIfData));
791 RT_NOREF2(pThis, pvIfData);
792 /*
793 * Input validation.
794 */
795 AssertPtr(pThis);
796 Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
797
798 rc = VINF_SUCCESS;
799 AssertRC(rc);
800}
801
802
803
804/**
805 * Implements the SUPDRV component factor interface query method.
806 *
807 * @returns Pointer to an interface. NULL if not supported.
808 *
809 * @param pSupDrvFactory Pointer to the component factory registration structure.
810 * @param pSession The session - unused.
811 * @param pszInterfaceUuid The factory interface id.
812 */
813static DECLCALLBACK(void *) vboxNetAdpWinQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession,
814 const char *pszInterfaceUuid)
815{
816 PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pSupDrvFactory - RT_UOFFSETOF(VBOXNETADPGLOBALS, SupDrvFactory));
817
818 /*
819 * Convert the UUID strings and compare them.
820 */
821 RTUUID UuidReq;
822 int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
823 if (RT_SUCCESS(rc))
824 {
825 if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
826 {
827 NdisAcquireSpinLock(&pGlobals->Lock);
828 if (pGlobals->enmIdcState == kVBoxNetAdpWinIdcState_Connected)
829 {
830 pGlobals->cFactoryRefs++;
831 NdisResetEvent(&pGlobals->EventUnloadAllowed);
832 }
833 NdisReleaseSpinLock(&pGlobals->Lock);
834 return &pGlobals->TrunkFactory;
835 }
836#ifdef LOG_ENABLED
837 else
838 Log(("VBoxNetFlt: unknown factory interface query (%s)\n", pszInterfaceUuid));
839#endif
840 }
841 else
842 Log(("VBoxNetFlt: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
843
844 RT_NOREF1(pSession);
845 return NULL;
846}
847
848
849DECLHIDDEN(void) vboxNetAdpWinReportCapabilities(PVBOXNETADP_ADAPTER pThis)
850{
851 if (pThis->pSwitchPort)
852 {
853 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->MacAddr);
854 /* Promiscuous mode makes no sense for host-only adapters, does it? */
855 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0,
856 INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
857 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
858 }
859}
860
861/**
862 * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
863 */
864static DECLCALLBACK(int) vboxNetAdpWinFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
865 PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
866 PINTNETTRUNKIFPORT *ppIfPort)
867{
868 PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_UOFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
869
870 LogFlow(("==>vboxNetAdpWinFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
871 Assert(pGlobals->cFactoryRefs > 0);
872 AssertMsgReturn(!(fFlags & ~(INTNETTRUNKFACTORY_FLAG_NO_PROMISC)),
873 ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
874
875 PVBOXNETADP_ADAPTER pAdapter = NULL;
876 NdisAcquireSpinLock(&pGlobals->Lock);
877 RTListForEach(&g_VBoxNetAdpGlobals.ListOfAdapters, pAdapter, VBOXNETADP_ADAPTER, node)
878 {
879 Log(("vboxNetAdpWinFactoryCreateAndConnect: evaluating adapter=%s\n", pAdapter->szName));
880 if (!RTStrICmp(pszName, pAdapter->szName))
881 {
882 pAdapter->pSwitchPort = pSwitchPort;
883 *ppIfPort = &pAdapter->MyPort;
884 NdisReleaseSpinLock(&g_VBoxNetAdpGlobals.Lock); /// @todo too early? adp should have been connected by the time we do this
885 Log(("vboxNetAdpWinFactoryCreateAndConnect: found matching adapter, name=%s\n", pszName));
886 vboxNetAdpWinReportCapabilities(pAdapter);
887 /// @todo I guess there is no need in vboxNetAdpWinRegisterIpAddrNotifier(pThis);
888 LogFlow(("<==vboxNetAdpWinFactoryCreateAndConnect: return VINF_SUCCESS\n"));
889 return VINF_SUCCESS;
890 }
891 }
892 NdisReleaseSpinLock(&pGlobals->Lock);
893 /// @todo vboxNetAdpLogErrorEvent(IO_ERR_INTERNAL_ERROR, STATUS_SUCCESS, 6);
894 LogFlow(("<==vboxNetAdpWinFactoryCreateAndConnect: return VERR_INTNET_FLT_IF_NOT_FOUND\n"));
895 return VERR_INTNET_FLT_IF_NOT_FOUND;
896}
897
898
899/**
900 * @copydoc INTNETTRUNKFACTORY::pfnRelease
901 */
902static DECLCALLBACK(void) vboxNetAdpWinFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
903{
904 PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
905
906 NdisAcquireSpinLock(&pGlobals->Lock);
907 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
908 if (cRefs == 0)
909 NdisSetEvent(&pGlobals->EventUnloadAllowed);
910 NdisReleaseSpinLock(&pGlobals->Lock);
911 Assert(cRefs >= 0); NOREF(cRefs);
912 LogFlow(("vboxNetAdpWinFactoryRelease: cRefs=%d (new)\n", cRefs));
913}
914
915
916
917/* IDC */
918
919DECLINLINE(const char *) vboxNetAdpWinIdcStateToText(uint32_t enmState)
920{
921 switch (enmState)
922 {
923 case kVBoxNetAdpWinIdcState_Disconnected: return "Disconnected";
924 case kVBoxNetAdpWinIdcState_Connecting: return "Connecting";
925 case kVBoxNetAdpWinIdcState_Connected: return "Connected";
926 case kVBoxNetAdpWinIdcState_Stopping: return "Stopping";
927 }
928 return "Unknown";
929}
930
931static VOID vboxNetAdpWinInitIdcWorker(PVOID pvContext)
932{
933 int rc;
934 PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)pvContext;
935
936 /*
937 * Note that we break the rules here and access IDC state wihout acquiring
938 * the lock. This is ok because vboxNetAdpWinUnload will wait for this
939 * thread to terminate itself and we always use atomic access to IDC state.
940 * We check the state (while holding the lock) further when we have succeeded
941 * to connect. We cannot take the lock here and release it later as we will
942 * be holding it for too long.
943 */
944 while (ASMAtomicReadU32(&pGlobals->enmIdcState) == kVBoxNetAdpWinIdcState_Connecting)
945 {
946 /*
947 * Establish a connection to SUPDRV and register our component factory.
948 */
949 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
950 if (RT_SUCCESS(rc))
951 {
952 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
953 if (RT_SUCCESS(rc))
954 {
955 /*
956 * At this point we should take the lock to access IDC state as
957 * we technically may now race with factory methods.
958 */
959 NdisAcquireSpinLock(&pGlobals->Lock);
960 bool fSuccess = ASMAtomicCmpXchgU32(&pGlobals->enmIdcState,
961 kVBoxNetAdpWinIdcState_Connected,
962 kVBoxNetAdpWinIdcState_Connecting);
963 NdisReleaseSpinLock(&pGlobals->Lock);
964 if (!fSuccess)
965 {
966 /* The state has been changed (the only valid transition is to "Stopping"), undo init */
967 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
968 AssertRC(rc);
969 SUPR0IdcClose(&pGlobals->SupDrvIDC);
970 Log(("vboxNetAdpWinInitIdcWorker: state change (Connecting -> %s) while initializing IDC, closed IDC, rc=0x%x\n",
971 vboxNetAdpWinIdcStateToText(ASMAtomicReadU32(&pGlobals->enmIdcState)), rc));
972 }
973 else
974 {
975 Log(("vboxNetAdpWinInitIdcWorker: IDC state change Connecting -> Connected\n"));
976 }
977 }
978 }
979 else
980 {
981 LARGE_INTEGER WaitIn100nsUnits;
982 WaitIn100nsUnits.QuadPart = -(LONGLONG)5000000; /* 0.5 sec */
983 KeDelayExecutionThread(KernelMode, FALSE /* non-alertable */, &WaitIn100nsUnits);
984 }
985 }
986 PsTerminateSystemThread(STATUS_SUCCESS);
987}
988
989
990DECLHIDDEN(int) vboxNetAdpWinStartInitIdcThread(PVBOXNETADPGLOBALS pGlobals)
991{
992 int rc = VERR_INVALID_STATE;
993
994 /* No locking needed yet */
995 if (ASMAtomicCmpXchgU32(&pGlobals->enmIdcState, kVBoxNetAdpWinIdcState_Connecting, kVBoxNetAdpWinIdcState_Disconnected))
996 {
997 Log(("vboxNetAdpWinStartInitIdcThread: IDC state change Diconnected -> Connecting\n"));
998
999 NTSTATUS Status = PsCreateSystemThread(&g_VBoxNetAdpGlobals.hInitIdcThread,
1000 THREAD_ALL_ACCESS,
1001 NULL,
1002 NULL,
1003 NULL,
1004 vboxNetAdpWinInitIdcWorker,
1005 &g_VBoxNetAdpGlobals);
1006 Log(("vboxNetAdpWinStartInitIdcThread: create IDC initialization thread, status=0x%x\n", Status));
1007 if (Status != STATUS_SUCCESS)
1008 {
1009 LogError(("vboxNetAdpWinStartInitIdcThread: IDC initialization failed (system thread creation, status=0x%x)\n", Status));
1010 /*
1011 * We failed to init IDC and there will be no second chance.
1012 */
1013 Log(("vboxNetAdpWinStartInitIdcThread: IDC state change Connecting -> Diconnected\n"));
1014 ASMAtomicWriteU32(&g_VBoxNetAdpGlobals.enmIdcState, kVBoxNetAdpWinIdcState_Disconnected);
1015 }
1016 rc = RTErrConvertFromNtStatus(Status);
1017 }
1018 return rc;
1019}
1020
1021
1022
1023/* === !!!! */
1024
1025
1026NDIS_OID g_SupportedOids[] =
1027{
1028 OID_GEN_CURRENT_LOOKAHEAD,
1029 OID_GEN_CURRENT_PACKET_FILTER,
1030 OID_GEN_INTERRUPT_MODERATION,
1031 OID_GEN_LINK_PARAMETERS,
1032 OID_GEN_MAXIMUM_TOTAL_SIZE,
1033 OID_GEN_RCV_OK,
1034 OID_GEN_RECEIVE_BLOCK_SIZE,
1035 OID_GEN_RECEIVE_BUFFER_SPACE,
1036 OID_GEN_STATISTICS,
1037 OID_GEN_TRANSMIT_BLOCK_SIZE,
1038 OID_GEN_TRANSMIT_BUFFER_SPACE,
1039 OID_GEN_VENDOR_DESCRIPTION,
1040 OID_GEN_VENDOR_DRIVER_VERSION,
1041 OID_GEN_VENDOR_ID,
1042 OID_GEN_XMIT_OK,
1043 OID_802_3_PERMANENT_ADDRESS,
1044 OID_802_3_CURRENT_ADDRESS,
1045 OID_802_3_MULTICAST_LIST,
1046 OID_802_3_MAXIMUM_LIST_SIZE,
1047 OID_PNP_CAPABILITIES,
1048 OID_PNP_QUERY_POWER,
1049 OID_PNP_SET_POWER
1050};
1051
1052DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinAllocAdapter(NDIS_HANDLE hAdapter, PVBOXNETADP_ADAPTER *ppAdapter, ULONG uIfIndex)
1053{
1054 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1055 PVBOXNETADP_ADAPTER pAdapter = NULL;
1056 PVBOXNETADPGLOBALS pGlobals = &g_VBoxNetAdpGlobals;
1057
1058 LogFlow(("==>vboxNetAdpWinAllocAdapter: adapter handle=%p\n", hAdapter));
1059
1060 /* Get the name */
1061 UNICODE_STRING strUnicodeName;
1062 Status = NdisMQueryAdapterInstanceName(&strUnicodeName, hAdapter);
1063 if (Status != NDIS_STATUS_SUCCESS)
1064 {
1065 LogError(("vboxNetAdpWinAllocAdapter: NdisMQueryAdapterInstanceName failed with 0x%x\n", Status));
1066 return Status;
1067 }
1068
1069 ANSI_STRING strAnsiName;
1070 /* We use the miniport name to associate this filter module with the netflt instance */
1071 NTSTATUS rc = RtlUnicodeStringToAnsiString(&strAnsiName,
1072 &strUnicodeName,
1073 TRUE);
1074 if (rc != STATUS_SUCCESS)
1075 {
1076 LogError(("vboxNetAdpWinAllocAdapter: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",
1077 strUnicodeName, rc));
1078 //vboxNetAdpLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2);
1079 NdisFreeMemory(strUnicodeName.Buffer, 0, 0);
1080 return NDIS_STATUS_FAILURE;
1081 }
1082 NdisFreeMemory(strUnicodeName.Buffer, 0, 0);
1083 DbgPrint("vboxNetAdpWinAllocAdapter: name=%Z\n", &strAnsiName);
1084
1085 *ppAdapter = NULL;
1086
1087 UINT cbAdapterWithNameExtra = sizeof(VBOXNETADP_ADAPTER) + strAnsiName.Length;
1088 pAdapter = (PVBOXNETADP_ADAPTER)NdisAllocateMemoryWithTagPriority(pGlobals->hMiniportDriver,
1089 cbAdapterWithNameExtra,
1090 VBOXNETADPWIN_TAG,
1091 NormalPoolPriority);
1092 if (!pAdapter)
1093 {
1094 RtlFreeAnsiString(&strAnsiName);
1095 Status = NDIS_STATUS_RESOURCES;
1096 Log(("vboxNetAdpWinAllocAdapter: Out of memory while allocating adapter context (size=%d)\n", sizeof(VBOXNETADP_ADAPTER)));
1097 }
1098 else
1099 {
1100 NdisZeroMemory(pAdapter, cbAdapterWithNameExtra);
1101 NdisMoveMemory(pAdapter->szName, strAnsiName.Buffer, strAnsiName.Length);
1102 RtlFreeAnsiString(&strAnsiName);
1103
1104 /* Allocate buffer pool */
1105 NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
1106 NdisZeroMemory(&PoolParams, sizeof(PoolParams));
1107 PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1108 PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
1109 PoolParams.Header.Size = sizeof(PoolParams);
1110 PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
1111 PoolParams.fAllocateNetBuffer = TRUE;
1112 PoolParams.ContextSize = 0;
1113 PoolParams.PoolTag = VBOXNETADP_MEM_TAG;
1114 pAdapter->hPool = NdisAllocateNetBufferListPool(hAdapter, &PoolParams);
1115 if (!pAdapter->hPool)
1116 {
1117 LogError(("vboxNetAdpWinAllocAdapter: NdisAllocateNetBufferListPool failed\n"));
1118 NdisFreeMemory(pAdapter, 0, 0);
1119 return NDIS_STATUS_RESOURCES;
1120 }
1121 Log4(("vboxNetAdpWinAllocAdapter: allocated NBL+NB pool 0x%p\n", pAdapter->hPool));
1122
1123 pAdapter->hAdapter = hAdapter;
1124 pAdapter->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION;
1125 pAdapter->MyPort.pfnRetain = vboxNetAdpWinPortRetain;
1126 pAdapter->MyPort.pfnRelease = vboxNetAdpWinPortRelease;
1127 pAdapter->MyPort.pfnDisconnectAndRelease = vboxNetAdpWinPortDisconnectAndRelease;
1128 pAdapter->MyPort.pfnSetState = vboxNetAdpWinPortSetState;
1129 pAdapter->MyPort.pfnWaitForIdle = vboxNetAdpWinPortWaitForIdle;
1130 pAdapter->MyPort.pfnXmit = vboxNetAdpWinPortXmit;
1131 pAdapter->MyPort.pfnNotifyMacAddress = vboxNetAdpWinPortNotifyMacAddress;
1132 pAdapter->MyPort.pfnConnectInterface = vboxNetAdpWinPortConnectInterface;
1133 pAdapter->MyPort.pfnDisconnectInterface = vboxNetAdpWinPortDisconnectInterface;
1134 pAdapter->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
1135 pAdapter->pGlobals = pGlobals;
1136 pAdapter->enmAdapterState = kVBoxNetAdpWinState_Initializing;
1137 pAdapter->enmTrunkState = INTNETTRUNKIFSTATE_INACTIVE;
1138 pAdapter->cBusy = 0;
1139 NdisInitializeEvent(&pAdapter->EventIdle);
1140 NdisSetEvent(&pAdapter->EventIdle); /* We are idle initially */
1141
1142 /* Use a locally administered version of the OUI we use for the guest NICs. */
1143 pAdapter->MacAddr.au8[0] = 0x08 | 2;
1144 pAdapter->MacAddr.au8[1] = 0x00;
1145 pAdapter->MacAddr.au8[2] = 0x27;
1146
1147 pAdapter->MacAddr.au8[3] = (uIfIndex >> 16) & 0xFF;
1148 pAdapter->MacAddr.au8[4] = (uIfIndex >> 8) & 0xFF;
1149 pAdapter->MacAddr.au8[5] = uIfIndex & 0xFF;
1150
1151 NdisAcquireSpinLock(&pGlobals->Lock);
1152 RTListPrepend(&pGlobals->ListOfAdapters, &pAdapter->node);
1153 NdisReleaseSpinLock(&pGlobals->Lock);
1154
1155 *ppAdapter = pAdapter;
1156 }
1157 LogFlow(("<==vboxNetAdpWinAllocAdapter: status=0x%x\n", Status));
1158 return Status;
1159}
1160
1161DECLHIDDEN(void) vboxNetAdpWinFreeAdapter(PVBOXNETADP_ADAPTER pAdapter)
1162{
1163 /* Remove from adapter chain */
1164 NdisAcquireSpinLock(&pAdapter->pGlobals->Lock);
1165 RTListNodeRemove(&pAdapter->node);
1166 NdisReleaseSpinLock(&pAdapter->pGlobals->Lock);
1167
1168 NdisFreeMemory(pAdapter, 0, 0);
1169}
1170
1171DECLINLINE(NDIS_MEDIA_CONNECT_STATE) vboxNetAdpWinGetConnectState(PVBOXNETADP_ADAPTER pAdapter)
1172{
1173 RT_NOREF1(pAdapter);
1174 return MediaConnectStateConnected;
1175}
1176
1177
1178DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinInitializeEx(IN NDIS_HANDLE NdisMiniportHandle,
1179 IN NDIS_HANDLE MiniportDriverContext,
1180 IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)
1181{
1182 RT_NOREF1(MiniportDriverContext);
1183 PVBOXNETADP_ADAPTER pAdapter = NULL;
1184 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1185
1186 LogFlow(("==>vboxNetAdpWinInitializeEx: miniport=0x%x\n", NdisMiniportHandle));
1187
1188 do
1189 {
1190 NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RAttrs = {0};
1191 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GAttrs = {0};
1192
1193 Status = vboxNetAdpWinAllocAdapter(NdisMiniportHandle, &pAdapter, MiniportInitParameters->IfIndex);
1194 if (Status != NDIS_STATUS_SUCCESS)
1195 {
1196 Log(("vboxNetAdpWinInitializeEx: Failed to allocate the adapter context with 0x%x\n", Status));
1197 break;
1198 }
1199
1200 RAttrs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
1201 RAttrs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
1202 RAttrs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
1203 RAttrs.MiniportAdapterContext = pAdapter;
1204 RAttrs.AttributeFlags = VBOXNETADPWIN_ATTR_FLAGS; // NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM
1205 RAttrs.CheckForHangTimeInSeconds = VBOXNETADPWIN_HANG_CHECK_TIME;
1206 RAttrs.InterfaceType = NdisInterfaceInternal;
1207
1208 Status = NdisMSetMiniportAttributes(NdisMiniportHandle,
1209 (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RAttrs);
1210 if (Status != NDIS_STATUS_SUCCESS)
1211 {
1212 Log(("vboxNetAdpWinInitializeEx: NdisMSetMiniportAttributes(registration) failed with 0x%x\n", Status));
1213 break;
1214 }
1215
1216 /// @todo Registry?
1217
1218 /// @todo WDM stack?
1219
1220 /// @todo DPC?
1221
1222 GAttrs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
1223 GAttrs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
1224 GAttrs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
1225
1226 GAttrs.MediaType = NdisMedium802_3;
1227 GAttrs.PhysicalMediumType = NdisPhysicalMediumUnspecified;
1228 GAttrs.MtuSize = 1500; /// @todo
1229 GAttrs.MaxXmitLinkSpeed = VBOXNETADPWIN_LINK_SPEED;
1230 GAttrs.XmitLinkSpeed = VBOXNETADPWIN_LINK_SPEED;
1231 GAttrs.MaxRcvLinkSpeed = VBOXNETADPWIN_LINK_SPEED;
1232 GAttrs.RcvLinkSpeed = VBOXNETADPWIN_LINK_SPEED;
1233 GAttrs.MediaConnectState = vboxNetAdpWinGetConnectState(pAdapter);
1234 GAttrs.MediaDuplexState = MediaDuplexStateFull;
1235 GAttrs.LookaheadSize = 1500; /// @todo
1236 GAttrs.MacOptions = VBOXNETADP_MAC_OPTIONS;
1237 GAttrs.SupportedPacketFilters = VBOXNETADP_SUPPORTED_FILTERS;
1238 GAttrs.MaxMulticastListSize = 32; /// @todo
1239
1240 GAttrs.MacAddressLength = ETH_LENGTH_OF_ADDRESS;
1241 Assert(GAttrs.MacAddressLength == sizeof(pAdapter->MacAddr));
1242 memcpy(GAttrs.PermanentMacAddress, pAdapter->MacAddr.au8, GAttrs.MacAddressLength);
1243 memcpy(GAttrs.CurrentMacAddress, pAdapter->MacAddr.au8, GAttrs.MacAddressLength);
1244
1245 GAttrs.RecvScaleCapabilities = NULL;
1246 GAttrs.AccessType = NET_IF_ACCESS_BROADCAST;
1247 GAttrs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
1248 GAttrs.ConnectionType = NET_IF_CONNECTION_DEDICATED;
1249 GAttrs.IfType = IF_TYPE_ETHERNET_CSMACD;
1250 GAttrs.IfConnectorPresent = false;
1251 GAttrs.SupportedStatistics = VBOXNETADPWIN_SUPPORTED_STATISTICS;
1252 GAttrs.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
1253 GAttrs.DataBackFillSize = 0;
1254 GAttrs.ContextBackFillSize = 0;
1255 GAttrs.SupportedOidList = g_SupportedOids;
1256 GAttrs.SupportedOidListLength = sizeof(g_SupportedOids);
1257 GAttrs.AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
1258 GAttrs.PowerManagementCapabilities = &g_VBoxNetAdpGlobals.PMCaps;
1259
1260 Status = NdisMSetMiniportAttributes(NdisMiniportHandle,
1261 (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GAttrs);
1262 if (Status != NDIS_STATUS_SUCCESS)
1263 {
1264 Log(("vboxNetAdpWinInitializeEx: NdisMSetMiniportAttributes(general) failed with 0x%x\n", Status));
1265 break;
1266 }
1267
1268 VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pAdapter, kVBoxNetAdpWinState_Paused);
1269 RT_NOREF1(enmPrevState);
1270 Assert(enmPrevState == kVBoxNetAdpWinState_Initializing);
1271 } while (false);
1272
1273 if (Status != NDIS_STATUS_SUCCESS)
1274 {
1275 if (pAdapter)
1276 vboxNetAdpWinFreeAdapter(pAdapter);
1277 }
1278
1279 LogFlow(("<==vboxNetAdpWinInitializeEx: status=0x%x\n", Status));
1280 return Status;
1281}
1282
1283DECLHIDDEN(VOID) vboxNetAdpWinHaltEx(IN NDIS_HANDLE MiniportAdapterContext,
1284 IN NDIS_HALT_ACTION HaltAction)
1285{
1286 RT_NOREF1(HaltAction);
1287 PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1288 LogFlow(("==>vboxNetAdpWinHaltEx\n"));
1289 AssertPtr(pThis);
1290 Assert(vboxNetAdpWinGetState(pThis) == kVBoxNetAdpWinState_Paused);
1291 /*
1292 * Check if the trunk is active which means the adapter gets disabled
1293 * while it is used by VM(s) and we need to disconnect the trunk.
1294 */
1295 if (pThis->pSwitchPort && pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE)
1296 pThis->pSwitchPort->pfnDisconnect(pThis->pSwitchPort, &pThis->MyPort, NULL);
1297 /*
1298 * Since we are already in the paused state and we have disconnected
1299 * the trunk, we can safely destroy this adapter.
1300 */
1301 vboxNetAdpWinFreeAdapter(pThis);
1302 LogFlow(("<==vboxNetAdpWinHaltEx\n"));
1303}
1304
1305DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinPause(IN NDIS_HANDLE MiniportAdapterContext,
1306 IN PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)
1307{
1308 RT_NOREF1(MiniportPauseParameters);
1309 PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1310 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1311 LogFlow(("==>vboxNetAdpWinPause\n"));
1312 VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Pausing);
1313 Assert(enmPrevState == kVBoxNetAdpWinState_Running);
1314 if (!NdisWaitEvent(&pThis->EventIdle, 1000 /* ms */))
1315 {
1316 LogError(("vboxNetAdpWinPause: timed out while pausing the adapter\n"));
1317 /// @todo implement NDIS_STATUS_PENDING case? probably not.
1318 }
1319 enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Paused);
1320 Assert(enmPrevState == kVBoxNetAdpWinState_Pausing);
1321 LogFlow(("<==vboxNetAdpWinPause: status=0x%x\n", Status));
1322 return Status;
1323}
1324
1325DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinRestart(IN NDIS_HANDLE MiniportAdapterContext,
1326 IN PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
1327{
1328 RT_NOREF1(MiniportRestartParameters);
1329 PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1330 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1331 LogFlow(("==>vboxNetAdpWinRestart\n"));
1332 VBOXNETADPWIN_ADAPTER_STATE enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Restarting);
1333 Assert(enmPrevState == kVBoxNetAdpWinState_Paused);
1334 /// @todo anything?
1335 enmPrevState = vboxNetAdpWinSetState(pThis, kVBoxNetAdpWinState_Running);
1336 Assert(enmPrevState == kVBoxNetAdpWinState_Restarting);
1337 LogFlow(("<==vboxNetAdpWinRestart: status=0x%x\n", Status));
1338 return Status;
1339}
1340
1341DECLINLINE(uint64_t) vboxNetAdpWinStatsTotals(uint64_t *pStats)
1342{
1343 return pStats[kVBoxNetAdpWinPacketType_Unicast]
1344 + pStats[kVBoxNetAdpWinPacketType_Multicast]
1345 + pStats[kVBoxNetAdpWinPacketType_Broadcast];
1346}
1347
1348DECLINLINE(PVOID) vboxNetAdpWinStatsU64(uint64_t *pTmp, ULONG *pcbTmp, uint64_t u64Stat)
1349{
1350 *pcbTmp = sizeof(*pTmp);
1351 *pTmp = u64Stat;
1352 return pTmp;
1353}
1354
1355DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqQuery(PVBOXNETADP_ADAPTER pThis,
1356 PNDIS_OID_REQUEST pRequest)
1357{
1358 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1359 struct _NDIS_OID_REQUEST::_REQUEST_DATA::_QUERY *pQuery = &pRequest->DATA.QUERY_INFORMATION;
1360
1361 LogFlow(("==>vboxNetAdpWinOidRqQuery\n"));
1362
1363 uint64_t u64Tmp = 0;
1364 ULONG ulTmp = 0;
1365 PVOID pInfo = &ulTmp;
1366 ULONG cbInfo = sizeof(ulTmp);
1367
1368 switch (pQuery->Oid)
1369 {
1370 case OID_GEN_INTERRUPT_MODERATION:
1371 {
1372 PNDIS_INTERRUPT_MODERATION_PARAMETERS pParams =
1373 (PNDIS_INTERRUPT_MODERATION_PARAMETERS)pQuery->InformationBuffer;
1374 cbInfo = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
1375 if (cbInfo > pQuery->InformationBufferLength)
1376 break;
1377 pParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1378 pParams->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
1379 pParams->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
1380 pParams->Flags = 0;
1381 pParams->InterruptModeration = NdisInterruptModerationNotSupported;
1382 pInfo = NULL; /* Do not copy */
1383 break;
1384 }
1385 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1386 case OID_GEN_RECEIVE_BLOCK_SIZE:
1387 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1388 ulTmp = VBOXNETADP_MAX_FRAME_SIZE;
1389 break;
1390 case OID_GEN_RECEIVE_BUFFER_SPACE:
1391 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1392 /// @todo Make configurable
1393 ulTmp = VBOXNETADP_MAX_FRAME_SIZE * 40;
1394 break;
1395 case OID_GEN_RCV_OK:
1396 pInfo = vboxNetAdpWinStatsU64(&u64Tmp, &cbInfo, vboxNetAdpWinStatsTotals(pThis->au64StatsInPackets));
1397 break;
1398 case OID_GEN_XMIT_OK:
1399 pInfo = vboxNetAdpWinStatsU64(&u64Tmp, &cbInfo, vboxNetAdpWinStatsTotals(pThis->au64StatsOutPackets));
1400 break;
1401 case OID_GEN_STATISTICS:
1402 {
1403 PNDIS_STATISTICS_INFO pStats =
1404 (PNDIS_STATISTICS_INFO)pQuery->InformationBuffer;
1405 cbInfo = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
1406 if (cbInfo > pQuery->InformationBufferLength)
1407 break;
1408 pInfo = NULL; /* Do not copy */
1409 memset(pStats, 0, cbInfo);
1410 pStats->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1411 pStats->Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
1412 pStats->Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
1413 pStats->SupportedStatistics =
1414 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV
1415 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV
1416 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV
1417 | NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV
1418 | NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS
1419 | NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR
1420 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT
1421 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT
1422 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT
1423 | NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT
1424 | NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR
1425 | NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS
1426 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV
1427 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV
1428 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV
1429 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT
1430 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT
1431 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
1432
1433 pStats->ifHCInOctets = vboxNetAdpWinStatsTotals(pThis->au64StatsInOctets);
1434 pStats->ifHCInUcastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Unicast]);
1435 pStats->ifHCInMulticastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Multicast]);
1436 pStats->ifHCInBroadcastPkts = ASMAtomicReadU64(&pThis->au64StatsInPackets[kVBoxNetAdpWinPacketType_Broadcast]);
1437 pStats->ifHCOutOctets = vboxNetAdpWinStatsTotals(pThis->au64StatsOutOctets);;
1438 pStats->ifHCOutUcastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Unicast]);
1439 pStats->ifHCOutMulticastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Multicast]);
1440 pStats->ifHCOutBroadcastPkts = ASMAtomicReadU64(&pThis->au64StatsOutPackets[kVBoxNetAdpWinPacketType_Broadcast]);
1441 pStats->ifHCInUcastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Unicast]);
1442 pStats->ifHCInMulticastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Multicast]);
1443 pStats->ifHCInBroadcastOctets = ASMAtomicReadU64(&pThis->au64StatsInOctets[kVBoxNetAdpWinPacketType_Broadcast]);
1444 pStats->ifHCOutUcastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Unicast]);
1445 pStats->ifHCOutMulticastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Multicast]);
1446 pStats->ifHCOutBroadcastOctets = ASMAtomicReadU64(&pThis->au64StatsOutOctets[kVBoxNetAdpWinPacketType_Broadcast]);
1447 break;
1448 }
1449 case OID_GEN_VENDOR_DESCRIPTION:
1450 pInfo = VBOXNETADP_VENDOR_NAME;
1451 cbInfo = sizeof(VBOXNETADP_VENDOR_NAME);
1452 break;
1453 case OID_GEN_VENDOR_DRIVER_VERSION:
1454 ulTmp = (VBOXNETADP_VERSION_NDIS_MAJOR << 16) | VBOXNETADP_VERSION_NDIS_MINOR;
1455 break;
1456 case OID_GEN_VENDOR_ID:
1457 ulTmp = VBOXNETADP_VENDOR_ID;
1458 break;
1459 case OID_802_3_PERMANENT_ADDRESS:
1460 case OID_802_3_CURRENT_ADDRESS:
1461 pInfo = &pThis->MacAddr;
1462 cbInfo = sizeof(pThis->MacAddr);
1463 break;
1464 //case OID_802_3_MULTICAST_LIST:
1465 case OID_802_3_MAXIMUM_LIST_SIZE:
1466 ulTmp = VBOXNETADP_MCAST_LIST_SIZE;
1467 break;
1468 case OID_PNP_CAPABILITIES:
1469 pInfo = &pThis->pGlobals->PMCaps;
1470 cbInfo = sizeof(pThis->pGlobals->PMCaps);
1471 break;
1472 case OID_PNP_QUERY_POWER:
1473 pInfo = NULL; /* Do not copy */
1474 cbInfo = 0;
1475 break;
1476 default:
1477 Status = NDIS_STATUS_NOT_SUPPORTED;
1478 break;
1479 }
1480
1481 if (Status == NDIS_STATUS_SUCCESS)
1482 {
1483 if (cbInfo > pQuery->InformationBufferLength)
1484 {
1485 pQuery->BytesNeeded = cbInfo;
1486 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
1487 }
1488 else
1489 {
1490 if (pInfo)
1491 NdisMoveMemory(pQuery->InformationBuffer, pInfo, cbInfo);
1492 pQuery->BytesWritten = cbInfo;
1493 }
1494 }
1495
1496 LogFlow(("<==vboxNetAdpWinOidRqQuery: status=0x%x\n", Status));
1497 return Status;
1498}
1499
1500DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRqSet(PVBOXNETADP_ADAPTER pAdapter,
1501 PNDIS_OID_REQUEST pRequest)
1502{
1503 RT_NOREF1(pAdapter);
1504 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1505 struct _NDIS_OID_REQUEST::_REQUEST_DATA::_SET *pSet = &pRequest->DATA.SET_INFORMATION;
1506
1507 LogFlow(("==>vboxNetAdpWinOidRqSet\n"));
1508
1509 switch (pSet->Oid)
1510 {
1511 case OID_GEN_CURRENT_LOOKAHEAD:
1512 if (pSet->InformationBufferLength != sizeof(ULONG))
1513 {
1514 pSet->BytesNeeded = sizeof(ULONG);
1515 Status = NDIS_STATUS_INVALID_LENGTH;
1516 break;
1517 }
1518 /// @todo For the time being we simply ignore lookahead settings.
1519 pSet->BytesRead = sizeof(ULONG);
1520 Status = NDIS_STATUS_SUCCESS;
1521 break;
1522
1523 case OID_GEN_CURRENT_PACKET_FILTER:
1524 if (pSet->InformationBufferLength != sizeof(ULONG))
1525 {
1526 pSet->BytesNeeded = sizeof(ULONG);
1527 Status = NDIS_STATUS_INVALID_LENGTH;
1528 break;
1529 }
1530 /// @todo For the time being we simply ignore packet filter settings.
1531 pSet->BytesRead = pSet->InformationBufferLength;
1532 Status = NDIS_STATUS_SUCCESS;
1533 break;
1534
1535 case OID_GEN_INTERRUPT_MODERATION:
1536 pSet->BytesNeeded = 0;
1537 pSet->BytesRead = 0;
1538 Status = NDIS_STATUS_INVALID_DATA;
1539 break;
1540
1541 case OID_PNP_SET_POWER:
1542 if (pSet->InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
1543 {
1544 Status = NDIS_STATUS_INVALID_LENGTH;
1545 break;
1546 }
1547 pSet->BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
1548 Status = NDIS_STATUS_SUCCESS;
1549 break;
1550
1551 default:
1552 Status = NDIS_STATUS_NOT_SUPPORTED;
1553 break;
1554 }
1555
1556 LogFlow(("<==vboxNetAdpWinOidRqSet: status=0x%x\n", Status));
1557 return Status;
1558}
1559
1560DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinOidRequest(IN NDIS_HANDLE MiniportAdapterContext,
1561 IN PNDIS_OID_REQUEST NdisRequest)
1562{
1563 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1564 PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1565 LogFlow(("==>vboxNetAdpWinOidRequest\n"));
1566 vboxNetCmnWinDumpOidRequest(__FUNCTION__, NdisRequest);
1567
1568 switch (NdisRequest->RequestType)
1569 {
1570#if 0
1571 case NdisRequestMethod:
1572 Status = vboxNetAdpWinOidRqMethod(pAdapter, NdisRequest);
1573 break;
1574#endif
1575
1576 case NdisRequestSetInformation:
1577 Status = vboxNetAdpWinOidRqSet(pAdapter, NdisRequest);
1578 break;
1579
1580 case NdisRequestQueryInformation:
1581 case NdisRequestQueryStatistics:
1582 Status = vboxNetAdpWinOidRqQuery(pAdapter, NdisRequest);
1583 break;
1584
1585 default:
1586 Status = NDIS_STATUS_NOT_SUPPORTED;
1587 break;
1588 }
1589 LogFlow(("<==vboxNetAdpWinOidRequest: status=0x%x\n", Status));
1590 return Status;
1591}
1592
1593DECLHIDDEN(VOID) vboxNetAdpWinSendNetBufferLists(IN NDIS_HANDLE MiniportAdapterContext,
1594 IN PNET_BUFFER_LIST NetBufferLists,
1595 IN NDIS_PORT_NUMBER PortNumber,
1596 IN ULONG SendFlags)
1597{
1598 RT_NOREF1(PortNumber);
1599 PVBOXNETADP_ADAPTER pAdapter = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1600 LogFlow(("==>vboxNetAdpWinSendNetBufferLists\n"));
1601 PNET_BUFFER_LIST pNbl = NetBufferLists;
1602 vboxNetAdpWinDumpPackets("vboxNetAdpWinSendNetBufferLists: got", pNbl);
1603
1604 /* We alwast complete all send requests. */
1605 for (pNbl = NetBufferLists; pNbl; pNbl = NET_BUFFER_LIST_NEXT_NBL(pNbl))
1606 {
1607 vboxNetAdpWinForwardToIntNet(pAdapter, pNbl, INTNETTRUNKDIR_HOST);
1608 NET_BUFFER_LIST_STATUS(pNbl) = NDIS_STATUS_SUCCESS;
1609 }
1610 NdisMSendNetBufferListsComplete(pAdapter->hAdapter, NetBufferLists,
1611 (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL) ?
1612 NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
1613 LogFlow(("<==vboxNetAdpWinSendNetBufferLists\n"));
1614}
1615
1616DECLHIDDEN(VOID) vboxNetAdpWinReturnNetBufferLists(IN NDIS_HANDLE MiniportAdapterContext,
1617 IN PNET_BUFFER_LIST NetBufferLists,
1618 IN ULONG ReturnFlags)
1619{
1620 LogFlow(("==>vboxNetAdpWinReturnNetBufferLists\n"));
1621 RT_NOREF1(ReturnFlags);
1622 PVBOXNETADP_ADAPTER pThis = (PVBOXNETADP_ADAPTER)MiniportAdapterContext;
1623 PNET_BUFFER_LIST pList = NetBufferLists;
1624 while (pList)
1625 {
1626 Assert(pList->SourceHandle == pThis->hAdapter);
1627 Assert(NET_BUFFER_LIST_FIRST_NB(pList));
1628 Assert(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
1629
1630 PNET_BUFFER_LIST pNextList = NET_BUFFER_LIST_NEXT_NBL(pList);
1631
1632 vboxNetAdpWinFreeMdlChain(NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pList)));
1633 NdisFreeNetBufferList(pList);
1634 Log4(("vboxNetLwfWinReturnNetBufferLists: freed NBL+NB+MDL+Data 0x%p\n", pList));
1635 Assert(ASMAtomicReadS32(&pThis->cBusy) > 0);
1636 if (ASMAtomicDecS32(&pThis->cBusy) == 0)
1637 NdisSetEvent(&pThis->EventIdle);
1638
1639 pList = pNextList;
1640 }
1641 LogFlow(("<==vboxNetAdpWinReturnNetBufferLists\n"));
1642}
1643
1644DECLHIDDEN(VOID) vboxNetAdpWinCancelSend(IN NDIS_HANDLE MiniportAdapterContext,
1645 IN PVOID CancelId)
1646{
1647 RT_NOREF2(MiniportAdapterContext, CancelId);
1648 LogFlow(("==>vboxNetAdpWinCancelSend\n"));
1649 Log(("vboxNetAdpWinCancelSend: We should not be here!\n"));
1650 LogFlow(("<==vboxNetAdpWinCancelSend\n"));
1651}
1652
1653
1654DECLHIDDEN(BOOLEAN) vboxNetAdpWinCheckForHangEx(IN NDIS_HANDLE MiniportAdapterContext)
1655{
1656 RT_NOREF1(MiniportAdapterContext);
1657 LogFlow(("==>vboxNetAdpWinCheckForHangEx\n"));
1658 LogFlow(("<==vboxNetAdpWinCheckForHangEx return false\n"));
1659 return FALSE;
1660}
1661
1662DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinResetEx(IN NDIS_HANDLE MiniportAdapterContext,
1663 OUT PBOOLEAN AddressingReset)
1664{
1665 RT_NOREF2(MiniportAdapterContext, AddressingReset);
1666 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1667 LogFlow(("==>vboxNetAdpWinResetEx\n"));
1668 LogFlow(("<==vboxNetAdpWinResetEx: status=0x%x\n", Status));
1669 return Status;
1670}
1671
1672DECLHIDDEN(VOID) vboxNetAdpWinDevicePnPEventNotify(IN NDIS_HANDLE MiniportAdapterContext,
1673 IN PNET_DEVICE_PNP_EVENT NetDevicePnPEvent)
1674{
1675 RT_NOREF2(MiniportAdapterContext, NetDevicePnPEvent);
1676 LogFlow(("==>vboxNetAdpWinDevicePnPEventNotify\n"));
1677 Log(("vboxNetAdpWinDevicePnPEventNotify: PnP event=%d\n", NetDevicePnPEvent->DevicePnPEvent));
1678 LogFlow(("<==vboxNetAdpWinDevicePnPEventNotify\n"));
1679}
1680
1681
1682DECLHIDDEN(VOID) vboxNetAdpWinShutdownEx(IN NDIS_HANDLE MiniportAdapterContext,
1683 IN NDIS_SHUTDOWN_ACTION ShutdownAction)
1684{
1685 RT_NOREF2(MiniportAdapterContext, ShutdownAction);
1686 LogFlow(("==>vboxNetAdpWinShutdownEx\n"));
1687 Log(("vboxNetAdpWinShutdownEx: action=%d\n", ShutdownAction));
1688 LogFlow(("<==vboxNetAdpWinShutdownEx\n"));
1689}
1690
1691DECLHIDDEN(VOID) vboxNetAdpWinCancelOidRequest(IN NDIS_HANDLE MiniportAdapterContext,
1692 IN PVOID RequestId)
1693{
1694 RT_NOREF2(MiniportAdapterContext, RequestId);
1695 LogFlow(("==>vboxNetAdpWinCancelOidRequest\n"));
1696 Log(("vboxNetAdpWinCancelOidRequest: req id=%p\n", RequestId));
1697 LogFlow(("<==vboxNetAdpWinCancelOidRequest\n"));
1698}
1699
1700
1701
1702DECLHIDDEN(VOID) vboxNetAdpWinUnload(IN PDRIVER_OBJECT DriverObject)
1703{
1704 RT_NOREF1(DriverObject);
1705 LogFlow(("==>vboxNetAdpWinUnload\n"));
1706 PVBOXNETADPGLOBALS pGlobals = &g_VBoxNetAdpGlobals;
1707 int rc;
1708 NDIS_STATUS Status;
1709 PKTHREAD pThread = NULL;
1710
1711 /* We are about to disconnect IDC, let's make it clear so the factories will know */
1712 NdisAcquireSpinLock(&pGlobals->Lock);
1713 uint32_t enmPrevState = ASMAtomicXchgU32(&g_VBoxNetAdpGlobals.enmIdcState, kVBoxNetAdpWinIdcState_Stopping);
1714 NdisReleaseSpinLock(&pGlobals->Lock);
1715 Log(("vboxNetAdpWinUnload: IDC state change %s -> Stopping\n", vboxNetAdpWinIdcStateToText(enmPrevState)));
1716
1717 switch (enmPrevState)
1718 {
1719 case kVBoxNetAdpWinIdcState_Disconnected:
1720 /* Have not even attempted to connect -- nothing to do. */
1721 break;
1722 case kVBoxNetAdpWinIdcState_Stopping:
1723 /* Impossible, but another thread is alreading doing StopIdc, bail out */
1724 LogError(("vboxNetAdpWinUnload: called in 'Stopping' state\n"));
1725 break;
1726 case kVBoxNetAdpWinIdcState_Connecting:
1727 /* the worker thread is running, let's wait for it to stop */
1728 Status = ObReferenceObjectByHandle(g_VBoxNetAdpGlobals.hInitIdcThread,
1729 THREAD_ALL_ACCESS, NULL, KernelMode,
1730 (PVOID*)&pThread, NULL);
1731 if (Status == STATUS_SUCCESS)
1732 {
1733 KeWaitForSingleObject(pThread, Executive, KernelMode, FALSE, NULL);
1734 ObDereferenceObject(pThread);
1735 }
1736 else
1737 {
1738 LogError(("vboxNetAdpWinStopIdc: ObReferenceObjectByHandle(%p) failed with 0x%x\n",
1739 g_VBoxNetAdpGlobals.hInitIdcThread, Status));
1740 }
1741 break;
1742 case kVBoxNetAdpWinIdcState_Connected:
1743 /* the worker succeeded in IDC init and terminated */
1744 /* Make sure nobody uses the trunk factory. Wait half a second if needed. */
1745 if (!NdisWaitEvent(&pGlobals->EventUnloadAllowed, 500))
1746 LogRel(("VBoxNetAdp: unloading driver while trunk factory is in use!\n"));
1747 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
1748 AssertRC(rc);
1749 SUPR0IdcClose(&pGlobals->SupDrvIDC);
1750 Log(("vboxNetAdpWinUnload: closed IDC, rc=0x%x\n", rc));
1751 break;
1752 }
1753 if (pGlobals->hMiniportDriver)
1754 NdisMDeregisterMiniportDriver(pGlobals->hMiniportDriver);
1755 NdisFreeSpinLock(&pGlobals->Lock);
1756 LogFlow(("<==vboxNetAdpWinUnload\n"));
1757 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
1758 RTLogDestroy(RTLogSetDefaultInstance(NULL));
1759 RTR0Term();
1760}
1761
1762
1763/**
1764 * register the miniport driver
1765 */
1766DECLHIDDEN(NDIS_STATUS) vboxNetAdpWinRegister(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPathStr)
1767{
1768 NDIS_MINIPORT_DRIVER_CHARACTERISTICS MChars;
1769
1770 NdisZeroMemory(&MChars, sizeof (MChars));
1771
1772 MChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
1773 MChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
1774 MChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
1775
1776 MChars.MajorNdisVersion = VBOXNETADP_VERSION_NDIS_MAJOR;
1777 MChars.MinorNdisVersion = VBOXNETADP_VERSION_NDIS_MINOR;
1778
1779 MChars.MajorDriverVersion = VBOXNETADP_VERSION_MAJOR;
1780 MChars.MinorDriverVersion = VBOXNETADP_VERSION_MINOR;
1781
1782 MChars.InitializeHandlerEx = vboxNetAdpWinInitializeEx;
1783 MChars.HaltHandlerEx = vboxNetAdpWinHaltEx;
1784 MChars.UnloadHandler = vboxNetAdpWinUnload;
1785 MChars.PauseHandler = vboxNetAdpWinPause;
1786 MChars.RestartHandler = vboxNetAdpWinRestart;
1787 MChars.OidRequestHandler = vboxNetAdpWinOidRequest;
1788 MChars.SendNetBufferListsHandler = vboxNetAdpWinSendNetBufferLists;
1789 MChars.ReturnNetBufferListsHandler = vboxNetAdpWinReturnNetBufferLists;
1790 MChars.CancelSendHandler = vboxNetAdpWinCancelSend;
1791 MChars.CheckForHangHandlerEx = vboxNetAdpWinCheckForHangEx;
1792 MChars.ResetHandlerEx = vboxNetAdpWinResetEx;
1793 MChars.DevicePnPEventNotifyHandler = vboxNetAdpWinDevicePnPEventNotify;
1794 MChars.ShutdownHandlerEx = vboxNetAdpWinShutdownEx;
1795 MChars.CancelOidRequestHandler = vboxNetAdpWinCancelOidRequest;
1796
1797 NDIS_STATUS Status;
1798 g_VBoxNetAdpGlobals.hMiniportDriver = NULL;
1799 Log(("vboxNetAdpWinRegister: registering miniport driver...\n"));
1800 Status = NdisMRegisterMiniportDriver(pDriverObject,
1801 pRegistryPathStr,
1802 (NDIS_HANDLE)&g_VBoxNetAdpGlobals,
1803 &MChars,
1804 &g_VBoxNetAdpGlobals.hMiniportDriver);
1805 Assert(Status == STATUS_SUCCESS);
1806 if (Status == STATUS_SUCCESS)
1807 {
1808 Log(("vboxNetAdpWinRegister: successfully registered miniport driver; registering device...\n"));
1809 }
1810 else
1811 {
1812 Log(("ERROR! vboxNetAdpWinRegister: failed to register miniport driver, status=0x%x", Status));
1813 }
1814 return Status;
1815}
1816
1817
1818RT_C_DECLS_BEGIN
1819
1820NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath);
1821
1822RT_C_DECLS_END
1823
1824NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
1825{
1826 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1827 int rc;
1828
1829
1830 rc = RTR0Init(0);
1831 AssertRC(rc);
1832 if (RT_SUCCESS(rc))
1833 {
1834 NdisZeroMemory(&g_VBoxNetAdpGlobals, sizeof (g_VBoxNetAdpGlobals));
1835 RTListInit(&g_VBoxNetAdpGlobals.ListOfAdapters);
1836 NdisAllocateSpinLock(&g_VBoxNetAdpGlobals.Lock);
1837 NdisInitializeEvent(&g_VBoxNetAdpGlobals.EventUnloadAllowed);
1838 //g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
1839 g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1840 g_VBoxNetAdpGlobals.PMCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
1841
1842 /* Initialize SupDrv interface */
1843 g_VBoxNetAdpGlobals.SupDrvFactory.pfnQueryFactoryInterface = vboxNetAdpWinQueryFactoryInterface;
1844 memcpy(g_VBoxNetAdpGlobals.SupDrvFactory.szName, "VBoxNetAdp", sizeof("VBoxNetAdp"));
1845 /* Initialize trunk factory interface */
1846 g_VBoxNetAdpGlobals.TrunkFactory.pfnRelease = vboxNetAdpWinFactoryRelease;
1847 g_VBoxNetAdpGlobals.TrunkFactory.pfnCreateAndConnect = vboxNetAdpWinFactoryCreateAndConnect;
1848
1849 rc = vboxNetAdpWinStartInitIdcThread(&g_VBoxNetAdpGlobals);
1850 if (RT_SUCCESS(rc))
1851 {
1852 Status = vboxNetAdpWinRegister(pDriverObject, pRegistryPath);
1853 Assert(Status == STATUS_SUCCESS);
1854 if (Status == NDIS_STATUS_SUCCESS)
1855 {
1856 Log(("NETADP: started successfully\n"));
1857 return STATUS_SUCCESS;
1858 }
1859 }
1860 else
1861 Status = NDIS_STATUS_FAILURE;
1862 NdisFreeSpinLock(&g_VBoxNetAdpGlobals.Lock);
1863 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
1864 RTLogDestroy(RTLogSetDefaultInstance(NULL));
1865
1866 RTR0Term();
1867 }
1868 else
1869 {
1870 Status = NDIS_STATUS_FAILURE;
1871 }
1872
1873 return Status;
1874}
1875
Note: See TracBrowser for help on using the repository browser.

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