VirtualBox

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

Last change on this file since 32189 was 29592, checked in by vboxsync, 14 years ago

netflt/win: fix loopback packets handling for no-packet-queue

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