VirtualBox

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

Last change on this file since 24026 was 23927, checked in by vboxsync, 16 years ago

netflt/win: alternative loopback handling mechanism (disabled for now)

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

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