VirtualBox

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

Last change on this file since 21361 was 21343, checked in by vboxsync, 16 years ago

export vboxnetflt for Windows to OSE

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