VirtualBox

Changeset 60333 in vbox for trunk


Ignore:
Timestamp:
Apr 5, 2016 1:26:26 PM (9 years ago)
Author:
vboxsync
Message:

VBoxNetLwf: Removed packet dump code from release build to prevent crashes in packet parsing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetLwf-win.cpp

    r60278 r60333  
    489489    return "invalid";
    490490}
    491 
    492 #else /* !DEBUG */
    493 #define vboxNetLwfWinDumpFilterTypes(uFlags)
    494 #define vboxNetLwfWinDumpOffloadSettings(p)
    495 #define vboxNetLwfWinDumpSetOffloadSettings(p)
    496 #endif /* DEBUG */
    497 
    498 DECLINLINE(bool) vboxNetLwfWinChangeState(PVBOXNETLWF_MODULE pModuleCtx, uint32_t enmNew, uint32_t enmOld = LwfState_32BitHack)
    499 {
    500     AssertReturn(pModuleCtx, false);
    501 
    502     bool fSuccess = true;
    503     if (enmOld != LwfState_32BitHack)
    504     {
    505         fSuccess = ASMAtomicCmpXchgU32(&pModuleCtx->enmState, enmNew, enmOld);
    506         if (fSuccess)
    507             Log(("vboxNetLwfWinChangeState: state change %s -> %s\n",
    508                  vboxNetLwfWinStateToText(enmOld),
    509                  vboxNetLwfWinStateToText(enmNew)));
    510         else
    511             Log(("ERROR! vboxNetLwfWinChangeState: failed state change %s (actual=%s) -> %s\n",
    512                  vboxNetLwfWinStateToText(enmOld),
    513                  vboxNetLwfWinStateToText(ASMAtomicReadU32(&pModuleCtx->enmState)),
    514                  vboxNetLwfWinStateToText(enmNew)));
    515         Assert(fSuccess);
    516     }
    517     else
    518     {
    519         uint32_t enmPrevState = ASMAtomicXchgU32(&pModuleCtx->enmState, enmNew);
    520         Log(("vboxNetLwfWinChangeState: state change %s -> %s\n",
    521              vboxNetLwfWinStateToText(enmPrevState),
    522              vboxNetLwfWinStateToText(enmNew)));
    523     }
    524     return fSuccess;
    525 }
    526 
    527 DECLINLINE(void) vboxNetLwfWinInitOidRequest(PVBOXNETLWF_OIDREQ pRequest)
    528 {
    529     NdisZeroMemory(pRequest, sizeof(VBOXNETLWF_OIDREQ));
    530 
    531     NdisInitializeEvent(&pRequest->Event);
    532 
    533     pRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
    534     pRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1;
    535     pRequest->Request.Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
    536 
    537     pRequest->Request.RequestId = (PVOID)VBOXNETLWF_REQ_ID;
    538 }
    539 
    540 static NDIS_STATUS vboxNetLwfWinSyncOidRequest(PVBOXNETLWF_MODULE pModuleCtx, PVBOXNETLWF_OIDREQ pRequest)
    541 {
    542     NDIS_STATUS Status = NdisFOidRequest(pModuleCtx->hFilter, &pRequest->Request);
    543     if (Status == NDIS_STATUS_PENDING)
    544     {
    545         NdisWaitEvent(&pRequest->Event, 0);
    546         Status = pRequest->Status;
    547     }
    548     return Status;
    549 }
    550 
    551 DECLINLINE(void) vboxNetLwfWinCopyOidRequestResults(PNDIS_OID_REQUEST pFrom, PNDIS_OID_REQUEST pTo)
    552 {
    553     switch (pFrom->RequestType)
    554     {
    555         case NdisRequestSetInformation:
    556             pTo->DATA.SET_INFORMATION.BytesRead   = pFrom->DATA.SET_INFORMATION.BytesRead;
    557             pTo->DATA.SET_INFORMATION.BytesNeeded = pFrom->DATA.SET_INFORMATION.BytesNeeded;
    558             break;
    559         case NdisRequestMethod:
    560             pTo->DATA.METHOD_INFORMATION.OutputBufferLength = pFrom->DATA.METHOD_INFORMATION.OutputBufferLength;
    561             pTo->DATA.METHOD_INFORMATION.BytesWritten       = pFrom->DATA.METHOD_INFORMATION.BytesWritten;
    562             pTo->DATA.METHOD_INFORMATION.BytesRead          = pFrom->DATA.METHOD_INFORMATION.BytesRead;
    563             pTo->DATA.METHOD_INFORMATION.BytesNeeded        = pFrom->DATA.METHOD_INFORMATION.BytesNeeded;
    564             break;
    565         case NdisRequestQueryInformation:
    566         case NdisRequestQueryStatistics:
    567         default:
    568             pTo->DATA.QUERY_INFORMATION.BytesWritten = pFrom->DATA.QUERY_INFORMATION.BytesWritten;
    569             pTo->DATA.QUERY_INFORMATION.BytesNeeded  = pFrom->DATA.QUERY_INFORMATION.BytesNeeded;
    570     }
    571 }
    572 
    573 void inline vboxNetLwfWinOverridePacketFiltersUp(PVBOXNETLWF_MODULE pModuleCtx, ULONG *pFilters)
    574 {
    575     if (ASMAtomicReadBool(&pModuleCtx->fActive) && !ASMAtomicReadBool(&pModuleCtx->fHostPromisc))
    576         *pFilters &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
    577 }
    578 
    579 NDIS_STATUS vboxNetLwfWinOidRequest(IN NDIS_HANDLE hModuleCtx,
    580                                     IN PNDIS_OID_REQUEST pOidRequest)
    581 {
    582     LogFlow(("==>vboxNetLwfWinOidRequest: module=%p\n", hModuleCtx));
    583     vboxNetCmnWinDumpOidRequest(__FUNCTION__, pOidRequest);
    584     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
    585     PNDIS_OID_REQUEST pClone = NULL;
    586     NDIS_STATUS Status = NdisAllocateCloneOidRequest(pModuleCtx->hFilter,
    587                                                      pOidRequest,
    588                                                      VBOXNETLWF_MEM_TAG,
    589                                                      &pClone);
    590     if (Status == NDIS_STATUS_SUCCESS)
    591     {
    592         /* Save the pointer to the original */
    593         *((PNDIS_OID_REQUEST*)(pClone->SourceReserved)) = pOidRequest;
    594 
    595         pClone->RequestId = pOidRequest->RequestId;
    596         /* We are not supposed to get another request until we are through with the one we "postponed" */
    597         PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, pClone, PNDIS_OID_REQUEST);
    598         Assert(pPrev == NULL);
    599         pModuleCtx->pPendingRequest = pClone;
    600         if (pOidRequest->RequestType == NdisRequestSetInformation
    601             && pOidRequest->DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
    602         {
    603             ASMAtomicWriteBool(&pModuleCtx->fHostPromisc, !!(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer & NDIS_PACKET_TYPE_PROMISCUOUS));
    604             Log(("vboxNetLwfWinOidRequest: host wanted to set packet filter value to:\n"));
    605             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
    606             /* Keep adapter in promisc mode as long as we are active. */
    607             if (ASMAtomicReadBool(&pModuleCtx->fActive))
    608                 *(ULONG*)pClone->DATA.SET_INFORMATION.InformationBuffer |= NDIS_PACKET_TYPE_PROMISCUOUS;
    609             Log5(("vboxNetLwfWinOidRequest: pass the following packet filters to miniport:\n"));
    610             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
    611         }
    612         if (pOidRequest->RequestType == NdisRequestSetInformation
    613             && pOidRequest->DATA.SET_INFORMATION.Oid == OID_TCP_OFFLOAD_CURRENT_CONFIG)
    614         {
    615             Log5(("vboxNetLwfWinOidRequest: offloading set to:\n"));
    616             vboxNetLwfWinDumpSetOffloadSettings((PNDIS_OFFLOAD)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
    617         }
    618 
    619         /* Forward the clone to underlying filters/miniport */
    620         Status = NdisFOidRequest(pModuleCtx->hFilter, pClone);
    621         if (Status != NDIS_STATUS_PENDING)
    622         {
    623             /* Synchronous completion */
    624             pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
    625             Assert(pPrev == pClone);
    626             Log5(("vboxNetLwfWinOidRequest: got the following packet filters from miniport:\n"));
    627             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    628             /*
    629              * The host does not expect the adapter to be in promisc mode,
    630              * unless it enabled the mode. Let's not disillusion it.
    631              */
    632             if (   pOidRequest->RequestType == NdisRequestQueryInformation
    633                 && pOidRequest->DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
    634                 vboxNetLwfWinOverridePacketFiltersUp(pModuleCtx, (ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    635             Log5(("vboxNetLwfWinOidRequest: reporting to the host the following packet filters:\n"));
    636             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    637             vboxNetLwfWinCopyOidRequestResults(pClone, pOidRequest);
    638             NdisFreeCloneOidRequest(pModuleCtx->hFilter, pClone);
    639         }
    640         /* In case of async completion we do the rest in vboxNetLwfWinOidRequestComplete() */
    641     }
    642     else
    643     {
    644         LogError(("vboxNetLwfWinOidRequest: NdisAllocateCloneOidRequest failed with 0x%x\n", Status));
    645     }
    646     LogFlow(("<==vboxNetLwfWinOidRequest: Status=0x%x\n", Status));
    647     return Status;
    648 }
    649 
    650 VOID vboxNetLwfWinOidRequestComplete(IN NDIS_HANDLE hModuleCtx,
    651                                      IN PNDIS_OID_REQUEST pRequest,
    652                                      IN NDIS_STATUS Status)
    653 {
    654     LogFlow(("==>vboxNetLwfWinOidRequestComplete: module=%p req=%p status=0x%x\n", hModuleCtx, pRequest, Status));
    655     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
    656     PNDIS_OID_REQUEST pOriginal = *((PNDIS_OID_REQUEST*)(pRequest->SourceReserved));
    657     if (pOriginal)
    658     {
    659         /* NDIS is supposed to serialize requests */
    660         PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
    661         Assert(pPrev == pRequest);
    662 
    663         Log5(("vboxNetLwfWinOidRequestComplete: completed rq type=%d oid=%x\n", pRequest->RequestType, pRequest->DATA.QUERY_INFORMATION.Oid));
    664         vboxNetLwfWinCopyOidRequestResults(pRequest, pOriginal);
    665         if (   pRequest->RequestType == NdisRequestQueryInformation
    666             && pRequest->DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
    667         {
    668             Log5(("vboxNetLwfWinOidRequestComplete: underlying miniport reports its packet filters:\n"));
    669             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    670             vboxNetLwfWinOverridePacketFiltersUp(pModuleCtx, (ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    671             Log5(("vboxNetLwfWinOidRequestComplete: reporting the following packet filters to upper protocol:\n"));
    672             vboxNetLwfWinDumpFilterTypes(*(ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
    673         }
    674         NdisFreeCloneOidRequest(pModuleCtx->hFilter, pRequest);
    675         NdisFOidRequestComplete(pModuleCtx->hFilter, pOriginal, Status);
    676     }
    677     else
    678     {
    679         /* This is not a clone, we originated it */
    680         Log(("vboxNetLwfWinOidRequestComplete: locally originated request (%p) completed, status=0x%x\n", pRequest, Status));
    681         PVBOXNETLWF_OIDREQ pRqWrapper = RT_FROM_MEMBER(pRequest, VBOXNETLWF_OIDREQ, Request);
    682         pRqWrapper->Status = Status;
    683         NdisSetEvent(&pRqWrapper->Event);
    684     }
    685     LogFlow(("<==vboxNetLwfWinOidRequestComplete\n"));
    686 }
    687 
    688 
    689 static bool vboxNetLwfWinIsPromiscuous(PVBOXNETLWF_MODULE pModuleCtx)
    690 {
    691     return ASMAtomicReadBool(&pModuleCtx->fHostPromisc);
    692 }
    693 
    694 #if 0
    695 static NDIS_STATUS vboxNetLwfWinGetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx)
    696 {
    697     LogFlow(("==>vboxNetLwfWinGetPacketFilter: module=%p\n", pModuleCtx));
    698     VBOXNETLWF_OIDREQ Rq;
    699     vboxNetLwfWinInitOidRequest(&Rq);
    700     Rq.Request.RequestType = NdisRequestQueryInformation;
    701     Rq.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
    702     Rq.Request.DATA.QUERY_INFORMATION.InformationBuffer = &pModuleCtx->uPacketFilter;
    703     Rq.Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pModuleCtx->uPacketFilter);
    704     NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
    705     if (Status != NDIS_STATUS_SUCCESS)
    706     {
    707         LogError(("vboxNetLwfWinGetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed with 0x%x\n", Status));
    708         return FALSE;
    709     }
    710     if (Rq.Request.DATA.QUERY_INFORMATION.BytesWritten != sizeof(pModuleCtx->uPacketFilter))
    711     {
    712         LogError(("vboxNetLwfWinGetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed to write neccessary amount (%d bytes), actually written %d bytes\n", sizeof(pModuleCtx->uPacketFilter), Rq.Request.DATA.QUERY_INFORMATION.BytesWritten));
    713     }
    714 
    715     Log5(("vboxNetLwfWinGetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER query returned the following filters:\n"));
    716     vboxNetLwfWinDumpFilterTypes(pModuleCtx->uPacketFilter);
    717 
    718     LogFlow(("<==vboxNetLwfWinGetPacketFilter: status=0x%x\n", Status));
    719     return Status;
    720 }
    721 #endif
    722 
    723 static NDIS_STATUS vboxNetLwfWinSetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx, bool fPromisc)
    724 {
    725     LogFlow(("==>vboxNetLwfWinSetPacketFilter: module=%p %s\n", pModuleCtx, fPromisc ? "promiscuous" : "normal"));
    726     ULONG uFilter = 0;
    727     VBOXNETLWF_OIDREQ Rq;
    728     vboxNetLwfWinInitOidRequest(&Rq);
    729     Rq.Request.RequestType = NdisRequestQueryInformation;
    730     Rq.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
    731     Rq.Request.DATA.QUERY_INFORMATION.InformationBuffer = &uFilter;
    732     Rq.Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(uFilter);
    733     NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
    734     if (Status != NDIS_STATUS_SUCCESS)
    735     {
    736         LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed with 0x%x\n", Status));
    737         return Status;
    738     }
    739     if (Rq.Request.DATA.QUERY_INFORMATION.BytesWritten != sizeof(uFilter))
    740     {
    741         LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed to write neccessary amount (%d bytes), actually written %d bytes\n", sizeof(uFilter), Rq.Request.DATA.QUERY_INFORMATION.BytesWritten));
    742         return NDIS_STATUS_FAILURE;
    743     }
    744 
    745     Log5(("vboxNetLwfWinSetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER query returned the following filters:\n"));
    746     vboxNetLwfWinDumpFilterTypes(uFilter);
    747 
    748     if (fPromisc)
    749     {
    750         /* If we about to go promiscuous, save the state before we change it. */
    751         ASMAtomicWriteBool(&pModuleCtx->fHostPromisc, !!(uFilter & NDIS_PACKET_TYPE_PROMISCUOUS));
    752         uFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
    753     }
    754     else
    755     {
    756         /* Reset promisc only if it was not enabled before we had changed it. */
    757         if (!ASMAtomicReadBool(&pModuleCtx->fHostPromisc))
    758             uFilter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
    759     }
    760 
    761     Log5(("vboxNetLwfWinSetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER about to set the following filters:\n"));
    762     vboxNetLwfWinDumpFilterTypes(uFilter);
    763 
    764     NdisResetEvent(&Rq.Event); /* need to reset as it has been set by query op */
    765     Rq.Request.RequestType = NdisRequestSetInformation;
    766     Rq.Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
    767     Rq.Request.DATA.SET_INFORMATION.InformationBuffer = &uFilter;
    768     Rq.Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(uFilter);
    769     Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
    770     if (Status != NDIS_STATUS_SUCCESS)
    771     {
    772         LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(set, OID_GEN_CURRENT_PACKET_FILTER, vvv below vvv) failed with 0x%x\n", Status));
    773         vboxNetLwfWinDumpFilterTypes(uFilter);
    774     }
    775     LogFlow(("<==vboxNetLwfWinSetPacketFilter: status=0x%x\n", Status));
    776     return Status;
    777 }
    778 
    779 
    780 static NTSTATUS vboxNetLwfWinDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
    781 {
    782     PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);;
    783     NTSTATUS Status = STATUS_SUCCESS;
    784 
    785     switch (pIrpSl->MajorFunction)
    786     {
    787         case IRP_MJ_DEVICE_CONTROL:
    788             Status = STATUS_NOT_SUPPORTED;
    789             break;
    790         case IRP_MJ_CREATE:
    791         case IRP_MJ_CLEANUP:
    792         case IRP_MJ_CLOSE:
    793             break;
    794         default:
    795             Assert(0);
    796             break;
    797     }
    798 
    799     pIrp->IoStatus.Status = Status;
    800     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    801 
    802     return Status;
    803 }
    804 
    805 /** @todo So far we had no use for device, should we even bother to create it? */
    806 static NDIS_STATUS vboxNetLwfWinDevCreate(PVBOXNETLWFGLOBALS pGlobals)
    807 {
    808     NDIS_STRING DevName, LinkName;
    809     PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
    810     NdisInitUnicodeString(&DevName, VBOXNETLWF_NAME_DEVICE);
    811     NdisInitUnicodeString(&LinkName, VBOXNETLWF_NAME_LINK);
    812 
    813     Assert(!pGlobals->hDevice);
    814     Assert(!pGlobals->pDevObj);
    815     NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
    816     aMajorFunctions[IRP_MJ_CREATE] = vboxNetLwfWinDevDispatch;
    817     aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetLwfWinDevDispatch;
    818     aMajorFunctions[IRP_MJ_CLOSE] = vboxNetLwfWinDevDispatch;
    819     aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetLwfWinDevDispatch;
    820 
    821     NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttributes;
    822     NdisZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
    823     DeviceAttributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
    824     DeviceAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
    825     DeviceAttributes.Header.Size = sizeof(DeviceAttributes);
    826     DeviceAttributes.DeviceName = &DevName;
    827     DeviceAttributes.SymbolicName = &LinkName;
    828     DeviceAttributes.MajorFunctions = aMajorFunctions;
    829     //DeviceAttributes.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION);
    830 
    831     NDIS_STATUS Status = NdisRegisterDeviceEx(pGlobals->hFilterDriver,
    832                                               &DeviceAttributes,
    833                                               &pGlobals->pDevObj,
    834                                               &pGlobals->hDevice);
    835     Log(("vboxNetLwfWinDevCreate: NdisRegisterDeviceEx returned 0x%x\n", Status));
    836     Assert(Status == NDIS_STATUS_SUCCESS);
    837 #if 0
    838     if (Status == NDIS_STATUS_SUCCESS)
    839     {
    840         PFILTER_DEVICE_EXTENSION pExtension;
    841         pExtension = NdisGetDeviceReservedExtension(pGlobals->pDevObj);
    842         pExtension->Signature = VBOXNETLWF_MEM_TAG;
    843         pExtension->Handle = pGlobals->hFilterDriver;
    844     }
    845 #endif
    846     return Status;
    847 }
    848 
    849 static void vboxNetLwfWinDevDestroy(PVBOXNETLWFGLOBALS pGlobals)
    850 {
    851     Assert(pGlobals->hDevice);
    852     Assert(pGlobals->pDevObj);
    853     NdisDeregisterDeviceEx(pGlobals->hDevice);
    854     pGlobals->hDevice = NULL;
    855     pGlobals->pDevObj = NULL;
    856 }
    857 
    858 static void vboxNetLwfWinUpdateSavedOffloadConfig(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)
    859 {
    860     pModuleCtx->SavedOffloadConfig = *pOffload;
    861     pModuleCtx->fOffloadConfigValid = true;
    862 }
    863 
    864 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS
    865 static void vboxNetLwfWinFreePools(PVBOXNETLWF_MODULE pModuleCtx, int cPools)
    866 {
    867     for (int i = 0; i < cPools; ++i)
    868     {
    869         if (pModuleCtx->hPool[i])
    870         {
    871             NdisFreeNetBufferListPool(pModuleCtx->hPool[i]);
    872             Log4(("vboxNetLwfWinAttach: freeed NBL+NB pool 0x%p\n", pModuleCtx->hPool[i]));
    873         }
    874     }
    875 }
    876 #endif /* VBOXNETLWF_FIXED_SIZE_POOLS */
    877 
    878 static NDIS_STATUS vboxNetLwfWinAttach(IN NDIS_HANDLE hFilter, IN NDIS_HANDLE hDriverCtx,
    879                                        IN PNDIS_FILTER_ATTACH_PARAMETERS pParameters)
    880 {
    881     LogFlow(("==>vboxNetLwfWinAttach: filter=%p\n", hFilter));
    882 
    883     PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)hDriverCtx;
    884     if (!pGlobals)
    885     {
    886         vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 1);
    887         return NDIS_STATUS_FAILURE;
    888     }
    889 
    890     ANSI_STRING strMiniportName;
    891     /* We use the miniport name to associate this filter module with the netflt instance */
    892     NTSTATUS rc = RtlUnicodeStringToAnsiString(&strMiniportName,
    893                                                pParameters->BaseMiniportName,
    894                                                TRUE);
    895     if (rc != STATUS_SUCCESS)
    896     {
    897         LogError(("vboxNetLwfWinAttach: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",
    898              pParameters->BaseMiniportName, rc));
    899         vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2);
    900         return NDIS_STATUS_FAILURE;
    901     }
    902     DbgPrint("vboxNetLwfWinAttach: friendly name=%wZ\n", pParameters->BaseMiniportInstanceName);
    903     DbgPrint("vboxNetLwfWinAttach: name=%Z\n", &strMiniportName);
    904 
    905     UINT cbModuleWithNameExtra = sizeof(VBOXNETLWF_MODULE) + strMiniportName.Length;
    906     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)NdisAllocateMemoryWithTagPriority(hFilter,
    907                                                                       cbModuleWithNameExtra,
    908                                                                       VBOXNETLWF_MEM_TAG,
    909                                                                       LowPoolPriority);
    910     if (!pModuleCtx)
    911     {
    912         LogError(("vboxNetLwfWinAttach: Failed to allocate module context for %ls\n", pParameters->BaseMiniportName));
    913         RtlFreeAnsiString(&strMiniportName);
    914         vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 3);
    915         return NDIS_STATUS_RESOURCES;
    916     }
    917     Log4(("vboxNetLwfWinAttach: allocated module context 0x%p\n", pModuleCtx));
    918 
    919     NdisZeroMemory(pModuleCtx, cbModuleWithNameExtra);
    920     NdisMoveMemory(pModuleCtx->szMiniportName, strMiniportName.Buffer, strMiniportName.Length);
    921     RtlFreeAnsiString(&strMiniportName);
    922 
    923     pModuleCtx->hWorkItem = NdisAllocateIoWorkItem(g_VBoxNetLwfGlobals.hFilterDriver);
    924     if (!pModuleCtx->hWorkItem)
    925     {
    926         LogError(("vboxNetLwfWinAttach: Failed to allocate work item for %ls\n",
    927                 pParameters->BaseMiniportName));
    928         NdisFreeMemory(pModuleCtx, 0, 0);
    929         vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 4);
    930         return NDIS_STATUS_RESOURCES;
    931     }
    932 
    933     Assert(pParameters->MacAddressLength == sizeof(RTMAC));
    934     NdisMoveMemory(&pModuleCtx->MacAddr, pParameters->CurrentMacAddress, RT_MIN(sizeof(RTMAC), pParameters->MacAddressLength));
    935     if (pParameters->DefaultOffloadConfiguration)
    936         vboxNetLwfWinUpdateSavedOffloadConfig(pModuleCtx, pParameters->DefaultOffloadConfiguration);
    937 
    938     pModuleCtx->pGlobals  = pGlobals;
    939     pModuleCtx->hFilter   = hFilter;
    940     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Attaching);
    941     /* Initialize transmission mutex and events */
    942     NDIS_INIT_MUTEX(&pModuleCtx->InTransmit);
    943 #ifdef VBOXNETLWF_SYNC_SEND
    944     KeInitializeEvent(&pModuleCtx->EventWire, SynchronizationEvent, FALSE);
    945     KeInitializeEvent(&pModuleCtx->EventHost, SynchronizationEvent, FALSE);
    946 #else /* !VBOXNETLWF_SYNC_SEND */
    947     NdisInitializeEvent(&pModuleCtx->EventSendComplete);
    948     pModuleCtx->cPendingBuffers = 0;
    949 #endif /* !VBOXNETLWF_SYNC_SEND */
    950 
    951 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS
    952     for (int i = 0; i < RT_ELEMENTS(g_cbPool); ++i)
    953     {
    954         /* Allocate buffer pools */
    955         NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
    956         NdisZeroMemory(&PoolParams, sizeof(PoolParams));
    957         PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
    958         PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
    959         PoolParams.Header.Size = sizeof(PoolParams);
    960         PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
    961         PoolParams.fAllocateNetBuffer = TRUE;
    962         PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */
    963         PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;
    964         PoolParams.DataSize = g_cbPool[i];
    965         pModuleCtx->hPool[i] = NdisAllocateNetBufferListPool(hFilter, &PoolParams);
    966         if (!pModuleCtx->hPool[i])
    967         {
    968             LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));
    969             vboxNetLwfWinFreePools(pModuleCtx, i);
    970             NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
    971             NdisFreeMemory(pModuleCtx, 0, 0);
    972             return NDIS_STATUS_RESOURCES;
    973         }
    974         Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool (data size=%u) 0x%p\n",
    975               PoolParams.DataSize, pModuleCtx->hPool[i]));
    976     }
    977 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    978     /* Allocate buffer pools */
    979     NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
    980     NdisZeroMemory(&PoolParams, sizeof(PoolParams));
    981     PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
    982     PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
    983     PoolParams.Header.Size = sizeof(PoolParams);
    984     PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
    985     PoolParams.fAllocateNetBuffer = TRUE;
    986     PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */
    987     PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;
    988     pModuleCtx->hPool = NdisAllocateNetBufferListPool(hFilter, &PoolParams);
    989     if (!pModuleCtx->hPool)
    990     {
    991         LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));
    992         NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
    993         NdisFreeMemory(pModuleCtx, 0, 0);
    994         return NDIS_STATUS_RESOURCES;
    995     }
    996     Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool 0x%p\n", pModuleCtx->hPool));
    997 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    998 
    999     NDIS_FILTER_ATTRIBUTES Attributes;
    1000     NdisZeroMemory(&Attributes, sizeof(Attributes));
    1001     Attributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
    1002     Attributes.Header.Size = sizeof(Attributes);
    1003     Attributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
    1004     Attributes.Flags = 0;
    1005     NDIS_STATUS Status = NdisFSetAttributes(hFilter, pModuleCtx, &Attributes);
    1006     if (Status != NDIS_STATUS_SUCCESS)
    1007     {
    1008         LogError(("vboxNetLwfWinAttach: NdisFSetAttributes failed with 0x%x\n", Status));
    1009 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS
    1010         vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));
    1011 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    1012         NdisFreeNetBufferListPool(pModuleCtx->hPool);
    1013         Log4(("vboxNetLwfWinAttach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
    1014 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    1015         NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
    1016         NdisFreeMemory(pModuleCtx, 0, 0);
    1017         vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_RESOURCES, 5);
    1018         return NDIS_STATUS_RESOURCES;
    1019     }
    1020     /* Insert into module chain */
    1021     NdisAcquireSpinLock(&pGlobals->Lock);
    1022     RTListPrepend(&pGlobals->listModules, &pModuleCtx->node);
    1023     NdisReleaseSpinLock(&pGlobals->Lock);
    1024 
    1025     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused);
    1026 
    1027     /// @todo Somehow the packet filter is 0 at this point: Status = vboxNetLwfWinGetPacketFilter(pModuleCtx);
    1028     /// @todo We actually update it later in status handler, perhaps we should not do anything here.
    1029 
    1030     LogFlow(("<==vboxNetLwfWinAttach: Status = 0x%x\n", Status));
    1031     return Status;
    1032 }
    1033 
    1034 static VOID vboxNetLwfWinDetach(IN NDIS_HANDLE hModuleCtx)
    1035 {
    1036     LogFlow(("==>vboxNetLwfWinDetach: module=%p\n", hModuleCtx));
    1037     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
    1038     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Detached, LwfState_Paused);
    1039 
    1040     /* Remove from module chain */
    1041     NdisAcquireSpinLock(&pModuleCtx->pGlobals->Lock);
    1042     RTListNodeRemove(&pModuleCtx->node);
    1043     NdisReleaseSpinLock(&pModuleCtx->pGlobals->Lock);
    1044 
    1045     PVBOXNETFLTINS pNetFltIns = pModuleCtx->pNetFlt; /// @todo Atomic?
    1046     if (pNetFltIns && vboxNetFltTryRetainBusyNotDisconnected(pNetFltIns))
    1047     {
    1048         /*
    1049          * Set hModuleCtx to null now in order to prevent filter restart,
    1050          * OID requests and other stuff associated with NetFlt deactivation.
    1051          */
    1052         pNetFltIns->u.s.WinIf.hModuleCtx = NULL;
    1053         /* Notify NetFlt that we are going down */
    1054         pNetFltIns->pSwitchPort->pfnDisconnect(pNetFltIns->pSwitchPort, &pNetFltIns->MyPort, vboxNetFltPortReleaseBusy);
    1055         /* We do not 'release' netflt instance since it has been done by pfnDisconnect */
    1056     }
    1057     pModuleCtx->pNetFlt = NULL;
    1058 
    1059     /*
    1060      * We have to make sure that all NET_BUFFER_LIST structures have been freed by now, but
    1061      * it does not require us to do anything here since it has already been taken care of
    1062      * by vboxNetLwfWinPause().
    1063      */
    1064 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS
    1065     vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));
    1066 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    1067     if (pModuleCtx->hPool)
    1068     {
    1069         NdisFreeNetBufferListPool(pModuleCtx->hPool);
    1070         Log4(("vboxNetLwfWinDetach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
    1071     }
    1072 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
    1073     NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
    1074     NdisFreeMemory(hModuleCtx, 0, 0);
    1075     Log4(("vboxNetLwfWinDetach: freed module context 0x%p\n", pModuleCtx));
    1076     LogFlow(("<==vboxNetLwfWinDetach\n"));
    1077 }
    1078 
    1079 
    1080 static NDIS_STATUS vboxNetLwfWinPause(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_PAUSE_PARAMETERS pParameters)
    1081 {
    1082     LogFlow(("==>vboxNetLwfWinPause: module=%p\n", hModuleCtx));
    1083     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
    1084     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Pausing, LwfState_Running);
    1085     /* Wait for pending send/indication operations to complete. */
    1086     NDIS_WAIT_FOR_MUTEX(&pModuleCtx->InTransmit);
    1087 #ifndef VBOXNETLWF_SYNC_SEND
    1088     NdisWaitEvent(&pModuleCtx->EventSendComplete, 1000 /* ms */);
    1089 #endif /* !VBOXNETLWF_SYNC_SEND */
    1090     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused, LwfState_Pausing);
    1091     NDIS_RELEASE_MUTEX(&pModuleCtx->InTransmit);
    1092     LogFlow(("<==vboxNetLwfWinPause\n"));
    1093     return NDIS_STATUS_SUCCESS; /* Failure is not an option */
    1094 }
    1095 
    1096 
    1097 static void vboxNetLwfWinIndicateOffload(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)
    1098 {
    1099     Log5(("vboxNetLwfWinIndicateOffload: offload config changed to:\n"));
    1100     vboxNetLwfWinDumpOffloadSettings(pOffload);
    1101     NDIS_STATUS_INDICATION OffloadingIndication;
    1102     NdisZeroMemory(&OffloadingIndication, sizeof(OffloadingIndication));
    1103     OffloadingIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
    1104     OffloadingIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
    1105     OffloadingIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
    1106     OffloadingIndication.SourceHandle = pModuleCtx->hFilter;
    1107     OffloadingIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
    1108     OffloadingIndication.StatusBuffer = pOffload;
    1109     OffloadingIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD);
    1110     NdisFIndicateStatus(pModuleCtx->hFilter, &OffloadingIndication);
    1111 }
    1112 
    1113 
    1114 static NDIS_STATUS vboxNetLwfWinRestart(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_RESTART_PARAMETERS pParameters)
    1115 {
    1116     LogFlow(("==>vboxNetLwfWinRestart: module=%p\n", hModuleCtx));
    1117     PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
    1118     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Restarting, LwfState_Paused);
    1119     vboxNetLwfWinChangeState(pModuleCtx, LwfState_Running, LwfState_Restarting);
    1120     NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    1121     LogFlow(("<==vboxNetLwfWinRestart: Status = 0x%x\n", Status));
    1122     return Status;
    1123 }
    1124 
    1125491
    1126492static void vboxNetLwfWinDumpPackets(const char *pszMsg, PNET_BUFFER_LIST pBufLists)
     
    1287653}
    1288654
     655#else /* !DEBUG */
     656#define vboxNetLwfWinDumpFilterTypes(uFlags)
     657#define vboxNetLwfWinDumpOffloadSettings(p)
     658#define vboxNetLwfWinDumpSetOffloadSettings(p)
     659#define vboxNetLwfWinDumpPackets(m,l)
     660#define vboxNetLwfWinDumpPacket(p,t)
     661#endif /* !DEBUG */
     662
     663DECLINLINE(bool) vboxNetLwfWinChangeState(PVBOXNETLWF_MODULE pModuleCtx, uint32_t enmNew, uint32_t enmOld = LwfState_32BitHack)
     664{
     665    AssertReturn(pModuleCtx, false);
     666
     667    bool fSuccess = true;
     668    if (enmOld != LwfState_32BitHack)
     669    {
     670        fSuccess = ASMAtomicCmpXchgU32(&pModuleCtx->enmState, enmNew, enmOld);
     671        if (fSuccess)
     672            Log(("vboxNetLwfWinChangeState: state change %s -> %s\n",
     673                 vboxNetLwfWinStateToText(enmOld),
     674                 vboxNetLwfWinStateToText(enmNew)));
     675        else
     676            Log(("ERROR! vboxNetLwfWinChangeState: failed state change %s (actual=%s) -> %s\n",
     677                 vboxNetLwfWinStateToText(enmOld),
     678                 vboxNetLwfWinStateToText(ASMAtomicReadU32(&pModuleCtx->enmState)),
     679                 vboxNetLwfWinStateToText(enmNew)));
     680        Assert(fSuccess);
     681    }
     682    else
     683    {
     684        uint32_t enmPrevState = ASMAtomicXchgU32(&pModuleCtx->enmState, enmNew);
     685        Log(("vboxNetLwfWinChangeState: state change %s -> %s\n",
     686             vboxNetLwfWinStateToText(enmPrevState),
     687             vboxNetLwfWinStateToText(enmNew)));
     688    }
     689    return fSuccess;
     690}
     691
     692DECLINLINE(void) vboxNetLwfWinInitOidRequest(PVBOXNETLWF_OIDREQ pRequest)
     693{
     694    NdisZeroMemory(pRequest, sizeof(VBOXNETLWF_OIDREQ));
     695
     696    NdisInitializeEvent(&pRequest->Event);
     697
     698    pRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
     699    pRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1;
     700    pRequest->Request.Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
     701
     702    pRequest->Request.RequestId = (PVOID)VBOXNETLWF_REQ_ID;
     703}
     704
     705static NDIS_STATUS vboxNetLwfWinSyncOidRequest(PVBOXNETLWF_MODULE pModuleCtx, PVBOXNETLWF_OIDREQ pRequest)
     706{
     707    NDIS_STATUS Status = NdisFOidRequest(pModuleCtx->hFilter, &pRequest->Request);
     708    if (Status == NDIS_STATUS_PENDING)
     709    {
     710        NdisWaitEvent(&pRequest->Event, 0);
     711        Status = pRequest->Status;
     712    }
     713    return Status;
     714}
     715
     716DECLINLINE(void) vboxNetLwfWinCopyOidRequestResults(PNDIS_OID_REQUEST pFrom, PNDIS_OID_REQUEST pTo)
     717{
     718    switch (pFrom->RequestType)
     719    {
     720        case NdisRequestSetInformation:
     721            pTo->DATA.SET_INFORMATION.BytesRead   = pFrom->DATA.SET_INFORMATION.BytesRead;
     722            pTo->DATA.SET_INFORMATION.BytesNeeded = pFrom->DATA.SET_INFORMATION.BytesNeeded;
     723            break;
     724        case NdisRequestMethod:
     725            pTo->DATA.METHOD_INFORMATION.OutputBufferLength = pFrom->DATA.METHOD_INFORMATION.OutputBufferLength;
     726            pTo->DATA.METHOD_INFORMATION.BytesWritten       = pFrom->DATA.METHOD_INFORMATION.BytesWritten;
     727            pTo->DATA.METHOD_INFORMATION.BytesRead          = pFrom->DATA.METHOD_INFORMATION.BytesRead;
     728            pTo->DATA.METHOD_INFORMATION.BytesNeeded        = pFrom->DATA.METHOD_INFORMATION.BytesNeeded;
     729            break;
     730        case NdisRequestQueryInformation:
     731        case NdisRequestQueryStatistics:
     732        default:
     733            pTo->DATA.QUERY_INFORMATION.BytesWritten = pFrom->DATA.QUERY_INFORMATION.BytesWritten;
     734            pTo->DATA.QUERY_INFORMATION.BytesNeeded  = pFrom->DATA.QUERY_INFORMATION.BytesNeeded;
     735    }
     736}
     737
     738void inline vboxNetLwfWinOverridePacketFiltersUp(PVBOXNETLWF_MODULE pModuleCtx, ULONG *pFilters)
     739{
     740    if (ASMAtomicReadBool(&pModuleCtx->fActive) && !ASMAtomicReadBool(&pModuleCtx->fHostPromisc))
     741        *pFilters &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
     742}
     743
     744NDIS_STATUS vboxNetLwfWinOidRequest(IN NDIS_HANDLE hModuleCtx,
     745                                    IN PNDIS_OID_REQUEST pOidRequest)
     746{
     747    LogFlow(("==>vboxNetLwfWinOidRequest: module=%p\n", hModuleCtx));
     748    vboxNetCmnWinDumpOidRequest(__FUNCTION__, pOidRequest);
     749    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
     750    PNDIS_OID_REQUEST pClone = NULL;
     751    NDIS_STATUS Status = NdisAllocateCloneOidRequest(pModuleCtx->hFilter,
     752                                                     pOidRequest,
     753                                                     VBOXNETLWF_MEM_TAG,
     754                                                     &pClone);
     755    if (Status == NDIS_STATUS_SUCCESS)
     756    {
     757        /* Save the pointer to the original */
     758        *((PNDIS_OID_REQUEST*)(pClone->SourceReserved)) = pOidRequest;
     759
     760        pClone->RequestId = pOidRequest->RequestId;
     761        /* We are not supposed to get another request until we are through with the one we "postponed" */
     762        PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, pClone, PNDIS_OID_REQUEST);
     763        Assert(pPrev == NULL);
     764        pModuleCtx->pPendingRequest = pClone;
     765        if (pOidRequest->RequestType == NdisRequestSetInformation
     766            && pOidRequest->DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
     767        {
     768            ASMAtomicWriteBool(&pModuleCtx->fHostPromisc, !!(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer & NDIS_PACKET_TYPE_PROMISCUOUS));
     769            Log(("vboxNetLwfWinOidRequest: host wanted to set packet filter value to:\n"));
     770            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
     771            /* Keep adapter in promisc mode as long as we are active. */
     772            if (ASMAtomicReadBool(&pModuleCtx->fActive))
     773                *(ULONG*)pClone->DATA.SET_INFORMATION.InformationBuffer |= NDIS_PACKET_TYPE_PROMISCUOUS;
     774            Log5(("vboxNetLwfWinOidRequest: pass the following packet filters to miniport:\n"));
     775            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
     776        }
     777        if (pOidRequest->RequestType == NdisRequestSetInformation
     778            && pOidRequest->DATA.SET_INFORMATION.Oid == OID_TCP_OFFLOAD_CURRENT_CONFIG)
     779        {
     780            Log5(("vboxNetLwfWinOidRequest: offloading set to:\n"));
     781            vboxNetLwfWinDumpSetOffloadSettings((PNDIS_OFFLOAD)pOidRequest->DATA.SET_INFORMATION.InformationBuffer);
     782        }
     783
     784        /* Forward the clone to underlying filters/miniport */
     785        Status = NdisFOidRequest(pModuleCtx->hFilter, pClone);
     786        if (Status != NDIS_STATUS_PENDING)
     787        {
     788            /* Synchronous completion */
     789            pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
     790            Assert(pPrev == pClone);
     791            Log5(("vboxNetLwfWinOidRequest: got the following packet filters from miniport:\n"));
     792            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     793            /*
     794             * The host does not expect the adapter to be in promisc mode,
     795             * unless it enabled the mode. Let's not disillusion it.
     796             */
     797            if (   pOidRequest->RequestType == NdisRequestQueryInformation
     798                && pOidRequest->DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
     799                vboxNetLwfWinOverridePacketFiltersUp(pModuleCtx, (ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     800            Log5(("vboxNetLwfWinOidRequest: reporting to the host the following packet filters:\n"));
     801            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pOidRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     802            vboxNetLwfWinCopyOidRequestResults(pClone, pOidRequest);
     803            NdisFreeCloneOidRequest(pModuleCtx->hFilter, pClone);
     804        }
     805        /* In case of async completion we do the rest in vboxNetLwfWinOidRequestComplete() */
     806    }
     807    else
     808    {
     809        LogError(("vboxNetLwfWinOidRequest: NdisAllocateCloneOidRequest failed with 0x%x\n", Status));
     810    }
     811    LogFlow(("<==vboxNetLwfWinOidRequest: Status=0x%x\n", Status));
     812    return Status;
     813}
     814
     815VOID vboxNetLwfWinOidRequestComplete(IN NDIS_HANDLE hModuleCtx,
     816                                     IN PNDIS_OID_REQUEST pRequest,
     817                                     IN NDIS_STATUS Status)
     818{
     819    LogFlow(("==>vboxNetLwfWinOidRequestComplete: module=%p req=%p status=0x%x\n", hModuleCtx, pRequest, Status));
     820    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
     821    PNDIS_OID_REQUEST pOriginal = *((PNDIS_OID_REQUEST*)(pRequest->SourceReserved));
     822    if (pOriginal)
     823    {
     824        /* NDIS is supposed to serialize requests */
     825        PNDIS_OID_REQUEST pPrev = ASMAtomicXchgPtrT(&pModuleCtx->pPendingRequest, NULL, PNDIS_OID_REQUEST);
     826        Assert(pPrev == pRequest);
     827
     828        Log5(("vboxNetLwfWinOidRequestComplete: completed rq type=%d oid=%x\n", pRequest->RequestType, pRequest->DATA.QUERY_INFORMATION.Oid));
     829        vboxNetLwfWinCopyOidRequestResults(pRequest, pOriginal);
     830        if (   pRequest->RequestType == NdisRequestQueryInformation
     831            && pRequest->DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER)
     832        {
     833            Log5(("vboxNetLwfWinOidRequestComplete: underlying miniport reports its packet filters:\n"));
     834            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     835            vboxNetLwfWinOverridePacketFiltersUp(pModuleCtx, (ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     836            Log5(("vboxNetLwfWinOidRequestComplete: reporting the following packet filters to upper protocol:\n"));
     837            vboxNetLwfWinDumpFilterTypes(*(ULONG*)pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
     838        }
     839        NdisFreeCloneOidRequest(pModuleCtx->hFilter, pRequest);
     840        NdisFOidRequestComplete(pModuleCtx->hFilter, pOriginal, Status);
     841    }
     842    else
     843    {
     844        /* This is not a clone, we originated it */
     845        Log(("vboxNetLwfWinOidRequestComplete: locally originated request (%p) completed, status=0x%x\n", pRequest, Status));
     846        PVBOXNETLWF_OIDREQ pRqWrapper = RT_FROM_MEMBER(pRequest, VBOXNETLWF_OIDREQ, Request);
     847        pRqWrapper->Status = Status;
     848        NdisSetEvent(&pRqWrapper->Event);
     849    }
     850    LogFlow(("<==vboxNetLwfWinOidRequestComplete\n"));
     851}
     852
     853
     854static bool vboxNetLwfWinIsPromiscuous(PVBOXNETLWF_MODULE pModuleCtx)
     855{
     856    return ASMAtomicReadBool(&pModuleCtx->fHostPromisc);
     857}
     858
     859#if 0
     860static NDIS_STATUS vboxNetLwfWinGetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx)
     861{
     862    LogFlow(("==>vboxNetLwfWinGetPacketFilter: module=%p\n", pModuleCtx));
     863    VBOXNETLWF_OIDREQ Rq;
     864    vboxNetLwfWinInitOidRequest(&Rq);
     865    Rq.Request.RequestType = NdisRequestQueryInformation;
     866    Rq.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
     867    Rq.Request.DATA.QUERY_INFORMATION.InformationBuffer = &pModuleCtx->uPacketFilter;
     868    Rq.Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pModuleCtx->uPacketFilter);
     869    NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
     870    if (Status != NDIS_STATUS_SUCCESS)
     871    {
     872        LogError(("vboxNetLwfWinGetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed with 0x%x\n", Status));
     873        return FALSE;
     874    }
     875    if (Rq.Request.DATA.QUERY_INFORMATION.BytesWritten != sizeof(pModuleCtx->uPacketFilter))
     876    {
     877        LogError(("vboxNetLwfWinGetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed to write neccessary amount (%d bytes), actually written %d bytes\n", sizeof(pModuleCtx->uPacketFilter), Rq.Request.DATA.QUERY_INFORMATION.BytesWritten));
     878    }
     879
     880    Log5(("vboxNetLwfWinGetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER query returned the following filters:\n"));
     881    vboxNetLwfWinDumpFilterTypes(pModuleCtx->uPacketFilter);
     882
     883    LogFlow(("<==vboxNetLwfWinGetPacketFilter: status=0x%x\n", Status));
     884    return Status;
     885}
     886#endif
     887
     888static NDIS_STATUS vboxNetLwfWinSetPacketFilter(PVBOXNETLWF_MODULE pModuleCtx, bool fPromisc)
     889{
     890    LogFlow(("==>vboxNetLwfWinSetPacketFilter: module=%p %s\n", pModuleCtx, fPromisc ? "promiscuous" : "normal"));
     891    ULONG uFilter = 0;
     892    VBOXNETLWF_OIDREQ Rq;
     893    vboxNetLwfWinInitOidRequest(&Rq);
     894    Rq.Request.RequestType = NdisRequestQueryInformation;
     895    Rq.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
     896    Rq.Request.DATA.QUERY_INFORMATION.InformationBuffer = &uFilter;
     897    Rq.Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(uFilter);
     898    NDIS_STATUS Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
     899    if (Status != NDIS_STATUS_SUCCESS)
     900    {
     901        LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed with 0x%x\n", Status));
     902        return Status;
     903    }
     904    if (Rq.Request.DATA.QUERY_INFORMATION.BytesWritten != sizeof(uFilter))
     905    {
     906        LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(query, OID_GEN_CURRENT_PACKET_FILTER) failed to write neccessary amount (%d bytes), actually written %d bytes\n", sizeof(uFilter), Rq.Request.DATA.QUERY_INFORMATION.BytesWritten));
     907        return NDIS_STATUS_FAILURE;
     908    }
     909
     910    Log5(("vboxNetLwfWinSetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER query returned the following filters:\n"));
     911    vboxNetLwfWinDumpFilterTypes(uFilter);
     912
     913    if (fPromisc)
     914    {
     915        /* If we about to go promiscuous, save the state before we change it. */
     916        ASMAtomicWriteBool(&pModuleCtx->fHostPromisc, !!(uFilter & NDIS_PACKET_TYPE_PROMISCUOUS));
     917        uFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
     918    }
     919    else
     920    {
     921        /* Reset promisc only if it was not enabled before we had changed it. */
     922        if (!ASMAtomicReadBool(&pModuleCtx->fHostPromisc))
     923            uFilter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
     924    }
     925
     926    Log5(("vboxNetLwfWinSetPacketFilter: OID_GEN_CURRENT_PACKET_FILTER about to set the following filters:\n"));
     927    vboxNetLwfWinDumpFilterTypes(uFilter);
     928
     929    NdisResetEvent(&Rq.Event); /* need to reset as it has been set by query op */
     930    Rq.Request.RequestType = NdisRequestSetInformation;
     931    Rq.Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
     932    Rq.Request.DATA.SET_INFORMATION.InformationBuffer = &uFilter;
     933    Rq.Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(uFilter);
     934    Status = vboxNetLwfWinSyncOidRequest(pModuleCtx, &Rq);
     935    if (Status != NDIS_STATUS_SUCCESS)
     936    {
     937        LogError(("vboxNetLwfWinSetPacketFilter: vboxNetLwfWinSyncOidRequest(set, OID_GEN_CURRENT_PACKET_FILTER, vvv below vvv) failed with 0x%x\n", Status));
     938        vboxNetLwfWinDumpFilterTypes(uFilter);
     939    }
     940    LogFlow(("<==vboxNetLwfWinSetPacketFilter: status=0x%x\n", Status));
     941    return Status;
     942}
     943
     944
     945static NTSTATUS vboxNetLwfWinDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
     946{
     947    PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);;
     948    NTSTATUS Status = STATUS_SUCCESS;
     949
     950    switch (pIrpSl->MajorFunction)
     951    {
     952        case IRP_MJ_DEVICE_CONTROL:
     953            Status = STATUS_NOT_SUPPORTED;
     954            break;
     955        case IRP_MJ_CREATE:
     956        case IRP_MJ_CLEANUP:
     957        case IRP_MJ_CLOSE:
     958            break;
     959        default:
     960            Assert(0);
     961            break;
     962    }
     963
     964    pIrp->IoStatus.Status = Status;
     965    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     966
     967    return Status;
     968}
     969
     970/** @todo So far we had no use for device, should we even bother to create it? */
     971static NDIS_STATUS vboxNetLwfWinDevCreate(PVBOXNETLWFGLOBALS pGlobals)
     972{
     973    NDIS_STRING DevName, LinkName;
     974    PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
     975    NdisInitUnicodeString(&DevName, VBOXNETLWF_NAME_DEVICE);
     976    NdisInitUnicodeString(&LinkName, VBOXNETLWF_NAME_LINK);
     977
     978    Assert(!pGlobals->hDevice);
     979    Assert(!pGlobals->pDevObj);
     980    NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
     981    aMajorFunctions[IRP_MJ_CREATE] = vboxNetLwfWinDevDispatch;
     982    aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetLwfWinDevDispatch;
     983    aMajorFunctions[IRP_MJ_CLOSE] = vboxNetLwfWinDevDispatch;
     984    aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetLwfWinDevDispatch;
     985
     986    NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttributes;
     987    NdisZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
     988    DeviceAttributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
     989    DeviceAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
     990    DeviceAttributes.Header.Size = sizeof(DeviceAttributes);
     991    DeviceAttributes.DeviceName = &DevName;
     992    DeviceAttributes.SymbolicName = &LinkName;
     993    DeviceAttributes.MajorFunctions = aMajorFunctions;
     994    //DeviceAttributes.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION);
     995
     996    NDIS_STATUS Status = NdisRegisterDeviceEx(pGlobals->hFilterDriver,
     997                                              &DeviceAttributes,
     998                                              &pGlobals->pDevObj,
     999                                              &pGlobals->hDevice);
     1000    Log(("vboxNetLwfWinDevCreate: NdisRegisterDeviceEx returned 0x%x\n", Status));
     1001    Assert(Status == NDIS_STATUS_SUCCESS);
     1002#if 0
     1003    if (Status == NDIS_STATUS_SUCCESS)
     1004    {
     1005        PFILTER_DEVICE_EXTENSION pExtension;
     1006        pExtension = NdisGetDeviceReservedExtension(pGlobals->pDevObj);
     1007        pExtension->Signature = VBOXNETLWF_MEM_TAG;
     1008        pExtension->Handle = pGlobals->hFilterDriver;
     1009    }
     1010#endif
     1011    return Status;
     1012}
     1013
     1014static void vboxNetLwfWinDevDestroy(PVBOXNETLWFGLOBALS pGlobals)
     1015{
     1016    Assert(pGlobals->hDevice);
     1017    Assert(pGlobals->pDevObj);
     1018    NdisDeregisterDeviceEx(pGlobals->hDevice);
     1019    pGlobals->hDevice = NULL;
     1020    pGlobals->pDevObj = NULL;
     1021}
     1022
     1023static void vboxNetLwfWinUpdateSavedOffloadConfig(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)
     1024{
     1025    pModuleCtx->SavedOffloadConfig = *pOffload;
     1026    pModuleCtx->fOffloadConfigValid = true;
     1027}
     1028
     1029#ifdef VBOXNETLWF_FIXED_SIZE_POOLS
     1030static void vboxNetLwfWinFreePools(PVBOXNETLWF_MODULE pModuleCtx, int cPools)
     1031{
     1032    for (int i = 0; i < cPools; ++i)
     1033    {
     1034        if (pModuleCtx->hPool[i])
     1035        {
     1036            NdisFreeNetBufferListPool(pModuleCtx->hPool[i]);
     1037            Log4(("vboxNetLwfWinAttach: freeed NBL+NB pool 0x%p\n", pModuleCtx->hPool[i]));
     1038        }
     1039    }
     1040}
     1041#endif /* VBOXNETLWF_FIXED_SIZE_POOLS */
     1042
     1043static NDIS_STATUS vboxNetLwfWinAttach(IN NDIS_HANDLE hFilter, IN NDIS_HANDLE hDriverCtx,
     1044                                       IN PNDIS_FILTER_ATTACH_PARAMETERS pParameters)
     1045{
     1046    LogFlow(("==>vboxNetLwfWinAttach: filter=%p\n", hFilter));
     1047
     1048    PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)hDriverCtx;
     1049    if (!pGlobals)
     1050    {
     1051        vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 1);
     1052        return NDIS_STATUS_FAILURE;
     1053    }
     1054
     1055    ANSI_STRING strMiniportName;
     1056    /* We use the miniport name to associate this filter module with the netflt instance */
     1057    NTSTATUS rc = RtlUnicodeStringToAnsiString(&strMiniportName,
     1058                                               pParameters->BaseMiniportName,
     1059                                               TRUE);
     1060    if (rc != STATUS_SUCCESS)
     1061    {
     1062        LogError(("vboxNetLwfWinAttach: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",
     1063             pParameters->BaseMiniportName, rc));
     1064        vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2);
     1065        return NDIS_STATUS_FAILURE;
     1066    }
     1067    DbgPrint("vboxNetLwfWinAttach: friendly name=%wZ\n", pParameters->BaseMiniportInstanceName);
     1068    DbgPrint("vboxNetLwfWinAttach: name=%Z\n", &strMiniportName);
     1069
     1070    UINT cbModuleWithNameExtra = sizeof(VBOXNETLWF_MODULE) + strMiniportName.Length;
     1071    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)NdisAllocateMemoryWithTagPriority(hFilter,
     1072                                                                      cbModuleWithNameExtra,
     1073                                                                      VBOXNETLWF_MEM_TAG,
     1074                                                                      LowPoolPriority);
     1075    if (!pModuleCtx)
     1076    {
     1077        LogError(("vboxNetLwfWinAttach: Failed to allocate module context for %ls\n", pParameters->BaseMiniportName));
     1078        RtlFreeAnsiString(&strMiniportName);
     1079        vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 3);
     1080        return NDIS_STATUS_RESOURCES;
     1081    }
     1082    Log4(("vboxNetLwfWinAttach: allocated module context 0x%p\n", pModuleCtx));
     1083
     1084    NdisZeroMemory(pModuleCtx, cbModuleWithNameExtra);
     1085    NdisMoveMemory(pModuleCtx->szMiniportName, strMiniportName.Buffer, strMiniportName.Length);
     1086    RtlFreeAnsiString(&strMiniportName);
     1087
     1088    pModuleCtx->hWorkItem = NdisAllocateIoWorkItem(g_VBoxNetLwfGlobals.hFilterDriver);
     1089    if (!pModuleCtx->hWorkItem)
     1090    {
     1091        LogError(("vboxNetLwfWinAttach: Failed to allocate work item for %ls\n",
     1092                pParameters->BaseMiniportName));
     1093        NdisFreeMemory(pModuleCtx, 0, 0);
     1094        vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 4);
     1095        return NDIS_STATUS_RESOURCES;
     1096    }
     1097
     1098    Assert(pParameters->MacAddressLength == sizeof(RTMAC));
     1099    NdisMoveMemory(&pModuleCtx->MacAddr, pParameters->CurrentMacAddress, RT_MIN(sizeof(RTMAC), pParameters->MacAddressLength));
     1100    if (pParameters->DefaultOffloadConfiguration)
     1101        vboxNetLwfWinUpdateSavedOffloadConfig(pModuleCtx, pParameters->DefaultOffloadConfiguration);
     1102
     1103    pModuleCtx->pGlobals  = pGlobals;
     1104    pModuleCtx->hFilter   = hFilter;
     1105    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Attaching);
     1106    /* Initialize transmission mutex and events */
     1107    NDIS_INIT_MUTEX(&pModuleCtx->InTransmit);
     1108#ifdef VBOXNETLWF_SYNC_SEND
     1109    KeInitializeEvent(&pModuleCtx->EventWire, SynchronizationEvent, FALSE);
     1110    KeInitializeEvent(&pModuleCtx->EventHost, SynchronizationEvent, FALSE);
     1111#else /* !VBOXNETLWF_SYNC_SEND */
     1112    NdisInitializeEvent(&pModuleCtx->EventSendComplete);
     1113    pModuleCtx->cPendingBuffers = 0;
     1114#endif /* !VBOXNETLWF_SYNC_SEND */
     1115
     1116#ifdef VBOXNETLWF_FIXED_SIZE_POOLS
     1117    for (int i = 0; i < RT_ELEMENTS(g_cbPool); ++i)
     1118    {
     1119        /* Allocate buffer pools */
     1120        NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
     1121        NdisZeroMemory(&PoolParams, sizeof(PoolParams));
     1122        PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
     1123        PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
     1124        PoolParams.Header.Size = sizeof(PoolParams);
     1125        PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
     1126        PoolParams.fAllocateNetBuffer = TRUE;
     1127        PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */
     1128        PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;
     1129        PoolParams.DataSize = g_cbPool[i];
     1130        pModuleCtx->hPool[i] = NdisAllocateNetBufferListPool(hFilter, &PoolParams);
     1131        if (!pModuleCtx->hPool[i])
     1132        {
     1133            LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));
     1134            vboxNetLwfWinFreePools(pModuleCtx, i);
     1135            NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
     1136            NdisFreeMemory(pModuleCtx, 0, 0);
     1137            return NDIS_STATUS_RESOURCES;
     1138        }
     1139        Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool (data size=%u) 0x%p\n",
     1140              PoolParams.DataSize, pModuleCtx->hPool[i]));
     1141    }
     1142#else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1143    /* Allocate buffer pools */
     1144    NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;
     1145    NdisZeroMemory(&PoolParams, sizeof(PoolParams));
     1146    PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
     1147    PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
     1148    PoolParams.Header.Size = sizeof(PoolParams);
     1149    PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
     1150    PoolParams.fAllocateNetBuffer = TRUE;
     1151    PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */
     1152    PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;
     1153    pModuleCtx->hPool = NdisAllocateNetBufferListPool(hFilter, &PoolParams);
     1154    if (!pModuleCtx->hPool)
     1155    {
     1156        LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));
     1157        NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
     1158        NdisFreeMemory(pModuleCtx, 0, 0);
     1159        return NDIS_STATUS_RESOURCES;
     1160    }
     1161    Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool 0x%p\n", pModuleCtx->hPool));
     1162#endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1163
     1164    NDIS_FILTER_ATTRIBUTES Attributes;
     1165    NdisZeroMemory(&Attributes, sizeof(Attributes));
     1166    Attributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
     1167    Attributes.Header.Size = sizeof(Attributes);
     1168    Attributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
     1169    Attributes.Flags = 0;
     1170    NDIS_STATUS Status = NdisFSetAttributes(hFilter, pModuleCtx, &Attributes);
     1171    if (Status != NDIS_STATUS_SUCCESS)
     1172    {
     1173        LogError(("vboxNetLwfWinAttach: NdisFSetAttributes failed with 0x%x\n", Status));
     1174#ifdef VBOXNETLWF_FIXED_SIZE_POOLS
     1175        vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));
     1176#else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1177        NdisFreeNetBufferListPool(pModuleCtx->hPool);
     1178        Log4(("vboxNetLwfWinAttach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
     1179#endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1180        NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
     1181        NdisFreeMemory(pModuleCtx, 0, 0);
     1182        vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_RESOURCES, 5);
     1183        return NDIS_STATUS_RESOURCES;
     1184    }
     1185    /* Insert into module chain */
     1186    NdisAcquireSpinLock(&pGlobals->Lock);
     1187    RTListPrepend(&pGlobals->listModules, &pModuleCtx->node);
     1188    NdisReleaseSpinLock(&pGlobals->Lock);
     1189
     1190    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused);
     1191
     1192    /// @todo Somehow the packet filter is 0 at this point: Status = vboxNetLwfWinGetPacketFilter(pModuleCtx);
     1193    /// @todo We actually update it later in status handler, perhaps we should not do anything here.
     1194
     1195    LogFlow(("<==vboxNetLwfWinAttach: Status = 0x%x\n", Status));
     1196    return Status;
     1197}
     1198
     1199static VOID vboxNetLwfWinDetach(IN NDIS_HANDLE hModuleCtx)
     1200{
     1201    LogFlow(("==>vboxNetLwfWinDetach: module=%p\n", hModuleCtx));
     1202    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
     1203    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Detached, LwfState_Paused);
     1204
     1205    /* Remove from module chain */
     1206    NdisAcquireSpinLock(&pModuleCtx->pGlobals->Lock);
     1207    RTListNodeRemove(&pModuleCtx->node);
     1208    NdisReleaseSpinLock(&pModuleCtx->pGlobals->Lock);
     1209
     1210    PVBOXNETFLTINS pNetFltIns = pModuleCtx->pNetFlt; /// @todo Atomic?
     1211    if (pNetFltIns && vboxNetFltTryRetainBusyNotDisconnected(pNetFltIns))
     1212    {
     1213        /*
     1214         * Set hModuleCtx to null now in order to prevent filter restart,
     1215         * OID requests and other stuff associated with NetFlt deactivation.
     1216         */
     1217        pNetFltIns->u.s.WinIf.hModuleCtx = NULL;
     1218        /* Notify NetFlt that we are going down */
     1219        pNetFltIns->pSwitchPort->pfnDisconnect(pNetFltIns->pSwitchPort, &pNetFltIns->MyPort, vboxNetFltPortReleaseBusy);
     1220        /* We do not 'release' netflt instance since it has been done by pfnDisconnect */
     1221    }
     1222    pModuleCtx->pNetFlt = NULL;
     1223
     1224    /*
     1225     * We have to make sure that all NET_BUFFER_LIST structures have been freed by now, but
     1226     * it does not require us to do anything here since it has already been taken care of
     1227     * by vboxNetLwfWinPause().
     1228     */
     1229#ifdef VBOXNETLWF_FIXED_SIZE_POOLS
     1230    vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));
     1231#else /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1232    if (pModuleCtx->hPool)
     1233    {
     1234        NdisFreeNetBufferListPool(pModuleCtx->hPool);
     1235        Log4(("vboxNetLwfWinDetach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));
     1236    }
     1237#endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */
     1238    NdisFreeIoWorkItem(pModuleCtx->hWorkItem);
     1239    NdisFreeMemory(hModuleCtx, 0, 0);
     1240    Log4(("vboxNetLwfWinDetach: freed module context 0x%p\n", pModuleCtx));
     1241    LogFlow(("<==vboxNetLwfWinDetach\n"));
     1242}
     1243
     1244
     1245static NDIS_STATUS vboxNetLwfWinPause(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_PAUSE_PARAMETERS pParameters)
     1246{
     1247    LogFlow(("==>vboxNetLwfWinPause: module=%p\n", hModuleCtx));
     1248    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
     1249    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Pausing, LwfState_Running);
     1250    /* Wait for pending send/indication operations to complete. */
     1251    NDIS_WAIT_FOR_MUTEX(&pModuleCtx->InTransmit);
     1252#ifndef VBOXNETLWF_SYNC_SEND
     1253    NdisWaitEvent(&pModuleCtx->EventSendComplete, 1000 /* ms */);
     1254#endif /* !VBOXNETLWF_SYNC_SEND */
     1255    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused, LwfState_Pausing);
     1256    NDIS_RELEASE_MUTEX(&pModuleCtx->InTransmit);
     1257    LogFlow(("<==vboxNetLwfWinPause\n"));
     1258    return NDIS_STATUS_SUCCESS; /* Failure is not an option */
     1259}
     1260
     1261
     1262static void vboxNetLwfWinIndicateOffload(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)
     1263{
     1264    Log5(("vboxNetLwfWinIndicateOffload: offload config changed to:\n"));
     1265    vboxNetLwfWinDumpOffloadSettings(pOffload);
     1266    NDIS_STATUS_INDICATION OffloadingIndication;
     1267    NdisZeroMemory(&OffloadingIndication, sizeof(OffloadingIndication));
     1268    OffloadingIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
     1269    OffloadingIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
     1270    OffloadingIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
     1271    OffloadingIndication.SourceHandle = pModuleCtx->hFilter;
     1272    OffloadingIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
     1273    OffloadingIndication.StatusBuffer = pOffload;
     1274    OffloadingIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD);
     1275    NdisFIndicateStatus(pModuleCtx->hFilter, &OffloadingIndication);
     1276}
     1277
     1278
     1279static NDIS_STATUS vboxNetLwfWinRestart(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_RESTART_PARAMETERS pParameters)
     1280{
     1281    LogFlow(("==>vboxNetLwfWinRestart: module=%p\n", hModuleCtx));
     1282    PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;
     1283    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Restarting, LwfState_Paused);
     1284    vboxNetLwfWinChangeState(pModuleCtx, LwfState_Running, LwfState_Restarting);
     1285    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
     1286    LogFlow(("<==vboxNetLwfWinRestart: Status = 0x%x\n", Status));
     1287    return Status;
     1288}
     1289
     1290
    12891291static void vboxNetLwfWinDestroySG(PINTNETSG pSG)
    12901292{
Note: See TracChangeset for help on using the changeset viewer.

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