VirtualBox

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

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

build fixes.

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