VirtualBox

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

Last change on this file was 99828, checked in by vboxsync, 16 months ago

*: A bunch of adjustments that allows using /permissive- with Visual C++ (qt 6.x necessity).

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