Sample Code
Windows Driver Samples/ Hyper-V Extensible Switch extension filter driver/ C++/ base/ SxBase.c/
/*++ Copyright (c) Microsoft Corporation. All Rights Reserved. Module Name: SxBase.c Abstract: This file contains the common code for building a switch extension. This file includes all the standard NDIS handling and exposes a function based interface for the control path and data path. This also has reusable code for basic operations such as pause/resume handling etc. --*/ #include "precomp.h" ULONG SxDebugLevel; NDIS_HANDLE SxDriverHandle = NULL; NDIS_HANDLE SxDriverObject; NDIS_SPIN_LOCK SxExtensionListLock; LIST_ENTRY SxExtensionList; NDIS_STRING SxExtensionFriendlyName; NDIS_STRING SxExtensionGuid; NDIS_STATUS SxpNdisProcessSetOid( __in PSX_SWITCH_OBJECT Switch, __inout PNDIS_OID_REQUEST OidRequest, __out PBOOLEAN Complete ); NDIS_STATUS SxpNdisProcessMethodOid( __in PSX_SWITCH_OBJECT Switch, __inout PNDIS_OID_REQUEST OidRequest, __out PBOOLEAN Complete, __out PULONG BytesNeeded ); // // DriverEntry // http://msdn.microsoft.com/en-us/library/ff544113(v=VS.85).aspx // _Use_decl_annotations_ NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ) { NDIS_STATUS status; NDIS_FILTER_DRIVER_CHARACTERISTICS fChars; NDIS_STRING serviceName; UNREFERENCED_PARAMETER(RegistryPath); // // Initialize extension specific data. // status = SxExtInitialize(); if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } RtlInitUnicodeString(&serviceName, SxExtServiceName); RtlInitUnicodeString(&SxExtensionFriendlyName, SxExtFriendlyName); RtlInitUnicodeString(&SxExtensionGuid, SxExtUniqueName); SxDriverObject = DriverObject; NdisZeroMemory(&fChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS)); fChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS; fChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS); fChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2; fChars.MajorNdisVersion = SxExtMajorNdisVersion; fChars.MinorNdisVersion = SxExtMinorNdisVersion; fChars.MajorDriverVersion = 1; fChars.MinorDriverVersion = 0; fChars.Flags = 0; fChars.FriendlyName = SxExtensionFriendlyName; fChars.UniqueName = SxExtensionGuid; fChars.ServiceName = serviceName; fChars.SetOptionsHandler = SxNdisSetOptions; fChars.SetFilterModuleOptionsHandler = SxNdisSetFilterModuleOptions; fChars.AttachHandler = SxNdisAttach; fChars.DetachHandler = SxNdisDetach; fChars.PauseHandler = SxNdisPause; fChars.RestartHandler = SxNdisRestart; fChars.SendNetBufferListsHandler = SxNdisSendNetBufferLists; fChars.SendNetBufferListsCompleteHandler = SxNdisSendNetBufferListsComplete; fChars.CancelSendNetBufferListsHandler = SxNdisCancelSendNetBufferLists; fChars.ReceiveNetBufferListsHandler = SxNdisReceiveNetBufferLists; fChars.ReturnNetBufferListsHandler = SxNdisReturnNetBufferLists; fChars.OidRequestHandler = SxNdisOidRequest; fChars.OidRequestCompleteHandler = SxNdisOidRequestComplete; fChars.CancelOidRequestHandler = SxNdisCancelOidRequest; fChars.NetPnPEventHandler = SxNdisNetPnPEvent; fChars.StatusHandler = SxNdisStatus; NdisAllocateSpinLock(&SxExtensionListLock); InitializeListHead(&SxExtensionList); DriverObject->DriverUnload = SxNdisUnload; status = NdisFRegisterFilterDriver(DriverObject, (NDIS_HANDLE)SxDriverObject, &fChars, &SxDriverHandle); Cleanup: if (status != NDIS_STATUS_SUCCESS) { if (SxDriverHandle != NULL) { NdisFDeregisterFilterDriver(SxDriverHandle); SxDriverHandle = NULL; } NdisFreeSpinLock(&SxExtensionListLock); SxExtUninitialize(); } return status; } // // Unload Routine // http://msdn.microsoft.com/en-us/library/ff564886(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisUnload( PDRIVER_OBJECT DriverObject ) { UNREFERENCED_PARAMETER(DriverObject); SxExtUninitialize(); NdisFDeregisterFilterDriver(SxDriverHandle); NdisFreeSpinLock(&SxExtensionListLock); } // // FilterSetOptions Function // http://msdn.microsoft.com/en-us/library/ff549972(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisSetOptions( NDIS_HANDLE NdisDriverHandle, NDIS_HANDLE DriverContext ) { UNREFERENCED_PARAMETER(NdisDriverHandle); UNREFERENCED_PARAMETER(DriverContext); return NDIS_STATUS_SUCCESS; } // // FilterSetModuleOptions Function // http://msdn.microsoft.com/en-us/library/ff549970(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisSetFilterModuleOptions( NDIS_HANDLE FilterModuleContext ) { UNREFERENCED_PARAMETER(FilterModuleContext); return NDIS_STATUS_SUCCESS; } // // FilterAttach Function // http://msdn.microsoft.com/en-us/library/ff549905(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisAttach( NDIS_HANDLE NdisFilterHandle, NDIS_HANDLE SxDriverContext, PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters ) { NDIS_STATUS status; NDIS_FILTER_ATTRIBUTES sxAttributes; ULONG switchObjectSize; NDIS_SWITCH_CONTEXT switchContext; NDIS_SWITCH_OPTIONAL_HANDLERS switchHandler; PSX_SWITCH_OBJECT switchObject; UNREFERENCED_PARAMETER(SxDriverContext); DEBUGP(DL_TRACE, ("===>SxAttach: NdisFilterHandle %p\n", NdisFilterHandle)); status = NDIS_STATUS_SUCCESS; switchObject = NULL; NT_ASSERT(SxDriverContext == (NDIS_HANDLE)SxDriverObject); if (AttachParameters->MiniportMediaType != NdisMedium802_3) { status = NDIS_STATUS_INVALID_PARAMETER; goto Cleanup; } switchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS; switchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1; switchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1; status = NdisFGetOptionalSwitchHandlers(NdisFilterHandle, &switchContext, &switchHandler); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_ERROR, ("SxAttach: Extension is running in non-switch environment.\n")); goto Cleanup; } switchObjectSize = sizeof(SX_SWITCH_OBJECT); switchObject = ExAllocatePoolWithTag(NonPagedPoolNx, switchObjectSize, SxExtAllocationTag); if (switchObject == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } RtlZeroMemory(switchObject, switchObjectSize); // // Initialize NDIS related information. // switchObject->NdisFilterHandle = NdisFilterHandle; switchObject->NdisSwitchContext = switchContext; RtlCopyMemory(&switchObject->NdisSwitchHandlers, &switchHandler, sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS)); // // Let the extension create its own context. // status = SxExtCreateSwitch(switchObject, &(switchObject->ExtensionContext)); if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } // // Register the object with NDIS because NDIS passes this object when it // calls into the driver. // NdisZeroMemory(&sxAttributes, sizeof(NDIS_FILTER_ATTRIBUTES)); sxAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1; sxAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES); sxAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES; sxAttributes.Flags = 0; NDIS_DECLARE_FILTER_MODULE_CONTEXT(SX_SWITCH_OBJECT); status = NdisFSetAttributes(NdisFilterHandle, switchObject, &sxAttributes); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_ERROR, ("SxBase: Failed to set attributes.\n")); goto Cleanup; } switchObject->ControlFlowState = SxSwitchAttached; switchObject->DataFlowState = SxSwitchPaused; NdisAcquireSpinLock(&SxExtensionListLock); InsertHeadList(&SxExtensionList, &switchObject->Link); NdisReleaseSpinLock(&SxExtensionListLock); Cleanup: if (status != NDIS_STATUS_SUCCESS) { if (switchObject != NULL) { ExFreePool(switchObject); } } DEBUGP(DL_TRACE, ("<===SxAttach: status %x\n", status)); return status; } // // FilterDetach Function // http://msdn.microsoft.com/en-us/library/ff549918(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisDetach( NDIS_HANDLE FilterModuleContext ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; DEBUGP(DL_TRACE, ("===>SxDetach: SxInstance %p\n", FilterModuleContext)); // // The extension must be in paused state. // NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused); switchObject->ControlFlowState = SxSwitchDetached; KeMemoryBarrier(); while(switchObject->PendingOidCount > 0) { NdisMSleep(1000); } SxExtDeleteSwitch(switchObject, switchObject->ExtensionContext); NdisAcquireSpinLock(&SxExtensionListLock); RemoveEntryList(&switchObject->Link); NdisReleaseSpinLock(&SxExtensionListLock); ExFreePool(switchObject); // // Alway return success. // DEBUGP(DL_TRACE, ("<===SxDetach Successfully\n")); return; } // // FilterRestart Function // http://msdn.microsoft.com/en-us/library/ff549962(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisPause( NDIS_HANDLE FilterModuleContext, PNDIS_FILTER_PAUSE_PARAMETERS PauseParameters ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)(FilterModuleContext); UNREFERENCED_PARAMETER(PauseParameters); DEBUGP(DL_TRACE, ("===>NDISLWF SxPause: SxInstance %p\n", FilterModuleContext)); SxExtPauseSwitch(switchObject, switchObject->ExtensionContext); // // Set the flag that the filter is going to pause. // NT_ASSERT(switchObject->DataFlowState == SxSwitchRunning); switchObject->DataFlowState = SxSwitchPaused; KeMemoryBarrier(); while(switchObject->PendingInjectedNblCount > 0) { NdisMSleep(1000); } DEBUGP(DL_TRACE, ("<===SxPause: status %x\n", NDIS_STATUS_SUCCESS)); return NDIS_STATUS_SUCCESS; } // // FilterPause Function // http://msdn.microsoft.com/en-us/library/ff549957(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisRestart( NDIS_HANDLE FilterModuleContext, PNDIS_FILTER_RESTART_PARAMETERS RestartParameters ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; UNREFERENCED_PARAMETER(RestartParameters); DEBUGP(DL_TRACE, ("===>SxRestart: FilterModuleContext %p\n", FilterModuleContext)); status = SxExtRestartSwitch(switchObject, switchObject->ExtensionContext); if (status != NDIS_STATUS_SUCCESS) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused); switchObject->DataFlowState = SxSwitchRunning; DEBUGP(DL_TRACE, ("<===SxRestart: FilterModuleContext %p, status %x\n", FilterModuleContext, NDIS_STATUS_SUCCESS)); Cleanup: return status; } // // FilterOidRequest Function // http://msdn.microsoft.com/en-us/library/ff549954(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisOidRequest( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST OidRequest ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; NDIS_STATUS status; PNDIS_OID_REQUEST clonedRequest=NULL; PVOID *cloneRequestContext; BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; status = NDIS_STATUS_SUCCESS; DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest)); NdisInterlockedIncrement(&switchObject->PendingOidCount); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, OidRequest, SxExtAllocationTag, &clonedRequest); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone OidRequest\n")); goto Cleanup; } cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]); *cloneRequestContext = OidRequest; switch (clonedRequest->RequestType) { case NdisRequestSetInformation: status = SxpNdisProcessSetOid(switchObject, clonedRequest, &completeOid); break; case NdisRequestMethod: status = SxpNdisProcessMethodOid(switchObject, clonedRequest, &completeOid, &bytesNeeded); break; } if (completeOid) { NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest); OidRequest->DATA.METHOD_INFORMATION.BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->PendingOidCount); goto Cleanup; } status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedRequest); if (status != NDIS_STATUS_PENDING) { SxNdisOidRequestComplete(switchObject, clonedRequest, status); // // We must still return status as pending because we complete the // request using NdisFOidRequestComplete() in SxOidRequestComplete(). // status = NDIS_STATUS_PENDING; } Cleanup: DEBUGP(DL_TRACE, ("<===SxOidRequest: status %8x.\n", status)); return status; } // // FilterCancelOidRequest Function // http://msdn.microsoft.com/en-us/library/ff549911(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisCancelOidRequest( NDIS_HANDLE FilterModuleContext, PVOID RequestId ) { UNREFERENCED_PARAMETER(FilterModuleContext); UNREFERENCED_PARAMETER(RequestId); } // // FilterOidRequestComplete Function // http://msdn.microsoft.com/en-us/library/ff549956(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisOidRequestComplete( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST NdisOidRequest, NDIS_STATUS Status ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; PNDIS_OID_REQUEST originalRequest; PVOID *oidRequestContext; PNDIS_SWITCH_NIC_OID_REQUEST nicOidRequestBuf; PNDIS_OBJECT_HEADER header; DEBUGP(DL_TRACE, ("===>SxOidRequestComplete, NdisOidRequest %p.\n", NdisOidRequest)); oidRequestContext = (PVOID*)(&NdisOidRequest->SourceReserved[0]); originalRequest = (*oidRequestContext); // // This is the internal request // if (originalRequest == NULL) { SxpNdisCompleteInternalOidRequest(switchObject, NdisOidRequest, Status); goto Cleanup; } // // Copy the information from the returned request to the original request // switch(NdisOidRequest->RequestType) { case NdisRequestMethod: originalRequest->DATA.METHOD_INFORMATION.OutputBufferLength = NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength; originalRequest->DATA.METHOD_INFORMATION.BytesRead = NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead; originalRequest->DATA.METHOD_INFORMATION.BytesNeeded = NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded; originalRequest->DATA.METHOD_INFORMATION.BytesWritten = NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten; if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_NIC_REQUEST && switchObject->OldNicRequest != NULL) { nicOidRequestBuf = NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer; Status = SxExtProcessNicRequestComplete(switchObject, switchObject->ExtensionContext, nicOidRequestBuf->OidRequest, nicOidRequestBuf->SourcePortId, nicOidRequestBuf->SourceNicIndex, nicOidRequestBuf->DestinationPortId, nicOidRequestBuf->DestinationNicIndex, Status); originalRequest->DATA.METHOD_INFORMATION.InformationBuffer = switchObject->OldNicRequest; switchObject->OldNicRequest = NULL; ExFreePoolWithTag(nicOidRequestBuf, SxExtAllocationTag); } break; case NdisRequestSetInformation: header = originalRequest->DATA.SET_INFORMATION.InformationBuffer; originalRequest->DATA.SET_INFORMATION.BytesRead = NdisOidRequest->DATA.SET_INFORMATION.BytesRead; originalRequest->DATA.SET_INFORMATION.BytesNeeded = NdisOidRequest->DATA.SET_INFORMATION.BytesNeeded; if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE && Status != NDIS_STATUS_SUCCESS) { SxExtDeletePort(switchObject, switchObject->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } else if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE && Status != NDIS_STATUS_SUCCESS) { SxExtDeleteNic(switchObject, switchObject->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: originalRequest->DATA.QUERY_INFORMATION.BytesWritten = NdisOidRequest->DATA.QUERY_INFORMATION.BytesWritten; originalRequest->DATA.QUERY_INFORMATION.BytesNeeded = NdisOidRequest->DATA.QUERY_INFORMATION.BytesNeeded; break; } (*oidRequestContext) = NULL; NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, NdisOidRequest); NdisFOidRequestComplete(switchObject->NdisFilterHandle, originalRequest, Status); DEBUGP(DL_TRACE, ("<===SxOidRequestComplete.\n")); Cleanup: NdisInterlockedDecrement(&switchObject->PendingOidCount); } // // FilterSendNetBufferLists Function // http://msdn.microsoft.com/en-us/library/ff549966(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisSendNetBufferLists( NDIS_HANDLE FilterModuleContext, PNET_BUFFER_LIST NetBufferLists, NDIS_PORT_NUMBER PortNumber, ULONG SendFlags ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; UNREFERENCED_PARAMETER(PortNumber); SxExtStartNetBufferListsIngress(switchObject, switchObject->ExtensionContext, NetBufferLists, SendFlags); } // // FilterSendNetBufferListsComplete Function // http://msdn.microsoft.com/en-us/library/ff549967(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisSendNetBufferListsComplete( NDIS_HANDLE FilterModuleContext, PNET_BUFFER_LIST NetBufferLists, ULONG SendCompleteFlags ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; SxExtStartCompleteNetBufferListsIngress(switchObject, switchObject->ExtensionContext, NetBufferLists, SendCompleteFlags); } // // FilterReceiveNetBufferLists Function // http://msdn.microsoft.com/en-us/library/ff549960(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisReceiveNetBufferLists( NDIS_HANDLE FilterModuleContext, PNET_BUFFER_LIST NetBufferLists, NDIS_PORT_NUMBER PortNumber, ULONG NumberOfNetBufferLists, ULONG ReceiveFlags ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; UNREFERENCED_PARAMETER(PortNumber); SxExtStartNetBufferListsEgress(switchObject, switchObject->ExtensionContext, NetBufferLists, NumberOfNetBufferLists, ReceiveFlags); } // // FilterReturnNetBufferLists Function // http://msdn.microsoft.com/en-us/library/ff549964(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisReturnNetBufferLists( NDIS_HANDLE FilterModuleContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; SxExtStartCompleteNetBufferListsEgress(switchObject, switchObject->ExtensionContext, NetBufferLists, ReturnFlags); } // // FilterCancelSendNetBufferLists Function // http://msdn.microsoft.com/en-us/library/ff549915(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisCancelSendNetBufferLists( NDIS_HANDLE FilterModuleContext, PVOID CancelId ) { UNREFERENCED_PARAMETER(FilterModuleContext); UNREFERENCED_PARAMETER(CancelId); } // // FilterNetPnPEvent Function // http://msdn.microsoft.com/en-us/library/ff549952(v=vs.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisNetPnPEvent( NDIS_HANDLE FilterModuleContext, PNET_PNP_EVENT_NOTIFICATION NetPnPEvent ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; if (NetPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) { // // Switch Activation must be passed along regardless of successful // initialization. // SxExtActivateSwitch(switchObject, switchObject->ExtensionContext); } return NdisFNetPnPEvent(switchObject->NdisFilterHandle, NetPnPEvent); } // // FilterStatus Function // http://msdn.microsoft.com/en-us/library/ff549973(v=VS.85).aspx // _Use_decl_annotations_ VOID SxNdisStatus( NDIS_HANDLE FilterModuleContext, PNDIS_STATUS_INDICATION StatusIndication ) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; PNDIS_SWITCH_NIC_STATUS_INDICATION nicIndication; PNDIS_STATUS_INDICATION originalIndication; if (StatusIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION || StatusIndication->Header.Revision != NDIS_STATUS_INDICATION_REVISION_1 || StatusIndication->Header.Size < NDIS_SIZEOF_STATUS_INDICATION_REVISION_1) { goto Cleanup; } // // Only NDIS_STATUS_SWITCH_NIC_STAUTUS indications need to be processed // by switch extensions. // if (StatusIndication->StatusCode != NDIS_STATUS_SWITCH_NIC_STATUS) { goto Cleanup; } nicIndication = StatusIndication->StatusBuffer; if (nicIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION || nicIndication->Header.Revision != NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1 || nicIndication->Header.Size < NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1) { goto Cleanup; } originalIndication = nicIndication->StatusIndication; status = SxExtProcessNicStatus(switchObject, switchObject->ExtensionContext, originalIndication, nicIndication->SourcePortId, nicIndication->SourceNicIndex); Cleanup: if (status == NDIS_STATUS_SUCCESS) { NdisFIndicateStatus(switchObject->NdisFilterHandle, StatusIndication); } return; } NDIS_STATUS SxpNdisProcessSetOid( __in PSX_SWITCH_OBJECT Switch, __inout PNDIS_OID_REQUEST OidRequest, __out PBOOLEAN Complete ) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NDIS_OID oid = OidRequest->DATA.SET_INFORMATION.Oid; PNDIS_OBJECT_HEADER header; ULONG bytesRestored = 0; *Complete = FALSE; header = OidRequest->DATA.SET_INFORMATION.InformationBuffer; if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != 0 && OidRequest->DATA.SET_INFORMATION.InformationBufferLength < sizeof(NDIS_OBJECT_HEADER)) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength == 0) { *Complete = FALSE; goto Cleanup; } switch(oid) { case OID_SWITCH_PROPERTY_ADD: case OID_SWITCH_PROPERTY_UPDATE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PROPERTY_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_PROPERTY_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } if (oid == OID_SWITCH_PROPERTY_ADD) { status = SxExtAddSwitchProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PROPERTY_PARAMETERS)header); } else { status = SxExtUpdateSwitchProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PROPERTY_PARAMETERS)header); } if (status == NDIS_STATUS_NOT_SUPPORTED) { status = NDIS_STATUS_SUCCESS; } else { *Complete = TRUE; goto Cleanup; } break; case OID_SWITCH_PROPERTY_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PROPERTY_DELETE_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_PROPERTY_DELETE_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } *Complete = SxExtDeleteSwitchProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS)header); break; case OID_SWITCH_PORT_PROPERTY_ADD: case OID_SWITCH_PORT_PROPERTY_UPDATE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } if (oid == OID_SWITCH_PORT_PROPERTY_ADD) { status = SxExtAddPortProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS)header); } else { status = SxExtUpdatePortProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS)header); } if (status == NDIS_STATUS_NOT_SUPPORTED) { status = NDIS_STATUS_SUCCESS; } else { *Complete = TRUE; goto Cleanup; } break; case OID_SWITCH_PORT_PROPERTY_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } *Complete = SxExtDeletePortProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS)header); break; case OID_SWITCH_PORT_CREATE: case OID_SWITCH_PORT_UPDATED: case OID_SWITCH_PORT_TEARDOWN: case OID_SWITCH_PORT_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PORT_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } if (oid == OID_SWITCH_PORT_CREATE) { status = SxExtCreatePort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; } } else if (oid == OID_SWITCH_PORT_UPDATED) { SxExtUpdatePort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } else if (oid == OID_SWITCH_PORT_TEARDOWN) { SxExtTeardownPort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } else { SxExtDeletePort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } break; case OID_SWITCH_NIC_CREATE: case OID_SWITCH_NIC_CONNECT: case OID_SWITCH_NIC_UPDATED: case OID_SWITCH_NIC_DISCONNECT: case OID_SWITCH_NIC_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } if (oid == OID_SWITCH_NIC_CREATE) { status = SxExtCreateNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; } } else if (oid == OID_SWITCH_NIC_CONNECT) { SxExtConnectNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } else if (oid == OID_SWITCH_NIC_UPDATED) { SxExtUpdateNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } else if (oid == OID_SWITCH_NIC_DISCONNECT) { SxExtDisconnectNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } else { SxExtDeleteNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } break; case OID_SWITCH_NIC_RESTORE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; goto Cleanup; } status = SxExtNicRestore(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header, &bytesRestored); if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; } else if (bytesRestored > 0) { *Complete = TRUE; } break; case OID_SWITCH_NIC_SAVE_COMPLETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } SxExtSaveNicComplete(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header); break; case OID_SWITCH_NIC_RESTORE_COMPLETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } SxExtNicRestoreComplete(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header); break; default: break; } Cleanup: return status; } NDIS_STATUS SxpNdisProcessMethodOid( __in PSX_SWITCH_OBJECT Switch, __inout PNDIS_OID_REQUEST OidRequest, __out PBOOLEAN Complete, __out PULONG BytesNeeded ) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NDIS_OID oid = OidRequest->DATA.SET_INFORMATION.Oid; PNDIS_OBJECT_HEADER header; PNDIS_SWITCH_NIC_OID_REQUEST nicOidRequest; PNDIS_SWITCH_NIC_OID_REQUEST newNicOidRequest = NULL; NDIS_SWITCH_PORT_ID destPort, sourcePort; NDIS_SWITCH_NIC_INDEX destNic, sourceNic; ULONG bytesWritten = 0; ULONG bytesNeeded = 0; *Complete = FALSE; *BytesNeeded = 0; header = OidRequest->DATA.METHOD_INFORMATION.InformationBuffer; switch(oid) { case OID_SWITCH_FEATURE_STATUS_QUERY: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } *Complete = SxExtQuerySwitchFeatureStatus(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_FEATURE_STATUS_PARAMETERS)header, BytesNeeded); if (*BytesNeeded > 0) { status = NDIS_STATUS_BUFFER_TOO_SHORT; } break; case OID_SWITCH_PORT_FEATURE_STATUS_QUERY: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } *Complete = SxExtQueryPortFeatureStatus(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS)header, BytesNeeded); if (*BytesNeeded > 0) { status = NDIS_STATUS_BUFFER_TOO_SHORT; } break; case OID_SWITCH_NIC_REQUEST: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } nicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)header; sourcePort = nicOidRequest->SourcePortId; sourceNic = nicOidRequest->SourceNicIndex; destPort = nicOidRequest->DestinationPortId; destNic = nicOidRequest->DestinationNicIndex; status = SxExtProcessNicRequest(Switch, Switch->ExtensionContext, nicOidRequest->OidRequest, &sourcePort, &sourceNic, &destPort, &destNic); if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; goto Cleanup; } if (sourcePort != nicOidRequest->SourcePortId || sourceNic != nicOidRequest->SourceNicIndex || destPort != nicOidRequest->DestinationPortId || destNic != nicOidRequest->DestinationNicIndex) { ASSERT(Switch->OldNicRequest == NULL); Switch->OldNicRequest = nicOidRequest; newNicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)ExAllocatePoolWithTag( NonPagedPoolNx, sizeof(NDIS_SWITCH_NIC_OID_REQUEST), SxExtAllocationTag); if (newNicOidRequest == NULL) { status = NDIS_STATUS_RESOURCES; *Complete = TRUE; goto Cleanup; } newNicOidRequest->Header = nicOidRequest->Header; newNicOidRequest->SourcePortId = sourcePort; newNicOidRequest->SourceNicIndex = sourceNic; newNicOidRequest->DestinationPortId = destPort; newNicOidRequest->DestinationNicIndex = destNic; newNicOidRequest->OidRequest = nicOidRequest->OidRequest; OidRequest->DATA.METHOD_INFORMATION.InformationBuffer = newNicOidRequest; } break; case OID_SWITCH_NIC_SAVE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } status = SxExtSaveNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header, &bytesWritten, &bytesNeeded); if (status == NDIS_STATUS_SUCCESS && bytesWritten > 0) { *Complete = TRUE; } else if (status == NDIS_STATUS_BUFFER_TOO_SHORT) { *BytesNeeded = ((PNDIS_SWITCH_NIC_SAVE_STATE)header)->SaveDataOffset + bytesNeeded; *Complete = TRUE; } else if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; } break; default: break; } Cleanup: return status; } VOID SxpNdisCompleteInternalOidRequest( __in PSX_SWITCH_OBJECT Switch, __in PNDIS_OID_REQUEST NdisRequest, __in NDIS_STATUS Status ) /*++ Routine Description: NDIS entry point indicating completion of a pended NDIS_OID_REQUEST. Arguments: Switch - pointer to switch object. NdisRequest - pointer to NDIS request Status - Status of request completion Return Value: None --*/ { PSX_OID_REQUEST oidRequest; ULONG bytesNeeded; UNREFERENCED_PARAMETER(Switch); bytesNeeded = 0; oidRequest = NULL; switch (NdisRequest->RequestType) { case NdisRequestSetInformation: bytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded; break; case NdisRequestQueryInformation: bytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded; break; case NdisRequestMethod: bytesNeeded = NdisRequest->DATA.METHOD_INFORMATION.BytesNeeded; break; } // // Get at the request context. // oidRequest = CONTAINING_RECORD(NdisRequest, SX_OID_REQUEST, NdisOidRequest); // // Save away the completion status. // oidRequest->Status = Status; // // Save bytesNeeded // oidRequest->BytesNeeded = bytesNeeded; // // Wake up the thread blocked for this request to complete. // NdisSetEvent(&oidRequest->ReqEvent); }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials