VirtualBox

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

Last change on this file since 68246 was 65720, checked in by vboxsync, 8 years ago

build fix?

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