VirtualBox

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

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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