- Timestamp:
- Apr 5, 2016 1:26:26 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetLwf-win.cpp
r60278 r60333 489 489 return "invalid"; 490 490 } 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 else511 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 else518 {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 == NdisRequestSetInformation601 && 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 == NdisRequestSetInformation613 && 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 == NdisRequestQueryInformation633 && 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 else643 {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 == NdisRequestQueryInformation666 && 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 else678 {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 0695 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 #endif722 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 else755 {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 0838 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 #endif846 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_POOLS865 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_SEND944 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_POOLS952 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_POOLS1010 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, but1061 * it does not require us to do anything here since it has already been taken care of1062 * by vboxNetLwfWinPause().1063 */1064 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS1065 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_SEND1088 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 1125 491 1126 492 static void vboxNetLwfWinDumpPackets(const char *pszMsg, PNET_BUFFER_LIST pBufLists) … … 1287 653 } 1288 654 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 663 DECLINLINE(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 692 DECLINLINE(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 705 static 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 716 DECLINLINE(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 738 void inline vboxNetLwfWinOverridePacketFiltersUp(PVBOXNETLWF_MODULE pModuleCtx, ULONG *pFilters) 739 { 740 if (ASMAtomicReadBool(&pModuleCtx->fActive) && !ASMAtomicReadBool(&pModuleCtx->fHostPromisc)) 741 *pFilters &= ~NDIS_PACKET_TYPE_PROMISCUOUS; 742 } 743 744 NDIS_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 815 VOID 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 854 static bool vboxNetLwfWinIsPromiscuous(PVBOXNETLWF_MODULE pModuleCtx) 855 { 856 return ASMAtomicReadBool(&pModuleCtx->fHostPromisc); 857 } 858 859 #if 0 860 static 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 888 static 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 945 static 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? */ 971 static 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 1014 static 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 1023 static 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 1030 static 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 1043 static 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 1199 static 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 1245 static 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 1262 static 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 1279 static 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 1289 1291 static void vboxNetLwfWinDestroySG(PINTNETSG pSG) 1290 1292 {
Note:
See TracChangeset
for help on using the changeset viewer.