VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.c@ 29108

Last change on this file since 29108 was 29108, checked in by vboxsync, 15 years ago

net[flt|adp]/win: disable delayed packet processing when intnet is on

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 96.1 KB
Line 
1/* $Id: VBoxNetFltMp-win.c 29108 2010-05-05 20:17:42Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Miniport edge of ndis filter driver
4 */
5
6/*
7 * Copyright (C) 2008 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/*
18 * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
19 * Copyright (c) 1993-1999, Microsoft Corporation
20 */
21
22#include "VBoxNetFltCommon-win.h"
23
24#ifdef VBOX_NETFLT_ONDEMAND_BIND
25# error "unsupported (VBOX_NETFLT_ONDEMAND_BIND)"
26#else
27
28/** driver handle */
29static NDIS_HANDLE g_hDriverHandle = NULL;
30/** Ndis wrapper handle */
31static NDIS_HANDLE g_hNdisWrapperHandle;
32/** device handle for ioctl interface this is not used currently and should be removed soon */
33static NDIS_HANDLE g_hNdisDeviceHandle = NULL;
34/** device object used for ioctl interface this is not used currently and should be removed soon */
35static PDEVICE_OBJECT g_pControlDeviceObject = NULL;
36/** ioctl device ref count */
37static LONG g_cControlDeviceRefs = 0;
38/** true if control device needs to be dereferenced before destroying */
39static bool g_bControlDeviceReferenced = false;
40
41enum _DEVICE_STATE
42{
43 /** ready for create/delete */
44 PS_DEVICE_STATE_READY = 0,
45 /** create operation in progress */
46 PS_DEVICE_STATE_CREATING,
47 /** delete operation in progress */
48 PS_DEVICE_STATE_DELETING
49} g_eControlDeviceState = PS_DEVICE_STATE_READY;
50
51/*
52 * miniport
53 */
54typedef struct {
55 PVOID aBuffer[8];
56}OUR_SECURITY_DESCRIPTOR_BUFFER;
57
58static PUCHAR vboxNetFltWinMpDbgGetOidName(ULONG oid);
59
60#ifdef VBOXNETFLT_WITH_IOCTL_SECURITY
61NTSYSAPI
62NTSTATUS
63NTAPI
64ZwSetSecurityObject(IN HANDLE hHandle,
65 IN SECURITY_INFORMATION SInfo,
66 IN PSECURITY_DESCRIPTOR pSDescriptor);
67/*
68 * makes our device object usable/accessible for non-privileged users
69 */
70static NTSTATUS vboxNetFltWinSetSecurity(PNDIS_STRING pDevName)
71{
72 NTSTATUS Status;
73 OBJECT_ATTRIBUTES ObjAttr;
74 IO_STATUS_BLOCK IoStatus;
75 HANDLE hFile;
76 OUR_SECURITY_DESCRIPTOR_BUFFER SecurityDes;
77
78 /*obtain the handle first*/
79 NdisZeroMemory(&ObjAttr, sizeof(ObjAttr));
80 InitializeObjectAttributes(&ObjAttr, pDevName,
81 OBJ_KERNEL_HANDLE /* ULONG Attributes */,
82 NULL /*HANDLE RootDirectory*/,
83 NULL /*PSECURITY_DESCRIPTOR SecurityDescriptor */
84 );
85
86 NdisZeroMemory(&IoStatus, sizeof(IoStatus));
87 Status = ZwOpenFile(&hFile /* PHANDLE FileHandle*/,
88 WRITE_DAC /*ACCESS_MASK DesiredAccess - we want to change the ACL */,
89 &ObjAttr /*POBJECT_ATTRIBUTES */,
90 &IoStatus /*PIO_STATUS_BLOCK */,
91 0 /*ULONG ShareAccess*/,
92 0 /*ULONG OpenOptions*/
93 );
94 Assert(Status == STATUS_SUCCESS);
95 if(Status == STATUS_SUCCESS)
96 {
97 /* create and set security descriptor */
98 NdisZeroMemory(&SecurityDes, sizeof(SecurityDes));
99 Status = RtlCreateSecurityDescriptor(&SecurityDes, SECURITY_DESCRIPTOR_REVISION);
100 Assert(Status == STATUS_SUCCESS);
101 if(Status == STATUS_SUCCESS)
102 {
103 Status = ZwSetSecurityObject(hFile, DACL_SECURITY_INFORMATION, &SecurityDes);
104 Assert(Status == STATUS_SUCCESS);
105 if(Status != STATUS_SUCCESS)
106 {
107 LogRel(("ZwSetSecurityObject error: Status (0x%x)\n", Status));
108 DBGPRINT(("ZwSetSecurityObject error: Status (0x%x)\n", Status));
109 }
110 }
111 else
112 {
113 LogRel(("RtlCreateSecurityDescriptor error: Status (0x%x)\n", Status));
114 DBGPRINT(("RtlCreateSecurityDescriptor error: Status (0x%x)\n", Status));
115 }
116
117 {
118 NTSTATUS Tmp = ZwClose(hFile);
119 Assert(Tmp == STATUS_SUCCESS);
120 if(Tmp != STATUS_SUCCESS)
121 {
122 LogRel(("ZwClose error: Status (0x%x), ignoring\n", Status));
123 DBGPRINT(("ZwClose error: Status (0x%x), ignoring\n", Status));
124 }
125 }
126 }
127 else
128 {
129 LogRel(("ZwOpenFile error: Status (0x%x)\n", Status));
130 DBGPRINT(("ZwOpenFile error: Status (0x%x)\n", Status));
131 }
132
133 return Status;
134}
135#endif
136/**
137 * Register an ioctl interface - a device object to be used for this
138 * purpose is created by NDIS when we call NdisMRegisterDevice.
139 *
140 * This routine is called whenever a new miniport instance is
141 * initialized. However, we only create one global device object,
142 * when the first miniport instance is initialized. This routine
143 * handles potential race conditions with vboxNetFltWinPtDeregisterDevice via
144 * the g_eControlDeviceState and g_cControlDeviceRefs variables.
145 *
146 * NOTE: do not call this from DriverEntry; it will prevent the driver
147 * from being unloaded (e.g. on uninstall).
148 *
149 * @return NDIS_STATUS_SUCCESS if we successfully register a device object. */
150static NDIS_STATUS
151vboxNetFltWinPtRegisterDevice(
152 VOID
153 )
154{
155 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
156 UNICODE_STRING DeviceName;
157 UNICODE_STRING DeviceLinkUnicodeString;
158 PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
159
160 LogFlow(("==>vboxNetFltWinPtRegisterDevice\n"));
161
162 NdisAcquireSpinLock(&g_GlobalLock);
163
164 ++g_cControlDeviceRefs;
165
166 if (1 == g_cControlDeviceRefs)
167 {
168 Assert(g_eControlDeviceState != PS_DEVICE_STATE_CREATING);
169
170 /* Another thread could be running vboxNetFltWinPtDeregisterDevice on
171 * behalf of another miniport instance. If so, wait for
172 * it to exit. */
173 while (g_eControlDeviceState != PS_DEVICE_STATE_READY)
174 {
175 NdisReleaseSpinLock(&g_GlobalLock);
176 NdisMSleep(1);
177 NdisAcquireSpinLock(&g_GlobalLock);
178 }
179
180 g_eControlDeviceState = PS_DEVICE_STATE_CREATING;
181
182 NdisReleaseSpinLock(&g_GlobalLock);
183
184
185 NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
186
187 DispatchTable[IRP_MJ_CREATE] = vboxNetFltWinPtDispatch;
188 DispatchTable[IRP_MJ_CLEANUP] = vboxNetFltWinPtDispatch;
189 DispatchTable[IRP_MJ_CLOSE] = vboxNetFltWinPtDispatch;
190 DispatchTable[IRP_MJ_DEVICE_CONTROL] = vboxNetFltWinPtDispatch;
191
192
193 NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
194 NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
195
196 /* Create a device object and register our dispatch handlers */
197
198 Status = NdisMRegisterDevice(
199 g_hNdisWrapperHandle,
200 &DeviceName,
201 &DeviceLinkUnicodeString,
202 &DispatchTable[0],
203 &g_pControlDeviceObject,
204 &g_hNdisDeviceHandle
205 );
206
207 Assert(Status == NDIS_STATUS_SUCCESS);
208 if(Status == NDIS_STATUS_SUCCESS)
209 {
210#ifdef VBOXNETFLT_WITH_IOCTL_SECURITY
211 /* NdisMRegisterDevice does not offers us the ability to set security attributes */
212 /* need to do this "manualy" for the device to be accessible by the non-privileged users */
213 Status = vboxNetFltWinSetSecurity(&DeviceLinkUnicodeString);
214 Assert(Status == STATUS_SUCCESS);
215 if(Status != STATUS_SUCCESS)
216 {
217 LogRel(("Failed to set security attributes for netflt control device, status (0x%x), ignoring\n", Status));
218 /* ignore the failure */
219 Status = NDIS_STATUS_SUCCESS;
220 }
221#endif
222
223 Status = ObReferenceObjectByPointer(g_pControlDeviceObject, FILE_READ_DATA, NULL, KernelMode);
224 Assert(Status == NDIS_STATUS_SUCCESS);
225 if(Status == NDIS_STATUS_SUCCESS)
226 {
227 g_bControlDeviceReferenced = true;
228 }
229 else
230 {
231 LogRel(("Failed to reference netflt control device, status (0x%x), ignoring\n", Status));
232 /* ignore the failure */
233 Status = NDIS_STATUS_SUCCESS;
234 g_bControlDeviceReferenced = false;
235 }
236 }
237
238 NdisAcquireSpinLock(&g_GlobalLock);
239
240 g_eControlDeviceState = PS_DEVICE_STATE_READY;
241 }
242
243 NdisReleaseSpinLock(&g_GlobalLock);
244
245 LogFlow(("<==vboxNetFltWinPtRegisterDevice: %x\n", Status));
246
247 return (Status);
248}
249
250/**
251 * Deregister the ioctl interface. This is called whenever a miniport
252 * instance is halted. When the last miniport instance is halted, we
253 * request NDIS to delete the device object
254 *
255 * @return NDIS_STATUS_SUCCESS if everything worked ok
256 * */
257static NDIS_STATUS
258vboxNetFltWinPtDeregisterDevice(
259 VOID
260 )
261{
262 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
263
264 LogFlow(("==>NetFltDeregisterDevice\n"));
265
266 NdisAcquireSpinLock(&g_GlobalLock);
267
268 Assert(g_cControlDeviceRefs > 0);
269
270 --g_cControlDeviceRefs;
271
272 if (0 == g_cControlDeviceRefs)
273 {
274 /* All miniport instances have been halted. Deregister
275 * the control device. */
276
277 Assert(g_eControlDeviceState == PS_DEVICE_STATE_READY);
278
279 /* Block vboxNetFltWinPtRegisterDevice() while we release the control
280 * device lock and deregister the device. */
281
282 g_eControlDeviceState = PS_DEVICE_STATE_DELETING;
283
284 NdisReleaseSpinLock(&g_GlobalLock);
285
286 if (g_hNdisDeviceHandle != NULL)
287 {
288 if(g_bControlDeviceReferenced)
289 {
290 g_bControlDeviceReferenced = false;
291 ObDereferenceObject(g_pControlDeviceObject);
292 }
293
294 Status = NdisMDeregisterDevice(g_hNdisDeviceHandle);
295 g_hNdisDeviceHandle = NULL;
296 }
297
298 NdisAcquireSpinLock(&g_GlobalLock);
299 g_eControlDeviceState = PS_DEVICE_STATE_READY;
300 }
301
302 NdisReleaseSpinLock(&g_GlobalLock);
303
304 LogFlow(("<== NetFltDeregisterDevice: %x\n", Status));
305 return Status;
306
307}
308#ifndef VBOXNETADP
309/**
310 * This is the initialize handler which gets called as a result of
311 * the BindAdapter handler calling NdisIMInitializeDeviceInstanceEx.
312 * The context parameter which we pass there is the adapter structure
313 * which we retrieve here.
314 *
315 * @param OpenErrorStatus Not used by us.
316 * @param SelectedMediumIndex Place-holder for what media we are using
317 * @param MediumArray Array of ndis media passed down to us to pick from
318 * @param MediumArraySize Size of the array
319 * @param MiniportAdapterHandle The handle NDIS uses to refer to us
320 * @param WrapperConfigurationContext For use by NdisOpenConfiguration
321 * @return NDIS_STATUS_SUCCESS unless something goes wrong
322 * */
323static NDIS_STATUS vboxNetFltWinMpInitialize(
324 OUT PNDIS_STATUS OpenErrorStatus,
325 OUT PUINT SelectedMediumIndex,
326 IN PNDIS_MEDIUM MediumArray,
327 IN UINT MediumArraySize,
328 IN NDIS_HANDLE MiniportAdapterHandle,
329 IN NDIS_HANDLE WrapperConfigurationContext
330 )
331{
332 UINT i;
333 PADAPT pAdapt;
334 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
335 NDIS_MEDIUM Medium;
336
337 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
338
339 do
340 {
341 /*
342 * Start off by retrieving our adapter context and storing
343 * the Miniport handle in it.
344 */
345 pAdapt = (PADAPT)NdisIMGetDeviceContext(MiniportAdapterHandle);
346 pAdapt->hMiniportHandle = MiniportAdapterHandle;
347
348 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing);
349 /* the MP state should be already set to kVBoxNetDevOpState_Initializing, just a paranoya
350 * in case NDIS for some reason calls us in some unregular way */
351 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initializing);
352
353 LogFlow(("==> Miniport Initialize: Adapt %p\n", pAdapt));
354
355 /*
356 * Usually we export the medium type of the adapter below as our
357 * virtual miniport's medium type. However if the adapter below us
358 * is a WAN device, then we claim to be of medium type 802.3.
359 */
360 Medium = pAdapt->Medium;
361
362 if (Medium == NdisMediumWan)
363 {
364 Medium = NdisMedium802_3;
365 }
366
367 for (i = 0; i < MediumArraySize; i++)
368 {
369 if (MediumArray[i] == Medium)
370 {
371 *SelectedMediumIndex = i;
372 break;
373 }
374 }
375
376 if (i == MediumArraySize)
377 {
378 Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
379 break;
380 }
381
382
383 /*
384 * Set the attributes now. NDIS_ATTRIBUTE_DESERIALIZE enables us
385 * to make up-calls to NDIS without having to call NdisIMSwitchToMiniport
386 * or NdisIMQueueCallBack. This also forces us to protect our data using
387 * spinlocks where appropriate. Also in this case NDIS does not queue
388 * packets on our behalf. Since this is a very simple pass-thru
389 * miniport, we do not have a need to protect anything. However in
390 * a general case there will be a need to use per-adapter spin-locks
391 * for the packet queues at the very least.
392 */
393 NdisMSetAttributesEx(MiniportAdapterHandle,
394 pAdapt,
395 0, /* CheckForHangTimeInSeconds */
396 NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
397 NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
398 NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
399 NDIS_ATTRIBUTE_DESERIALIZE |
400 NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
401 (NDIS_INTERFACE_TYPE)0);
402
403 /*
404 * Initialize LastIndicatedStatus to be NDIS_STATUS_MEDIA_CONNECT
405 */
406 pAdapt->LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT;
407
408 /*
409 * Initialize the power states for both the lower binding (PTDeviceState)
410 * and our miniport edge to Powered On.
411 */
412 Assert(vboxNetFltWinGetPowerState(&pAdapt->MPState) == NdisDeviceStateD3);
413 vboxNetFltWinSetPowerState(&pAdapt->MPState, NdisDeviceStateD0);
414 Assert(pAdapt->MPState.OpState == kVBoxNetDevOpState_Initializing);
415 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
416
417 Status = NDIS_STATUS_SUCCESS;
418 }
419 while (FALSE);
420
421 /*
422 * If we had received an UnbindAdapter notification on the underlying
423 * adapter, we would have blocked that thread waiting for the IM Init
424 * process to complete. Wake up any such thread.
425 */
426 if(Status != NDIS_STATUS_SUCCESS)
427 {
428 Assert(vboxNetFltWinGetPowerState(&pAdapt->MPState) == NdisDeviceStateD3);
429 Assert(pAdapt->MPState.OpState == kVBoxNetDevOpState_Initializing);
430 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
431 }
432 NdisSetEvent(&pAdapt->MiniportInitEvent);
433
434 LogFlow(("<== Miniport Initialize: Adapt %p, Status %x\n", pAdapt, Status));
435
436 *OpenErrorStatus = Status;
437
438 return Status;
439}
440
441/**
442 * process the packet send in a "passthru" mode
443 */
444static NDIS_STATUS
445vboxNetFltWinSendPassThru(
446 IN PADAPT pAdapt,
447 IN PNDIS_PACKET pPacket
448 )
449{
450 PNDIS_PACKET pMyPacket;
451 NDIS_STATUS fStatus;
452
453 fStatus = vboxNetFltWinPrepareSendPacket(pAdapt, pPacket, &pMyPacket/*, false*/);
454
455 Assert(fStatus == NDIS_STATUS_SUCCESS);
456 if (fStatus == NDIS_STATUS_SUCCESS)
457 {
458#if !defined(VBOX_LOOPBACK_USEFLAGS) /* || defined(DEBUG_NETFLT_PACKETS) */
459 /* no need for the loop enqueue & check in a passthru mode , ndis will do everything for us */
460#endif
461 NdisSend(&fStatus,
462 pAdapt->hBindingHandle,
463 pMyPacket);
464 if (fStatus != NDIS_STATUS_PENDING)
465 {
466#ifndef WIN9X
467 NdisIMCopySendCompletePerPacketInfo (pPacket, pMyPacket);
468#endif
469 NdisFreePacket(pMyPacket);
470 }
471 }
472 return fStatus;
473}
474
475#else /* defined VBOXNETADP */
476DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDoDeinitialization(PADAPT pAdapt)
477{
478 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
479 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
480 uint64_t NanoTS = RTTimeSystemNanoTS();
481 int cPPUsage;
482
483 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
484 /*
485 * Set the flag that the miniport below is unbinding, so the request handlers will
486 * fail any request comming later
487 */
488 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
489
490 ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true);
491 ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false);
492 ASMAtomicUoWriteU64(&pNetFlt->NanoTSLastRediscovery, NanoTS);
493
494 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
495
496 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
497
498 vboxNetFltWinWaitDereference(&pAdapt->MPState);
499
500 /* check packet pool is empty */
501 cPPUsage = NdisPacketPoolUsage(pAdapt->hRecvPacketPoolHandle);
502 Assert(cPPUsage == 0);
503 /* for debugging only, ignore the err in release */
504 NOREF(cPPUsage);
505
506 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
507
508// pAdapt->hMiniportHandle = NULL;
509
510 return NDIS_STATUS_SUCCESS;
511}
512
513static NDIS_STATUS vboxNetFltWinMpReadApplyConfig(PADAPT pAdapt, NDIS_HANDLE hMiniportAdapter, NDIS_HANDLE hWrapperConfigurationContext)
514{
515 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
516 NDIS_HANDLE hConfiguration;
517 PNDIS_CONFIGURATION_PARAMETER pParameterValue;
518 NDIS_STRING strMAC = NDIS_STRING_CONST("MAC");
519 PVBOXNETFLTINS pThis = PADAPT_2_PVBOXNETFLTINS(pAdapt);
520 RTMAC mac;
521
522 //
523 // Open the registry for this adapter to read advanced
524 // configuration parameters stored by the INF file.
525 //
526 NdisOpenConfiguration(
527 &Status,
528 &hConfiguration,
529 hWrapperConfigurationContext);
530 Assert(Status == NDIS_STATUS_SUCCESS);
531 if(Status == NDIS_STATUS_SUCCESS)
532 {
533 do
534 {
535 int rc;
536 NDIS_CONFIGURATION_PARAMETER param;
537 WCHAR MacBuf[13];
538
539
540 NdisReadConfiguration(&Status,
541 &pParameterValue,
542 hConfiguration,
543 &strMAC,
544 NdisParameterString);
545// Assert(Status == NDIS_STATUS_SUCCESS);
546 if(Status == NDIS_STATUS_SUCCESS)
547 {
548
549 rc = vboxNetFltWinMACFromNdisString(&mac, &pParameterValue->ParameterData.StringData);
550 AssertRC(rc);
551 if(RT_SUCCESS(rc))
552 {
553 break;
554 }
555 }
556
557 vboxNetFltWinGenerateMACAddress(&mac);
558 param.ParameterType = NdisParameterString;
559 param.ParameterData.StringData.Buffer = MacBuf;
560 param.ParameterData.StringData.MaximumLength = sizeof(MacBuf);
561
562 rc = vboxNetFltWinMAC2NdisString(&mac, &param.ParameterData.StringData);
563 Assert(RT_SUCCESS(rc));
564 if(RT_SUCCESS(rc))
565 {
566 NdisWriteConfiguration(&Status,
567 hConfiguration,
568 &strMAC,
569 &param);
570 Assert(Status == NDIS_STATUS_SUCCESS);
571 if(Status != NDIS_STATUS_SUCCESS)
572 {
573 /* ignore the failure */
574 Status = NDIS_STATUS_SUCCESS;
575 }
576 }
577 }while(0);
578
579 NdisCloseConfiguration(hConfiguration);
580 }
581 else
582 {
583 vboxNetFltWinGenerateMACAddress(&mac);
584 }
585
586 pThis->u.s.MacAddr = mac;
587
588 return NDIS_STATUS_SUCCESS;
589}
590
591DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDoInitialization(PADAPT pAdapt, NDIS_HANDLE hMiniportAdapter, NDIS_HANDLE hWrapperConfigurationContext)
592{
593 NDIS_STATUS Status;
594 pAdapt->hMiniportHandle = hMiniportAdapter;
595
596 LogFlow(("==> vboxNetFltWinMpDoInitialization: Adapt %p\n", pAdapt));
597
598 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
599 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initializing);
600
601 vboxNetFltWinMpReadApplyConfig(pAdapt, hMiniportAdapter, hWrapperConfigurationContext);
602
603 NdisMSetAttributesEx(hMiniportAdapter,
604 pAdapt,
605 0, /* CheckForHangTimeInSeconds */
606 NDIS_ATTRIBUTE_DESERIALIZE |
607 NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
608 NdisInterfaceInternal/*(NDIS_INTERFACE_TYPE)0*/);
609
610 /*
611 * Initialize the power states for both the lower binding (PTDeviceState)
612 * and our miniport edge to Powered On.
613 */
614 Assert(vboxNetFltWinGetPowerState(&pAdapt->MPState) == NdisDeviceStateD3);
615 vboxNetFltWinSetPowerState(&pAdapt->MPState, NdisDeviceStateD0);
616 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing);
617 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
618
619 Status = NDIS_STATUS_SUCCESS;
620
621
622// *OpenErrorStatus = Status;
623
624 LogFlow(("<== vboxNetFltWinMpDoInitialization: Adapt %p, Status %x\n", pAdapt, Status));
625
626 return Status;
627}
628
629/**
630 * This is the initialize handler which gets called as a result of
631 * the BindAdapter handler calling NdisIMInitializeDeviceInstanceEx.
632 * The context parameter which we pass there is the adapter structure
633 * which we retrieve here.
634 *
635 * @param OpenErrorStatus Not used by us.
636 * @param SelectedMediumIndex Place-holder for what media we are using
637 * @param MediumArray Array of ndis media passed down to us to pick from
638 * @param MediumArraySize Size of the array
639 * @param MiniportAdapterHandle The handle NDIS uses to refer to us
640 * @param WrapperConfigurationContext For use by NdisOpenConfiguration
641 * @return NDIS_STATUS_SUCCESS unless something goes wrong
642 * */
643static NDIS_STATUS vboxNetFltWinMpInitialize(
644 OUT PNDIS_STATUS OpenErrorStatus,
645 OUT PUINT SelectedMediumIndex,
646 IN PNDIS_MEDIUM MediumArray,
647 IN UINT MediumArraySize,
648 IN NDIS_HANDLE MiniportAdapterHandle,
649 IN NDIS_HANDLE WrapperConfigurationContext
650 )
651{
652 UINT i;
653 PADAPT pAdapt;
654 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
655 NDIS_MEDIUM Medium;
656
657 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
658
659 Medium = NdisMedium802_3;
660
661 if (Medium == NdisMediumWan)
662 {
663 Medium = NdisMedium802_3;
664 }
665
666 for (i = 0; i < MediumArraySize; i++)
667 {
668 if (MediumArray[i] == Medium)
669 {
670 *SelectedMediumIndex = i;
671 break;
672 }
673 }
674
675 if (i != MediumArraySize)
676 {
677 PDEVICE_OBJECT pPdo, pFdo;
678#define KEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
679 UCHAR Buf[512];
680 PUCHAR pSuffix;
681 ULONG cbBuf;
682 NDIS_STRING RtlStr;
683
684 wcscpy((WCHAR*)Buf, KEY_PREFIX);
685 pSuffix = Buf + (sizeof(KEY_PREFIX)-2);
686
687 NdisMGetDeviceProperty(MiniportAdapterHandle,
688 &pPdo,
689 &pFdo,
690 NULL, //Next Device Object
691 NULL,
692 NULL);
693
694 Status = IoGetDeviceProperty (pPdo,
695 DevicePropertyDriverKeyName,
696 sizeof(Buf) - (sizeof(KEY_PREFIX)-2),
697 pSuffix,
698 &cbBuf);
699 if(Status == STATUS_SUCCESS)
700 {
701 OBJECT_ATTRIBUTES ObjAttr;
702 HANDLE hDrvKey;
703 RtlStr.Buffer=(WCHAR*)Buf;
704 RtlStr.Length=(USHORT)cbBuf - 2 + sizeof(KEY_PREFIX) - 2;
705 RtlStr.MaximumLength=sizeof(Buf);
706
707 InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE, NULL, NULL);
708
709 Status = ZwOpenKey(&hDrvKey, KEY_READ, &ObjAttr);
710 if(Status == STATUS_SUCCESS)
711 {
712 static UNICODE_STRING NetCfgInstanceIdValue = NDIS_STRING_CONST("NetCfgInstanceId");
713// UCHAR valBuf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + RTUUID_STR_LENGTH*2 + 10];
714// ULONG cLength = sizeof(valBuf);
715#define NAME_PREFIX L"\\DEVICE\\"
716 PKEY_VALUE_PARTIAL_INFORMATION pInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
717 Status = ZwQueryValueKey(hDrvKey,
718 &NetCfgInstanceIdValue,
719 KeyValuePartialInformation,
720 pInfo,
721 sizeof(Buf),
722 &cbBuf);
723 if(Status == STATUS_SUCCESS)
724 {
725 if(pInfo->Type == REG_SZ && pInfo->DataLength > 2)
726 {
727 WCHAR *pName;
728 Status = vboxNetFltWinMemAlloc(&pName, pInfo->DataLength + sizeof(NAME_PREFIX));
729 if(Status == STATUS_SUCCESS)
730 {
731 wcscpy(pName, NAME_PREFIX);
732 wcscpy(pName+(sizeof(NAME_PREFIX)-2)/2, (WCHAR*)pInfo->Data);
733 RtlStr.Buffer=pName;
734 RtlStr.Length = (USHORT)pInfo->DataLength - 2 + sizeof(NAME_PREFIX) - 2;
735 RtlStr.MaximumLength = (USHORT)pInfo->DataLength + sizeof(NAME_PREFIX);
736
737 Status = vboxNetFltWinPtInitBind(&pAdapt, MiniportAdapterHandle, &RtlStr, WrapperConfigurationContext);
738
739 if(Status == STATUS_SUCCESS)
740 {
741 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
742 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
743#if 0
744 NdisMIndicateStatus(pAdapt->hMiniportHandle,
745 NDIS_STATUS_MEDIA_CONNECT,
746 (PVOID)NULL,
747 0);
748#endif
749 }
750 else
751 {
752 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
753 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
754 }
755
756 vboxNetFltWinMemFree(pName);
757
758 }
759 }
760 else
761 {
762 Status = NDIS_STATUS_FAILURE;
763 }
764 }
765 }
766 }
767 }
768 else
769 {
770 Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
771 }
772
773 if(Status != NDIS_STATUS_SUCCESS)
774 {
775 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
776 }
777
778 /* TODO: */
779 *OpenErrorStatus = Status;
780
781 return Status;
782}
783#endif
784
785
786/**
787 * Send Packet Array handler. Either this or our SendPacket handler is called
788 * based on which one is enabled in our Miniport Characteristics.
789 *
790 * @param MiniportAdapterContext Pointer to our adapter
791 * @param PacketArray Set of packets to send
792 * @param NumberOfPackets Self-explanatory
793 * @return none */
794static VOID
795vboxNetFltWinMpSendPackets(
796 IN NDIS_HANDLE fMiniportAdapterContext,
797 IN PPNDIS_PACKET pPacketArray,
798 IN UINT cNumberOfPackets
799 )
800{
801 PADAPT pAdapt = (PADAPT)fMiniportAdapterContext;
802 NDIS_STATUS fStatus = NDIS_STATUS_SUCCESS;
803 UINT i;
804 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
805 bool bNetFltActive;
806
807 Assert(cNumberOfPackets);
808
809 if(vboxNetFltWinIncReferenceAdaptNetFlt(pNetFlt, pAdapt, cNumberOfPackets, &bNetFltActive))
810 {
811 uint32_t cAdaptRefs = cNumberOfPackets;
812 uint32_t cNetFltRefs;
813 uint32_t cPassThruRefs;
814 if(bNetFltActive)
815 {
816 cNetFltRefs = cNumberOfPackets;
817 cPassThruRefs = 0;
818 }
819 else
820 {
821 cPassThruRefs = cNumberOfPackets;
822 cNetFltRefs = 0;
823 }
824
825 for (i = 0; i < cNumberOfPackets; i++)
826 {
827 PNDIS_PACKET pPacket;
828
829 pPacket = pPacketArray[i];
830
831 if(!cNetFltRefs
832#ifdef VBOXNETFLT_NO_PACKET_QUEUE
833 || !vboxNetFltWinPostIntnet(pNetFlt, pPacket, PACKET_SRC_HOST)
834#else
835 || (fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_SRC_HOST)) != NDIS_STATUS_SUCCESS
836#endif
837 )
838 {
839#ifndef VBOXNETADP
840 fStatus = vboxNetFltWinSendPassThru(pAdapt, pPacket);
841#else
842 if(!cNetFltRefs)
843 {
844# ifdef VBOXNETADP_REPORT_DISCONNECTED
845 fStatus = NDIS_STATUS_MEDIA_DISCONNECT;
846 STATISTIC_INCREASE(pAdapt->cTxError);
847# else
848 fStatus = NDIS_STATUS_SUCCESS;
849# endif
850 }
851#endif
852
853 if (fStatus != NDIS_STATUS_PENDING)
854 {
855 NdisMSendComplete(pAdapt->hMiniportHandle,
856 pPacket,
857 fStatus);
858 }
859 else
860 {
861 cAdaptRefs--;
862 }
863 }
864 else
865 {
866#ifdef VBOXNETFLT_NO_PACKET_QUEUE
867 NdisMSendComplete(pAdapt->hMiniportHandle,
868 pPacket,
869 NDIS_STATUS_SUCCESS);
870#else
871 cAdaptRefs--;
872 cNetFltRefs--;
873#endif
874 }
875 }
876
877 if(cNetFltRefs)
878 {
879 vboxNetFltWinDecReferenceNetFlt(pNetFlt, cNetFltRefs);
880 }
881 else if(cPassThruRefs)
882 {
883 vboxNetFltWinDecReferenceModePassThru(pNetFlt, cPassThruRefs);
884 }
885 if(cAdaptRefs)
886 {
887 vboxNetFltWinDecReferenceAdapt(pAdapt, cAdaptRefs);
888 }
889 }
890 else
891 {
892 NDIS_HANDLE h = pAdapt->hMiniportHandle;
893 Assert(0);
894 if(h)
895 {
896 for (i = 0; i < cNumberOfPackets; i++)
897 {
898 PNDIS_PACKET pPacket;
899 pPacket = pPacketArray[i];
900 NdisMSendComplete(h,
901 pPacket,
902 NDIS_STATUS_FAILURE);
903 }
904 }
905 }
906}
907#ifndef VBOXNETADP
908/**
909 * Entry point called by NDIS to query for the value of the specified OID.
910 * Typical processing is to forward the query down to the underlying miniport.
911 *
912 * The following OIDs are filtered here:
913 * OID_PNP_QUERY_POWER - return success right here
914 * OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up
915 * multiple instances of private GUIDs supported by the underlying miniport.
916 * OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but
917 * the values returned are postprocessed before we complete this request;
918 * see vboxNetFltWinPtRequestComplete.
919 *
920 * NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents
921 * of data it passes through such that a lower miniport may not be able
922 * to perform TCP task offload, then it should not forward this OID down,
923 * but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to
924 * avoid performing incorrect transformations on data.
925 *
926 * If our miniport edge (upper edge) is at a low-power state, fail the request.
927 * If our protocol edge (lower edge) has been notified of a low-power state,
928 * we pend this request until the miniport below has been set to D0. Since
929 * requests to miniports are serialized always, at most a single request will
930 * be pended.
931 *
932 * @param MiniportAdapterContext Pointer to the adapter structure
933 * @param Oid Oid for this query
934 * @param InformationBuffer Buffer for information
935 * @param InformationBufferLength Size of this buffer
936 * @param BytesWritten Specifies how much info is written
937 * @param BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
938 * @return Return code from the NdisRequest below.
939 * */
940static NDIS_STATUS
941vboxNetFltWinMpQueryInformation(
942 IN NDIS_HANDLE MiniportAdapterContext,
943 IN NDIS_OID Oid,
944 IN PVOID InformationBuffer,
945 IN ULONG InformationBufferLength,
946 OUT PULONG BytesWritten,
947 OUT PULONG BytesNeeded
948 )
949{
950 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
951 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
952 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
953 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
954
955 do
956 {
957 if (Oid == OID_PNP_QUERY_POWER)
958 {
959 /*
960 * Do not forward this.
961 */
962 Status = NDIS_STATUS_SUCCESS;
963 break;
964 }
965
966 if (Oid == OID_GEN_SUPPORTED_GUIDS)
967 {
968 /*
969 * Do not forward this, otherwise we will end up with multiple
970 * instances of private GUIDs that the underlying miniport
971 * supports.
972 */
973 Status = NDIS_STATUS_NOT_SUPPORTED;
974 break;
975 }
976
977 if (Oid == OID_TCP_TASK_OFFLOAD)
978 {
979 /* we want to receive packets with checksums calculated
980 * since we are passing them to IntNet
981 */
982 Status = NDIS_STATUS_NOT_SUPPORTED;
983 break;
984 }
985
986 /*
987 * If the miniport below is unbinding, just fail any request
988 */
989 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized) /* protocol unbind in progress */
990 {
991 Status = NDIS_STATUS_FAILURE;
992 break;
993 }
994
995 /*
996 * All other queries are failed, if the miniport is not at D0,
997 */
998 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0)
999 {
1000 Status = NDIS_STATUS_FAILURE;
1001 break;
1002 }
1003
1004 pAdapt->Request.RequestType = NdisRequestQueryInformation;
1005 pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
1006 pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
1007 pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
1008 pAdapt->BytesNeeded = BytesNeeded;
1009 pAdapt->BytesReadOrWritten = BytesWritten;
1010
1011 /*
1012 * If the miniport below is binding, fail the request
1013 */
1014 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1015
1016 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1017 {
1018 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1019 Status = NDIS_STATUS_FAILURE;
1020 break;
1021 }
1022 /*
1023 * If the Protocol device state is OFF, mark this request as being
1024 * pended. We queue this until the device state is back to D0.
1025 */
1026 if ((vboxNetFltWinGetPowerState(&pAdapt->PTState) > NdisDeviceStateD0)
1027 && (pAdapt->bStandingBy == FALSE))
1028 {
1029 pAdapt->bQueuedRequest = TRUE;
1030 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1031 Status = NDIS_STATUS_PENDING;
1032 break;
1033 }
1034 /*
1035 * This is in the process of powering down the system, always fail the request
1036 */
1037 if (pAdapt->bStandingBy == TRUE)
1038 {
1039 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1040 Status = NDIS_STATUS_FAILURE;
1041 break;
1042 }
1043 pAdapt->bOutstandingRequests = TRUE;
1044
1045 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1046 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
1047 {
1048 bool fNetFltActive;
1049 const bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &fNetFltActive);
1050
1051 Assert(InformationBuffer);
1052 Assert(!pAdapt->fProcessingPacketFilter);
1053
1054 if(fNetFltActive)
1055 {
1056 /* netflt is active, simply return the cached value */
1057 *((PULONG)InformationBuffer) = pAdapt->fUpperProtocolSetFilter;
1058
1059 Status = NDIS_STATUS_SUCCESS;
1060 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1061 vboxNetFltWinDereferenceAdapt(pAdapt);
1062
1063 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1064 pAdapt->bOutstandingRequests = FALSE;
1065 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1066 break;
1067 }
1068 else if(fAdaptActive)
1069 {
1070 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU;
1071 /* we're cleaning it in RequestComplete */
1072 }
1073 }
1074
1075 /*
1076 * default case, most requests will be passed to the miniport below
1077 */
1078 NdisRequest(&Status,
1079 pAdapt->hBindingHandle,
1080 &pAdapt->Request);
1081
1082
1083 if (Status != NDIS_STATUS_PENDING)
1084 {
1085 vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, Status);
1086 Status = NDIS_STATUS_PENDING;
1087 }
1088
1089 } while (FALSE);
1090
1091 return(Status);
1092
1093}
1094/**
1095 * Postprocess a request for OID_PNP_CAPABILITIES that was forwarded
1096 * down to the underlying miniport, and has been completed by it.
1097 *
1098 * @param pAdapt - Pointer to the adapter structure
1099 * @param pStatus - Place to return final status
1100 * @return None. */
1101DECLHIDDEN(VOID)
1102vboxNetFltWinMpQueryPNPCapabilities(
1103 IN OUT PADAPT pAdapt,
1104 OUT PNDIS_STATUS pStatus
1105 )
1106{
1107 PNDIS_PNP_CAPABILITIES pPNPCapabilities;
1108 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
1109
1110 if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))
1111 {
1112 pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);
1113
1114 /*
1115 * The following fields must be overwritten by an IM driver.
1116 */
1117 pPMstruct= & pPNPCapabilities->WakeUpCapabilities;
1118 pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1119 pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
1120 pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
1121 *pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
1122 *pAdapt->BytesNeeded = 0;
1123
1124
1125 *pStatus = NDIS_STATUS_SUCCESS;
1126 }
1127 else
1128 {
1129 *pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);
1130 *pStatus = NDIS_STATUS_RESOURCES;
1131 }
1132}
1133
1134#endif /* ifndef VBOXNETADP*/
1135
1136/**
1137 * This routine does all the procssing for a request with a SetPower Oid
1138 * The miniport shoud accept the Set Power and transition to the new state
1139 *
1140 * The Set Power should not be passed to the miniport below
1141 *
1142 * If the IM miniport is going into a low power state, then there is no guarantee if it will ever
1143 * be asked go back to D0, before getting halted. No requests should be pended or queued.
1144 *
1145 * @param pNdisStatus - Status of the operation
1146 * @param pAdapt - The Adapter structure
1147 * @param InformationBuffer - The New DeviceState
1148 * @param InformationBufferLength
1149 * @param BytesRead - No of bytes read
1150 * @param BytesNeeded - No of bytes needed
1151 * @return Status - NDIS_STATUS_SUCCESS if all the wait events succeed. */
1152static VOID
1153vboxNetFltWinMpProcessSetPowerOid(
1154 IN OUT PNDIS_STATUS pNdisStatus,
1155 IN PADAPT pAdapt,
1156 IN PVOID InformationBuffer,
1157 IN ULONG InformationBufferLength,
1158 OUT PULONG BytesRead,
1159 OUT PULONG BytesNeeded
1160 )
1161{
1162
1163
1164 NDIS_DEVICE_POWER_STATE NewDeviceState;
1165
1166 LogFlow(("==>vboxNetFltWinMpProcessSetPowerOid: Adapt %p\n", pAdapt));
1167
1168 Assert (InformationBuffer != NULL);
1169
1170 *pNdisStatus = NDIS_STATUS_FAILURE;
1171
1172 do
1173 {
1174 /*
1175 * Check for invalid length
1176 */
1177 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
1178 {
1179 *pNdisStatus = NDIS_STATUS_INVALID_LENGTH;
1180 break;
1181 }
1182
1183 NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);
1184
1185 /*
1186 * Check for invalid device state
1187 */
1188 if ((vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0))
1189 {
1190 /*
1191 * If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0
1192 */
1193 Assert (!(vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0));
1194
1195 *pNdisStatus = NDIS_STATUS_FAILURE;
1196 break;
1197 }
1198
1199#ifndef VBOXNETADP
1200 /*
1201 * Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)
1202 * If so, then set the bStandingBy Flag - (Block all incoming requests)
1203 */
1204 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)
1205 {
1206 pAdapt->bStandingBy = TRUE;
1207 }
1208
1209 /*
1210 * If the miniport is transitioning from a low power state to ON (D0), then clear the bStandingBy flag
1211 * All incoming requests will be pended until the physical miniport turns ON.
1212 */
1213 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0 && NewDeviceState == NdisDeviceStateD0)
1214 {
1215 pAdapt->bStandingBy = FALSE;
1216 }
1217#endif
1218 /*
1219 * Now update the state in the pAdapt structure;
1220 */
1221 vboxNetFltWinSetPowerState(&pAdapt->MPState, NewDeviceState);
1222#ifndef VBOXNETADP
1223 if(NewDeviceState != NdisDeviceStateD0)
1224 {
1225 vboxNetFltWinPtFlushReceiveQueue(pAdapt,
1226 true ); /* just return */
1227 }
1228#endif
1229 *pNdisStatus = NDIS_STATUS_SUCCESS;
1230
1231
1232 } while (FALSE);
1233
1234 if (*pNdisStatus == NDIS_STATUS_SUCCESS)
1235 {
1236#ifndef VBOXNETADP
1237 /*
1238 * The miniport resume from low power state
1239 */
1240 if (pAdapt->bStandingBy == FALSE)
1241 {
1242 /*
1243 * If we need to indicate the media connect state
1244 */
1245 if (pAdapt->LastIndicatedStatus != pAdapt->LatestUnIndicateStatus)
1246 {
1247 NdisMIndicateStatus(pAdapt->hMiniportHandle,
1248 pAdapt->LatestUnIndicateStatus,
1249 (PVOID)NULL,
1250 0);
1251 NdisMIndicateStatusComplete(pAdapt->hMiniportHandle);
1252 pAdapt->LastIndicatedStatus = pAdapt->LatestUnIndicateStatus;
1253 }
1254 }
1255 else
1256 {
1257 /*
1258 * Initialize LatestUnIndicatedStatus
1259 */
1260 pAdapt->LatestUnIndicateStatus = pAdapt->LastIndicatedStatus;
1261 }
1262#endif
1263 *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
1264 *BytesNeeded = 0;
1265 }
1266 else
1267 {
1268 *BytesRead = 0;
1269 *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1270 }
1271
1272 LogFlow(("<==vboxNetFltWinMpProcessSetPowerOid: Adapt %p\n", pAdapt));
1273}
1274#ifndef VBOXNETADP
1275/**
1276 * Miniport SetInfo handler.
1277 *
1278 * In the case of OID_PNP_SET_POWER, record the power state and return the OID.
1279 * Do not pass below
1280 * If the device is suspended, do not block the SET_POWER_OID
1281 * as it is used to reactivate the NetFlt miniport
1282 *
1283 * PM- If the MP is not ON (DeviceState > D0) return immediately (except for 'query power' and 'set power')
1284 * If MP is ON, but the PT is not at D0, then queue the queue the request for later processing
1285 *
1286 * Requests to miniports are always serialized
1287 *
1288 * @param MiniportAdapterContext Pointer to the adapter structure
1289 * @param Oid Oid for this query
1290 * @param InformationBuffer Buffer for information
1291 * @param InformationBufferLength Size of this buffer
1292 * @param BytesRead Specifies how much info is read
1293 * @param BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
1294 * @return Return code from the NdisRequest below. */
1295static NDIS_STATUS
1296vboxNetFltWinMpSetInformation(
1297 IN NDIS_HANDLE MiniportAdapterContext,
1298 IN NDIS_OID Oid,
1299 IN PVOID InformationBuffer,
1300 IN ULONG InformationBufferLength,
1301 OUT PULONG BytesRead,
1302 OUT PULONG BytesNeeded
1303 )
1304{
1305 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
1306 NDIS_STATUS Status;
1307 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1308 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
1309
1310 Status = NDIS_STATUS_FAILURE;
1311
1312 do
1313 {
1314 /*
1315 * The Set Power should not be sent to the miniport below the NetFlt, but is handled internally
1316 */
1317 if (Oid == OID_PNP_SET_POWER)
1318 {
1319 vboxNetFltWinMpProcessSetPowerOid(&Status,
1320 pAdapt,
1321 InformationBuffer,
1322 InformationBufferLength,
1323 BytesRead,
1324 BytesNeeded);
1325 break;
1326
1327 }
1328
1329 /*
1330 * If the miniport below is unbinding, fail the request
1331 */
1332 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1333 {
1334 Status = NDIS_STATUS_FAILURE;
1335 break;
1336 }
1337
1338 /*
1339 * All other Set Information requests are failed, if the miniport is
1340 * not at D0 or is transitioning to a device state greater than D0.
1341 */
1342 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0)
1343 {
1344 Status = NDIS_STATUS_FAILURE;
1345 break;
1346 }
1347
1348 /* Set up the Request and return the result */
1349 pAdapt->Request.RequestType = NdisRequestSetInformation;
1350 pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;
1351 pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
1352 pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
1353 pAdapt->BytesNeeded = BytesNeeded;
1354 pAdapt->BytesReadOrWritten = BytesRead;
1355
1356 /*
1357 * If the miniport below is unbinding, fail the request
1358 */
1359 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1360 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1361 {
1362 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1363 Status = NDIS_STATUS_FAILURE;
1364 break;
1365 }
1366
1367 /*
1368 * If the device below is at a low power state, we cannot send it the
1369 * request now, and must pend it.
1370 */
1371 if ((vboxNetFltWinGetPowerState(&pAdapt->PTState) > NdisDeviceStateD0)
1372 && (pAdapt->bStandingBy == FALSE))
1373 {
1374 pAdapt->bQueuedRequest = TRUE;
1375 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1376 Status = NDIS_STATUS_PENDING;
1377 break;
1378 }
1379 /*
1380 * This is in the process of powering down the system, always fail the request
1381 */
1382 if (pAdapt->bStandingBy == TRUE)
1383 {
1384 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1385 Status = NDIS_STATUS_FAILURE;
1386 break;
1387 }
1388 pAdapt->bOutstandingRequests = TRUE;
1389
1390 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1391
1392 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
1393 {
1394 /* need to disable cleaning promiscuous here ?? */
1395 bool fNetFltActive;
1396 const bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &fNetFltActive);
1397
1398 Assert(InformationBuffer);
1399 Assert(!pAdapt->fProcessingPacketFilter);
1400
1401 if(fNetFltActive)
1402 {
1403 Assert(fAdaptActive);
1404
1405 /* netflt is active, update the cached value */
1406 /* TODO: in case we are are not in promiscuous now, we are issuing a request.
1407 * what should we do in case of a failure?
1408 * i.e. should we update the fUpperProtocolSetFilter in completion routine in this case? etc. */
1409 pAdapt->fUpperProtocolSetFilter = *((PULONG)InformationBuffer);
1410 pAdapt->bUpperProtSetFilterInitialized = true;
1411
1412 if(!(pAdapt->fOurSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS))
1413 {
1414 pAdapt->fSetFilterBuffer = NDIS_PACKET_TYPE_PROMISCUOUS;
1415 pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = &pAdapt->fSetFilterBuffer;
1416 pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(pAdapt->fSetFilterBuffer);
1417 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_NETFLT;
1418 /* we'll do dereferencing in request complete */
1419 }
1420 else
1421 {
1422 Status = NDIS_STATUS_SUCCESS;
1423 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1424 vboxNetFltWinDereferenceAdapt(pAdapt);
1425
1426 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1427 pAdapt->bOutstandingRequests = FALSE;
1428 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1429 break;
1430 }
1431 }
1432 else if(fAdaptActive)
1433 {
1434 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU;
1435 /* dereference on completion */
1436 }
1437 }
1438
1439 /*
1440 * Forward the request to the device below.
1441 */
1442 NdisRequest(&Status,
1443 pAdapt->hBindingHandle,
1444 &pAdapt->Request);
1445
1446 if (Status != NDIS_STATUS_PENDING)
1447 {
1448 vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, Status);
1449 }
1450
1451 } while (FALSE);
1452
1453 return(Status);
1454}
1455#else
1456static NDIS_OID g_vboxNetFltWinMpSupportedOids[] =
1457{
1458 OID_GEN_SUPPORTED_LIST,
1459 OID_GEN_HARDWARE_STATUS,
1460 OID_GEN_MEDIA_SUPPORTED,
1461 OID_GEN_MEDIA_IN_USE,
1462 OID_GEN_MAXIMUM_LOOKAHEAD,
1463 OID_GEN_MAXIMUM_FRAME_SIZE,
1464 OID_GEN_LINK_SPEED,
1465 OID_GEN_TRANSMIT_BUFFER_SPACE,
1466 OID_GEN_RECEIVE_BUFFER_SPACE,
1467 OID_GEN_TRANSMIT_BLOCK_SIZE,
1468 OID_GEN_RECEIVE_BLOCK_SIZE,
1469 OID_GEN_VENDOR_ID,
1470 OID_GEN_VENDOR_DESCRIPTION,
1471 OID_GEN_VENDOR_DRIVER_VERSION,
1472 OID_GEN_CURRENT_PACKET_FILTER,
1473 OID_GEN_CURRENT_LOOKAHEAD,
1474 OID_GEN_DRIVER_VERSION,
1475 OID_GEN_MAXIMUM_TOTAL_SIZE,
1476 OID_GEN_PROTOCOL_OPTIONS,
1477 OID_GEN_MAC_OPTIONS,
1478 OID_GEN_MEDIA_CONNECT_STATUS,
1479 OID_GEN_MAXIMUM_SEND_PACKETS,
1480 OID_GEN_XMIT_OK,
1481 OID_GEN_RCV_OK,
1482 OID_GEN_XMIT_ERROR,
1483 OID_GEN_RCV_ERROR,
1484 OID_GEN_RCV_NO_BUFFER,
1485 OID_GEN_RCV_CRC_ERROR,
1486 OID_GEN_TRANSMIT_QUEUE_LENGTH,
1487 OID_802_3_PERMANENT_ADDRESS,
1488 OID_802_3_CURRENT_ADDRESS,
1489 OID_802_3_MULTICAST_LIST,
1490 OID_802_3_MAC_OPTIONS,
1491 OID_802_3_MAXIMUM_LIST_SIZE,
1492 OID_802_3_RCV_ERROR_ALIGNMENT,
1493 OID_802_3_XMIT_ONE_COLLISION,
1494 OID_802_3_XMIT_MORE_COLLISIONS,
1495 OID_802_3_XMIT_DEFERRED,
1496 OID_802_3_XMIT_MAX_COLLISIONS,
1497 OID_802_3_RCV_OVERRUN,
1498 OID_802_3_XMIT_UNDERRUN,
1499 OID_802_3_XMIT_HEARTBEAT_FAILURE,
1500 OID_802_3_XMIT_TIMES_CRS_LOST,
1501 OID_802_3_XMIT_LATE_COLLISIONS
1502#ifndef INTERFACE_WITH_NDISPROT
1503 ,
1504 OID_PNP_CAPABILITIES,
1505 OID_PNP_SET_POWER,
1506 OID_PNP_QUERY_POWER
1507# if 0
1508 ,
1509 OID_PNP_ADD_WAKE_UP_PATTERN,
1510 OID_PNP_REMOVE_WAKE_UP_PATTERN,
1511 OID_PNP_ENABLE_WAKE_UP
1512# endif
1513#endif
1514};
1515
1516static NDIS_STATUS
1517vboxNetFltWinMpQueryInformation(
1518 IN NDIS_HANDLE MiniportAdapterContext,
1519 IN NDIS_OID Oid,
1520 IN PVOID InformationBuffer,
1521 IN ULONG InformationBufferLength,
1522 OUT PULONG BytesWritten,
1523 OUT PULONG BytesNeeded)
1524/*++
1525
1526Routine Description:
1527
1528 Entry point called by NDIS to query for the value of the specified OID.
1529 MiniportQueryInformation runs at IRQL = DISPATCH_LEVEL.
1530
1531Arguments:
1532
1533 MiniportAdapterContext Pointer to the adapter structure
1534 Oid Oid for this query
1535 InformationBuffer Buffer for information
1536 InformationBufferLength Size of this buffer
1537 BytesWritten Specifies how much info is written
1538 BytesNeeded In case the buffer is smaller than
1539 what we need, tell them how much is needed
1540
1541
1542Return Value:
1543
1544 Return code from the NdisRequest below.
1545
1546Notes: Read "Minimizing Miniport Driver Initialization Time" in the DDK
1547 for more info on how to handle certain OIDs that affect the init of
1548 a miniport.
1549
1550--*/
1551{
1552 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1553 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
1554 NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
1555 NDIS_MEDIUM Medium = NdisMedium802_3;
1556 UCHAR VendorDesc[] = VBOXNETADP_VENDOR_DESC;
1557 ULONG ulInfo = 0;
1558 USHORT usInfo = 0;
1559 ULONG64 ulInfo64 = 0;
1560 PVOID pInfo = (PVOID) &ulInfo;
1561 ULONG ulInfoLen = sizeof(ulInfo);
1562 NDIS_PNP_CAPABILITIES PMCaps;
1563
1564 LogFlow(("==> vboxNetFltWinMpQueryInformation %s\n", vboxNetFltWinMpDbgGetOidName(Oid)));
1565
1566 // Initialize the result
1567 *BytesWritten = 0;
1568 *BytesNeeded = 0;
1569
1570 switch(Oid)
1571 {
1572 case OID_GEN_SUPPORTED_LIST:
1573 //
1574 // The OID_GEN_SUPPORTED_LIST OID specifies an array of OIDs
1575 // for objects that the underlying driver or its NIC supports.
1576 // Objects include general, media-specific, and implementation-
1577 // specific objects. NDIS forwards a subset of the returned
1578 // list to protocols that make this query. That is, NDIS filters
1579 // any supported statistics OIDs out of the list because
1580 // protocols never make statistics queries.
1581 //
1582 pInfo = (PVOID) g_vboxNetFltWinMpSupportedOids;
1583 ulInfoLen = sizeof(g_vboxNetFltWinMpSupportedOids);
1584 break;
1585
1586 case OID_GEN_HARDWARE_STATUS:
1587 //
1588 // Specify the current hardware status of the underlying NIC as
1589 // one of the following NDIS_HARDWARE_STATUS-type values.
1590 //
1591 pInfo = (PVOID) &HardwareStatus;
1592 ulInfoLen = sizeof(NDIS_HARDWARE_STATUS);
1593 break;
1594
1595 case OID_GEN_MEDIA_SUPPORTED:
1596 //
1597 // Specify the media types that the NIC can support but not
1598 // necessarily the media types that the NIC currently uses.
1599 // fallthrough:
1600 case OID_GEN_MEDIA_IN_USE:
1601 //
1602 // Specifiy a complete list of the media types that the NIC
1603 // currently uses.
1604 //
1605 pInfo = (PVOID) &Medium;
1606 ulInfoLen = sizeof(NDIS_MEDIUM);
1607 break;
1608
1609 case OID_GEN_CURRENT_LOOKAHEAD:
1610 case OID_GEN_MAXIMUM_LOOKAHEAD:
1611 //
1612 // If the miniport driver indicates received data by calling
1613 // NdisXxxIndicateReceive, it should respond to OID_GEN_MAXIMUM_LOOKAHEAD
1614 // with the maximum number of bytes the NIC can provide as
1615 // lookahead data. If that value is different from the size of the
1616 // lookahead buffer supported by bound protocols, NDIS will call
1617 // MiniportSetInformation to set the size of the lookahead buffer
1618 // provided by the miniport driver to the minimum of the miniport
1619 // driver and protocol(s) values. If the driver always indicates
1620 // up full packets with NdisMIndicateReceivePacket, it should
1621 // set this value to the maximum total packet size, which
1622 // excludes the header.
1623 // Upper-layer drivers examine lookahead data to determine whether
1624 // a packet that is associated with the lookahead data is intended
1625 // for one or more of their clients. If the underlying driver
1626 // supports multipacket receive indications, bound protocols are
1627 // given full net packets on every indication. Consequently,
1628 // this value is identical to that returned for
1629 // OID_GEN_RECEIVE_BLOCK_SIZE.
1630 //
1631 ulInfo = VBOXNETADP_MAX_LOOKAHEAD_SIZE;
1632 break;
1633
1634 case OID_GEN_MAXIMUM_FRAME_SIZE:
1635 //
1636 // Specifiy the maximum network packet size, in bytes, that the
1637 // NIC supports excluding the header. A NIC driver that emulates
1638 // another medium type for binding to a transport must ensure that
1639 // the maximum frame size for a protocol-supplied net packet does
1640 // not exceed the size limitations for the true network medium.
1641 //
1642 ulInfo = VBOXNETADP_MAX_PACKET_SIZE - VBOXNETADP_HEADER_SIZE;
1643 break;
1644
1645 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1646 //
1647 // Specify the maximum total packet length, in bytes, the NIC
1648 // supports including the header. A protocol driver might use
1649 // this returned length as a gauge to determine the maximum
1650 // size packet that a NIC driver could forward to the
1651 // protocol driver. The miniport driver must never indicate
1652 // up to the bound protocol driver packets received over the
1653 // network that are longer than the packet size specified by
1654 // OID_GEN_MAXIMUM_TOTAL_SIZE.
1655 //
1656 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1657 //
1658 // The OID_GEN_TRANSMIT_BLOCK_SIZE OID specifies the minimum
1659 // number of bytes that a single net packet occupies in the
1660 // transmit buffer space of the NIC. For example, a NIC that
1661 // has a transmit space divided into 256-byte pieces would have
1662 // a transmit block size of 256 bytes. To calculate the total
1663 // transmit buffer space on such a NIC, its driver multiplies
1664 // the number of transmit buffers on the NIC by its transmit
1665 // block size. In our case, the transmit block size is
1666 // identical to its maximum packet size.
1667
1668 case OID_GEN_RECEIVE_BLOCK_SIZE:
1669 //
1670 // The OID_GEN_RECEIVE_BLOCK_SIZE OID specifies the amount of
1671 // storage, in bytes, that a single packet occupies in the receive
1672 // buffer space of the NIC.
1673 //
1674 ulInfo = (ULONG) VBOXNETADP_MAX_PACKET_SIZE;
1675 break;
1676
1677 case OID_GEN_MAC_OPTIONS:
1678 //
1679 // Specify a bitmask that defines optional properties of the NIC.
1680 // This miniport indicates receive with NdisMIndicateReceivePacket
1681 // function. It has no MiniportTransferData function. Such a driver
1682 // should set this NDIS_MAC_OPTION_TRANSFERS_NOT_PEND flag.
1683 //
1684 // NDIS_MAC_OPTION_NO_LOOPBACK tells NDIS that NIC has no internal
1685 // loopback support so NDIS will manage loopbacks on behalf of
1686 // this driver.
1687 //
1688 // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA tells the protocol that
1689 // our receive buffer is not on a device-specific card. If
1690 // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA is not set, multi-buffer
1691 // indications are copied to a single flat buffer.
1692 //
1693 ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
1694 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
1695 NDIS_MAC_OPTION_NO_LOOPBACK;
1696 break;
1697
1698 case OID_GEN_LINK_SPEED:
1699 //
1700 // Specify the maximum speed of the NIC in kbps.
1701 // The unit of measurement is 100 bps
1702 //
1703 ulInfo = VBOXNETADP_LINK_SPEED;
1704 break;
1705
1706 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1707 //
1708 // Specify the amount of memory, in bytes, on the NIC that
1709 // is available for buffering transmit data. A protocol can
1710 // use this OID as a guide for sizing the amount of transmit
1711 // data per send.
1712 //
1713 ulInfo = VBOXNETADP_MAX_PACKET_SIZE * PACKET_INFO_POOL_SIZE;
1714 break;
1715
1716 case OID_GEN_RECEIVE_BUFFER_SPACE:
1717 //
1718 // Specify the amount of memory on the NIC that is available
1719 // for buffering receive data. A protocol driver can use this
1720 // OID as a guide for advertising its receive window after it
1721 // establishes sessions with remote nodes.
1722 //
1723
1724 ulInfo = VBOXNETADP_MAX_PACKET_SIZE * PACKET_INFO_POOL_SIZE;
1725 break;
1726
1727 case OID_GEN_VENDOR_ID:
1728 //
1729 // Specify a three-byte IEEE-registered vendor code, followed
1730 // by a single byte that the vendor assigns to identify a
1731 // particular NIC. The IEEE code uniquely identifies the vendor
1732 // and is the same as the three bytes appearing at the beginning
1733 // of the NIC hardware address. Vendors without an IEEE-registered
1734 // code should use the value 0xFFFFFF.
1735 //
1736 ulInfo = VBOXNETADP_VENDOR_ID;
1737 break;
1738
1739 case OID_GEN_VENDOR_DESCRIPTION:
1740 //
1741 // Specify a zero-terminated string describing the NIC vendor.
1742 //
1743 pInfo = VendorDesc;
1744 ulInfoLen = sizeof(VendorDesc);
1745 break;
1746
1747 case OID_GEN_VENDOR_DRIVER_VERSION:
1748 //
1749 // Specify the vendor-assigned version number of the NIC driver.
1750 // The low-order half of the return value specifies the minor
1751 // version; the high-order half specifies the major version.
1752 //
1753 ulInfo = VBOXNETADP_VENDOR_DRIVER_VERSION;
1754 break;
1755
1756 case OID_GEN_DRIVER_VERSION:
1757 //
1758 // Specify the NDIS version in use by the NIC driver. The high
1759 // byte is the major version number; the low byte is the minor
1760 // version number.
1761 //
1762 usInfo = (USHORT) (VBOXNETFLT_MAJOR_NDIS_VERSION<<8) + VBOXNETFLT_MINOR_NDIS_VERSION;
1763 pInfo = (PVOID) &usInfo;
1764 ulInfoLen = sizeof(USHORT);
1765 break;
1766
1767 case OID_GEN_MAXIMUM_SEND_PACKETS:
1768 //
1769 // If a miniport driver registers a MiniportSendPackets function,
1770 // MiniportQueryInformation will be called with the
1771 // OID_GEN_MAXIMUM_SEND_PACKETS request. The miniport driver must
1772 // respond with the maximum number of packets it is prepared to
1773 // handle on a single send request. The miniport driver should
1774 // pick a maximum that minimizes the number of packets that it
1775 // has to queue internally because it has no resources
1776 // (its device is full). A miniport driver for a bus-master DMA
1777 // NIC should attempt to pick a value that keeps its NIC filled
1778 // under anticipated loads.
1779 //
1780 ulInfo = PACKET_INFO_POOL_SIZE;
1781 break;
1782
1783 case OID_GEN_MEDIA_CONNECT_STATUS:
1784 //
1785 // Return the connection status of the NIC on the network as one
1786 // of the following system-defined values: NdisMediaStateConnected
1787 // or NdisMediaStateDisconnected.
1788 //
1789#ifdef VBOXNETADP_REPORT_DISCONNECTED
1790 {
1791 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1792 bool bNetFltActive;
1793 bool bActive = vboxNetFltWinReferenceAdaptNetFltFromAdapt(pNetFlt, pAdapt, bNetFltActive);
1794 if(bActive && bNetFltActive)
1795 {
1796 ulInfo = NdisMediaStateConnected;
1797 }
1798 else
1799 {
1800 ulInfo = NdisMediaStateDisconnected;
1801 }
1802
1803 if(bActive)
1804 {
1805 vboxNetFltWinDereferenceAdapt(pAdapt);
1806 }
1807 if(bNetFltActive)
1808 {
1809 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1810 }
1811 else
1812 {
1813 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1814 }
1815 }
1816#else
1817 ulInfo = NdisMediaStateConnected;
1818#endif
1819 break;
1820
1821 case OID_GEN_CURRENT_PACKET_FILTER:
1822 //
1823 // Specifiy the types of net packets such as directed, broadcast
1824 // multicast, for which a protocol receives indications from a
1825 // NIC driver. After NIC is initialized, a protocol driver
1826 // can send a set OID_GEN_CURRENT_PACKET_FILTER to a non-zero value,
1827 // thereby enabling the miniport driver to indicate receive packets
1828 // to that protocol.
1829 //
1830 ulInfo = (
1831 NDIS_PACKET_TYPE_BROADCAST
1832 | NDIS_PACKET_TYPE_DIRECTED
1833 | NDIS_PACKET_TYPE_ALL_FUNCTIONAL
1834 | NDIS_PACKET_TYPE_ALL_LOCAL
1835 | NDIS_PACKET_TYPE_GROUP
1836 | NDIS_PACKET_TYPE_MULTICAST
1837 );
1838 break;
1839
1840 case OID_PNP_CAPABILITIES:
1841 //
1842 // Return the wake-up capabilities of its NIC. If you return
1843 // NDIS_STATUS_NOT_SUPPORTED, NDIS considers the miniport driver
1844 // to be not Power management aware and doesn't send any power
1845 // or wake-up related queries such as
1846 // OID_PNP_SET_POWER, OID_PNP_QUERY_POWER,
1847 // OID_PNP_ADD_WAKE_UP_PATTERN, OID_PNP_REMOVE_WAKE_UP_PATTERN,
1848 // OID_PNP_ENABLE_WAKE_UP. Here, we are expecting the driver below
1849 // us to do the right thing.
1850 //
1851 RtlZeroMemory (&PMCaps, sizeof(NDIS_PNP_CAPABILITIES));
1852 ulInfoLen = sizeof (NDIS_PNP_CAPABILITIES);
1853 pInfo = (PVOID) &PMCaps;
1854 PMCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1855 PMCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
1856 break;
1857
1858 case OID_PNP_QUERY_POWER:
1859 Status = NDIS_STATUS_SUCCESS;
1860 break;
1861
1862 //
1863 // Following 4 OIDs are for querying Ethernet Operational
1864 // Characteristics.
1865 //
1866 case OID_802_3_PERMANENT_ADDRESS:
1867 //
1868 // Return the MAC address of the NIC burnt in the hardware.
1869 //
1870 {
1871 PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt));
1872 pInfo = &pNetFlt->u.s.MacAddr;
1873 ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH;
1874 }
1875 break;
1876
1877 case OID_802_3_CURRENT_ADDRESS:
1878 //
1879 // Return the MAC address the NIC is currently programmed to
1880 // use. Note that this address could be different from the
1881 // permananent address as the user can override using
1882 // registry. Read NdisReadNetworkAddress doc for more info.
1883 //
1884 {
1885 PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt));
1886 pInfo = &pNetFlt->u.s.MacAddr;
1887 ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH;
1888 }
1889 break;
1890
1891 case OID_802_3_MAXIMUM_LIST_SIZE:
1892 //
1893 // The maximum number of multicast addresses the NIC driver
1894 // can manage. This list is global for all protocols bound
1895 // to (or above) the NIC. Consequently, a protocol can receive
1896 // NDIS_STATUS_MULTICAST_FULL from the NIC driver when
1897 // attempting to set the multicast address list, even if
1898 // the number of elements in the given list is less than
1899 // the number originally returned for this query.
1900 //
1901 ulInfo = VBOXNETADP_MAX_MCAST_LIST;
1902 break;
1903
1904 case OID_802_3_MAC_OPTIONS:
1905 //
1906 // A protocol can use this OID to determine features supported
1907 // by the underlying driver such as NDIS_802_3_MAC_OPTION_PRIORITY.
1908 // Return zero indicating that it supports no options.
1909 //
1910 ulInfo = 0;
1911 break;
1912
1913 //
1914 // Following list consists of both general and Ethernet
1915 // specific statistical OIDs.
1916 //
1917
1918 case OID_GEN_XMIT_OK:
1919 ulInfo64 = pAdapt->cTxSuccess;
1920 pInfo = &ulInfo64;
1921 if (InformationBufferLength >= sizeof(ULONG64) ||
1922 InformationBufferLength == 0)
1923 {
1924 ulInfoLen = sizeof(ULONG64);
1925 }
1926 else
1927 {
1928 ulInfoLen = sizeof(ULONG);
1929 }
1930 // We should always report that 8 bytes are required to keep ndistest happy
1931 *BytesNeeded = sizeof(ULONG64);
1932 break;
1933
1934 case OID_GEN_RCV_OK:
1935 ulInfo64 = pAdapt->cRxSuccess;
1936 pInfo = &ulInfo64;
1937 if (InformationBufferLength >= sizeof(ULONG64) ||
1938 InformationBufferLength == 0)
1939 {
1940 ulInfoLen = sizeof(ULONG64);
1941 }
1942 else
1943 {
1944 ulInfoLen = sizeof(ULONG);
1945 }
1946 // We should always report that 8 bytes are required to keep ndistest happy
1947 *BytesNeeded = sizeof(ULONG64);
1948 break;
1949
1950 case OID_GEN_XMIT_ERROR:
1951
1952 ulInfo = pAdapt->cTxError;
1953 break;
1954
1955 case OID_GEN_RCV_ERROR:
1956 ulInfo = pAdapt->cRxError;
1957 break;
1958
1959 case OID_GEN_RCV_NO_BUFFER:
1960 ulInfo = 0;
1961 break;
1962
1963 case OID_GEN_RCV_CRC_ERROR:
1964 ulInfo = 0;
1965 break;
1966
1967 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
1968 ulInfo = PACKET_INFO_POOL_SIZE;
1969 break;
1970
1971 case OID_802_3_RCV_ERROR_ALIGNMENT:
1972 ulInfo = 0;
1973 break;
1974
1975 case OID_802_3_XMIT_ONE_COLLISION:
1976 ulInfo = 0;
1977 break;
1978
1979 case OID_802_3_XMIT_MORE_COLLISIONS:
1980 ulInfo = 0;
1981 break;
1982
1983 case OID_802_3_XMIT_DEFERRED:
1984 ulInfo = 0;
1985 break;
1986
1987 case OID_802_3_XMIT_MAX_COLLISIONS:
1988 ulInfo = 0;
1989 break;
1990
1991 case OID_802_3_RCV_OVERRUN:
1992 ulInfo = 0;
1993 break;
1994
1995 case OID_802_3_XMIT_UNDERRUN:
1996 ulInfo = 0;
1997 break;
1998
1999 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
2000 ulInfo = 0;
2001 break;
2002
2003 case OID_802_3_XMIT_TIMES_CRS_LOST:
2004 ulInfo = 0;
2005 break;
2006
2007 case OID_802_3_XMIT_LATE_COLLISIONS:
2008 ulInfo = 0;
2009 break;
2010
2011 default:
2012 Status = NDIS_STATUS_NOT_SUPPORTED;
2013 break;
2014 }
2015
2016 if(Status == NDIS_STATUS_SUCCESS)
2017 {
2018 if(ulInfoLen <= InformationBufferLength)
2019 {
2020 // Copy result into InformationBuffer
2021 *BytesWritten = ulInfoLen;
2022 if(ulInfoLen)
2023 {
2024 NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen);
2025 }
2026 }
2027 else
2028 {
2029 // too short
2030 *BytesNeeded = ulInfoLen;
2031 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2032 }
2033 }
2034
2035
2036 LogFlow(("<== vboxNetFltWinMpQueryInformation Status = 0x%08x\n",
2037 Status));
2038
2039 return(Status);
2040}
2041
2042NDIS_STATUS
2043vboxNetFltWinMpSetMulticastList(
2044 IN PADAPT pAdapt,
2045 IN PVOID InformationBuffer,
2046 IN ULONG InformationBufferLength,
2047 OUT PULONG pBytesRead,
2048 OUT PULONG pBytesNeeded
2049 )
2050/*++
2051Routine Description:
2052 This routine will set up the adapter for a specified multicast
2053 address list.
2054
2055Arguments:
2056 IN PMP_ADAPTER Adapter - Pointer to adapter block
2057 InformationBuffer - Buffer for information
2058 InformationBufferLength Size of this buffer
2059 pBytesRead Specifies how much info is read
2060 BytesNeeded In case the buffer is smaller than
2061
2062Return Value:
2063
2064 NDIS_STATUS
2065
2066--*/
2067{
2068 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
2069#if 0
2070 ULONG index;
2071#endif
2072
2073 LogFlow(("==> vboxNetFltWinMpSetMulticastList\n"));
2074
2075 //
2076 // Initialize.
2077 //
2078 *pBytesNeeded = 0;
2079 *pBytesRead = InformationBufferLength;
2080
2081 do
2082 {
2083 if (InformationBufferLength % VBOXNETADP_ETH_ADDRESS_LENGTH)
2084 {
2085 Status = NDIS_STATUS_INVALID_LENGTH;
2086 break;
2087 }
2088
2089 if (InformationBufferLength > (VBOXNETADP_MAX_MCAST_LIST * VBOXNETADP_ETH_ADDRESS_LENGTH))
2090 {
2091 Status = NDIS_STATUS_MULTICAST_FULL;
2092 *pBytesNeeded = VBOXNETADP_MAX_MCAST_LIST * VBOXNETADP_ETH_ADDRESS_LENGTH;
2093 break;
2094 }
2095#if 0
2096 //
2097 // Protect the list update with a lock if it can be updated by
2098 // another thread simultaneously.
2099 //
2100
2101 NdisZeroMemory(pAdapt->aMCList,
2102 sizeof(pAdapt->aMCList));
2103
2104 NdisMoveMemory(pAdapt->aMCList,
2105 InformationBuffer,
2106 InformationBufferLength);
2107
2108 pAdapt->cMCList = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
2109#endif
2110
2111 }
2112 while (FALSE);
2113
2114 //
2115 // Program the hardware to add suport for these muticast addresses
2116 //
2117
2118 LogFlow(("<== vboxNetFltWinMpSetMulticastList\n"));
2119
2120 return(Status);
2121
2122}
2123
2124
2125static NDIS_STATUS
2126vboxNetFltWinMpSetInformation(
2127 IN NDIS_HANDLE MiniportAdapterContext,
2128 IN NDIS_OID Oid,
2129 IN PVOID InformationBuffer,
2130 IN ULONG InformationBufferLength,
2131 OUT PULONG BytesRead,
2132 OUT PULONG BytesNeeded)
2133/*++
2134
2135Routine Description:
2136
2137 This is the handler for an OID set operation.
2138 MiniportSetInformation runs at IRQL = DISPATCH_LEVEL.
2139
2140Arguments:
2141
2142 MiniportAdapterContext Pointer to the adapter structure
2143 Oid Oid for this query
2144 InformationBuffer Buffer for information
2145 InformationBufferLength Size of this buffer
2146 BytesRead Specifies how much info is read
2147 BytesNeeded In case the buffer is smaller than what
2148 we need, tell them how much is needed
2149
2150Return Value:
2151
2152 Return code from the NdisRequest below.
2153
2154--*/
2155{
2156 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
2157 PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
2158 PNDIS_PM_PACKET_PATTERN pPmPattern = NULL;
2159
2160 LogFlow(("==> vboxNetFltWinMpSetInformation %s\n", vboxNetFltWinMpDbgGetOidName(Oid)));
2161
2162 *BytesRead = 0;
2163 *BytesNeeded = 0;
2164
2165 switch(Oid)
2166 {
2167 case OID_802_3_MULTICAST_LIST:
2168 //
2169 // Set the multicast address list on the NIC for packet reception.
2170 // The NIC driver can set a limit on the number of multicast
2171 // addresses bound protocol drivers can enable simultaneously.
2172 // NDIS returns NDIS_STATUS_MULTICAST_FULL if a protocol driver
2173 // exceeds this limit or if it specifies an invalid multicast
2174 // address.
2175 //
2176 Status = vboxNetFltWinMpSetMulticastList(
2177 pAdapt,
2178 InformationBuffer,
2179 InformationBufferLength,
2180 BytesRead,
2181 BytesNeeded);
2182 break;
2183
2184 case OID_GEN_CURRENT_PACKET_FILTER:
2185 //
2186 // Program the hardware to indicate the packets
2187 // of certain filter types.
2188 //
2189 if(InformationBufferLength != sizeof(ULONG))
2190 {
2191 *BytesNeeded = sizeof(ULONG);
2192 Status = NDIS_STATUS_INVALID_LENGTH;
2193 break;
2194 }
2195
2196 *BytesRead = InformationBufferLength;
2197
2198 break;
2199
2200 case OID_GEN_CURRENT_LOOKAHEAD:
2201 //
2202 // A protocol driver can set a suggested value for the number
2203 // of bytes to be used in its binding; however, the underlying
2204 // NIC driver is never required to limit its indications to
2205 // the value set.
2206 //
2207 if(InformationBufferLength != sizeof(ULONG)){
2208 *BytesNeeded = sizeof(ULONG);
2209 Status = NDIS_STATUS_INVALID_LENGTH;
2210 break;
2211 }
2212
2213 break;
2214
2215 case OID_PNP_SET_POWER:
2216 //
2217 // This OID notifies a miniport driver that its NIC will be
2218 // transitioning to the device power state specified in the
2219 // InformationBuffer. The miniport driver must always return
2220 // NDIS_STATUS_SUCCESS to an OID_PNP_SET_POWER request. An
2221 // OID_PNP_SET_POWER request may or may not be preceded by an
2222 // OID_PNP_QUERY_POWER request.
2223 //
2224 if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
2225 {
2226 Status = NDIS_STATUS_INVALID_LENGTH;
2227 break;
2228 }
2229
2230 vboxNetFltWinMpProcessSetPowerOid(&Status, pAdapt, InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded);
2231 break;
2232/*
2233 case OID_PNP_ADD_WAKE_UP_PATTERN:
2234 //
2235 // This OID is sent by a protocol driver to a miniport driver to
2236 // specify a wake-up pattern. The wake-up pattern, along with its mask,
2237 // is described by an NDIS_PM_PACKET_PATTERN structure.
2238 //
2239 pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
2240 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
2241 {
2242 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2243
2244 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
2245 break;
2246 }
2247 if (InformationBufferLength < pPmPattern->PatternOffset + pPmPattern->PatternSize)
2248 {
2249 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2250
2251 *BytesNeeded = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2252 break;
2253 }
2254 *BytesRead = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2255 Status = NDIS_STATUS_SUCCESS;
2256 bForwardRequest = TRUE;
2257 break;
2258
2259 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
2260 //
2261 // This OID requests the miniport driver to delete a wake-up pattern
2262 // that it previously received in an OID_PNP_ADD_WAKE_UP_PATTERN request.
2263 // The wake-up pattern, along with its mask, is described by an
2264 // NDIS_PM_PACKET_PATTERN structure.
2265 //
2266 pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
2267 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
2268 {
2269 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2270
2271 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
2272 break;
2273 }
2274 if (InformationBufferLength < pPmPattern->PatternOffset + pPmPattern->PatternSize)
2275 {
2276 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2277
2278 *BytesNeeded = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2279 break;
2280 }
2281 *BytesRead = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2282 Status = NDIS_STATUS_SUCCESS;
2283 bForwardRequest = TRUE;
2284
2285 break;
2286
2287 case OID_PNP_ENABLE_WAKE_UP:
2288 //
2289 // This OID specifies which wake-up capabilities a miniport
2290 // driver should enable in its NIC. Before the miniport
2291 // transitions to a low-power state (that is, before NDIS
2292 // sends the miniport driver an OID_PNP_SET_POWER request),
2293 // NDIS sends the miniport an OID_PNP_ENABLE_WAKE_UP request to
2294 // enable the appropriate wake-up capabilities.
2295 //
2296 DEBUGP(MP_INFO, ("--> OID_PNP_ENABLE_WAKE_UP\n"));
2297 if(InformationBufferLength != sizeof(ULONG))
2298 {
2299 *BytesNeeded = sizeof(ULONG);
2300 Status = NDIS_STATUS_INVALID_LENGTH;
2301 break;
2302 }
2303 *BytesRead = sizeof(ULONG);
2304 Status = NDIS_STATUS_SUCCESS;
2305 bForwardRequest = TRUE;
2306 break;
2307*/
2308 default:
2309 Status = NDIS_STATUS_INVALID_OID;
2310 break;
2311
2312 }
2313
2314
2315 LogFlow(("<== vboxNetFltWinMpSetInformation Status = 0x%08x\n", Status));
2316
2317 return(Status);
2318}
2319
2320static PUCHAR vboxNetFltWinMpDbgGetOidName(ULONG oid)
2321{
2322 PCHAR oidName;
2323
2324 switch (oid){
2325
2326 #undef MAKECASE
2327 #define MAKECASE(oidx) case oidx: oidName = #oidx; break;
2328
2329 MAKECASE(OID_GEN_SUPPORTED_LIST)
2330 MAKECASE(OID_GEN_HARDWARE_STATUS)
2331 MAKECASE(OID_GEN_MEDIA_SUPPORTED)
2332 MAKECASE(OID_GEN_MEDIA_IN_USE)
2333 MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD)
2334 MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE)
2335 MAKECASE(OID_GEN_LINK_SPEED)
2336 MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE)
2337 MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE)
2338 MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE)
2339 MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE)
2340 MAKECASE(OID_GEN_VENDOR_ID)
2341 MAKECASE(OID_GEN_VENDOR_DESCRIPTION)
2342 MAKECASE(OID_GEN_CURRENT_PACKET_FILTER)
2343 MAKECASE(OID_GEN_CURRENT_LOOKAHEAD)
2344 MAKECASE(OID_GEN_DRIVER_VERSION)
2345 MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE)
2346 MAKECASE(OID_GEN_PROTOCOL_OPTIONS)
2347 MAKECASE(OID_GEN_MAC_OPTIONS)
2348 MAKECASE(OID_GEN_MEDIA_CONNECT_STATUS)
2349 MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS)
2350 MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION)
2351 MAKECASE(OID_GEN_SUPPORTED_GUIDS)
2352 MAKECASE(OID_GEN_NETWORK_LAYER_ADDRESSES)
2353 MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET)
2354 MAKECASE(OID_GEN_MEDIA_CAPABILITIES)
2355 MAKECASE(OID_GEN_PHYSICAL_MEDIUM)
2356 MAKECASE(OID_GEN_XMIT_OK)
2357 MAKECASE(OID_GEN_RCV_OK)
2358 MAKECASE(OID_GEN_XMIT_ERROR)
2359 MAKECASE(OID_GEN_RCV_ERROR)
2360 MAKECASE(OID_GEN_RCV_NO_BUFFER)
2361 MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT)
2362 MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT)
2363 MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT)
2364 MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT)
2365 MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT)
2366 MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT)
2367 MAKECASE(OID_GEN_DIRECTED_BYTES_RCV)
2368 MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV)
2369 MAKECASE(OID_GEN_MULTICAST_BYTES_RCV)
2370 MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV)
2371 MAKECASE(OID_GEN_BROADCAST_BYTES_RCV)
2372 MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV)
2373 MAKECASE(OID_GEN_RCV_CRC_ERROR)
2374 MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH)
2375 MAKECASE(OID_GEN_GET_TIME_CAPS)
2376 MAKECASE(OID_GEN_GET_NETCARD_TIME)
2377 MAKECASE(OID_GEN_NETCARD_LOAD)
2378 MAKECASE(OID_GEN_DEVICE_PROFILE)
2379 MAKECASE(OID_GEN_INIT_TIME_MS)
2380 MAKECASE(OID_GEN_RESET_COUNTS)
2381 MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS)
2382 MAKECASE(OID_PNP_CAPABILITIES)
2383 MAKECASE(OID_PNP_SET_POWER)
2384 MAKECASE(OID_PNP_QUERY_POWER)
2385 MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN)
2386 MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN)
2387 MAKECASE(OID_PNP_ENABLE_WAKE_UP)
2388 MAKECASE(OID_802_3_PERMANENT_ADDRESS)
2389 MAKECASE(OID_802_3_CURRENT_ADDRESS)
2390 MAKECASE(OID_802_3_MULTICAST_LIST)
2391 MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE)
2392 MAKECASE(OID_802_3_MAC_OPTIONS)
2393 MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT)
2394 MAKECASE(OID_802_3_XMIT_ONE_COLLISION)
2395 MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS)
2396 MAKECASE(OID_802_3_XMIT_DEFERRED)
2397 MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS)
2398 MAKECASE(OID_802_3_RCV_OVERRUN)
2399 MAKECASE(OID_802_3_XMIT_UNDERRUN)
2400 MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE)
2401 MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST)
2402 MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS)
2403
2404 default:
2405 oidName = "<** UNKNOWN OID **>";
2406 break;
2407 }
2408
2409 return oidName;
2410}
2411#endif
2412
2413/**
2414 * NDIS Miniport entry point called whenever protocols are done with
2415 * a packet that we had indicated up and they had queued up for returning
2416 * later.
2417 *
2418 * @param MiniportAdapterContext - pointer to ADAPT structure
2419 * @param Packet - packet being returned.
2420 * @return None. */
2421DECLHIDDEN(VOID)
2422vboxNetFltWinMpReturnPacket(
2423 IN NDIS_HANDLE MiniportAdapterContext,
2424 IN PNDIS_PACKET Packet
2425 )
2426{
2427 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2428
2429 {
2430 /*
2431 * This is a packet allocated from this IM's receive packet pool.
2432 * Reclaim our packet, and return the original to the driver below.
2433 */
2434
2435 PNDIS_PACKET MyPacket;
2436 PRECV_RSVD RecvRsvd;
2437
2438 RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved);
2439 MyPacket = RecvRsvd->pOriginalPkt;
2440
2441 if(MyPacket)
2442 {
2443 /* the packet was sent from underlying miniport */
2444 NdisFreePacket(Packet);
2445 NdisReturnPackets(&MyPacket, 1);
2446 }
2447 else
2448 {
2449 PVOID pBufToFree = RecvRsvd->pBufToFree;
2450
2451 /* the packet was sent from NetFlt */
2452 vboxNetFltWinFreeSGNdisPacket(Packet, !pBufToFree);
2453 if(pBufToFree)
2454 {
2455 vboxNetFltWinMemFree(pBufToFree);
2456 }
2457 }
2458
2459 vboxNetFltWinDereferenceAdapt(pAdapt);
2460 }
2461}
2462
2463/** Miniport's transfer data handler.
2464 *
2465 * @param Packet Destination packet
2466 * @param BytesTransferred Place-holder for how much data was copied
2467 * @param MiniportAdapterContext Pointer to the adapter structure
2468 * @param MiniportReceiveContext Context
2469 * @param ByteOffset Offset into the packet for copying data
2470 * @param BytesToTransfer How much to copy.
2471 * @return Status of transfer */
2472static NDIS_STATUS
2473vboxNetFltWinMpTransferData(
2474 OUT PNDIS_PACKET Packet,
2475 OUT PUINT BytesTransferred,
2476 IN NDIS_HANDLE MiniportAdapterContext,
2477 IN NDIS_HANDLE MiniportReceiveContext,
2478 IN UINT ByteOffset,
2479 IN UINT BytesToTransfer
2480 )
2481{
2482#ifndef VBOXNETADP
2483
2484 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2485 NDIS_STATUS Status;
2486
2487 /*
2488 * Return, if the device is OFF
2489 */
2490 if (vboxNetFltWinGetPowerState(&pAdapt->PTState) != NdisDeviceStateD0
2491 || vboxNetFltWinGetPowerState(&pAdapt->MPState) != NdisDeviceStateD0)
2492 {
2493 return NDIS_STATUS_FAILURE;
2494 }
2495
2496 NdisTransferData(&Status,
2497 pAdapt->hBindingHandle,
2498 MiniportReceiveContext,
2499 ByteOffset,
2500 BytesToTransfer,
2501 Packet,
2502 BytesTransferred);
2503
2504 return(Status);
2505#else
2506 /* should never be here */
2507 Assert(0);
2508 return NDIS_STATUS_FAILURE;
2509#endif
2510}
2511
2512/**
2513 * Halt handler. All the hard-work for clean-up is done here.
2514 *
2515 * @param MiniportAdapterContext Pointer to the Adapter
2516 * @return None. */
2517static VOID
2518vboxNetFltWinMpHalt(
2519 IN NDIS_HANDLE MiniportAdapterContext
2520 )
2521{
2522 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2523#ifndef VBOXNETADP
2524 NDIS_STATUS Status;
2525#endif
2526
2527 LogFlow(("==>MiniportHalt: Adapt %p\n", pAdapt));
2528
2529#ifndef VBOXNETADP
2530// Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing);
2531// if(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing)
2532 if(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Disconnecting)
2533 {
2534 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitializing);
2535 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
2536 /* we're called from protocolUnbinAdapter, do our job */
2537 /*
2538 * If we have a valid bind, close the miniport below the protocol
2539 */
2540 vboxNetFltWinPtCloseAdapter(pAdapt, &Status);
2541
2542 Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing);
2543 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
2544 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2545 }
2546 else
2547#endif
2548 {
2549 /* we're NOT called from protocolUnbinAdapter, perform a full disconnect */
2550 NDIS_STATUS Status;
2551
2552 Assert(/*vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing
2553 ||*/ vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
2554#ifndef VBOXNETADP
2555 AssertBreakpoint();
2556#endif
2557 Status = vboxNetFltWinDetachFromInterface(pAdapt, false);
2558 Assert(Status == NDIS_STATUS_SUCCESS);
2559/* you can not access the pAdapt after closure
2560 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2561 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2562#ifndef VBOXNETADP
2563 Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitialized);
2564 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
2565#endif
2566*/
2567 }
2568
2569 LogFlow(("<== MiniportHalt: pAdapt %p\n", pAdapt));
2570}
2571
2572/**
2573 * register the miniport edge
2574 */
2575DECLHIDDEN(NDIS_STATUS)
2576vboxNetFltWinMpRegister(
2577 IN PDRIVER_OBJECT DriverObject,
2578 IN PUNICODE_STRING RegistryPath
2579 )
2580{
2581 NDIS_MINIPORT_CHARACTERISTICS MChars;
2582 NDIS_STATUS Status;
2583
2584 NdisMInitializeWrapper(&g_hNdisWrapperHandle, DriverObject, RegistryPath, NULL);
2585
2586 /*
2587 * Register the miniport with NDIS. Note that it is the miniport
2588 * which was started as a driver and not the protocol. Also the miniport
2589 * must be registered prior to the protocol since the protocol's BindAdapter
2590 * handler can be initiated anytime and when it is, it must be ready to
2591 * start driver instances.
2592 */
2593
2594 NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
2595
2596 MChars.MajorNdisVersion = VBOXNETFLT_MAJOR_NDIS_VERSION;
2597 MChars.MinorNdisVersion = VBOXNETFLT_MINOR_NDIS_VERSION;
2598
2599 MChars.InitializeHandler = vboxNetFltWinMpInitialize;
2600 MChars.QueryInformationHandler = vboxNetFltWinMpQueryInformation;
2601 MChars.SetInformationHandler = vboxNetFltWinMpSetInformation;
2602 MChars.ResetHandler = NULL;
2603 MChars.TransferDataHandler = vboxNetFltWinMpTransferData;
2604 MChars.HaltHandler = vboxNetFltWinMpHalt;
2605
2606 /*
2607 * We will disable the check for hang timeout so we do not
2608 * need a check for hang handler!
2609 */
2610 MChars.CheckForHangHandler = NULL;
2611 MChars.ReturnPacketHandler = vboxNetFltWinMpReturnPacket;
2612
2613 /*
2614 * Either the Send or the SendPackets handler should be specified.
2615 * If SendPackets handler is specified, SendHandler is ignored
2616 */
2617 MChars.SendHandler = NULL; /* vboxNetFltWinMpSend; */
2618 MChars.SendPacketsHandler = vboxNetFltWinMpSendPackets;
2619
2620#ifndef VBOXNETADP
2621 Status = NdisIMRegisterLayeredMiniport(g_hNdisWrapperHandle,
2622 &MChars,
2623 sizeof(MChars),
2624 &g_hDriverHandle);
2625#else
2626 Status = NdisMRegisterMiniport(
2627 g_hNdisWrapperHandle,
2628 &MChars,
2629 sizeof(MChars));
2630#endif
2631 if(Status == NDIS_STATUS_SUCCESS)
2632 {
2633# ifndef WIN9X
2634 NdisMRegisterUnloadHandler(g_hNdisWrapperHandle, vboxNetFltWinUnload);
2635# endif
2636 }
2637
2638 return Status;
2639}
2640
2641/**
2642 * deregister the miniport edge
2643 */
2644DECLHIDDEN(NDIS_STATUS)
2645vboxNetFltWinMpDeregister()
2646{
2647#ifndef VBOXNETADP
2648 NdisIMDeregisterLayeredMiniport(g_hDriverHandle);
2649#else
2650 /* don't need to do anything here */
2651#endif
2652 NdisTerminateWrapper(g_hNdisWrapperHandle, NULL);
2653 return NDIS_STATUS_SUCCESS;
2654}
2655
2656#ifndef VBOXNETADP
2657/**
2658 * return the miniport edge handle
2659 */
2660DECLHIDDEN(NDIS_HANDLE) vboxNetFltWinMpGetHandle()
2661{
2662 return g_hDriverHandle;
2663}
2664
2665/**
2666 * initialize the instance of a device used for ioctl handling
2667 */
2668DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpInitializeDevideInstance(PADAPT pAdapt)
2669{
2670 NDIS_STATUS Status;
2671 /*
2672 * Now ask NDIS to initialize our miniport (upper) edge.
2673 * Set the flag below to synchronize with a possible call
2674 * to our protocol Unbind handler that may come in before
2675 * our miniport initialization happens.
2676 */
2677 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2678 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initializing);
2679 /* this is doe in vboxNetFltWinPtInitPADAPT*/
2680 /* NdisInitializeEvent(&pAdapt->MiniportInitEvent); */
2681
2682 Status = NdisIMInitializeDeviceInstanceEx(g_hDriverHandle,
2683 &pAdapt->DeviceName,
2684 pAdapt);
2685 /* ensure we're taking into account the pAdapt->Status if our miniport halt handler was called */
2686 if(Status == NDIS_STATUS_SUCCESS)
2687 {
2688 if(pAdapt->Status == NDIS_STATUS_SUCCESS)
2689 {
2690// Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
2691// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
2692 return NDIS_STATUS_SUCCESS;
2693 }
2694 AssertBreakpoint();
2695 vboxNetFltWinMpDeInitializeDevideInstance(pAdapt, &Status);
2696 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2697 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2698 return pAdapt->Status;
2699 }
2700 else
2701 {
2702 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2703 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2704 }
2705 return Status;
2706}
2707
2708/**
2709 * deinitialize the instance of a device used for ioctl handling
2710 */
2711DECLHIDDEN(bool) vboxNetFltWinMpDeInitializeDevideInstance(PADAPT pAdapt, PNDIS_STATUS pStatus)
2712{
2713# ifndef WIN9X
2714 NDIS_STATUS LocalStatus;
2715 /*
2716 * Check if we had called NdisIMInitializeDeviceInstanceEx and
2717 * we are awaiting a call to MiniportInitialize.
2718 */
2719 if (vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing)
2720 {
2721 /*
2722 * Try to cancel the pending IMInit process.
2723 */
2724 LocalStatus = NdisIMCancelInitializeDeviceInstance(
2725 g_hDriverHandle,
2726 &pAdapt->DeviceName);
2727
2728 if (LocalStatus == NDIS_STATUS_SUCCESS)
2729 {
2730 /*
2731 * Successfully cancelled IM Initialization; our
2732 * Miniport Initialize routine will not be called
2733 * for this device.
2734 */
2735 Assert(pAdapt->hMiniportHandle == NULL);
2736 }
2737 else
2738 {
2739 /*
2740 * Our Miniport Initialize routine will be called
2741 * (may be running on another thread at this time).
2742 * Wait for it to finish.
2743 */
2744 NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);
2745 }
2746
2747 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2748 }
2749#endif
2750
2751 /*
2752 * Call NDIS to remove our device-instance. We do most of the work
2753 * inside the HaltHandler.
2754 *
2755 * The Handle will be NULL if our miniport Halt Handler has been called or
2756 * if the IM device was never initialized
2757 */
2758
2759 if (vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized)
2760 {
2761 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
2762
2763 *pStatus = NdisIMDeInitializeDeviceInstance(pAdapt->hMiniportHandle);
2764
2765 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2766
2767 if (*pStatus != NDIS_STATUS_SUCCESS)
2768 {
2769 *pStatus = NDIS_STATUS_FAILURE;
2770 }
2771
2772 return true;
2773 }
2774
2775 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2776
2777 return false;
2778}
2779#endif
2780
2781DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpReferenceControlDevice()
2782{
2783 return vboxNetFltWinPtRegisterDevice();
2784}
2785
2786DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDereferenceControlDevice()
2787{
2788 return vboxNetFltWinPtDeregisterDevice();
2789}
2790
2791#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND*/
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