VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltP-win.cpp@ 79846

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.1 KB
Line 
1/* $Id: VBoxNetFltP-win.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxNetFltP-win.cpp - Bridged Networking Driver, Windows Specific Code.
4 * Protocol edge
5 */
6/*
7 * Copyright (C) 2011-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26#include "VBoxNetFltCmn-win.h"
27
28#ifdef VBOXNETADP
29# error "No protocol edge"
30#endif
31
32#define VBOXNETFLT_PT_STATUS_IS_FILTERED(_s) (\
33 (_s) == NDIS_STATUS_MEDIA_CONNECT \
34 || (_s) == NDIS_STATUS_MEDIA_DISCONNECT \
35 )
36
37/**
38 * performs binding to the given adapter
39 */
40DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoBinding(PVBOXNETFLTINS pThis, PNDIS_STRING pOurDeviceName, PNDIS_STRING pBindToDeviceName)
41{
42 Assert(pThis->u.s.WinIf.PtState.PowerState == NdisDeviceStateD3);
43 Assert(pThis->u.s.WinIf.PtState.OpState == kVBoxNetDevOpState_Deinitialized);
44 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
45
46 vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Initializing);
47
48 NDIS_STATUS Status = vboxNetFltWinCopyString(&pThis->u.s.WinIf.MpDeviceName, pOurDeviceName);
49 Assert (Status == NDIS_STATUS_SUCCESS);
50 if (Status == NDIS_STATUS_SUCCESS)
51 {
52 vboxNetFltWinSetPowerState(&pThis->u.s.WinIf.PtState, NdisDeviceStateD0);
53 pThis->u.s.WinIf.OpenCloseStatus = NDIS_STATUS_SUCCESS;
54
55 UINT iMedium;
56 NDIS_STATUS TmpStatus;
57 NDIS_MEDIUM aenmNdisMedium[] =
58 {
59 /* Ethernet */
60 NdisMedium802_3,
61 /* Wan */
62 NdisMediumWan
63 };
64
65 NdisResetEvent(&pThis->u.s.WinIf.OpenCloseEvent);
66
67 NdisOpenAdapter(&Status, &TmpStatus, &pThis->u.s.WinIf.hBinding, &iMedium,
68 aenmNdisMedium, RT_ELEMENTS(aenmNdisMedium),
69 g_VBoxNetFltGlobalsWin.Pt.hProtocol,
70 pThis,
71 pBindToDeviceName,
72 0, /* IN UINT OpenOptions, (reserved, should be NULL) */
73 NULL /* IN PSTRING AddressingInformation OPTIONAL */
74 );
75 Assert(Status == NDIS_STATUS_PENDING || Status == STATUS_SUCCESS);
76 if (Status == NDIS_STATUS_PENDING)
77 {
78 NdisWaitEvent(&pThis->u.s.WinIf.OpenCloseEvent, 0);
79 Status = pThis->u.s.WinIf.OpenCloseStatus;
80 }
81
82 Assert(Status == NDIS_STATUS_SUCCESS);
83 if (Status == NDIS_STATUS_SUCCESS)
84 {
85 Assert(pThis->u.s.WinIf.hBinding);
86 pThis->u.s.WinIf.enmMedium = aenmNdisMedium[iMedium];
87 vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Initialized);
88
89 Status = vboxNetFltWinMpInitializeDevideInstance(pThis);
90 Assert(Status == NDIS_STATUS_SUCCESS);
91 if (Status == NDIS_STATUS_SUCCESS)
92 {
93 return NDIS_STATUS_SUCCESS;
94 }
95 else
96 {
97 LogRelFunc(("vboxNetFltWinMpInitializeDevideInstance failed, Status 0x%x\n", Status));
98 }
99
100 vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitializing);
101 vboxNetFltWinPtCloseInterface(pThis, &TmpStatus);
102 Assert(TmpStatus == NDIS_STATUS_SUCCESS);
103 vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
104 }
105 else
106 {
107 LogRelFunc(("NdisOpenAdapter failed, Status (0x%x)", Status));
108 }
109
110 vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
111 pThis->u.s.WinIf.hBinding = NULL;
112 }
113
114 return Status;
115}
116
117static VOID vboxNetFltWinPtBindAdapter(OUT PNDIS_STATUS pStatus,
118 IN NDIS_HANDLE hBindContext,
119 IN PNDIS_STRING pDeviceNameStr,
120 IN PVOID pvSystemSpecific1,
121 IN PVOID pvSystemSpecific2)
122{
123 LogFlowFuncEnter();
124 RT_NOREF2(hBindContext, pvSystemSpecific2);
125
126 NDIS_STATUS Status;
127 NDIS_HANDLE hConfig = NULL;
128
129 NdisOpenProtocolConfiguration(&Status, &hConfig, (PNDIS_STRING)pvSystemSpecific1);
130 Assert(Status == NDIS_STATUS_SUCCESS);
131 if (Status == NDIS_STATUS_SUCCESS)
132 {
133 PNDIS_CONFIGURATION_PARAMETER pParam;
134 NDIS_STRING UppedBindStr = NDIS_STRING_CONST("UpperBindings");
135 NdisReadConfiguration(&Status, &pParam, hConfig, &UppedBindStr, NdisParameterString);
136 Assert(Status == NDIS_STATUS_SUCCESS);
137 if (Status == NDIS_STATUS_SUCCESS)
138 {
139 PVBOXNETFLTINS pNetFlt;
140 Status = vboxNetFltWinPtInitBind(&pNetFlt, &pParam->ParameterData.StringData, pDeviceNameStr);
141 Assert(Status == NDIS_STATUS_SUCCESS);
142 }
143
144 NdisCloseConfiguration(hConfig);
145 }
146
147 *pStatus = Status;
148
149 LogFlowFunc(("LEAVE: Status 0x%x\n", Status));
150}
151
152static VOID vboxNetFltWinPtOpenAdapterComplete(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS Status, IN NDIS_STATUS OpenErrorStatus)
153{
154 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
155 RT_NOREF1(OpenErrorStatus);
156
157 LogFlowFunc(("ENTER: pNetFlt (0x%p), Status (0x%x), OpenErrorStatus(0x%x)\n", pNetFlt, Status, OpenErrorStatus));
158 Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
159 Assert(Status == NDIS_STATUS_SUCCESS);
160 if (pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS)
161 {
162 pNetFlt->u.s.WinIf.OpenCloseStatus = Status;
163 Assert(Status == NDIS_STATUS_SUCCESS);
164 if (Status != NDIS_STATUS_SUCCESS)
165 LogRelFunc(("Open Complete status is 0x%x", Status));
166 }
167 else
168 LogRelFunc(("Adapter maintained status is 0x%x", pNetFlt->u.s.WinIf.OpenCloseStatus));
169 NdisSetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
170 LogFlowFunc(("LEAVE: pNetFlt (0x%p), Status (0x%x), OpenErrorStatus(0x%x)\n", pNetFlt, Status, OpenErrorStatus));
171}
172
173static void vboxNetFltWinPtRequestsWaitComplete(PVBOXNETFLTINS pNetFlt)
174{
175 /* wait for request to complete */
176 while (vboxNetFltWinAtomicUoReadWinState(pNetFlt->u.s.WinIf.StateFlags).fRequestInfo == VBOXNDISREQUEST_INPROGRESS)
177 {
178 vboxNetFltWinSleep(2);
179 }
180
181 /*
182 * If the below miniport is going to low power state, complete the queued request
183 */
184 RTSpinlockAcquire(pNetFlt->hSpinlock);
185 if (pNetFlt->u.s.WinIf.StateFlags.fRequestInfo & VBOXNDISREQUEST_QUEUED)
186 {
187 /* mark the request as InProgress before posting it to RequestComplete */
188 pNetFlt->u.s.WinIf.StateFlags.fRequestInfo = VBOXNDISREQUEST_INPROGRESS;
189 RTSpinlockRelease(pNetFlt->hSpinlock);
190 vboxNetFltWinPtRequestComplete(pNetFlt, &pNetFlt->u.s.WinIf.PassDownRequest, NDIS_STATUS_FAILURE);
191 }
192 else
193 {
194 RTSpinlockRelease(pNetFlt->hSpinlock);
195 }
196}
197
198DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoUnbinding(PVBOXNETFLTINS pNetFlt, bool bOnUnbind)
199{
200 NDIS_STATUS Status;
201 uint64_t NanoTS = RTTimeSystemNanoTS();
202 int cPPUsage;
203
204 LogFlowFunc(("ENTER: pNetFlt 0x%p\n", pNetFlt));
205
206 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
207
208 Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) == kVBoxNetDevOpState_Initialized);
209
210 RTSpinlockAcquire(pNetFlt->hSpinlock);
211
212 ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true);
213 ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false);
214 ASMAtomicUoWriteU64(&pNetFlt->NanoTSLastRediscovery, NanoTS);
215
216 vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitializing);
217 if (!bOnUnbind)
218 {
219 vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitializing);
220 }
221
222 RTSpinlockRelease(pNetFlt->hSpinlock);
223
224 vboxNetFltWinPtRequestsWaitComplete(pNetFlt);
225
226 vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.MpState);
227 vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.PtState);
228
229 /* check packet pool is empty */
230 cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hSendPacketPool);
231 Assert(cPPUsage == 0);
232 cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hRecvPacketPool);
233 Assert(cPPUsage == 0);
234 /* for debugging only, ignore the err in release */
235 NOREF(cPPUsage);
236
237 if (!bOnUnbind || !vboxNetFltWinMpDeInitializeDeviceInstance(pNetFlt, &Status))
238 {
239 vboxNetFltWinPtCloseInterface(pNetFlt, &Status);
240 vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
241
242 if (!bOnUnbind)
243 {
244 Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitializing);
245 vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitialized);
246 }
247 else
248 {
249 Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
250 }
251 }
252 else
253 {
254 Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
255 }
256
257 LogFlowFunc(("LEAVE: pNetFlt 0x%p\n", pNetFlt));
258
259 return Status;
260}
261
262static VOID vboxNetFltWinPtUnbindAdapter(OUT PNDIS_STATUS pStatus,
263 IN NDIS_HANDLE hContext,
264 IN NDIS_HANDLE hUnbindContext)
265{
266 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hContext;
267 RT_NOREF1(hUnbindContext);
268
269 LogFlowFunc(("ENTER: pNetFlt (0x%p)\n", pNetFlt));
270
271 *pStatus = vboxNetFltWinDetachFromInterface(pNetFlt, true);
272 Assert(*pStatus == NDIS_STATUS_SUCCESS);
273
274 LogFlowFunc(("LEAVE: pNetFlt (0x%p)\n", pNetFlt));
275}
276
277static VOID vboxNetFltWinPtUnloadProtocol()
278{
279 LogFlowFuncEnter();
280 NDIS_STATUS Status = vboxNetFltWinPtDeregister(&g_VBoxNetFltGlobalsWin.Pt);
281 Assert(Status == NDIS_STATUS_SUCCESS); NOREF(Status);
282 LogFlowFunc(("LEAVE: PtDeregister Status (0x%x)\n", Status));
283}
284
285
286static VOID vboxNetFltWinPtCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status)
287{
288 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)ProtocolBindingContext;
289
290 LogFlowFunc(("ENTER: pNetFlt (0x%p), Status (0x%x)\n", pNetFlt, Status));
291 Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
292 Assert(Status == NDIS_STATUS_SUCCESS);
293 Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
294 if (pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS)
295 {
296 pNetFlt->u.s.WinIf.OpenCloseStatus = Status;
297 }
298 NdisSetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
299 LogFlowFunc(("LEAVE: pNetFlt (0x%p), Status (0x%x)\n", pNetFlt, Status));
300}
301
302static VOID vboxNetFltWinPtResetComplete(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS Status)
303{
304 RT_NOREF2(hProtocolBindingContext, Status);
305 LogFlowFunc(("ENTER: pNetFlt 0x%p, Status 0x%x\n", hProtocolBindingContext, Status));
306 /*
307 * should never be here
308 */
309 AssertFailed();
310 LogFlowFunc(("LEAVE: pNetFlt 0x%p, Status 0x%x\n", hProtocolBindingContext, Status));
311}
312
313static NDIS_STATUS vboxNetFltWinPtHandleQueryInfoComplete(PVBOXNETFLTINS pNetFlt, NDIS_STATUS Status)
314{
315 PNDIS_REQUEST pRequest = &pNetFlt->u.s.WinIf.PassDownRequest;
316
317 switch (pRequest->DATA.QUERY_INFORMATION.Oid)
318 {
319 case OID_PNP_CAPABILITIES:
320 {
321 if (Status == NDIS_STATUS_SUCCESS)
322 {
323 if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
324 {
325 PNDIS_PNP_CAPABILITIES pPnPCaps = (PNDIS_PNP_CAPABILITIES)(pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
326 PNDIS_PM_WAKE_UP_CAPABILITIES pPmWuCaps = &pPnPCaps->WakeUpCapabilities;
327 pPmWuCaps->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
328 pPmWuCaps->MinPatternWakeUp = NdisDeviceStateUnspecified;
329 pPmWuCaps->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
330 *pNetFlt->u.s.WinIf.pcPDRBytesRW = sizeof (NDIS_PNP_CAPABILITIES);
331 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = 0;
332 Status = NDIS_STATUS_SUCCESS;
333 }
334 else
335 {
336 AssertFailed();
337 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof(NDIS_PNP_CAPABILITIES);
338 Status = NDIS_STATUS_RESOURCES;
339 }
340 }
341 break;
342 }
343
344 case OID_GEN_MAC_OPTIONS:
345 {
346 if (Status == NDIS_STATUS_SUCCESS)
347 {
348 if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (ULONG))
349 {
350 pNetFlt->u.s.WinIf.fMacOptions = *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
351#ifndef VBOX_LOOPBACK_USEFLAGS
352 /* clearing this flag tells ndis we'll handle loopback ourselves
353 * the ndis layer or nic driver below us would loopback packets as necessary */
354 *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
355#else
356 /* we have to catch loopbacks from the underlying driver, so no duplications will occur,
357 * just indicate NDIS to handle loopbacks for the packets coming from the protocol */
358 *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer |= NDIS_MAC_OPTION_NO_LOOPBACK;
359#endif
360 }
361 else
362 {
363 AssertFailed();
364 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
365 Status = NDIS_STATUS_RESOURCES;
366 }
367 }
368 break;
369 }
370
371 case OID_GEN_CURRENT_PACKET_FILTER:
372 {
373 if (VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
374 {
375 /* we're here _ONLY_ in the passthru mode */
376 Assert(pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter && !pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt);
377 if (pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter && !pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt)
378 {
379 Assert(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
380 vboxNetFltWinDereferenceModePassThru(pNetFlt);
381 vboxNetFltWinDereferenceWinIf(pNetFlt);
382 }
383
384 if (Status == NDIS_STATUS_SUCCESS)
385 {
386 if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (ULONG))
387 {
388 /* the filter request is issued below only in case netflt is not active,
389 * simply update the cache here */
390 /* cache the filter used by upper protocols */
391 pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
392 pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized = TRUE;
393 }
394 else
395 {
396 AssertFailed();
397 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
398 Status = NDIS_STATUS_RESOURCES;
399 }
400 }
401 }
402 break;
403 }
404
405 default:
406 Assert(pRequest->DATA.QUERY_INFORMATION.Oid != OID_PNP_QUERY_POWER);
407 break;
408 }
409
410 *pNetFlt->u.s.WinIf.pcPDRBytesRW = pRequest->DATA.QUERY_INFORMATION.BytesWritten;
411 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = pRequest->DATA.QUERY_INFORMATION.BytesNeeded;
412
413 return Status;
414}
415
416static NDIS_STATUS vboxNetFltWinPtHandleSetInfoComplete(PVBOXNETFLTINS pNetFlt, NDIS_STATUS Status)
417{
418 PNDIS_REQUEST pRequest = &pNetFlt->u.s.WinIf.PassDownRequest;
419
420 switch (pRequest->DATA.SET_INFORMATION.Oid)
421 {
422 case OID_GEN_CURRENT_PACKET_FILTER:
423 {
424 if (VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
425 {
426 Assert(Status == NDIS_STATUS_SUCCESS);
427 if (pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter)
428 {
429 if (pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt)
430 {
431 Assert(pNetFlt->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE);
432 pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt = 0;
433 if (Status == NDIS_STATUS_SUCCESS)
434 {
435 if (pRequest->DATA.SET_INFORMATION.InformationBufferLength >= sizeof (ULONG))
436 {
437 pNetFlt->u.s.WinIf.fOurSetFilter = *((PULONG)pRequest->DATA.SET_INFORMATION.InformationBuffer);
438 Assert(pNetFlt->u.s.WinIf.fOurSetFilter == NDIS_PACKET_TYPE_PROMISCUOUS);
439 }
440 else
441 {
442 AssertFailed();
443 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
444 Status = NDIS_STATUS_RESOURCES;
445 }
446 }
447 vboxNetFltWinDereferenceNetFlt(pNetFlt);
448 }
449 else
450 {
451 Assert(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
452
453 if (Status == NDIS_STATUS_SUCCESS)
454 {
455 if (pRequest->DATA.SET_INFORMATION.InformationBufferLength >= sizeof (ULONG))
456 {
457 /* the request was issued when the netflt was not active, simply update the cache here */
458 pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = *((PULONG)pRequest->DATA.SET_INFORMATION.InformationBuffer);
459 pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized = TRUE;
460 }
461 else
462 {
463 AssertFailed();
464 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
465 Status = NDIS_STATUS_RESOURCES;
466 }
467 }
468 vboxNetFltWinDereferenceModePassThru(pNetFlt);
469 }
470
471 pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter = 0;
472 vboxNetFltWinDereferenceWinIf(pNetFlt);
473 }
474#ifdef DEBUG_misha
475 else
476 {
477 AssertFailed();
478 }
479#endif
480 }
481 break;
482 }
483
484 default:
485 Assert(pRequest->DATA.SET_INFORMATION.Oid != OID_PNP_SET_POWER);
486 break;
487 }
488
489 *pNetFlt->u.s.WinIf.pcPDRBytesRW = pRequest->DATA.SET_INFORMATION.BytesRead;
490 *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = pRequest->DATA.SET_INFORMATION.BytesNeeded;
491
492 return Status;
493}
494
495DECLHIDDEN(VOID) vboxNetFltWinPtRequestComplete(NDIS_HANDLE hContext, PNDIS_REQUEST pNdisRequest, NDIS_STATUS Status)
496{
497 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hContext;
498 PNDIS_REQUEST pSynchRequest = pNetFlt->u.s.WinIf.pSynchRequest;
499
500 LogFlowFunc(("ENTER: pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
501
502 if (pSynchRequest == pNdisRequest)
503 {
504 /* asynchronous completion of our sync request */
505 /*1.set the status */
506 pNetFlt->u.s.WinIf.SynchCompletionStatus = Status;
507 /* 2. set event */
508 KeSetEvent(&pNetFlt->u.s.WinIf.hSynchCompletionEvent, 0, FALSE);
509 /* 3. return; */
510
511 LogFlowFunc(("LEAVE: pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
512 return;
513 }
514
515 Assert(&pNetFlt->u.s.WinIf.PassDownRequest == pNdisRequest);
516 Assert(pNetFlt->u.s.WinIf.StateFlags.fRequestInfo == VBOXNDISREQUEST_INPROGRESS);
517 vboxNetFltWinMpRequestStateComplete(pNetFlt);
518
519 switch (pNdisRequest->RequestType)
520 {
521 case NdisRequestQueryInformation:
522 Status = vboxNetFltWinPtHandleQueryInfoComplete(pNetFlt, Status);
523 NdisMQueryInformationComplete(pNetFlt->u.s.WinIf.hMiniport, Status);
524 break;
525
526 case NdisRequestSetInformation:
527 Status = vboxNetFltWinPtHandleSetInfoComplete(pNetFlt, Status);
528 NdisMSetInformationComplete(pNetFlt->u.s.WinIf.hMiniport, Status);
529 break;
530
531 default:
532 AssertFailed();
533 break;
534 }
535
536 LogFlowFunc(("LEAVE: pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
537}
538
539static VOID vboxNetFltWinPtStatus(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS GeneralStatus, IN PVOID pvStatusBuffer, IN UINT cbStatusBuffer)
540{
541 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
542
543 LogFlowFunc(("ENTER: pNetFlt (0x%p), GeneralStatus (0x%x)\n", pNetFlt, GeneralStatus));
544
545 if (vboxNetFltWinReferenceWinIf(pNetFlt))
546 {
547 Assert(pNetFlt->u.s.WinIf.hMiniport);
548
549 if (VBOXNETFLT_PT_STATUS_IS_FILTERED(GeneralStatus))
550 {
551 pNetFlt->u.s.WinIf.MpIndicatedMediaStatus = GeneralStatus;
552 }
553 NdisMIndicateStatus(pNetFlt->u.s.WinIf.hMiniport,
554 GeneralStatus,
555 pvStatusBuffer,
556 cbStatusBuffer);
557
558 vboxNetFltWinDereferenceWinIf(pNetFlt);
559 }
560 else
561 {
562 if (pNetFlt->u.s.WinIf.hMiniport != NULL
563 && VBOXNETFLT_PT_STATUS_IS_FILTERED(GeneralStatus)
564 )
565 {
566 pNetFlt->u.s.WinIf.MpUnindicatedMediaStatus = GeneralStatus;
567 }
568 }
569
570 LogFlowFunc(("LEAVE: pNetFlt (0x%p), GeneralStatus (0x%x)\n", pNetFlt, GeneralStatus));
571}
572
573
574static VOID vboxNetFltWinPtStatusComplete(IN NDIS_HANDLE hProtocolBindingContext)
575{
576 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
577
578 LogFlowFunc(("ENTER: pNetFlt (0x%p)\n", pNetFlt));
579
580 if (vboxNetFltWinReferenceWinIf(pNetFlt))
581 {
582 NdisMIndicateStatusComplete(pNetFlt->u.s.WinIf.hMiniport);
583
584 vboxNetFltWinDereferenceWinIf(pNetFlt);
585 }
586
587 LogFlowFunc(("LEAVE: pNetFlt (0x%p)\n", pNetFlt));
588}
589
590static VOID vboxNetFltWinPtSendComplete(IN NDIS_HANDLE hProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status)
591{
592 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
593 PVBOXNETFLT_PKTRSVD_PT pSendInfo = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
594 PNDIS_PACKET pOrigPacket = pSendInfo->pOrigPacket;
595 PVOID pBufToFree = pSendInfo->pBufToFree;
596 LogFlowFunc(("ENTER: pNetFlt (0x%p), pPacket (0x%p), Status (0x%x)\n", pNetFlt, pPacket, Status));
597
598#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
599 /** @todo for optimization we could check only for netflt-mode packets
600 * do it for all for now */
601 vboxNetFltWinLbRemoveSendPacket(pNetFlt, pPacket);
602#endif
603
604 if (pOrigPacket)
605 {
606 NdisIMCopySendCompletePerPacketInfo(pOrigPacket, pPacket);
607 NdisFreePacket(pPacket);
608 /* the ptk was posted from the upperlying protocol */
609 NdisMSendComplete(pNetFlt->u.s.WinIf.hMiniport, pOrigPacket, Status);
610 }
611 else
612 {
613 /* if the pOrigPacket is zero - the ptk was originated by netFlt send/receive
614 * need to free packet buffers */
615 vboxNetFltWinFreeSGNdisPacket(pPacket, !pBufToFree);
616 }
617
618 if (pBufToFree)
619 {
620 vboxNetFltWinMemFree(pBufToFree);
621 }
622
623 vboxNetFltWinDereferenceWinIf(pNetFlt);
624
625 LogFlowFunc(("LEAVE: pNetFlt (0x%p), pPacket (0x%p), Status (0x%x)\n", pNetFlt, pPacket, Status));
626}
627
628/**
629 * removes searches for the packet in the list and removes it if found
630 * @return true if the packet was found and removed, false - otherwise
631 */
632static bool vboxNetFltWinRemovePacketFromList(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket)
633{
634 PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
635 return vboxNetFltWinInterlockedSearchListEntry(pList, &pTDR->ListEntry, true /* remove*/);
636}
637
638/**
639 * puts the packet to the tail of the list
640 */
641static void vboxNetFltWinPutPacketToList(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket, PNDIS_BUFFER pOrigBuffer)
642{
643 PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
644 pTDR->pOrigBuffer = pOrigBuffer;
645 vboxNetFltWinInterlockedPutTail(pList, &pTDR->ListEntry);
646}
647
648static bool vboxNetFltWinPtTransferDataCompleteActive(PVBOXNETFLTINS pNetFltIf, PNDIS_PACKET pPacket, NDIS_STATUS Status)
649{
650 PNDIS_BUFFER pBuffer;
651 PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR;
652
653 if (!vboxNetFltWinRemovePacketFromList(&pNetFltIf->u.s.WinIf.TransferDataList, pPacket))
654 return false;
655
656 pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
657 Assert(pTDR);
658 Assert(pTDR->pOrigBuffer);
659
660 do
661 {
662 NdisUnchainBufferAtFront(pPacket, &pBuffer);
663
664 Assert(pBuffer);
665
666 NdisFreeBuffer(pBuffer);
667
668 pBuffer = pTDR->pOrigBuffer;
669
670 NdisChainBufferAtBack(pPacket, pBuffer);
671
672 /* data transfer was initiated when the netFlt was active
673 * the netFlt is still retained by us
674 * 1. check if loopback
675 * 2. enqueue packet
676 * 3. release netFlt */
677
678 if (Status == NDIS_STATUS_SUCCESS)
679 {
680
681#ifdef VBOX_LOOPBACK_USEFLAGS
682 if (vboxNetFltWinIsLoopedBackPacket(pPacket))
683 {
684 /* should not be here */
685 AssertFailed();
686 }
687#else
688 PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pNetFltIf, pPacket, false);
689 if (pLb)
690 {
691#ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
692 /* should not be here */
693 AssertFailed();
694#endif
695 if (!vboxNetFltWinLbIsFromIntNet(pLb))
696 {
697 /* the packet is not from int net, need to pass it up to the host */
698 NdisMIndicateReceivePacket(pNetFltIf->u.s.WinIf.hMiniport, &pPacket, 1);
699 /* dereference NetFlt, WinIf will be dereferenced on Packet return */
700 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
701 break;
702 }
703 }
704#endif
705 else
706 {
707 /* 2. enqueue */
708 /* use the same packet info to put the packet in the processing packet queue */
709 PVBOXNETFLT_PKTRSVD_MP pRecvInfo = (PVBOXNETFLT_PKTRSVD_MP)pPacket->MiniportReserved;
710
711 VBOXNETFLT_LBVERIFY(pNetFltIf, pPacket);
712
713 pRecvInfo->pOrigPacket = NULL;
714 pRecvInfo->pBufToFree = NULL;
715
716 NdisGetPacketFlags(pPacket) = 0;
717# ifdef VBOXNETFLT_NO_PACKET_QUEUE
718 if (vboxNetFltWinPostIntnet(pNetFltIf, pPacket, 0))
719 {
720 /* drop it */
721 vboxNetFltWinFreeSGNdisPacket(pPacket, true);
722 vboxNetFltWinDereferenceWinIf(pNetFltIf);
723 }
724 else
725 {
726 NdisMIndicateReceivePacket(pNetFltIf->u.s.WinIf.hMiniport, &pPacket, 1);
727 }
728 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
729 break;
730# else
731 Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, PACKET_MINE);
732 if (Status == NDIS_STATUS_SUCCESS)
733 {
734 break;
735 }
736 AssertFailed();
737# endif
738 }
739 }
740 else
741 {
742 AssertFailed();
743 }
744 /* we are here because of error either in data transfer or in enqueueing the packet */
745 vboxNetFltWinFreeSGNdisPacket(pPacket, true);
746 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
747 vboxNetFltWinDereferenceWinIf(pNetFltIf);
748 } while (0);
749
750 return true;
751}
752
753static VOID vboxNetFltWinPtTransferDataComplete(IN NDIS_HANDLE hProtocolBindingContext,
754 IN PNDIS_PACKET pPacket,
755 IN NDIS_STATUS Status,
756 IN UINT cbTransferred)
757{
758 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
759 LogFlowFunc(("ENTER: pNetFlt (0x%p), pPacket (0x%p), Status (0x%x), cbTransfered (%d)\n", pNetFlt, pPacket, Status, cbTransferred));
760 if (!vboxNetFltWinPtTransferDataCompleteActive(pNetFlt, pPacket, Status))
761 {
762 if (pNetFlt->u.s.WinIf.hMiniport)
763 {
764 NdisMTransferDataComplete(pNetFlt->u.s.WinIf.hMiniport,
765 pPacket,
766 Status,
767 cbTransferred);
768 }
769
770 vboxNetFltWinDereferenceWinIf(pNetFlt);
771 }
772 /* else - all processing is done with vboxNetFltWinPtTransferDataCompleteActive already */
773
774 LogFlowFunc(("LEAVE: pNetFlt (0x%p), pPacket (0x%p), Status (0x%x), cbTransfered (%d)\n", pNetFlt, pPacket, Status, cbTransferred));
775}
776
777static INT vboxNetFltWinRecvPacketPassThru(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket)
778{
779 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
780
781 PNDIS_PACKET pMyPacket;
782 NDIS_STATUS Status = vboxNetFltWinPrepareRecvPacket(pNetFlt, pPacket, &pMyPacket, true);
783 /* the Status holds the current packet status it will be checked for NDIS_STATUS_RESOURCES later
784 * (see below) */
785 Assert(pMyPacket);
786 if (pMyPacket)
787 {
788 NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
789 if (Status == NDIS_STATUS_RESOURCES)
790 {
791 NdisDprFreePacket(pMyPacket);
792 return 0;
793 }
794
795 return 1;
796 }
797
798 return 0;
799}
800
801/**
802 * process the packet receive in a "passthru" mode
803 */
804static NDIS_STATUS vboxNetFltWinRecvPassThru(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket)
805{
806 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
807
808 NDIS_STATUS Status;
809 PNDIS_PACKET pMyPacket;
810
811 NdisDprAllocatePacket(&Status, &pMyPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
812 Assert(Status == NDIS_STATUS_SUCCESS);
813 if (Status == NDIS_STATUS_SUCCESS)
814 {
815 vboxNetFltWinCopyPacketInfoOnRecv(pMyPacket, pPacket, true /* force NDIS_STATUS_RESOURCES */);
816 Assert(NDIS_GET_PACKET_STATUS(pMyPacket) == NDIS_STATUS_RESOURCES);
817
818 NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
819
820 NdisDprFreePacket(pMyPacket);
821 }
822 return Status;
823}
824
825static VOID vboxNetFltWinRecvIndicatePassThru(PVBOXNETFLTINS pNetFlt, NDIS_HANDLE MacReceiveContext,
826 PVOID pHeaderBuffer, UINT cbHeaderBuffer, PVOID pLookAheadBuffer, UINT cbLookAheadBuffer, UINT cbPacket)
827{
828 /* Note: we're using KeGetCurrentProcessorNumber, which is not entirely correct in case
829 * we're running on 64bit win7+, which can handle > 64 CPUs, however since KeGetCurrentProcessorNumber
830 * always returns the number < than the number of CPUs in the first group, we're guaranteed to have CPU index < 64
831 * @todo: use KeGetCurrentProcessorNumberEx for Win7+ 64 and dynamically extended array */
832 ULONG Proc = KeGetCurrentProcessorNumber();
833 Assert(Proc < RT_ELEMENTS(pNetFlt->u.s.WinIf.abIndicateRxComplete));
834 pNetFlt->u.s.WinIf.abIndicateRxComplete[Proc] = TRUE;
835 switch (pNetFlt->u.s.WinIf.enmMedium)
836 {
837 case NdisMedium802_3:
838 case NdisMediumWan:
839 NdisMEthIndicateReceive(pNetFlt->u.s.WinIf.hMiniport,
840 MacReceiveContext,
841 (PCHAR)pHeaderBuffer,
842 cbHeaderBuffer,
843 pLookAheadBuffer,
844 cbLookAheadBuffer,
845 cbPacket);
846 break;
847 default:
848 AssertFailed();
849 break;
850 }
851}
852
853/**
854 * process the ProtocolReceive in an "active" mode
855 *
856 * @return NDIS_STATUS_SUCCESS - the packet is processed
857 * NDIS_STATUS_PENDING - the packet is being processed, we are waiting for the ProtocolTransferDataComplete to be called
858 * NDIS_STATUS_NOT_ACCEPTED - the packet is not needed - typically this is because this is a loopback packet
859 * NDIS_STATUS_FAILURE - packet processing failed
860 */
861static NDIS_STATUS vboxNetFltWinPtReceiveActive(PVBOXNETFLTINS pNetFlt, NDIS_HANDLE MacReceiveContext, PVOID pHeaderBuffer, UINT cbHeaderBuffer,
862 PVOID pLookaheadBuffer, UINT cbLookaheadBuffer, UINT cbPacket)
863{
864 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
865
866 do
867 {
868 if (cbHeaderBuffer != VBOXNETFLT_PACKET_ETHEADER_SIZE)
869 {
870 Status = NDIS_STATUS_NOT_ACCEPTED;
871 break;
872 }
873
874#ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
875 if (cbPacket == cbLookaheadBuffer)
876 {
877 PINTNETSG pSG;
878 PUCHAR pRcvData;
879#ifndef VBOX_LOOPBACK_USEFLAGS
880 PNDIS_PACKET pLb;
881#endif
882
883 /* allocate SG buffer */
884 Status = vboxNetFltWinAllocSG(cbPacket + cbHeaderBuffer, &pSG);
885 if (Status != NDIS_STATUS_SUCCESS)
886 {
887 AssertFailed();
888 break;
889 }
890
891 pRcvData = (PUCHAR)pSG->aSegs[0].pv;
892
893 NdisMoveMappedMemory(pRcvData, pHeaderBuffer, cbHeaderBuffer);
894
895 NdisCopyLookaheadData(pRcvData+cbHeaderBuffer,
896 pLookaheadBuffer,
897 cbLookaheadBuffer,
898 pNetFlt->u.s.WinIf.fMacOptions);
899#ifndef VBOX_LOOPBACK_USEFLAGS
900 pLb = vboxNetFltWinLbSearchLoopBackBySG(pNetFlt, pSG, false);
901 if (pLb)
902 {
903#ifndef DEBUG_NETFLT_RECV_NOPACKET
904 /* should not be here */
905 AssertFailed();
906#endif
907 if (!vboxNetFltWinLbIsFromIntNet(pLb))
908 {
909 PNDIS_PACKET pMyPacket;
910 pMyPacket = vboxNetFltWinNdisPacketFromSG(pNetFlt, /* PVBOXNETFLTINS */
911 pSG, /* PINTNETSG */
912 pSG, /* PVOID pBufToFree */
913 false, /* bool bToWire */
914 false); /* bool bCopyMemory */
915 if (pMyPacket)
916 {
917 NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
918 /* dereference the NetFlt here & indicate SUCCESS, which would mean the caller would not do a dereference
919 * the WinIf dereference will be done on packet return */
920 vboxNetFltWinDereferenceNetFlt(pNetFlt);
921 Status = NDIS_STATUS_SUCCESS;
922 }
923 else
924 {
925 vboxNetFltWinMemFree(pSG);
926 Status = NDIS_STATUS_FAILURE;
927 }
928 }
929 else
930 {
931 vboxNetFltWinMemFree(pSG);
932 Status = NDIS_STATUS_NOT_ACCEPTED;
933 }
934 break;
935 }
936#endif
937 VBOXNETFLT_LBVERIFYSG(pNetFlt, pSG);
938
939 /* enqueue SG */
940# ifdef VBOXNETFLT_NO_PACKET_QUEUE
941 if (vboxNetFltWinPostIntnet(pNetFlt, pSG, VBOXNETFLT_PACKET_SG))
942 {
943 /* drop it */
944 vboxNetFltWinMemFree(pSG);
945 vboxNetFltWinDereferenceWinIf(pNetFlt);
946 }
947 else
948 {
949 PNDIS_PACKET pMyPacket = vboxNetFltWinNdisPacketFromSG(pNetFlt, /* PVBOXNETFLTINS */
950 pSG, /* PINTNETSG */
951 pSG, /* PVOID pBufToFree */
952 false, /* bool bToWire */
953 false); /* bool bCopyMemory */
954 Assert(pMyPacket);
955 if (pMyPacket)
956 {
957 NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS);
958
959 DBG_CHECK_PACKET_AND_SG(pMyPacket, pSG);
960
961 LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket));
962 NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
963 }
964 else
965 {
966 vboxNetFltWinDereferenceWinIf(pNetFlt);
967 Status = NDIS_STATUS_RESOURCES;
968 }
969 }
970 vboxNetFltWinDereferenceNetFlt(pNetFlt);
971# else
972 Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, PACKET_SG | PACKET_MINE);
973 if (Status != NDIS_STATUS_SUCCESS)
974 {
975 AssertFailed();
976 vboxNetFltWinMemFree(pSG);
977 break;
978 }
979# endif
980#endif
981 }
982 else
983 {
984 PNDIS_PACKET pPacket;
985 PNDIS_BUFFER pTransferBuffer;
986 PNDIS_BUFFER pOrigBuffer;
987 PUCHAR pMemBuf;
988 UINT cbBuf = cbPacket + cbHeaderBuffer;
989 UINT cbTransferred;
990
991 /* allocate NDIS Packet buffer */
992 NdisAllocatePacket(&Status, &pPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
993 if (Status != NDIS_STATUS_SUCCESS)
994 {
995 AssertFailed();
996 break;
997 }
998
999 VBOXNETFLT_OOB_INIT(pPacket);
1000
1001#ifdef VBOX_LOOPBACK_USEFLAGS
1002 /* set "don't loopback" flags */
1003 NdisGetPacketFlags(pPacket) = g_VBoxNetFltGlobalsWin.fPacketDontLoopBack;
1004#else
1005 NdisGetPacketFlags(pPacket) = 0;
1006#endif
1007
1008 Status = vboxNetFltWinMemAlloc((PVOID*)(&pMemBuf), cbBuf);
1009 if (Status != NDIS_STATUS_SUCCESS)
1010 {
1011 AssertFailed();
1012 NdisFreePacket(pPacket);
1013 break;
1014 }
1015 NdisAllocateBuffer(&Status, &pTransferBuffer, pNetFlt->u.s.WinIf.hRecvBufferPool, pMemBuf + cbHeaderBuffer, cbPacket);
1016 if (Status != NDIS_STATUS_SUCCESS)
1017 {
1018 AssertFailed();
1019 Status = NDIS_STATUS_FAILURE;
1020 NdisFreePacket(pPacket);
1021 vboxNetFltWinMemFree(pMemBuf);
1022 break;
1023 }
1024
1025 NdisAllocateBuffer(&Status, &pOrigBuffer, pNetFlt->u.s.WinIf.hRecvBufferPool, pMemBuf, cbBuf);
1026 if (Status != NDIS_STATUS_SUCCESS)
1027 {
1028 AssertFailed();
1029 Status = NDIS_STATUS_FAILURE;
1030 NdisFreeBuffer(pTransferBuffer);
1031 NdisFreePacket(pPacket);
1032 vboxNetFltWinMemFree(pMemBuf);
1033 break;
1034 }
1035
1036 NdisChainBufferAtBack(pPacket, pTransferBuffer);
1037
1038 NdisMoveMappedMemory(pMemBuf, pHeaderBuffer, cbHeaderBuffer);
1039
1040 vboxNetFltWinPutPacketToList(&pNetFlt->u.s.WinIf.TransferDataList, pPacket, pOrigBuffer);
1041
1042#ifdef DEBUG_NETFLT_RECV_TRANSFERDATA
1043 if (cbPacket == cbLookaheadBuffer)
1044 {
1045 NdisCopyLookaheadData(pMemBuf+cbHeaderBuffer,
1046 pLookaheadBuffer,
1047 cbLookaheadBuffer,
1048 pNetFlt->u.s.WinIf.fMacOptions);
1049 }
1050 else
1051#endif
1052 {
1053 Assert(cbPacket > cbLookaheadBuffer);
1054
1055 NdisTransferData(&Status, pNetFlt->u.s.WinIf.hBinding, MacReceiveContext,
1056 0, /* ByteOffset */
1057 cbPacket, pPacket, &cbTransferred);
1058 }
1059
1060 if (Status != NDIS_STATUS_PENDING)
1061 {
1062 vboxNetFltWinPtTransferDataComplete(pNetFlt, pPacket, Status, cbTransferred);
1063 }
1064 }
1065 } while (0);
1066
1067 return Status;
1068}
1069
1070static NDIS_STATUS vboxNetFltWinPtReceive(IN NDIS_HANDLE hProtocolBindingContext,
1071 IN NDIS_HANDLE MacReceiveContext,
1072 IN PVOID pHeaderBuffer,
1073 IN UINT cbHeaderBuffer,
1074 IN PVOID pLookAheadBuffer,
1075 IN UINT cbLookAheadBuffer,
1076 IN UINT cbPacket)
1077{
1078 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
1079 PNDIS_PACKET pPacket = NULL;
1080 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1081 bool bNetFltActive;
1082 bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &bNetFltActive);
1083 const bool bPassThruActive = !bNetFltActive;
1084
1085 LogFlowFunc(("ENTER: pNetFlt (0x%p)\n", pNetFlt));
1086
1087 if (fWinIfActive)
1088 {
1089 do
1090 {
1091#ifndef DEBUG_NETFLT_RECV_NOPACKET
1092 pPacket = NdisGetReceivedPacket(pNetFlt->u.s.WinIf.hBinding, MacReceiveContext);
1093 if (pPacket)
1094 {
1095# ifndef VBOX_LOOPBACK_USEFLAGS
1096 PNDIS_PACKET pLb = NULL;
1097# else
1098 if (vboxNetFltWinIsLoopedBackPacket(pPacket))
1099 {
1100 AssertFailed();
1101 /* nothing else to do here, just return the packet */
1102 //NdisReturnPackets(&pPacket, 1);
1103 Status = NDIS_STATUS_NOT_ACCEPTED;
1104 break;
1105 }
1106
1107 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1108# endif
1109
1110 if (bNetFltActive)
1111 {
1112# ifndef VBOX_LOOPBACK_USEFLAGS
1113 pLb = vboxNetFltWinLbSearchLoopBack(pNetFlt, pPacket, false);
1114 if (!pLb)
1115# endif
1116 {
1117 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1118
1119# ifdef VBOXNETFLT_NO_PACKET_QUEUE
1120 if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
1121 {
1122 /* drop it */
1123 break;
1124 }
1125# else
1126 Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_COPY);
1127 Assert(Status == NDIS_STATUS_SUCCESS);
1128 if (Status == NDIS_STATUS_SUCCESS)
1129 {
1130 //NdisReturnPackets(&pPacket, 1);
1131 fWinIfActive = false;
1132 bNetFltActive = false;
1133 break;
1134 }
1135# endif
1136 }
1137# ifndef VBOX_LOOPBACK_USEFLAGS
1138 else if (vboxNetFltWinLbIsFromIntNet(pLb))
1139 {
1140 /* nothing else to do here, just return the packet */
1141 //NdisReturnPackets(&pPacket, 1);
1142 Status = NDIS_STATUS_NOT_ACCEPTED;
1143 break;
1144 }
1145 /* we are here because this is a looped back packet set not from intnet
1146 * we will post it to the upper protocol */
1147# endif
1148 }
1149
1150 Assert(Status == STATUS_SUCCESS);
1151 if (Status == STATUS_SUCCESS)
1152 {
1153# ifndef VBOX_LOOPBACK_USEFLAGS
1154 Assert(!pLb || !vboxNetFltWinLbIsFromIntNet(pLb));
1155# endif
1156 Status = vboxNetFltWinRecvPassThru(pNetFlt, pPacket);
1157 Assert(Status == STATUS_SUCCESS);
1158 /* we are done with packet processing, and we will
1159 * not receive packet return event for this packet,
1160 * fWinIfActive should be true to ensure we release WinIf*/
1161 Assert(fWinIfActive);
1162 if (Status == STATUS_SUCCESS)
1163 break;
1164 }
1165 else
1166 {
1167 /* intnet processing failed - fall back to no-packet mode */
1168 Assert(bNetFltActive);
1169 Assert(fWinIfActive);
1170 }
1171
1172 }
1173#endif /* #ifndef DEBUG_NETFLT_RECV_NOPACKET */
1174
1175 if (bNetFltActive)
1176 {
1177 Status = vboxNetFltWinPtReceiveActive(pNetFlt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer,
1178 pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
1179 if (NT_SUCCESS(Status))
1180 {
1181 if (Status != NDIS_STATUS_NOT_ACCEPTED)
1182 {
1183 fWinIfActive = false;
1184 bNetFltActive = false;
1185 }
1186 else
1187 {
1188#ifndef VBOX_LOOPBACK_USEFLAGS
1189 /* this is a loopback packet, nothing to do here */
1190#else
1191 AssertFailed();
1192 /* should not be here */
1193#endif
1194 }
1195 break;
1196 }
1197 }
1198
1199 /* we are done with packet processing, and we will
1200 * not receive packet return event for this packet,
1201 * fWinIfActive should be true to ensure we release WinIf*/
1202 Assert(fWinIfActive);
1203
1204 vboxNetFltWinRecvIndicatePassThru(pNetFlt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer, pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
1205 /* the status could contain an error value here in case the IntNet recv failed,
1206 * ensure we return back success status */
1207 Status = NDIS_STATUS_SUCCESS;
1208
1209 } while (0);
1210
1211 if (bNetFltActive)
1212 {
1213 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1214 }
1215 else if (bPassThruActive)
1216 {
1217 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1218 }
1219 if (fWinIfActive)
1220 {
1221 vboxNetFltWinDereferenceWinIf(pNetFlt);
1222 }
1223 }
1224 else
1225 {
1226 Status = NDIS_STATUS_FAILURE;
1227 }
1228
1229 LogFlowFunc(("LEAVE: pNetFlt (0x%p)\n", pNetFlt));
1230
1231 return Status;
1232
1233}
1234
1235static VOID vboxNetFltWinPtReceiveComplete(NDIS_HANDLE hProtocolBindingContext)
1236{
1237 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
1238 bool fNetFltActive;
1239 bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &fNetFltActive);
1240 NDIS_HANDLE hMiniport = pNetFlt->u.s.WinIf.hMiniport;
1241 /* Note: we're using KeGetCurrentProcessorNumber, which is not entirely correct in case
1242 * we're running on 64bit win7+, which can handle > 64 CPUs, however since KeGetCurrentProcessorNumber
1243 * always returns the number < than the number of CPUs in the first group, we're guaranteed to have CPU index < 64
1244 * @todo: use KeGetCurrentProcessorNumberEx for Win7+ 64 and dynamically extended array */
1245 ULONG iProc = KeGetCurrentProcessorNumber();
1246 Assert(iProc < RT_ELEMENTS(pNetFlt->u.s.WinIf.abIndicateRxComplete));
1247
1248 LogFlowFunc(("ENTER: pNetFlt (0x%p)\n", pNetFlt));
1249
1250 if (hMiniport != NULL && pNetFlt->u.s.WinIf.abIndicateRxComplete[iProc])
1251 {
1252 switch (pNetFlt->u.s.WinIf.enmMedium)
1253 {
1254 case NdisMedium802_3:
1255 case NdisMediumWan:
1256 NdisMEthIndicateReceiveComplete(hMiniport);
1257 break;
1258 default:
1259 AssertFailed();
1260 break;
1261 }
1262 }
1263
1264 pNetFlt->u.s.WinIf.abIndicateRxComplete[iProc] = FALSE;
1265
1266 if (fWinIfActive)
1267 {
1268 if (fNetFltActive)
1269 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1270 else
1271 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1272 vboxNetFltWinDereferenceWinIf(pNetFlt);
1273 }
1274
1275 LogFlowFunc(("LEAVE: pNetFlt (0x%p)\n", pNetFlt));
1276}
1277
1278static INT vboxNetFltWinPtReceivePacket(NDIS_HANDLE hProtocolBindingContext, PNDIS_PACKET pPacket)
1279{
1280 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
1281 INT cRefCount = 0;
1282 bool bNetFltActive;
1283 bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &bNetFltActive);
1284 const bool bPassThruActive = !bNetFltActive;
1285
1286 LogFlowFunc(("ENTER: pNetFlt (0x%p)\n", pNetFlt));
1287
1288 if (fWinIfActive)
1289 {
1290 do
1291 {
1292#ifdef VBOX_LOOPBACK_USEFLAGS
1293 if (vboxNetFltWinIsLoopedBackPacket(pPacket))
1294 {
1295 AssertFailed();
1296 Log(("lb_rp"));
1297
1298 /* nothing else to do here, just return the packet */
1299 cRefCount = 0;
1300 //NdisReturnPackets(&pPacket, 1);
1301 break;
1302 }
1303
1304 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1305#endif
1306
1307 if (bNetFltActive)
1308 {
1309#ifndef VBOX_LOOPBACK_USEFLAGS
1310 PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pNetFlt, pPacket, false);
1311 if (!pLb)
1312#endif
1313 {
1314#ifndef VBOXNETFLT_NO_PACKET_QUEUE
1315 NDIS_STATUS fStatus;
1316#endif
1317 bool fResources = NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES; NOREF(fResources);
1318
1319 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1320#ifdef DEBUG_misha
1321 /** @todo remove this assert.
1322 * this is a temporary assert for debugging purposes:
1323 * we're probably doing something wrong with the packets if the miniport reports NDIS_STATUS_RESOURCES */
1324 Assert(!fResources);
1325#endif
1326
1327#ifdef VBOXNETFLT_NO_PACKET_QUEUE
1328 if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
1329 {
1330 /* drop it */
1331 cRefCount = 0;
1332 break;
1333 }
1334
1335#else
1336 fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, fResources ? PACKET_COPY : 0);
1337 if (fStatus == NDIS_STATUS_SUCCESS)
1338 {
1339 bNetFltActive = false;
1340 fWinIfActive = false;
1341 if (fResources)
1342 {
1343 cRefCount = 0;
1344 //NdisReturnPackets(&pPacket, 1);
1345 }
1346 else
1347 cRefCount = 1;
1348 break;
1349 }
1350 else
1351 {
1352 AssertFailed();
1353 }
1354#endif
1355 }
1356#ifndef VBOX_LOOPBACK_USEFLAGS
1357 else if (vboxNetFltWinLbIsFromIntNet(pLb))
1358 {
1359 /* the packet is from intnet, it has already been set to the host,
1360 * no need for loopng it back to the host again */
1361 /* nothing else to do here, just return the packet */
1362 cRefCount = 0;
1363 //NdisReturnPackets(&pPacket, 1);
1364 break;
1365 }
1366#endif
1367 }
1368
1369 cRefCount = vboxNetFltWinRecvPacketPassThru(pNetFlt, pPacket);
1370 if (cRefCount)
1371 {
1372 Assert(cRefCount == 1);
1373 fWinIfActive = false;
1374 }
1375
1376 } while (FALSE);
1377
1378 if (bNetFltActive)
1379 {
1380 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1381 }
1382 else if (bPassThruActive)
1383 {
1384 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1385 }
1386 if (fWinIfActive)
1387 {
1388 vboxNetFltWinDereferenceWinIf(pNetFlt);
1389 }
1390 }
1391 else
1392 {
1393 cRefCount = 0;
1394 //NdisReturnPackets(&pPacket, 1);
1395 }
1396
1397 LogFlowFunc(("LEAVE: pNetFlt (0x%p), cRefCount (%d)\n", pNetFlt, cRefCount));
1398
1399 return cRefCount;
1400}
1401
1402DECLHIDDEN(bool) vboxNetFltWinPtCloseInterface(PVBOXNETFLTINS pNetFlt, PNDIS_STATUS pStatus)
1403{
1404 RTSpinlockAcquire(pNetFlt->hSpinlock);
1405
1406 if (pNetFlt->u.s.WinIf.StateFlags.fInterfaceClosing)
1407 {
1408 RTSpinlockRelease(pNetFlt->hSpinlock);
1409 AssertFailed();
1410 return false;
1411 }
1412 if (pNetFlt->u.s.WinIf.hBinding == NULL)
1413 {
1414 RTSpinlockRelease(pNetFlt->hSpinlock);
1415 AssertFailed();
1416 return false;
1417 }
1418
1419 pNetFlt->u.s.WinIf.StateFlags.fInterfaceClosing = TRUE;
1420 RTSpinlockRelease(pNetFlt->hSpinlock);
1421
1422 NdisResetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
1423 NdisCloseAdapter(pStatus, pNetFlt->u.s.WinIf.hBinding);
1424 if (*pStatus == NDIS_STATUS_PENDING)
1425 {
1426 NdisWaitEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent, 0);
1427 *pStatus = pNetFlt->u.s.WinIf.OpenCloseStatus;
1428 }
1429
1430 Assert (*pStatus == NDIS_STATUS_SUCCESS);
1431
1432 pNetFlt->u.s.WinIf.hBinding = NULL;
1433
1434 return true;
1435}
1436
1437static NDIS_STATUS vboxNetFltWinPtPnPSetPower(PVBOXNETFLTINS pNetFlt, NDIS_DEVICE_POWER_STATE enmPowerState)
1438{
1439 NDIS_DEVICE_POWER_STATE enmPrevPowerState = vboxNetFltWinGetPowerState(&pNetFlt->u.s.WinIf.PtState);
1440
1441 RTSpinlockAcquire(pNetFlt->hSpinlock);
1442
1443 vboxNetFltWinSetPowerState(&pNetFlt->u.s.WinIf.PtState, enmPowerState);
1444
1445 if (vboxNetFltWinGetPowerState(&pNetFlt->u.s.WinIf.PtState) > NdisDeviceStateD0)
1446 {
1447 if (enmPrevPowerState == NdisDeviceStateD0)
1448 {
1449 pNetFlt->u.s.WinIf.StateFlags.fStandBy = TRUE;
1450 }
1451 RTSpinlockRelease(pNetFlt->hSpinlock);
1452 vboxNetFltWinPtRequestsWaitComplete(pNetFlt);
1453 vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.MpState);
1454 vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.PtState);
1455
1456 /* check packet pool is empty */
1457 UINT cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hSendPacketPool);
1458 Assert(cPPUsage == 0);
1459 cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hRecvPacketPool);
1460 Assert(cPPUsage == 0);
1461 /* for debugging only, ignore the err in release */
1462 NOREF(cPPUsage);
1463
1464 Assert(!pNetFlt->u.s.WinIf.StateFlags.fRequestInfo);
1465 }
1466 else
1467 {
1468 if (enmPrevPowerState > NdisDeviceStateD0)
1469 {
1470 pNetFlt->u.s.WinIf.StateFlags.fStandBy = FALSE;
1471 }
1472
1473 if (pNetFlt->u.s.WinIf.StateFlags.fRequestInfo & VBOXNDISREQUEST_QUEUED)
1474 {
1475 pNetFlt->u.s.WinIf.StateFlags.fRequestInfo = VBOXNDISREQUEST_INPROGRESS;
1476 RTSpinlockRelease(pNetFlt->hSpinlock);
1477
1478 vboxNetFltWinMpRequestPost(pNetFlt);
1479 }
1480 else
1481 {
1482 RTSpinlockRelease(pNetFlt->hSpinlock);
1483 }
1484 }
1485
1486 return NDIS_STATUS_SUCCESS;
1487}
1488
1489
1490static NDIS_STATUS vboxNetFltWinPtPnPEvent(IN NDIS_HANDLE hProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
1491{
1492 PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
1493
1494 LogFlowFunc(("ENTER: pNetFlt (0x%p), NetEvent (%d)\n", pNetFlt, pNetPnPEvent->NetEvent));
1495
1496 switch (pNetPnPEvent->NetEvent)
1497 {
1498 case NetEventSetPower:
1499 {
1500 NDIS_DEVICE_POWER_STATE enmPowerState = *((PNDIS_DEVICE_POWER_STATE)pNetPnPEvent->Buffer);
1501 NDIS_STATUS rcNdis = vboxNetFltWinPtPnPSetPower(pNetFlt, enmPowerState);
1502 LogFlowFunc(("LEAVE: pNetFlt (0x%p), NetEvent (%d), rcNdis=%#x\n", pNetFlt, pNetPnPEvent->NetEvent, rcNdis));
1503 return rcNdis;
1504 }
1505
1506 case NetEventReconfigure:
1507 {
1508 if (!pNetFlt)
1509 {
1510 NdisReEnumerateProtocolBindings(g_VBoxNetFltGlobalsWin.Pt.hProtocol);
1511 }
1512 }
1513 /** @todo r=bird: Is the fall thru intentional?? */
1514 default:
1515 LogFlowFunc(("LEAVE: pNetFlt (0x%p), NetEvent (%d)\n", pNetFlt, pNetPnPEvent->NetEvent));
1516 return NDIS_STATUS_SUCCESS;
1517 }
1518
1519}
1520
1521#ifdef __cplusplus
1522# define PTCHARS_40(_p) ((_p).Ndis40Chars)
1523#else
1524# define PTCHARS_40(_p) (_p)
1525#endif
1526
1527/**
1528 * register the protocol edge
1529 */
1530DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtRegister(PVBOXNETFLTGLOBALS_PT pGlobalsPt, PDRIVER_OBJECT pDriverObject,
1531 PUNICODE_STRING pRegistryPathStr)
1532{
1533 RT_NOREF2(pDriverObject, pRegistryPathStr);
1534 NDIS_PROTOCOL_CHARACTERISTICS PtChars;
1535 NDIS_STRING NameStr;
1536
1537 NdisInitUnicodeString(&NameStr, VBOXNETFLT_NAME_PROTOCOL);
1538
1539 NdisZeroMemory(&PtChars, sizeof (PtChars));
1540 PTCHARS_40(PtChars).MajorNdisVersion = VBOXNETFLT_VERSION_PT_NDIS_MAJOR;
1541 PTCHARS_40(PtChars).MinorNdisVersion = VBOXNETFLT_VERSION_PT_NDIS_MINOR;
1542
1543 PTCHARS_40(PtChars).Name = NameStr;
1544 PTCHARS_40(PtChars).OpenAdapterCompleteHandler = vboxNetFltWinPtOpenAdapterComplete;
1545 PTCHARS_40(PtChars).CloseAdapterCompleteHandler = vboxNetFltWinPtCloseAdapterComplete;
1546 PTCHARS_40(PtChars).SendCompleteHandler = vboxNetFltWinPtSendComplete;
1547 PTCHARS_40(PtChars).TransferDataCompleteHandler = vboxNetFltWinPtTransferDataComplete;
1548 PTCHARS_40(PtChars).ResetCompleteHandler = vboxNetFltWinPtResetComplete;
1549 PTCHARS_40(PtChars).RequestCompleteHandler = vboxNetFltWinPtRequestComplete;
1550 PTCHARS_40(PtChars).ReceiveHandler = vboxNetFltWinPtReceive;
1551 PTCHARS_40(PtChars).ReceiveCompleteHandler = vboxNetFltWinPtReceiveComplete;
1552 PTCHARS_40(PtChars).StatusHandler = vboxNetFltWinPtStatus;
1553 PTCHARS_40(PtChars).StatusCompleteHandler = vboxNetFltWinPtStatusComplete;
1554 PTCHARS_40(PtChars).BindAdapterHandler = vboxNetFltWinPtBindAdapter;
1555 PTCHARS_40(PtChars).UnbindAdapterHandler = vboxNetFltWinPtUnbindAdapter;
1556 PTCHARS_40(PtChars).UnloadHandler = vboxNetFltWinPtUnloadProtocol;
1557#if !defined(DEBUG_NETFLT_RECV)
1558 PTCHARS_40(PtChars).ReceivePacketHandler = vboxNetFltWinPtReceivePacket;
1559#endif
1560 PTCHARS_40(PtChars).PnPEventHandler = vboxNetFltWinPtPnPEvent;
1561
1562 NDIS_STATUS Status;
1563 NdisRegisterProtocol(&Status, &pGlobalsPt->hProtocol, &PtChars, sizeof (PtChars));
1564 Assert(Status == STATUS_SUCCESS);
1565 return Status;
1566}
1567
1568/**
1569 * deregister the protocol edge
1570 */
1571DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDeregister(PVBOXNETFLTGLOBALS_PT pGlobalsPt)
1572{
1573 if (!pGlobalsPt->hProtocol)
1574 return NDIS_STATUS_SUCCESS;
1575
1576 NDIS_STATUS Status;
1577
1578 NdisDeregisterProtocol(&Status, pGlobalsPt->hProtocol);
1579 Assert (Status == NDIS_STATUS_SUCCESS);
1580 if (Status == NDIS_STATUS_SUCCESS)
1581 {
1582 NdisZeroMemory(pGlobalsPt, sizeof (*pGlobalsPt));
1583 }
1584 return Status;
1585}
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