VirtualBox

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

最後變更 在這個檔案從108380是 108380,由 vboxsync 提交於 3 週 前

Networking/Windows: Implemented minimal support for NDIS 6.3 to also support Windows/ARM hosts. This only does the bare minimum required to get NDIS 6.3 working, i.e. there are features we don't support (and not need so far). Also tested on this Win11/amd64. bugref:10846

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 74.3 KB
 
1/* $Id: VBoxNetAdp-win.cpp 108380 2025-02-25 15:46:16Z vboxsync $ */
2/** @file
3 * VBoxNetAdp-win.cpp - NDIS6 Host-only Networking Driver, Windows-specific code.
4 */
5/*
6 * Copyright (C) 2014-2024 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.alldomusa.eu.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 = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
1787 MChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
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
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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