VirtualBox

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

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

IntNet,VBoxNetFlt: Cleaned up the locking protocol between IntNet and NetFlt. Eleminated the out-bound trunk lock that IntNet always took when calling NetFlt.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 95.8 KB
Line 
1/* $Id: VBoxNetFltMp-win.c 28830 2010-04-27 14:05:25Z 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;
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 || (fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_SRC_HOST)) != NDIS_STATUS_SUCCESS)
833 {
834#ifndef VBOXNETADP
835 fStatus = vboxNetFltWinSendPassThru(pAdapt, pPacket);
836#else
837 if(!cNetFltRefs)
838 {
839# ifdef VBOXNETADP_REPORT_DISCONNECTED
840 fStatus = NDIS_STATUS_MEDIA_DISCONNECT;
841 STATISTIC_INCREASE(pAdapt->cTxError);
842# else
843 fStatus = NDIS_STATUS_SUCCESS;
844# endif
845 }
846#endif
847
848 if (fStatus != NDIS_STATUS_PENDING)
849 {
850 NdisMSendComplete(pAdapt->hMiniportHandle,
851 pPacket,
852 fStatus);
853 }
854 else
855 {
856 cAdaptRefs--;
857 }
858 }
859 else
860 {
861 cAdaptRefs--;
862 cNetFltRefs--;
863 }
864 }
865
866 if(cNetFltRefs)
867 {
868 vboxNetFltWinDecReferenceNetFlt(pNetFlt, cNetFltRefs);
869 }
870 else if(cPassThruRefs)
871 {
872 vboxNetFltWinDecReferenceModePassThru(pNetFlt, cPassThruRefs);
873 }
874 if(cAdaptRefs)
875 {
876 vboxNetFltWinDecReferenceAdapt(pAdapt, cAdaptRefs);
877 }
878 }
879 else
880 {
881 NDIS_HANDLE h = pAdapt->hMiniportHandle;
882 Assert(0);
883 if(h)
884 {
885 for (i = 0; i < cNumberOfPackets; i++)
886 {
887 PNDIS_PACKET pPacket;
888 pPacket = pPacketArray[i];
889 NdisMSendComplete(h,
890 pPacket,
891 NDIS_STATUS_FAILURE);
892 }
893 }
894 }
895}
896#ifndef VBOXNETADP
897/**
898 * Entry point called by NDIS to query for the value of the specified OID.
899 * Typical processing is to forward the query down to the underlying miniport.
900 *
901 * The following OIDs are filtered here:
902 * OID_PNP_QUERY_POWER - return success right here
903 * OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up
904 * multiple instances of private GUIDs supported by the underlying miniport.
905 * OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but
906 * the values returned are postprocessed before we complete this request;
907 * see vboxNetFltWinPtRequestComplete.
908 *
909 * NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents
910 * of data it passes through such that a lower miniport may not be able
911 * to perform TCP task offload, then it should not forward this OID down,
912 * but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to
913 * avoid performing incorrect transformations on data.
914 *
915 * If our miniport edge (upper edge) is at a low-power state, fail the request.
916 * If our protocol edge (lower edge) has been notified of a low-power state,
917 * we pend this request until the miniport below has been set to D0. Since
918 * requests to miniports are serialized always, at most a single request will
919 * be pended.
920 *
921 * @param MiniportAdapterContext Pointer to the adapter structure
922 * @param Oid Oid for this query
923 * @param InformationBuffer Buffer for information
924 * @param InformationBufferLength Size of this buffer
925 * @param BytesWritten Specifies how much info is written
926 * @param BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
927 * @return Return code from the NdisRequest below.
928 * */
929static NDIS_STATUS
930vboxNetFltWinMpQueryInformation(
931 IN NDIS_HANDLE MiniportAdapterContext,
932 IN NDIS_OID Oid,
933 IN PVOID InformationBuffer,
934 IN ULONG InformationBufferLength,
935 OUT PULONG BytesWritten,
936 OUT PULONG BytesNeeded
937 )
938{
939 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
940 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
941 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
942 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
943
944 do
945 {
946 if (Oid == OID_PNP_QUERY_POWER)
947 {
948 /*
949 * Do not forward this.
950 */
951 Status = NDIS_STATUS_SUCCESS;
952 break;
953 }
954
955 if (Oid == OID_GEN_SUPPORTED_GUIDS)
956 {
957 /*
958 * Do not forward this, otherwise we will end up with multiple
959 * instances of private GUIDs that the underlying miniport
960 * supports.
961 */
962 Status = NDIS_STATUS_NOT_SUPPORTED;
963 break;
964 }
965
966 if (Oid == OID_TCP_TASK_OFFLOAD)
967 {
968 /* we want to receive packets with checksums calculated
969 * since we are passing them to IntNet
970 */
971 Status = NDIS_STATUS_NOT_SUPPORTED;
972 break;
973 }
974
975 /*
976 * If the miniport below is unbinding, just fail any request
977 */
978 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized) /* protocol unbind in progress */
979 {
980 Status = NDIS_STATUS_FAILURE;
981 break;
982 }
983
984 /*
985 * All other queries are failed, if the miniport is not at D0,
986 */
987 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0)
988 {
989 Status = NDIS_STATUS_FAILURE;
990 break;
991 }
992
993 pAdapt->Request.RequestType = NdisRequestQueryInformation;
994 pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
995 pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
996 pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
997 pAdapt->BytesNeeded = BytesNeeded;
998 pAdapt->BytesReadOrWritten = BytesWritten;
999
1000 /*
1001 * If the miniport below is binding, fail the request
1002 */
1003 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1004
1005 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1006 {
1007 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1008 Status = NDIS_STATUS_FAILURE;
1009 break;
1010 }
1011 /*
1012 * If the Protocol device state is OFF, mark this request as being
1013 * pended. We queue this until the device state is back to D0.
1014 */
1015 if ((vboxNetFltWinGetPowerState(&pAdapt->PTState) > NdisDeviceStateD0)
1016 && (pAdapt->bStandingBy == FALSE))
1017 {
1018 pAdapt->bQueuedRequest = TRUE;
1019 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1020 Status = NDIS_STATUS_PENDING;
1021 break;
1022 }
1023 /*
1024 * This is in the process of powering down the system, always fail the request
1025 */
1026 if (pAdapt->bStandingBy == TRUE)
1027 {
1028 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1029 Status = NDIS_STATUS_FAILURE;
1030 break;
1031 }
1032 pAdapt->bOutstandingRequests = TRUE;
1033
1034 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1035 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
1036 {
1037 bool fNetFltActive;
1038 const bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &fNetFltActive);
1039
1040 Assert(InformationBuffer);
1041 Assert(!pAdapt->fProcessingPacketFilter);
1042
1043 if(fNetFltActive)
1044 {
1045 /* netflt is active, simply return the cached value */
1046 *((PULONG)InformationBuffer) = pAdapt->fUpperProtocolSetFilter;
1047
1048 Status = NDIS_STATUS_SUCCESS;
1049 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1050 vboxNetFltWinDereferenceAdapt(pAdapt);
1051
1052 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1053 pAdapt->bOutstandingRequests = FALSE;
1054 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1055 break;
1056 }
1057 else if(fAdaptActive)
1058 {
1059 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU;
1060 /* we're cleaning it in RequestComplete */
1061 }
1062 }
1063
1064 /*
1065 * default case, most requests will be passed to the miniport below
1066 */
1067 NdisRequest(&Status,
1068 pAdapt->hBindingHandle,
1069 &pAdapt->Request);
1070
1071
1072 if (Status != NDIS_STATUS_PENDING)
1073 {
1074 vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, Status);
1075 Status = NDIS_STATUS_PENDING;
1076 }
1077
1078 } while (FALSE);
1079
1080 return(Status);
1081
1082}
1083/**
1084 * Postprocess a request for OID_PNP_CAPABILITIES that was forwarded
1085 * down to the underlying miniport, and has been completed by it.
1086 *
1087 * @param pAdapt - Pointer to the adapter structure
1088 * @param pStatus - Place to return final status
1089 * @return None. */
1090DECLHIDDEN(VOID)
1091vboxNetFltWinMpQueryPNPCapabilities(
1092 IN OUT PADAPT pAdapt,
1093 OUT PNDIS_STATUS pStatus
1094 )
1095{
1096 PNDIS_PNP_CAPABILITIES pPNPCapabilities;
1097 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
1098
1099 if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))
1100 {
1101 pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);
1102
1103 /*
1104 * The following fields must be overwritten by an IM driver.
1105 */
1106 pPMstruct= & pPNPCapabilities->WakeUpCapabilities;
1107 pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1108 pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
1109 pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
1110 *pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
1111 *pAdapt->BytesNeeded = 0;
1112
1113
1114 *pStatus = NDIS_STATUS_SUCCESS;
1115 }
1116 else
1117 {
1118 *pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);
1119 *pStatus = NDIS_STATUS_RESOURCES;
1120 }
1121}
1122
1123#endif /* ifndef VBOXNETADP*/
1124
1125/**
1126 * This routine does all the procssing for a request with a SetPower Oid
1127 * The miniport shoud accept the Set Power and transition to the new state
1128 *
1129 * The Set Power should not be passed to the miniport below
1130 *
1131 * If the IM miniport is going into a low power state, then there is no guarantee if it will ever
1132 * be asked go back to D0, before getting halted. No requests should be pended or queued.
1133 *
1134 * @param pNdisStatus - Status of the operation
1135 * @param pAdapt - The Adapter structure
1136 * @param InformationBuffer - The New DeviceState
1137 * @param InformationBufferLength
1138 * @param BytesRead - No of bytes read
1139 * @param BytesNeeded - No of bytes needed
1140 * @return Status - NDIS_STATUS_SUCCESS if all the wait events succeed. */
1141static VOID
1142vboxNetFltWinMpProcessSetPowerOid(
1143 IN OUT PNDIS_STATUS pNdisStatus,
1144 IN PADAPT pAdapt,
1145 IN PVOID InformationBuffer,
1146 IN ULONG InformationBufferLength,
1147 OUT PULONG BytesRead,
1148 OUT PULONG BytesNeeded
1149 )
1150{
1151
1152
1153 NDIS_DEVICE_POWER_STATE NewDeviceState;
1154
1155 LogFlow(("==>vboxNetFltWinMpProcessSetPowerOid: Adapt %p\n", pAdapt));
1156
1157 Assert (InformationBuffer != NULL);
1158
1159 *pNdisStatus = NDIS_STATUS_FAILURE;
1160
1161 do
1162 {
1163 /*
1164 * Check for invalid length
1165 */
1166 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
1167 {
1168 *pNdisStatus = NDIS_STATUS_INVALID_LENGTH;
1169 break;
1170 }
1171
1172 NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);
1173
1174 /*
1175 * Check for invalid device state
1176 */
1177 if ((vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0))
1178 {
1179 /*
1180 * If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0
1181 */
1182 Assert (!(vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0));
1183
1184 *pNdisStatus = NDIS_STATUS_FAILURE;
1185 break;
1186 }
1187
1188#ifndef VBOXNETADP
1189 /*
1190 * Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)
1191 * If so, then set the bStandingBy Flag - (Block all incoming requests)
1192 */
1193 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)
1194 {
1195 pAdapt->bStandingBy = TRUE;
1196 }
1197
1198 /*
1199 * If the miniport is transitioning from a low power state to ON (D0), then clear the bStandingBy flag
1200 * All incoming requests will be pended until the physical miniport turns ON.
1201 */
1202 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0 && NewDeviceState == NdisDeviceStateD0)
1203 {
1204 pAdapt->bStandingBy = FALSE;
1205 }
1206#endif
1207 /*
1208 * Now update the state in the pAdapt structure;
1209 */
1210 vboxNetFltWinSetPowerState(&pAdapt->MPState, NewDeviceState);
1211#ifndef VBOXNETADP
1212 if(NewDeviceState != NdisDeviceStateD0)
1213 {
1214 vboxNetFltWinPtFlushReceiveQueue(pAdapt,
1215 true ); /* just return */
1216 }
1217#endif
1218 *pNdisStatus = NDIS_STATUS_SUCCESS;
1219
1220
1221 } while (FALSE);
1222
1223 if (*pNdisStatus == NDIS_STATUS_SUCCESS)
1224 {
1225#ifndef VBOXNETADP
1226 /*
1227 * The miniport resume from low power state
1228 */
1229 if (pAdapt->bStandingBy == FALSE)
1230 {
1231 /*
1232 * If we need to indicate the media connect state
1233 */
1234 if (pAdapt->LastIndicatedStatus != pAdapt->LatestUnIndicateStatus)
1235 {
1236 NdisMIndicateStatus(pAdapt->hMiniportHandle,
1237 pAdapt->LatestUnIndicateStatus,
1238 (PVOID)NULL,
1239 0);
1240 NdisMIndicateStatusComplete(pAdapt->hMiniportHandle);
1241 pAdapt->LastIndicatedStatus = pAdapt->LatestUnIndicateStatus;
1242 }
1243 }
1244 else
1245 {
1246 /*
1247 * Initialize LatestUnIndicatedStatus
1248 */
1249 pAdapt->LatestUnIndicateStatus = pAdapt->LastIndicatedStatus;
1250 }
1251#endif
1252 *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
1253 *BytesNeeded = 0;
1254 }
1255 else
1256 {
1257 *BytesRead = 0;
1258 *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1259 }
1260
1261 LogFlow(("<==vboxNetFltWinMpProcessSetPowerOid: Adapt %p\n", pAdapt));
1262}
1263#ifndef VBOXNETADP
1264/**
1265 * Miniport SetInfo handler.
1266 *
1267 * In the case of OID_PNP_SET_POWER, record the power state and return the OID.
1268 * Do not pass below
1269 * If the device is suspended, do not block the SET_POWER_OID
1270 * as it is used to reactivate the NetFlt miniport
1271 *
1272 * PM- If the MP is not ON (DeviceState > D0) return immediately (except for 'query power' and 'set power')
1273 * If MP is ON, but the PT is not at D0, then queue the queue the request for later processing
1274 *
1275 * Requests to miniports are always serialized
1276 *
1277 * @param MiniportAdapterContext Pointer to the adapter structure
1278 * @param Oid Oid for this query
1279 * @param InformationBuffer Buffer for information
1280 * @param InformationBufferLength Size of this buffer
1281 * @param BytesRead Specifies how much info is read
1282 * @param BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
1283 * @return Return code from the NdisRequest below. */
1284static NDIS_STATUS
1285vboxNetFltWinMpSetInformation(
1286 IN NDIS_HANDLE MiniportAdapterContext,
1287 IN NDIS_OID Oid,
1288 IN PVOID InformationBuffer,
1289 IN ULONG InformationBufferLength,
1290 OUT PULONG BytesRead,
1291 OUT PULONG BytesNeeded
1292 )
1293{
1294 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
1295 NDIS_STATUS Status;
1296 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1297 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
1298
1299 Status = NDIS_STATUS_FAILURE;
1300
1301 do
1302 {
1303 /*
1304 * The Set Power should not be sent to the miniport below the NetFlt, but is handled internally
1305 */
1306 if (Oid == OID_PNP_SET_POWER)
1307 {
1308 vboxNetFltWinMpProcessSetPowerOid(&Status,
1309 pAdapt,
1310 InformationBuffer,
1311 InformationBufferLength,
1312 BytesRead,
1313 BytesNeeded);
1314 break;
1315
1316 }
1317
1318 /*
1319 * If the miniport below is unbinding, fail the request
1320 */
1321 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1322 {
1323 Status = NDIS_STATUS_FAILURE;
1324 break;
1325 }
1326
1327 /*
1328 * All other Set Information requests are failed, if the miniport is
1329 * not at D0 or is transitioning to a device state greater than D0.
1330 */
1331 if (vboxNetFltWinGetPowerState(&pAdapt->MPState) > NdisDeviceStateD0)
1332 {
1333 Status = NDIS_STATUS_FAILURE;
1334 break;
1335 }
1336
1337 /* Set up the Request and return the result */
1338 pAdapt->Request.RequestType = NdisRequestSetInformation;
1339 pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;
1340 pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
1341 pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
1342 pAdapt->BytesNeeded = BytesNeeded;
1343 pAdapt->BytesReadOrWritten = BytesRead;
1344
1345 /*
1346 * If the miniport below is unbinding, fail the request
1347 */
1348 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1349 if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized)
1350 {
1351 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1352 Status = NDIS_STATUS_FAILURE;
1353 break;
1354 }
1355
1356 /*
1357 * If the device below is at a low power state, we cannot send it the
1358 * request now, and must pend it.
1359 */
1360 if ((vboxNetFltWinGetPowerState(&pAdapt->PTState) > NdisDeviceStateD0)
1361 && (pAdapt->bStandingBy == FALSE))
1362 {
1363 pAdapt->bQueuedRequest = TRUE;
1364 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1365 Status = NDIS_STATUS_PENDING;
1366 break;
1367 }
1368 /*
1369 * This is in the process of powering down the system, always fail the request
1370 */
1371 if (pAdapt->bStandingBy == TRUE)
1372 {
1373 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1374 Status = NDIS_STATUS_FAILURE;
1375 break;
1376 }
1377 pAdapt->bOutstandingRequests = TRUE;
1378
1379 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1380
1381 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
1382 {
1383 /* need to disable cleaning promiscuous here ?? */
1384 bool fNetFltActive;
1385 const bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &fNetFltActive);
1386
1387 Assert(InformationBuffer);
1388 Assert(!pAdapt->fProcessingPacketFilter);
1389
1390 if(fNetFltActive)
1391 {
1392 Assert(fAdaptActive);
1393
1394 /* netflt is active, update the cached value */
1395 /* TODO: in case we are are not in promiscuous now, we are issuing a request.
1396 * what should we do in case of a failure?
1397 * i.e. should we update the fUpperProtocolSetFilter in completion routine in this case? etc. */
1398 pAdapt->fUpperProtocolSetFilter = *((PULONG)InformationBuffer);
1399 pAdapt->bUpperProtSetFilterInitialized = true;
1400
1401 if(!(pAdapt->fOurSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS))
1402 {
1403 pAdapt->fSetFilterBuffer = NDIS_PACKET_TYPE_PROMISCUOUS;
1404 pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = &pAdapt->fSetFilterBuffer;
1405 pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(pAdapt->fSetFilterBuffer);
1406 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_NETFLT;
1407 /* we'll do dereferencing in request complete */
1408 }
1409 else
1410 {
1411 Status = NDIS_STATUS_SUCCESS;
1412 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1413 vboxNetFltWinDereferenceAdapt(pAdapt);
1414
1415 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1416 pAdapt->bOutstandingRequests = FALSE;
1417 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1418 break;
1419 }
1420 }
1421 else if(fAdaptActive)
1422 {
1423 pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU;
1424 /* dereference on completion */
1425 }
1426 }
1427
1428 /*
1429 * Forward the request to the device below.
1430 */
1431 NdisRequest(&Status,
1432 pAdapt->hBindingHandle,
1433 &pAdapt->Request);
1434
1435 if (Status != NDIS_STATUS_PENDING)
1436 {
1437 vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, Status);
1438 }
1439
1440 } while (FALSE);
1441
1442 return(Status);
1443}
1444#else
1445static NDIS_OID g_vboxNetFltWinMpSupportedOids[] =
1446{
1447 OID_GEN_SUPPORTED_LIST,
1448 OID_GEN_HARDWARE_STATUS,
1449 OID_GEN_MEDIA_SUPPORTED,
1450 OID_GEN_MEDIA_IN_USE,
1451 OID_GEN_MAXIMUM_LOOKAHEAD,
1452 OID_GEN_MAXIMUM_FRAME_SIZE,
1453 OID_GEN_LINK_SPEED,
1454 OID_GEN_TRANSMIT_BUFFER_SPACE,
1455 OID_GEN_RECEIVE_BUFFER_SPACE,
1456 OID_GEN_TRANSMIT_BLOCK_SIZE,
1457 OID_GEN_RECEIVE_BLOCK_SIZE,
1458 OID_GEN_VENDOR_ID,
1459 OID_GEN_VENDOR_DESCRIPTION,
1460 OID_GEN_VENDOR_DRIVER_VERSION,
1461 OID_GEN_CURRENT_PACKET_FILTER,
1462 OID_GEN_CURRENT_LOOKAHEAD,
1463 OID_GEN_DRIVER_VERSION,
1464 OID_GEN_MAXIMUM_TOTAL_SIZE,
1465 OID_GEN_PROTOCOL_OPTIONS,
1466 OID_GEN_MAC_OPTIONS,
1467 OID_GEN_MEDIA_CONNECT_STATUS,
1468 OID_GEN_MAXIMUM_SEND_PACKETS,
1469 OID_GEN_XMIT_OK,
1470 OID_GEN_RCV_OK,
1471 OID_GEN_XMIT_ERROR,
1472 OID_GEN_RCV_ERROR,
1473 OID_GEN_RCV_NO_BUFFER,
1474 OID_GEN_RCV_CRC_ERROR,
1475 OID_GEN_TRANSMIT_QUEUE_LENGTH,
1476 OID_802_3_PERMANENT_ADDRESS,
1477 OID_802_3_CURRENT_ADDRESS,
1478 OID_802_3_MULTICAST_LIST,
1479 OID_802_3_MAC_OPTIONS,
1480 OID_802_3_MAXIMUM_LIST_SIZE,
1481 OID_802_3_RCV_ERROR_ALIGNMENT,
1482 OID_802_3_XMIT_ONE_COLLISION,
1483 OID_802_3_XMIT_MORE_COLLISIONS,
1484 OID_802_3_XMIT_DEFERRED,
1485 OID_802_3_XMIT_MAX_COLLISIONS,
1486 OID_802_3_RCV_OVERRUN,
1487 OID_802_3_XMIT_UNDERRUN,
1488 OID_802_3_XMIT_HEARTBEAT_FAILURE,
1489 OID_802_3_XMIT_TIMES_CRS_LOST,
1490 OID_802_3_XMIT_LATE_COLLISIONS
1491#ifndef INTERFACE_WITH_NDISPROT
1492 ,
1493 OID_PNP_CAPABILITIES,
1494 OID_PNP_SET_POWER,
1495 OID_PNP_QUERY_POWER
1496# if 0
1497 ,
1498 OID_PNP_ADD_WAKE_UP_PATTERN,
1499 OID_PNP_REMOVE_WAKE_UP_PATTERN,
1500 OID_PNP_ENABLE_WAKE_UP
1501# endif
1502#endif
1503};
1504
1505static NDIS_STATUS
1506vboxNetFltWinMpQueryInformation(
1507 IN NDIS_HANDLE MiniportAdapterContext,
1508 IN NDIS_OID Oid,
1509 IN PVOID InformationBuffer,
1510 IN ULONG InformationBufferLength,
1511 OUT PULONG BytesWritten,
1512 OUT PULONG BytesNeeded)
1513/*++
1514
1515Routine Description:
1516
1517 Entry point called by NDIS to query for the value of the specified OID.
1518 MiniportQueryInformation runs at IRQL = DISPATCH_LEVEL.
1519
1520Arguments:
1521
1522 MiniportAdapterContext Pointer to the adapter structure
1523 Oid Oid for this query
1524 InformationBuffer Buffer for information
1525 InformationBufferLength Size of this buffer
1526 BytesWritten Specifies how much info is written
1527 BytesNeeded In case the buffer is smaller than
1528 what we need, tell them how much is needed
1529
1530
1531Return Value:
1532
1533 Return code from the NdisRequest below.
1534
1535Notes: Read "Minimizing Miniport Driver Initialization Time" in the DDK
1536 for more info on how to handle certain OIDs that affect the init of
1537 a miniport.
1538
1539--*/
1540{
1541 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1542 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
1543 NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
1544 NDIS_MEDIUM Medium = NdisMedium802_3;
1545 UCHAR VendorDesc[] = VBOXNETADP_VENDOR_DESC;
1546 ULONG ulInfo = 0;
1547 USHORT usInfo = 0;
1548 ULONG64 ulInfo64 = 0;
1549 PVOID pInfo = (PVOID) &ulInfo;
1550 ULONG ulInfoLen = sizeof(ulInfo);
1551 NDIS_PNP_CAPABILITIES PMCaps;
1552
1553 LogFlow(("==> vboxNetFltWinMpQueryInformation %s\n", vboxNetFltWinMpDbgGetOidName(Oid)));
1554
1555 // Initialize the result
1556 *BytesWritten = 0;
1557 *BytesNeeded = 0;
1558
1559 switch(Oid)
1560 {
1561 case OID_GEN_SUPPORTED_LIST:
1562 //
1563 // The OID_GEN_SUPPORTED_LIST OID specifies an array of OIDs
1564 // for objects that the underlying driver or its NIC supports.
1565 // Objects include general, media-specific, and implementation-
1566 // specific objects. NDIS forwards a subset of the returned
1567 // list to protocols that make this query. That is, NDIS filters
1568 // any supported statistics OIDs out of the list because
1569 // protocols never make statistics queries.
1570 //
1571 pInfo = (PVOID) g_vboxNetFltWinMpSupportedOids;
1572 ulInfoLen = sizeof(g_vboxNetFltWinMpSupportedOids);
1573 break;
1574
1575 case OID_GEN_HARDWARE_STATUS:
1576 //
1577 // Specify the current hardware status of the underlying NIC as
1578 // one of the following NDIS_HARDWARE_STATUS-type values.
1579 //
1580 pInfo = (PVOID) &HardwareStatus;
1581 ulInfoLen = sizeof(NDIS_HARDWARE_STATUS);
1582 break;
1583
1584 case OID_GEN_MEDIA_SUPPORTED:
1585 //
1586 // Specify the media types that the NIC can support but not
1587 // necessarily the media types that the NIC currently uses.
1588 // fallthrough:
1589 case OID_GEN_MEDIA_IN_USE:
1590 //
1591 // Specifiy a complete list of the media types that the NIC
1592 // currently uses.
1593 //
1594 pInfo = (PVOID) &Medium;
1595 ulInfoLen = sizeof(NDIS_MEDIUM);
1596 break;
1597
1598 case OID_GEN_CURRENT_LOOKAHEAD:
1599 case OID_GEN_MAXIMUM_LOOKAHEAD:
1600 //
1601 // If the miniport driver indicates received data by calling
1602 // NdisXxxIndicateReceive, it should respond to OID_GEN_MAXIMUM_LOOKAHEAD
1603 // with the maximum number of bytes the NIC can provide as
1604 // lookahead data. If that value is different from the size of the
1605 // lookahead buffer supported by bound protocols, NDIS will call
1606 // MiniportSetInformation to set the size of the lookahead buffer
1607 // provided by the miniport driver to the minimum of the miniport
1608 // driver and protocol(s) values. If the driver always indicates
1609 // up full packets with NdisMIndicateReceivePacket, it should
1610 // set this value to the maximum total packet size, which
1611 // excludes the header.
1612 // Upper-layer drivers examine lookahead data to determine whether
1613 // a packet that is associated with the lookahead data is intended
1614 // for one or more of their clients. If the underlying driver
1615 // supports multipacket receive indications, bound protocols are
1616 // given full net packets on every indication. Consequently,
1617 // this value is identical to that returned for
1618 // OID_GEN_RECEIVE_BLOCK_SIZE.
1619 //
1620 ulInfo = VBOXNETADP_MAX_LOOKAHEAD_SIZE;
1621 break;
1622
1623 case OID_GEN_MAXIMUM_FRAME_SIZE:
1624 //
1625 // Specifiy the maximum network packet size, in bytes, that the
1626 // NIC supports excluding the header. A NIC driver that emulates
1627 // another medium type for binding to a transport must ensure that
1628 // the maximum frame size for a protocol-supplied net packet does
1629 // not exceed the size limitations for the true network medium.
1630 //
1631 ulInfo = VBOXNETADP_MAX_PACKET_SIZE - VBOXNETADP_HEADER_SIZE;
1632 break;
1633
1634 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1635 //
1636 // Specify the maximum total packet length, in bytes, the NIC
1637 // supports including the header. A protocol driver might use
1638 // this returned length as a gauge to determine the maximum
1639 // size packet that a NIC driver could forward to the
1640 // protocol driver. The miniport driver must never indicate
1641 // up to the bound protocol driver packets received over the
1642 // network that are longer than the packet size specified by
1643 // OID_GEN_MAXIMUM_TOTAL_SIZE.
1644 //
1645 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1646 //
1647 // The OID_GEN_TRANSMIT_BLOCK_SIZE OID specifies the minimum
1648 // number of bytes that a single net packet occupies in the
1649 // transmit buffer space of the NIC. For example, a NIC that
1650 // has a transmit space divided into 256-byte pieces would have
1651 // a transmit block size of 256 bytes. To calculate the total
1652 // transmit buffer space on such a NIC, its driver multiplies
1653 // the number of transmit buffers on the NIC by its transmit
1654 // block size. In our case, the transmit block size is
1655 // identical to its maximum packet size.
1656
1657 case OID_GEN_RECEIVE_BLOCK_SIZE:
1658 //
1659 // The OID_GEN_RECEIVE_BLOCK_SIZE OID specifies the amount of
1660 // storage, in bytes, that a single packet occupies in the receive
1661 // buffer space of the NIC.
1662 //
1663 ulInfo = (ULONG) VBOXNETADP_MAX_PACKET_SIZE;
1664 break;
1665
1666 case OID_GEN_MAC_OPTIONS:
1667 //
1668 // Specify a bitmask that defines optional properties of the NIC.
1669 // This miniport indicates receive with NdisMIndicateReceivePacket
1670 // function. It has no MiniportTransferData function. Such a driver
1671 // should set this NDIS_MAC_OPTION_TRANSFERS_NOT_PEND flag.
1672 //
1673 // NDIS_MAC_OPTION_NO_LOOPBACK tells NDIS that NIC has no internal
1674 // loopback support so NDIS will manage loopbacks on behalf of
1675 // this driver.
1676 //
1677 // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA tells the protocol that
1678 // our receive buffer is not on a device-specific card. If
1679 // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA is not set, multi-buffer
1680 // indications are copied to a single flat buffer.
1681 //
1682 ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
1683 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
1684 NDIS_MAC_OPTION_NO_LOOPBACK;
1685 break;
1686
1687 case OID_GEN_LINK_SPEED:
1688 //
1689 // Specify the maximum speed of the NIC in kbps.
1690 // The unit of measurement is 100 bps
1691 //
1692 ulInfo = VBOXNETADP_LINK_SPEED;
1693 break;
1694
1695 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1696 //
1697 // Specify the amount of memory, in bytes, on the NIC that
1698 // is available for buffering transmit data. A protocol can
1699 // use this OID as a guide for sizing the amount of transmit
1700 // data per send.
1701 //
1702 ulInfo = VBOXNETADP_MAX_PACKET_SIZE * PACKET_INFO_POOL_SIZE;
1703 break;
1704
1705 case OID_GEN_RECEIVE_BUFFER_SPACE:
1706 //
1707 // Specify the amount of memory on the NIC that is available
1708 // for buffering receive data. A protocol driver can use this
1709 // OID as a guide for advertising its receive window after it
1710 // establishes sessions with remote nodes.
1711 //
1712
1713 ulInfo = VBOXNETADP_MAX_PACKET_SIZE * PACKET_INFO_POOL_SIZE;
1714 break;
1715
1716 case OID_GEN_VENDOR_ID:
1717 //
1718 // Specify a three-byte IEEE-registered vendor code, followed
1719 // by a single byte that the vendor assigns to identify a
1720 // particular NIC. The IEEE code uniquely identifies the vendor
1721 // and is the same as the three bytes appearing at the beginning
1722 // of the NIC hardware address. Vendors without an IEEE-registered
1723 // code should use the value 0xFFFFFF.
1724 //
1725 ulInfo = VBOXNETADP_VENDOR_ID;
1726 break;
1727
1728 case OID_GEN_VENDOR_DESCRIPTION:
1729 //
1730 // Specify a zero-terminated string describing the NIC vendor.
1731 //
1732 pInfo = VendorDesc;
1733 ulInfoLen = sizeof(VendorDesc);
1734 break;
1735
1736 case OID_GEN_VENDOR_DRIVER_VERSION:
1737 //
1738 // Specify the vendor-assigned version number of the NIC driver.
1739 // The low-order half of the return value specifies the minor
1740 // version; the high-order half specifies the major version.
1741 //
1742 ulInfo = VBOXNETADP_VENDOR_DRIVER_VERSION;
1743 break;
1744
1745 case OID_GEN_DRIVER_VERSION:
1746 //
1747 // Specify the NDIS version in use by the NIC driver. The high
1748 // byte is the major version number; the low byte is the minor
1749 // version number.
1750 //
1751 usInfo = (USHORT) (VBOXNETFLT_MAJOR_NDIS_VERSION<<8) + VBOXNETFLT_MINOR_NDIS_VERSION;
1752 pInfo = (PVOID) &usInfo;
1753 ulInfoLen = sizeof(USHORT);
1754 break;
1755
1756 case OID_GEN_MAXIMUM_SEND_PACKETS:
1757 //
1758 // If a miniport driver registers a MiniportSendPackets function,
1759 // MiniportQueryInformation will be called with the
1760 // OID_GEN_MAXIMUM_SEND_PACKETS request. The miniport driver must
1761 // respond with the maximum number of packets it is prepared to
1762 // handle on a single send request. The miniport driver should
1763 // pick a maximum that minimizes the number of packets that it
1764 // has to queue internally because it has no resources
1765 // (its device is full). A miniport driver for a bus-master DMA
1766 // NIC should attempt to pick a value that keeps its NIC filled
1767 // under anticipated loads.
1768 //
1769 ulInfo = PACKET_INFO_POOL_SIZE;
1770 break;
1771
1772 case OID_GEN_MEDIA_CONNECT_STATUS:
1773 //
1774 // Return the connection status of the NIC on the network as one
1775 // of the following system-defined values: NdisMediaStateConnected
1776 // or NdisMediaStateDisconnected.
1777 //
1778#ifdef VBOXNETADP_REPORT_DISCONNECTED
1779 {
1780 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1781 bool bNetFltActive;
1782 bool bActive = vboxNetFltWinReferenceAdaptNetFltFromAdapt(pNetFlt, pAdapt, bNetFltActive);
1783 if(bActive && bNetFltActive)
1784 {
1785 ulInfo = NdisMediaStateConnected;
1786 }
1787 else
1788 {
1789 ulInfo = NdisMediaStateDisconnected;
1790 }
1791
1792 if(bActive)
1793 {
1794 vboxNetFltWinDereferenceAdapt(pAdapt);
1795 }
1796 if(bNetFltActive)
1797 {
1798 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1799 }
1800 else
1801 {
1802 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1803 }
1804 }
1805#else
1806 ulInfo = NdisMediaStateConnected;
1807#endif
1808 break;
1809
1810 case OID_GEN_CURRENT_PACKET_FILTER:
1811 //
1812 // Specifiy the types of net packets such as directed, broadcast
1813 // multicast, for which a protocol receives indications from a
1814 // NIC driver. After NIC is initialized, a protocol driver
1815 // can send a set OID_GEN_CURRENT_PACKET_FILTER to a non-zero value,
1816 // thereby enabling the miniport driver to indicate receive packets
1817 // to that protocol.
1818 //
1819 ulInfo = (
1820 NDIS_PACKET_TYPE_BROADCAST
1821 | NDIS_PACKET_TYPE_DIRECTED
1822 | NDIS_PACKET_TYPE_ALL_FUNCTIONAL
1823 | NDIS_PACKET_TYPE_ALL_LOCAL
1824 | NDIS_PACKET_TYPE_GROUP
1825 | NDIS_PACKET_TYPE_MULTICAST
1826 );
1827 break;
1828
1829 case OID_PNP_CAPABILITIES:
1830 //
1831 // Return the wake-up capabilities of its NIC. If you return
1832 // NDIS_STATUS_NOT_SUPPORTED, NDIS considers the miniport driver
1833 // to be not Power management aware and doesn't send any power
1834 // or wake-up related queries such as
1835 // OID_PNP_SET_POWER, OID_PNP_QUERY_POWER,
1836 // OID_PNP_ADD_WAKE_UP_PATTERN, OID_PNP_REMOVE_WAKE_UP_PATTERN,
1837 // OID_PNP_ENABLE_WAKE_UP. Here, we are expecting the driver below
1838 // us to do the right thing.
1839 //
1840 RtlZeroMemory (&PMCaps, sizeof(NDIS_PNP_CAPABILITIES));
1841 ulInfoLen = sizeof (NDIS_PNP_CAPABILITIES);
1842 pInfo = (PVOID) &PMCaps;
1843 PMCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1844 PMCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
1845 break;
1846
1847 case OID_PNP_QUERY_POWER:
1848 Status = NDIS_STATUS_SUCCESS;
1849 break;
1850
1851 //
1852 // Following 4 OIDs are for querying Ethernet Operational
1853 // Characteristics.
1854 //
1855 case OID_802_3_PERMANENT_ADDRESS:
1856 //
1857 // Return the MAC address of the NIC burnt in the hardware.
1858 //
1859 {
1860 PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt));
1861 pInfo = &pNetFlt->u.s.MacAddr;
1862 ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH;
1863 }
1864 break;
1865
1866 case OID_802_3_CURRENT_ADDRESS:
1867 //
1868 // Return the MAC address the NIC is currently programmed to
1869 // use. Note that this address could be different from the
1870 // permananent address as the user can override using
1871 // registry. Read NdisReadNetworkAddress doc for more info.
1872 //
1873 {
1874 PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt));
1875 pInfo = &pNetFlt->u.s.MacAddr;
1876 ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH;
1877 }
1878 break;
1879
1880 case OID_802_3_MAXIMUM_LIST_SIZE:
1881 //
1882 // The maximum number of multicast addresses the NIC driver
1883 // can manage. This list is global for all protocols bound
1884 // to (or above) the NIC. Consequently, a protocol can receive
1885 // NDIS_STATUS_MULTICAST_FULL from the NIC driver when
1886 // attempting to set the multicast address list, even if
1887 // the number of elements in the given list is less than
1888 // the number originally returned for this query.
1889 //
1890 ulInfo = VBOXNETADP_MAX_MCAST_LIST;
1891 break;
1892
1893 case OID_802_3_MAC_OPTIONS:
1894 //
1895 // A protocol can use this OID to determine features supported
1896 // by the underlying driver such as NDIS_802_3_MAC_OPTION_PRIORITY.
1897 // Return zero indicating that it supports no options.
1898 //
1899 ulInfo = 0;
1900 break;
1901
1902 //
1903 // Following list consists of both general and Ethernet
1904 // specific statistical OIDs.
1905 //
1906
1907 case OID_GEN_XMIT_OK:
1908 ulInfo64 = pAdapt->cTxSuccess;
1909 pInfo = &ulInfo64;
1910 if (InformationBufferLength >= sizeof(ULONG64) ||
1911 InformationBufferLength == 0)
1912 {
1913 ulInfoLen = sizeof(ULONG64);
1914 }
1915 else
1916 {
1917 ulInfoLen = sizeof(ULONG);
1918 }
1919 // We should always report that 8 bytes are required to keep ndistest happy
1920 *BytesNeeded = sizeof(ULONG64);
1921 break;
1922
1923 case OID_GEN_RCV_OK:
1924 ulInfo64 = pAdapt->cRxSuccess;
1925 pInfo = &ulInfo64;
1926 if (InformationBufferLength >= sizeof(ULONG64) ||
1927 InformationBufferLength == 0)
1928 {
1929 ulInfoLen = sizeof(ULONG64);
1930 }
1931 else
1932 {
1933 ulInfoLen = sizeof(ULONG);
1934 }
1935 // We should always report that 8 bytes are required to keep ndistest happy
1936 *BytesNeeded = sizeof(ULONG64);
1937 break;
1938
1939 case OID_GEN_XMIT_ERROR:
1940
1941 ulInfo = pAdapt->cTxError;
1942 break;
1943
1944 case OID_GEN_RCV_ERROR:
1945 ulInfo = pAdapt->cRxError;
1946 break;
1947
1948 case OID_GEN_RCV_NO_BUFFER:
1949 ulInfo = 0;
1950 break;
1951
1952 case OID_GEN_RCV_CRC_ERROR:
1953 ulInfo = 0;
1954 break;
1955
1956 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
1957 ulInfo = PACKET_INFO_POOL_SIZE;
1958 break;
1959
1960 case OID_802_3_RCV_ERROR_ALIGNMENT:
1961 ulInfo = 0;
1962 break;
1963
1964 case OID_802_3_XMIT_ONE_COLLISION:
1965 ulInfo = 0;
1966 break;
1967
1968 case OID_802_3_XMIT_MORE_COLLISIONS:
1969 ulInfo = 0;
1970 break;
1971
1972 case OID_802_3_XMIT_DEFERRED:
1973 ulInfo = 0;
1974 break;
1975
1976 case OID_802_3_XMIT_MAX_COLLISIONS:
1977 ulInfo = 0;
1978 break;
1979
1980 case OID_802_3_RCV_OVERRUN:
1981 ulInfo = 0;
1982 break;
1983
1984 case OID_802_3_XMIT_UNDERRUN:
1985 ulInfo = 0;
1986 break;
1987
1988 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
1989 ulInfo = 0;
1990 break;
1991
1992 case OID_802_3_XMIT_TIMES_CRS_LOST:
1993 ulInfo = 0;
1994 break;
1995
1996 case OID_802_3_XMIT_LATE_COLLISIONS:
1997 ulInfo = 0;
1998 break;
1999
2000 default:
2001 Status = NDIS_STATUS_NOT_SUPPORTED;
2002 break;
2003 }
2004
2005 if(Status == NDIS_STATUS_SUCCESS)
2006 {
2007 if(ulInfoLen <= InformationBufferLength)
2008 {
2009 // Copy result into InformationBuffer
2010 *BytesWritten = ulInfoLen;
2011 if(ulInfoLen)
2012 {
2013 NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen);
2014 }
2015 }
2016 else
2017 {
2018 // too short
2019 *BytesNeeded = ulInfoLen;
2020 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2021 }
2022 }
2023
2024
2025 LogFlow(("<== vboxNetFltWinMpQueryInformation Status = 0x%08x\n",
2026 Status));
2027
2028 return(Status);
2029}
2030
2031NDIS_STATUS
2032vboxNetFltWinMpSetMulticastList(
2033 IN PADAPT pAdapt,
2034 IN PVOID InformationBuffer,
2035 IN ULONG InformationBufferLength,
2036 OUT PULONG pBytesRead,
2037 OUT PULONG pBytesNeeded
2038 )
2039/*++
2040Routine Description:
2041 This routine will set up the adapter for a specified multicast
2042 address list.
2043
2044Arguments:
2045 IN PMP_ADAPTER Adapter - Pointer to adapter block
2046 InformationBuffer - Buffer for information
2047 InformationBufferLength Size of this buffer
2048 pBytesRead Specifies how much info is read
2049 BytesNeeded In case the buffer is smaller than
2050
2051Return Value:
2052
2053 NDIS_STATUS
2054
2055--*/
2056{
2057 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
2058#if 0
2059 ULONG index;
2060#endif
2061
2062 LogFlow(("==> vboxNetFltWinMpSetMulticastList\n"));
2063
2064 //
2065 // Initialize.
2066 //
2067 *pBytesNeeded = 0;
2068 *pBytesRead = InformationBufferLength;
2069
2070 do
2071 {
2072 if (InformationBufferLength % VBOXNETADP_ETH_ADDRESS_LENGTH)
2073 {
2074 Status = NDIS_STATUS_INVALID_LENGTH;
2075 break;
2076 }
2077
2078 if (InformationBufferLength > (VBOXNETADP_MAX_MCAST_LIST * VBOXNETADP_ETH_ADDRESS_LENGTH))
2079 {
2080 Status = NDIS_STATUS_MULTICAST_FULL;
2081 *pBytesNeeded = VBOXNETADP_MAX_MCAST_LIST * VBOXNETADP_ETH_ADDRESS_LENGTH;
2082 break;
2083 }
2084#if 0
2085 //
2086 // Protect the list update with a lock if it can be updated by
2087 // another thread simultaneously.
2088 //
2089
2090 NdisZeroMemory(pAdapt->aMCList,
2091 sizeof(pAdapt->aMCList));
2092
2093 NdisMoveMemory(pAdapt->aMCList,
2094 InformationBuffer,
2095 InformationBufferLength);
2096
2097 pAdapt->cMCList = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
2098#endif
2099
2100 }
2101 while (FALSE);
2102
2103 //
2104 // Program the hardware to add suport for these muticast addresses
2105 //
2106
2107 LogFlow(("<== vboxNetFltWinMpSetMulticastList\n"));
2108
2109 return(Status);
2110
2111}
2112
2113
2114static NDIS_STATUS
2115vboxNetFltWinMpSetInformation(
2116 IN NDIS_HANDLE MiniportAdapterContext,
2117 IN NDIS_OID Oid,
2118 IN PVOID InformationBuffer,
2119 IN ULONG InformationBufferLength,
2120 OUT PULONG BytesRead,
2121 OUT PULONG BytesNeeded)
2122/*++
2123
2124Routine Description:
2125
2126 This is the handler for an OID set operation.
2127 MiniportSetInformation runs at IRQL = DISPATCH_LEVEL.
2128
2129Arguments:
2130
2131 MiniportAdapterContext Pointer to the adapter structure
2132 Oid Oid for this query
2133 InformationBuffer Buffer for information
2134 InformationBufferLength Size of this buffer
2135 BytesRead Specifies how much info is read
2136 BytesNeeded In case the buffer is smaller than what
2137 we need, tell them how much is needed
2138
2139Return Value:
2140
2141 Return code from the NdisRequest below.
2142
2143--*/
2144{
2145 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
2146 PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
2147 PNDIS_PM_PACKET_PATTERN pPmPattern = NULL;
2148
2149 LogFlow(("==> vboxNetFltWinMpSetInformation %s\n", vboxNetFltWinMpDbgGetOidName(Oid)));
2150
2151 *BytesRead = 0;
2152 *BytesNeeded = 0;
2153
2154 switch(Oid)
2155 {
2156 case OID_802_3_MULTICAST_LIST:
2157 //
2158 // Set the multicast address list on the NIC for packet reception.
2159 // The NIC driver can set a limit on the number of multicast
2160 // addresses bound protocol drivers can enable simultaneously.
2161 // NDIS returns NDIS_STATUS_MULTICAST_FULL if a protocol driver
2162 // exceeds this limit or if it specifies an invalid multicast
2163 // address.
2164 //
2165 Status = vboxNetFltWinMpSetMulticastList(
2166 pAdapt,
2167 InformationBuffer,
2168 InformationBufferLength,
2169 BytesRead,
2170 BytesNeeded);
2171 break;
2172
2173 case OID_GEN_CURRENT_PACKET_FILTER:
2174 //
2175 // Program the hardware to indicate the packets
2176 // of certain filter types.
2177 //
2178 if(InformationBufferLength != sizeof(ULONG))
2179 {
2180 *BytesNeeded = sizeof(ULONG);
2181 Status = NDIS_STATUS_INVALID_LENGTH;
2182 break;
2183 }
2184
2185 *BytesRead = InformationBufferLength;
2186
2187 break;
2188
2189 case OID_GEN_CURRENT_LOOKAHEAD:
2190 //
2191 // A protocol driver can set a suggested value for the number
2192 // of bytes to be used in its binding; however, the underlying
2193 // NIC driver is never required to limit its indications to
2194 // the value set.
2195 //
2196 if(InformationBufferLength != sizeof(ULONG)){
2197 *BytesNeeded = sizeof(ULONG);
2198 Status = NDIS_STATUS_INVALID_LENGTH;
2199 break;
2200 }
2201
2202 break;
2203
2204 case OID_PNP_SET_POWER:
2205 //
2206 // This OID notifies a miniport driver that its NIC will be
2207 // transitioning to the device power state specified in the
2208 // InformationBuffer. The miniport driver must always return
2209 // NDIS_STATUS_SUCCESS to an OID_PNP_SET_POWER request. An
2210 // OID_PNP_SET_POWER request may or may not be preceded by an
2211 // OID_PNP_QUERY_POWER request.
2212 //
2213 if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
2214 {
2215 Status = NDIS_STATUS_INVALID_LENGTH;
2216 break;
2217 }
2218
2219 vboxNetFltWinMpProcessSetPowerOid(&Status, pAdapt, InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded);
2220 break;
2221/*
2222 case OID_PNP_ADD_WAKE_UP_PATTERN:
2223 //
2224 // This OID is sent by a protocol driver to a miniport driver to
2225 // specify a wake-up pattern. The wake-up pattern, along with its mask,
2226 // is described by an NDIS_PM_PACKET_PATTERN structure.
2227 //
2228 pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
2229 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
2230 {
2231 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2232
2233 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
2234 break;
2235 }
2236 if (InformationBufferLength < pPmPattern->PatternOffset + pPmPattern->PatternSize)
2237 {
2238 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2239
2240 *BytesNeeded = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2241 break;
2242 }
2243 *BytesRead = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2244 Status = NDIS_STATUS_SUCCESS;
2245 bForwardRequest = TRUE;
2246 break;
2247
2248 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
2249 //
2250 // This OID requests the miniport driver to delete a wake-up pattern
2251 // that it previously received in an OID_PNP_ADD_WAKE_UP_PATTERN request.
2252 // The wake-up pattern, along with its mask, is described by an
2253 // NDIS_PM_PACKET_PATTERN structure.
2254 //
2255 pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
2256 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
2257 {
2258 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2259
2260 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
2261 break;
2262 }
2263 if (InformationBufferLength < pPmPattern->PatternOffset + pPmPattern->PatternSize)
2264 {
2265 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
2266
2267 *BytesNeeded = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2268 break;
2269 }
2270 *BytesRead = pPmPattern->PatternOffset + pPmPattern->PatternSize;
2271 Status = NDIS_STATUS_SUCCESS;
2272 bForwardRequest = TRUE;
2273
2274 break;
2275
2276 case OID_PNP_ENABLE_WAKE_UP:
2277 //
2278 // This OID specifies which wake-up capabilities a miniport
2279 // driver should enable in its NIC. Before the miniport
2280 // transitions to a low-power state (that is, before NDIS
2281 // sends the miniport driver an OID_PNP_SET_POWER request),
2282 // NDIS sends the miniport an OID_PNP_ENABLE_WAKE_UP request to
2283 // enable the appropriate wake-up capabilities.
2284 //
2285 DEBUGP(MP_INFO, ("--> OID_PNP_ENABLE_WAKE_UP\n"));
2286 if(InformationBufferLength != sizeof(ULONG))
2287 {
2288 *BytesNeeded = sizeof(ULONG);
2289 Status = NDIS_STATUS_INVALID_LENGTH;
2290 break;
2291 }
2292 *BytesRead = sizeof(ULONG);
2293 Status = NDIS_STATUS_SUCCESS;
2294 bForwardRequest = TRUE;
2295 break;
2296*/
2297 default:
2298 Status = NDIS_STATUS_INVALID_OID;
2299 break;
2300
2301 }
2302
2303
2304 LogFlow(("<== vboxNetFltWinMpSetInformation Status = 0x%08x\n", Status));
2305
2306 return(Status);
2307}
2308
2309static PUCHAR vboxNetFltWinMpDbgGetOidName(ULONG oid)
2310{
2311 PCHAR oidName;
2312
2313 switch (oid){
2314
2315 #undef MAKECASE
2316 #define MAKECASE(oidx) case oidx: oidName = #oidx; break;
2317
2318 MAKECASE(OID_GEN_SUPPORTED_LIST)
2319 MAKECASE(OID_GEN_HARDWARE_STATUS)
2320 MAKECASE(OID_GEN_MEDIA_SUPPORTED)
2321 MAKECASE(OID_GEN_MEDIA_IN_USE)
2322 MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD)
2323 MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE)
2324 MAKECASE(OID_GEN_LINK_SPEED)
2325 MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE)
2326 MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE)
2327 MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE)
2328 MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE)
2329 MAKECASE(OID_GEN_VENDOR_ID)
2330 MAKECASE(OID_GEN_VENDOR_DESCRIPTION)
2331 MAKECASE(OID_GEN_CURRENT_PACKET_FILTER)
2332 MAKECASE(OID_GEN_CURRENT_LOOKAHEAD)
2333 MAKECASE(OID_GEN_DRIVER_VERSION)
2334 MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE)
2335 MAKECASE(OID_GEN_PROTOCOL_OPTIONS)
2336 MAKECASE(OID_GEN_MAC_OPTIONS)
2337 MAKECASE(OID_GEN_MEDIA_CONNECT_STATUS)
2338 MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS)
2339 MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION)
2340 MAKECASE(OID_GEN_SUPPORTED_GUIDS)
2341 MAKECASE(OID_GEN_NETWORK_LAYER_ADDRESSES)
2342 MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET)
2343 MAKECASE(OID_GEN_MEDIA_CAPABILITIES)
2344 MAKECASE(OID_GEN_PHYSICAL_MEDIUM)
2345 MAKECASE(OID_GEN_XMIT_OK)
2346 MAKECASE(OID_GEN_RCV_OK)
2347 MAKECASE(OID_GEN_XMIT_ERROR)
2348 MAKECASE(OID_GEN_RCV_ERROR)
2349 MAKECASE(OID_GEN_RCV_NO_BUFFER)
2350 MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT)
2351 MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT)
2352 MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT)
2353 MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT)
2354 MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT)
2355 MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT)
2356 MAKECASE(OID_GEN_DIRECTED_BYTES_RCV)
2357 MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV)
2358 MAKECASE(OID_GEN_MULTICAST_BYTES_RCV)
2359 MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV)
2360 MAKECASE(OID_GEN_BROADCAST_BYTES_RCV)
2361 MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV)
2362 MAKECASE(OID_GEN_RCV_CRC_ERROR)
2363 MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH)
2364 MAKECASE(OID_GEN_GET_TIME_CAPS)
2365 MAKECASE(OID_GEN_GET_NETCARD_TIME)
2366 MAKECASE(OID_GEN_NETCARD_LOAD)
2367 MAKECASE(OID_GEN_DEVICE_PROFILE)
2368 MAKECASE(OID_GEN_INIT_TIME_MS)
2369 MAKECASE(OID_GEN_RESET_COUNTS)
2370 MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS)
2371 MAKECASE(OID_PNP_CAPABILITIES)
2372 MAKECASE(OID_PNP_SET_POWER)
2373 MAKECASE(OID_PNP_QUERY_POWER)
2374 MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN)
2375 MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN)
2376 MAKECASE(OID_PNP_ENABLE_WAKE_UP)
2377 MAKECASE(OID_802_3_PERMANENT_ADDRESS)
2378 MAKECASE(OID_802_3_CURRENT_ADDRESS)
2379 MAKECASE(OID_802_3_MULTICAST_LIST)
2380 MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE)
2381 MAKECASE(OID_802_3_MAC_OPTIONS)
2382 MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT)
2383 MAKECASE(OID_802_3_XMIT_ONE_COLLISION)
2384 MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS)
2385 MAKECASE(OID_802_3_XMIT_DEFERRED)
2386 MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS)
2387 MAKECASE(OID_802_3_RCV_OVERRUN)
2388 MAKECASE(OID_802_3_XMIT_UNDERRUN)
2389 MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE)
2390 MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST)
2391 MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS)
2392
2393 default:
2394 oidName = "<** UNKNOWN OID **>";
2395 break;
2396 }
2397
2398 return oidName;
2399}
2400#endif
2401
2402/**
2403 * NDIS Miniport entry point called whenever protocols are done with
2404 * a packet that we had indicated up and they had queued up for returning
2405 * later.
2406 *
2407 * @param MiniportAdapterContext - pointer to ADAPT structure
2408 * @param Packet - packet being returned.
2409 * @return None. */
2410DECLHIDDEN(VOID)
2411vboxNetFltWinMpReturnPacket(
2412 IN NDIS_HANDLE MiniportAdapterContext,
2413 IN PNDIS_PACKET Packet
2414 )
2415{
2416 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2417
2418 {
2419 /*
2420 * This is a packet allocated from this IM's receive packet pool.
2421 * Reclaim our packet, and return the original to the driver below.
2422 */
2423
2424 PNDIS_PACKET MyPacket;
2425 PRECV_RSVD RecvRsvd;
2426
2427 RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved);
2428 MyPacket = RecvRsvd->pOriginalPkt;
2429
2430 if(MyPacket)
2431 {
2432 /* the packet was sent from underlying miniport */
2433 NdisFreePacket(Packet);
2434 NdisReturnPackets(&MyPacket, 1);
2435 }
2436 else
2437 {
2438 PVOID pBufToFree = RecvRsvd->pBufToFree;
2439
2440 /* the packet was sent from NetFlt */
2441 vboxNetFltWinFreeSGNdisPacket(Packet, !pBufToFree);
2442 if(pBufToFree)
2443 {
2444 vboxNetFltWinMemFree(pBufToFree);
2445 }
2446 }
2447
2448 vboxNetFltWinDereferenceAdapt(pAdapt);
2449 }
2450}
2451
2452/** Miniport's transfer data handler.
2453 *
2454 * @param Packet Destination packet
2455 * @param BytesTransferred Place-holder for how much data was copied
2456 * @param MiniportAdapterContext Pointer to the adapter structure
2457 * @param MiniportReceiveContext Context
2458 * @param ByteOffset Offset into the packet for copying data
2459 * @param BytesToTransfer How much to copy.
2460 * @return Status of transfer */
2461static NDIS_STATUS
2462vboxNetFltWinMpTransferData(
2463 OUT PNDIS_PACKET Packet,
2464 OUT PUINT BytesTransferred,
2465 IN NDIS_HANDLE MiniportAdapterContext,
2466 IN NDIS_HANDLE MiniportReceiveContext,
2467 IN UINT ByteOffset,
2468 IN UINT BytesToTransfer
2469 )
2470{
2471#ifndef VBOXNETADP
2472
2473 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2474 NDIS_STATUS Status;
2475
2476 /*
2477 * Return, if the device is OFF
2478 */
2479 if (vboxNetFltWinGetPowerState(&pAdapt->PTState) != NdisDeviceStateD0
2480 || vboxNetFltWinGetPowerState(&pAdapt->MPState) != NdisDeviceStateD0)
2481 {
2482 return NDIS_STATUS_FAILURE;
2483 }
2484
2485 NdisTransferData(&Status,
2486 pAdapt->hBindingHandle,
2487 MiniportReceiveContext,
2488 ByteOffset,
2489 BytesToTransfer,
2490 Packet,
2491 BytesTransferred);
2492
2493 return(Status);
2494#else
2495 /* should never be here */
2496 Assert(0);
2497 return NDIS_STATUS_FAILURE;
2498#endif
2499}
2500
2501/**
2502 * Halt handler. All the hard-work for clean-up is done here.
2503 *
2504 * @param MiniportAdapterContext Pointer to the Adapter
2505 * @return None. */
2506static VOID
2507vboxNetFltWinMpHalt(
2508 IN NDIS_HANDLE MiniportAdapterContext
2509 )
2510{
2511 PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
2512#ifndef VBOXNETADP
2513 NDIS_STATUS Status;
2514#endif
2515
2516 LogFlow(("==>MiniportHalt: Adapt %p\n", pAdapt));
2517
2518#ifndef VBOXNETADP
2519// Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing);
2520// if(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing)
2521 if(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Disconnecting)
2522 {
2523 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitializing);
2524 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
2525 /* we're called from protocolUnbinAdapter, do our job */
2526 /*
2527 * If we have a valid bind, close the miniport below the protocol
2528 */
2529 vboxNetFltWinPtCloseAdapter(pAdapt, &Status);
2530
2531 Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitializing);
2532 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
2533 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2534 }
2535 else
2536#endif
2537 {
2538 /* we're NOT called from protocolUnbinAdapter, perform a full disconnect */
2539 NDIS_STATUS Status;
2540
2541 Assert(/*vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing
2542 ||*/ vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
2543#ifndef VBOXNETADP
2544 AssertBreakpoint();
2545#endif
2546 Status = vboxNetFltWinDetachFromInterface(pAdapt, false);
2547 Assert(Status == NDIS_STATUS_SUCCESS);
2548/* you can not access the pAdapt after closure
2549 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2550 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2551#ifndef VBOXNETADP
2552 Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitialized);
2553 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
2554#endif
2555*/
2556 }
2557
2558 LogFlow(("<== MiniportHalt: pAdapt %p\n", pAdapt));
2559}
2560
2561/**
2562 * register the miniport edge
2563 */
2564DECLHIDDEN(NDIS_STATUS)
2565vboxNetFltWinMpRegister(
2566 IN PDRIVER_OBJECT DriverObject,
2567 IN PUNICODE_STRING RegistryPath
2568 )
2569{
2570 NDIS_MINIPORT_CHARACTERISTICS MChars;
2571 NDIS_STATUS Status;
2572
2573 NdisMInitializeWrapper(&g_hNdisWrapperHandle, DriverObject, RegistryPath, NULL);
2574
2575 /*
2576 * Register the miniport with NDIS. Note that it is the miniport
2577 * which was started as a driver and not the protocol. Also the miniport
2578 * must be registered prior to the protocol since the protocol's BindAdapter
2579 * handler can be initiated anytime and when it is, it must be ready to
2580 * start driver instances.
2581 */
2582
2583 NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
2584
2585 MChars.MajorNdisVersion = VBOXNETFLT_MAJOR_NDIS_VERSION;
2586 MChars.MinorNdisVersion = VBOXNETFLT_MINOR_NDIS_VERSION;
2587
2588 MChars.InitializeHandler = vboxNetFltWinMpInitialize;
2589 MChars.QueryInformationHandler = vboxNetFltWinMpQueryInformation;
2590 MChars.SetInformationHandler = vboxNetFltWinMpSetInformation;
2591 MChars.ResetHandler = NULL;
2592 MChars.TransferDataHandler = vboxNetFltWinMpTransferData;
2593 MChars.HaltHandler = vboxNetFltWinMpHalt;
2594
2595 /*
2596 * We will disable the check for hang timeout so we do not
2597 * need a check for hang handler!
2598 */
2599 MChars.CheckForHangHandler = NULL;
2600 MChars.ReturnPacketHandler = vboxNetFltWinMpReturnPacket;
2601
2602 /*
2603 * Either the Send or the SendPackets handler should be specified.
2604 * If SendPackets handler is specified, SendHandler is ignored
2605 */
2606 MChars.SendHandler = NULL; /* vboxNetFltWinMpSend; */
2607 MChars.SendPacketsHandler = vboxNetFltWinMpSendPackets;
2608
2609#ifndef VBOXNETADP
2610 Status = NdisIMRegisterLayeredMiniport(g_hNdisWrapperHandle,
2611 &MChars,
2612 sizeof(MChars),
2613 &g_hDriverHandle);
2614#else
2615 Status = NdisMRegisterMiniport(
2616 g_hNdisWrapperHandle,
2617 &MChars,
2618 sizeof(MChars));
2619#endif
2620 if(Status == NDIS_STATUS_SUCCESS)
2621 {
2622# ifndef WIN9X
2623 NdisMRegisterUnloadHandler(g_hNdisWrapperHandle, vboxNetFltWinUnload);
2624# endif
2625 }
2626
2627 return Status;
2628}
2629
2630/**
2631 * deregister the miniport edge
2632 */
2633DECLHIDDEN(NDIS_STATUS)
2634vboxNetFltWinMpDeregister()
2635{
2636#ifndef VBOXNETADP
2637 NdisIMDeregisterLayeredMiniport(g_hDriverHandle);
2638#else
2639 /* don't need to do anything here */
2640#endif
2641 NdisTerminateWrapper(g_hNdisWrapperHandle, NULL);
2642 return NDIS_STATUS_SUCCESS;
2643}
2644
2645#ifndef VBOXNETADP
2646/**
2647 * return the miniport edge handle
2648 */
2649DECLHIDDEN(NDIS_HANDLE) vboxNetFltWinMpGetHandle()
2650{
2651 return g_hDriverHandle;
2652}
2653
2654/**
2655 * initialize the instance of a device used for ioctl handling
2656 */
2657DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpInitializeDevideInstance(PADAPT pAdapt)
2658{
2659 NDIS_STATUS Status;
2660 /*
2661 * Now ask NDIS to initialize our miniport (upper) edge.
2662 * Set the flag below to synchronize with a possible call
2663 * to our protocol Unbind handler that may come in before
2664 * our miniport initialization happens.
2665 */
2666 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2667 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initializing);
2668 /* this is doe in vboxNetFltWinPtInitPADAPT*/
2669 /* NdisInitializeEvent(&pAdapt->MiniportInitEvent); */
2670
2671 Status = NdisIMInitializeDeviceInstanceEx(g_hDriverHandle,
2672 &pAdapt->DeviceName,
2673 pAdapt);
2674 /* ensure we're taking into account the pAdapt->Status if our miniport halt handler was called */
2675 if(Status == NDIS_STATUS_SUCCESS)
2676 {
2677 if(pAdapt->Status == NDIS_STATUS_SUCCESS)
2678 {
2679// Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
2680// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
2681 return NDIS_STATUS_SUCCESS;
2682 }
2683 AssertBreakpoint();
2684 vboxNetFltWinMpDeInitializeDevideInstance(pAdapt, &Status);
2685 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2686 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2687 return pAdapt->Status;
2688 }
2689 else
2690 {
2691 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
2692 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2693 }
2694 return Status;
2695}
2696
2697/**
2698 * deinitialize the instance of a device used for ioctl handling
2699 */
2700DECLHIDDEN(bool) vboxNetFltWinMpDeInitializeDevideInstance(PADAPT pAdapt, PNDIS_STATUS pStatus)
2701{
2702# ifndef WIN9X
2703 NDIS_STATUS LocalStatus;
2704 /*
2705 * Check if we had called NdisIMInitializeDeviceInstanceEx and
2706 * we are awaiting a call to MiniportInitialize.
2707 */
2708 if (vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initializing)
2709 {
2710 /*
2711 * Try to cancel the pending IMInit process.
2712 */
2713 LocalStatus = NdisIMCancelInitializeDeviceInstance(
2714 g_hDriverHandle,
2715 &pAdapt->DeviceName);
2716
2717 if (LocalStatus == NDIS_STATUS_SUCCESS)
2718 {
2719 /*
2720 * Successfully cancelled IM Initialization; our
2721 * Miniport Initialize routine will not be called
2722 * for this device.
2723 */
2724 Assert(pAdapt->hMiniportHandle == NULL);
2725 }
2726 else
2727 {
2728 /*
2729 * Our Miniport Initialize routine will be called
2730 * (may be running on another thread at this time).
2731 * Wait for it to finish.
2732 */
2733 NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);
2734 }
2735
2736 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2737 }
2738#endif
2739
2740 /*
2741 * Call NDIS to remove our device-instance. We do most of the work
2742 * inside the HaltHandler.
2743 *
2744 * The Handle will be NULL if our miniport Halt Handler has been called or
2745 * if the IM device was never initialized
2746 */
2747
2748 if (vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized)
2749 {
2750 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
2751
2752 *pStatus = NdisIMDeInitializeDeviceInstance(pAdapt->hMiniportHandle);
2753
2754 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2755
2756 if (*pStatus != NDIS_STATUS_SUCCESS)
2757 {
2758 *pStatus = NDIS_STATUS_FAILURE;
2759 }
2760
2761 return true;
2762 }
2763
2764 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
2765
2766 return false;
2767}
2768#endif
2769
2770DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpReferenceControlDevice()
2771{
2772 return vboxNetFltWinPtRegisterDevice();
2773}
2774
2775DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDereferenceControlDevice()
2776{
2777 return vboxNetFltWinPtDeregisterDevice();
2778}
2779
2780#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND*/
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette