VirtualBox

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

Last change on this file since 55998 was 52618, checked in by vboxsync, 10 years ago

HostDrivers, Runtime, Devices, Additions: TSC delta measurement and other changes resulting from bumping supdrv major version. TSC delta measurement currently disabled.

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