VirtualBox

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

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

netflt/win: wait for pending ops to complete before switching netflt mode on/off

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