diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /network/ndis/extension/base | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'network/ndis/extension/base')
| -rw-r--r-- | network/ndis/extension/base/SxApi.h | 1196 | ||||
| -rw-r--r-- | network/ndis/extension/base/SxBase.c | 1395 | ||||
| -rw-r--r-- | network/ndis/extension/base/SxBase.h | 168 | ||||
| -rw-r--r-- | network/ndis/extension/base/SxLibrary.c | 839 | ||||
| -rw-r--r-- | network/ndis/extension/base/SxLibrary.h | 464 | ||||
| -rw-r--r-- | network/ndis/extension/base/precomp.h | 11 | ||||
| -rw-r--r-- | network/ndis/extension/base/precompsrc.c | 1 | ||||
| -rw-r--r-- | network/ndis/extension/base/sxbase.vcxproj | 130 | ||||
| -rw-r--r-- | network/ndis/extension/base/sxbase.vcxproj.Filters | 32 |
9 files changed, 4236 insertions, 0 deletions
diff --git a/network/ndis/extension/base/SxApi.h b/network/ndis/extension/base/SxApi.h new file mode 100644 index 00000000..64dca5f7 --- /dev/null +++ b/network/ndis/extension/base/SxApi.h @@ -0,0 +1,1196 @@ +/*++ + +Copyright (c) Microsoft Corporation. All Rights Reserved. + +Module Name: + + SxApi.h + +Abstract: + + This file contains the API that must be implemented to + create a switch extension using the SxBase library. + + +--*/ + +// +// The major version of NDIS the driver is using. +// For NDIS 6.30, use NDIS_FILTER_MAJOR_VERSION. +// +extern UCHAR SxExtMajorNdisVersion; + +// +// The minor version of NDIS the driver is using. +// For NDIS 6.30, use NDIS_FILTER_MINOR_VERSION. +// +extern UCHAR SxExtMinorNdisVersion; + +// +// The friendly name of the extension. +// +extern PWCHAR SxExtFriendlyName; + +// +// The unique name of the extension. +// +extern PWCHAR SxExtUniqueName; + +// +// The service name of the extension from the INF. +// +extern PWCHAR SxExtServiceName; + +// +// The memory pool tag using in the extension. +// +extern ULONG SxExtAllocationTag; + +// +// The request ID used to identify OIDs initiated from this extension. +// +extern ULONG SxExtOidRequestId; + + +/*++ + +SxExtInitialize + +Routine Description: + This function is called from the SxBase Library during DriverEntry. + An extension should allocate/initalize all global data in this function. + +Arguments: + NULL + +Return Value: + NDIS_STATUS_SUCCESS succeeds driver entry. + + NDIS_STATUS_*** fails driver entry. + +--*/ +NDIS_STATUS +SxExtInitialize(); + + +/*++ + +SxExtUninitialize + +Routine Description: + This function is called from the SxBase Library during DriverUnload. + An extension should free/reset all global data in this function. + +Arguments: + NULL + +Return Value: + VOID + +--*/ +VOID +SxExtUninitialize(); + + +/*++ + +SxExtCreateSwitch + +Routine Description: + This function is called when an extension binds to a new switch. + All switch specific data should be allocated during this function. + OIDs cannot be sent from this function, and both the control + and data paths are inactive. + +Arguments: + Switch - the Switch Object currently being created + + ExtensionContext - Extension context specific to the switch being + createf. This context will be passed back to the + extension for all function calls in SxApi + +Return Value: + NDIS_STATUS_SUCCESS succeeds switch creation. + + NDIS_STATUS_RESOURCES fails switch creation because of insufficient + resources. + + NDIS_STATUS_FAILURE fails switch creation. + +--*/ +NDIS_STATUS +SxExtCreateSwitch( + _In_ PSX_SWITCH_OBJECT Switch, + _Outptr_result_maybenull_ PNDIS_HANDLE *ExtensionContext + ); + + +/*++ + +SxExtDeleteSwitch + +Routine Description: + This function is called when an extension binds to a new switch. + All switch specific data should be allocated/initialized during + this function. + +Arguments: + Switch - the Switch being deleted + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch being deleted. + +Return Value: + VOID + +--*/ +VOID +SxExtDeleteSwitch( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext + ); + + +/*++ + +SxExtActivateSwitch + +Routine Description: + This function is called to activate a switch. The function can be called + while the switch is Running or Paused and should be used to bootstrap + the switch if it was not Active when it was created. + +Arguments: + Switch - the Switch being activated + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch being restarted. + +Return Value: + VOID + +--*/ +VOID +SxExtActivateSwitch( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext + ); + + +/*++ + +SxExtRestartSwitch + +Routine Description: + This function is called to restart a switch from a paused state. + +Arguments: + Switch - the Switch being restarted + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch being restarted. + +Return Value: + NDIS_STATUS_SUCCESS succeeds switch restart. + + NDIS_STATUS_RESOURCES fails switch restart because of insufficient + resources. + + NDIS_STATUS_FAILURE fails switch restart. + +--*/ +NDIS_STATUS +SxExtRestartSwitch( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext + ); + + +/*++ + +SxExtPauseSwitch + +Routine Description: + This function is called to pause a switch from a running state. + +Arguments: + Switch - the Switch being paused + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch being paused + +Return Value: + VOID + +--*/ +VOID +SxExtPauseSwitch( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext + ); + + +/*++ + +SxExtCreatePort + +Routine Description: + This function is called to create a new port on a switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Port - the Port being created + +Return Value: + NDIS_STATUS_SUCCESS to succeed port creation + + NDIS_STATUS_*** to fail port creation + +--*/ +NDIS_STATUS +SxExtCreatePort( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PARAMETERS Port + ); + + +/*++ + +SxExtUpdatePort + +Routine Description: + This function is called to update an already created port. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Port - the port being updated + +Return Value: + VOID + +--*/ +VOID +SxExtUpdatePort( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PARAMETERS Port + ); + + +/*++ + +SxExtCreateNic + +Routine Description: + This function is called to create a new NIC to be connected + to a switch. + The extension may allocate context for this NIC, and traffic may + start to flow from this NIC, but it may not be used as a destination + until SxExtConnectNic has been called. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Nic - the NIC being created + +Return Value: + NDIS_STATUS_SUCCESS to succeed NIC creation + + NDIS_STATUS_*** to fail NIC creation + +--*/ +NDIS_STATUS +SxExtCreateNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic + ); + + +/*++ + +SxExtConnectNic + +Routine Description: + This function is called to connect a NIC to a switch. + After returning from this function the extension can use this NIC + as a destination. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Nic - the NIC being connected + +Return Value: + VOID + +--*/ +VOID +SxExtConnectNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic + ); + + +/*++ + +SxExtUpdateNic + +Routine Description: + This function is called to update an already created NIC. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Nic - the NIC being updated + +Return Value: + VOID + +--*/ +VOID +SxExtUpdateNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic + ); + + +/*++ + +SxExtDisconnectNic + +Routine Description: + This function is called to disconnect a NIC from a switch. + After returning from this function the extension cannot use + this NIC as a destination. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Nic - the NIC being disconnected + +Return Value: + VOID + +--*/ +VOID +SxExtDisconnectNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic + ); + + +/*++ + +SxExtDeleteNic + +Routine Description: + This function is called to delete a NIC from a switch. + No futher traffic/control will be recieved for this NIC. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Nic - the NIC being deleted + +Return Value: + VOID + +--*/ +VOID +SxExtDeleteNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic + ); + + +/*++ + +SxExtTeardownPort + +Routine Description: + This function is called to start deletion of a port on a switch. + Upon recieving this call, no further references may be taken + on the given port. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Port - the Port being deleted + +Return Value: + VOID + +--*/ +VOID +SxExtTeardownPort( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PARAMETERS Port + ); + + +/*++ + +SxExtDeletePort + +Routine Description: + This function is called to finish deletion of a port on a switch. + Upon recieving this call, no traffic/control will be recieved + for this port. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + Port - the Port being deleted + +Return Value: + VOID + +--*/ +VOID +SxExtDeletePort( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PARAMETERS Port + ); + + +/*++ + +SxExtSaveNic + +Routine Description: + This function is called to retrieve save data for a given NIC. + This function will be called until all extensions have finished + saving data. + + An new save for this NIC will not start until SxExtSaveNicComplete + has been received. + + If returning NDIS_STATUS_SUCCESS from this function, and + BytesWritten > 0 you must write to the ExtensionId, + ExtensionFriendlyName, SaveDataSize and SaveData fields in + SaveState. SxExtUniqueName MUST be written to ExtensionId. + SxExtFriendlyName should be written to ExtensionFriendlyName. + + If returning NDIS_STATUS_SUCCESS with BytesWritten == 0, + DO NOT write any data to any fields. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SaveState - the save information and buffer to save to + + BytesWritten - the # of bytes written to the save buffer + + BytesNeeded - the length of the save buffer needed + +Return Value: + NDIS_STATUS_SUCCESS - if the buffer was successfully written, or not + needed and BytesWritten is set to 0 + + NDIS_STATUS_BUFFER_TOO_SHORT - if the buffer is too short for the + necessary save, write the length needed + in BytesNeeded + + NDIS_STATUS_*** - to fail the save operation + +--*/ +NDIS_STATUS +SxExtSaveNic( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _Inout_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState, + _Out_ PULONG BytesWritten, + _Out_ PULONG BytesNeeded + ); + + +/*++ + +SxExtSaveNicComplete + +Routine Description: + This function is called to notify the extension that saving + the given NIC has been completed by all extensions. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SaveState - the save information + +Return Value: + VOID + +--*/ +VOID +SxExtSaveNicComplete( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState + ); + + +/*++ + +SxExtNicRestore + +Routine Description: + This function is called to restore previously saved data. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SaveState - the save information + + BytesRestored - the number of bytes restored from the saved data + +Return Value: + NDIS_STATUS_SUCCESS - if this data belongs to this extension, and was + successfully restored (BytesRestored written) + OR + this data does not belong to this extension + (BytesRestored == 0) + + NDIS_STATUS_*** - there was an error while attempting to restore + this data + +--*/ +NDIS_STATUS +SxExtNicRestore( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState, + _Out_ PULONG BytesRestored + ); + + +/*++ + +SxExtNicRestoreComplete + +Routine Description: + This function is called to signify the end of a restore operation. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SaveState - the save information + +Return Value: + VOID + +--*/ +VOID +SxExtNicRestoreComplete( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState + ); + + +/*++ + +SxExtAddSwitchProperty + +Routine Description: + This function is called to add a property on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SwitchProperty - the property to be applied + +Return Value: + NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension + + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and + can successfully be enforced + + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this + extension, but cannot be enforced + + NDIS_STATUS_*** - if the policy is consumed by this extension, and + setting the valid policy failed + +--*/ +NDIS_STATUS +SxExtAddSwitchProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty + ); + + +/*++ + +SxExtUpdateSwitchProperty + +Routine Description: + This function is called to update a property on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SwitchProperty - the property to be updated + +Return Value: + NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension + + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and + can successfully be enforced + + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this + extension, but cannot be enforced + + NDIS_STATUS_*** - if the policy is consumed by this extension, and + setting the valid policy failed + +--*/ +NDIS_STATUS +SxExtUpdateSwitchProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty + ); + + +/*++ + +SxExtDeleteSwitchProperty + +Routine Description: + This function is called to delete a property on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SwitchProperty - the property to be deleted + +Return Value: + TRUE - if the policy belongs to this extension + + FALSE - otherwise + +--*/ +BOOLEAN +SxExtDeleteSwitchProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS SwitchProperty + ); + + +/*++ + +SxExtAddPortProperty + +Routine Description: + This function is called to add a property on the given port, + on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + PortProperty - the property to be applied + +Return Value: + NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension + + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and + can successfully be enforced + + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this + extension, but cannot be enforced + + NDIS_STATUS_*** - if the policy is consumed by this extension, and + setting the valid policy failed + +--*/ +NDIS_STATUS +SxExtAddPortProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty + ); + + +/*++ + +SxExtUpdatePortProperty + +Routine Description: + This function is called to update a property on the given port, + on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + PortProperty - the property to be applied + +Return Value: + NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension + + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and + can successfully be enforced + + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this + extension, but cannot be enforced + + NDIS_STATUS_*** - if the policy is consumed by this extension, and + setting the valid policy failed + +--*/ +NDIS_STATUS +SxExtUpdatePortProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty + ); + + +/*++ + +SxExtDeletePortProperty + +Routine Description: + This function is called to delete a property on the given port, + on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SwitchProperty - the property to be deleted + +Return Value: + TRUE - if the policy is not consumed by this extension + + FALSE - otherwise + +--*/ +BOOLEAN +SxExtDeletePortProperty( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS PortProperty + ); + + +/*++ + +SxExtQuerySwitchFeatureStatus + +Routine Description: + This function is called to query the status of a custom property + on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + SwitchFeatureStatus - the property buffer + + BytesNeeded - if SwitchFeatureStatus is too small, this should be set + to the size buffer needed + +Return Value: + TRUE - return true if this property belongs to this extension, if + BytesNeeded > 0, the buffer will be reallocated and + this function will be called again + + FALSE - otherwise + +--*/ +BOOLEAN +SxExtQuerySwitchFeatureStatus( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _Inout_ PNDIS_SWITCH_FEATURE_STATUS_PARAMETERS SwitchFeatureStatus, + _Inout_ PULONG BytesNeeded + ); + + +/*++ + +SxExtQueryPortFeatureStatus + +Routine Description: + This function is called to query the status of a custom property + on the given port, on the given switch. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + PortFeatureStatus - the property buffer + + BytesNeeded - if PortFeatureStatus is too small, this should be set + to the size buffer needed + +Return Value: + TRUE - return true if this property belongs to this extension, if + BytesNeeded > 0, the buffer will be reallocated and + this function will be called again + + FALSE - otherwise + +--*/ +BOOLEAN +SxExtQueryPortFeatureStatus( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _Inout_ PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS PortFeatureStatus, + _Inout_ PULONG BytesNeeded + ); + + +/*++ + +SxExtProcessNicRequest + +Routine Description: + This function is called upon the reciept of an OID_SWITCH_NIC_REQUEST + to the extension. + If an extension wishes to redirect the OID, it must return a valid + DestinationPortId and DestinationNicIndex, which it has taken a + reference on. + If an extension wishes to set source information, it must return + a valid SourcePortId and SourceNicIndex, which it has taken a + reference on. + The extension can change the OidRequest if it needs to. + + !! This function should only be used by forwarding extensions. !! + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + OidRequest - the OID wrapped by the NIC request + + SourcePortId - the source PortId to set + + SourceNicIndex - the source NicIndex to set + + DestinationPortId - the destination PortId to set + + DestinationNicIndex - the destination NicIndex to set + +Return Value: + NDIS_STATUS_SUCCESS - sends OID + + NDIS_STATUS_*** - complete OID with given status + +--*/ +NDIS_STATUS +SxExtProcessNicRequest( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _Inout_ PNDIS_OID_REQUEST OidRequest, + _Inout_ PNDIS_SWITCH_PORT_ID SourcePortId, + _Inout_ PNDIS_SWITCH_NIC_INDEX SourceNicIndex, + _Inout_ PNDIS_SWITCH_PORT_ID DestinationPortId, + _Inout_ PNDIS_SWITCH_NIC_INDEX DestinationNicIndex + ); + + +/*++ + +SxExtProcessNicRequestComplete + +Routine Description: + This function is called upon the completion of an OID_SWITCH_NIC_REQUEST + that this extension has previously altered. + The extension must derefernce all NICs it had previously taken references + on. + If the OidRequest buffer was changed (along with underlying buffers), + the previous data must be replaced. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + NicOidRequest - the OID buffer, encapsulated with source/destination info + + Status - the status the OID completed with + +Return Value: + NDIS_STATUS - the status to complete the OID request with + +--*/ +NDIS_STATUS +SxExtProcessNicRequestComplete( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _Inout_ PNDIS_OID_REQUEST OidRequest, + _In_ NDIS_SWITCH_PORT_ID SourcePortId, + _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex, + _In_ NDIS_SWITCH_PORT_ID DestinationPortId, + _In_ NDIS_SWITCH_NIC_INDEX DestinationNicIndex, + _In_ NDIS_STATUS Status + ); + + +/*++ + +SxExtProcessNicStatus + +Routine Description: + This function is called upon the reciept of an NDIS_STATUS_SWITCH_NIC_STATUS + to the extension. + If the extension wishes to modify the status indication, it should + send its own status indication using NdisFIndicateStatus and return a + failure status. + If the extension wishes to drop the status indiction, it should return + failure status, though this should be done very sparingly and carefully. + + !! This function should only be used by forwarding extensions. !! + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + StatusIndication - the indication wrapped by the NIC status indication + + SourcePortId - the source PortId of the indication + + SourceNicIndex - the source NicIndex of the indication + +Return Value: + NDIS_STATUS_SUCCESS - return to continue forwarding this indication + + NDIS_STATUS_*** - if the extension wants to modify the status + if modifying the status the extension should indicate + its own modified status using + SxLibIssueNicStatusIndicationUnsafe as soon as possible + +--*/ +NDIS_STATUS +SxExtProcessNicStatus( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNDIS_STATUS_INDICATION StatusIndication, + _In_ NDIS_SWITCH_PORT_ID SourcePortId, + _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex + ); + + +/*++ + +SxExtStartNetBufferListsIngress + +Routine Description: + This function is called upon the receipt on an NBL on ingress. + The extension should call SxLibSendNetBufferListsIngress to continue + the send of the NBL on ingress. + The extension should call SxLibCompleteNetBufferListsIngress to + drop the NBL. + This function may also be call from egress to inject an NBL. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + NetBufferLists - the NBL to be sent + + SendFlags - the send flags from NDIS, equivalent to NDIS send flags for + NdisFSendNetBufferLists + +Return Value: + VOID + +--*/ +VOID +SxExtStartNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendFlags + ); + + +/*++ + +SxExtStartNetBufferListsEgress + +Routine Description: + This function is called upon the receipt on an NBL on egress. + The extension should call SxLibSendNetBufferListsEgress to continue + the send of the NBL on egress. + The extension should call SxLibSendNetBufferListsEgressComplete to + drop the NBL. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + NetBufferLists - the NBL to be sent + + NumberOfNetBufferLists - the number of NBLs in NetBufferLists + + ReceiveFlags - the receive flags from NDIS, equivalent to NDIS receive flags for + NdisFIndicateReceiveNetBufferLists + +Return Value: + VOID + +--*/ +VOID +SxExtStartNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG NumberOfNetBufferLists, + _In_ ULONG ReceiveFlags + ); + + +/*++ + +SxExtStartCompleteNetBufferListsEgress + +Routine Description: + This function is called upon the completion of an NBL on egress. + The extension must call SxLibCompleteNetBufferListsEgress + once it has finished processing the NBL. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + NetBufferLists - the NBL being completed + + ReturnFlags - the return flags from NDIS, equivalent to NDIS return flags for + NdisFReturnNetBufferLists + +Return Value: + VOID + +--*/ +VOID +SxExtStartCompleteNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG ReturnFlags + ); + + +/*++ + +SxExtStartCompleteNetBufferListsIngress + +Routine Description: + This function is called upon the completion of an NBL on ingress. + The extension must call SxLibCompleteNetBufferListsIngress + once it has finished processing the NBL. + + If there are NBLs injected by this extension in NetBufferLists, + the extension must NOT call SxLibCompleteNetBufferListsIngress, and + instead call SxLibCompletedInjectedNetBufferLists with the number + of injected NBLs completed. + +Arguments: + Switch - the Switch context + + ExtensionContext - The extension context allocated in SxExtCreateSwitch + for the switch + + NetBufferLists - the NBL being completed + + SendCompleteFlags - the send complete flags from NDIS, equivalent to + NDIS send complete flags for + NdisFSendNetBufferListsComplete + +Return Value: + VOID + +--*/ +VOID +SxExtStartCompleteNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_HANDLE ExtensionContext, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendCompleteFlags + ); + diff --git a/network/ndis/extension/base/SxBase.c b/network/ndis/extension/base/SxBase.c new file mode 100644 index 00000000..b76ef7a4 --- /dev/null +++ b/network/ndis/extension/base/SxBase.c @@ -0,0 +1,1395 @@ +/*++ + +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); +} + diff --git a/network/ndis/extension/base/SxBase.h b/network/ndis/extension/base/SxBase.h new file mode 100644 index 00000000..1e57b0f1 --- /dev/null +++ b/network/ndis/extension/base/SxBase.h @@ -0,0 +1,168 @@ +/*++ + +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. + + +--*/ + +extern NDIS_STRING SxExtensionFriendlyName; +extern NDIS_STRING SxExtensionGuid; + +typedef enum _SX_SWITCH_DATAFLOW_STATE +{ + SxSwitchPaused, + SxSwitchRunning +} SX_SWITCH_DATAFLOW_STATE, *PSX_SWITCH_DATAFLOW_STATE; + +typedef enum _SX_SWITCH_CONTROFLOW_STATE +{ + SxSwitchUnknown, + SxSwitchAttached, + SxSwitchDetached +} SX_SWITCH_CONTROLFLOW_STATE, *PSX_SWITCH_CONTROLFLOW_STATE; + +typedef struct _SX_SWITCH_OBJECT +{ + // + // The Link *must* always be the first field. + // + LIST_ENTRY Link; + + // + // The extension context is the context used in the specific logic + // of this extension. + // This is allocated and returned in SxExtSwitchCreate + // + PNDIS_HANDLE ExtensionContext; + + // + // Ndis related fields. + // + NDIS_HANDLE NdisFilterHandle; + NDIS_SWITCH_CONTEXT NdisSwitchContext; + NDIS_SWITCH_OPTIONAL_HANDLERS NdisSwitchHandlers; + + // + // Switch state. + // + SX_SWITCH_DATAFLOW_STATE DataFlowState; + SX_SWITCH_CONTROLFLOW_STATE ControlFlowState; + + // + // Management fields. + // + volatile LONG PendingInjectedNblCount; + volatile LONG PendingOidCount; + + // + // Control Path Management. + // + PNDIS_SWITCH_NIC_OID_REQUEST OldNicRequest; + +} SX_SWITCH_OBJECT, *PSX_SWITCH_OBJECT; + +typedef struct _SX_OID_REQUEST +{ + NDIS_OID_REQUEST NdisOidRequest; + NDIS_EVENT ReqEvent; + NDIS_STATUS Status; + ULONG BytesNeeded; + +} SX_OID_REQUEST, *PSX_OID_REQUEST; + +typedef struct _FILTER_DEVICE_EXTENSION +{ + ULONG Signature; + NDIS_HANDLE Handle; +} FILTER_DEVICE_EXTENSION, *PFILTER_DEVICE_EXTENSION; + + +// +// Function prototypes +// +DRIVER_INITIALIZE DriverEntry; + +DRIVER_UNLOAD SxNdisUnload; + +FILTER_SET_OPTIONS SxNdisSetOptions; + +FILTER_SET_MODULE_OPTIONS SxNdisSetFilterModuleOptions; + +FILTER_ATTACH SxNdisAttach; + +FILTER_DETACH SxNdisDetach; + +FILTER_PAUSE SxNdisPause; + +FILTER_RESTART SxNdisRestart; + +FILTER_OID_REQUEST SxNdisOidRequest; + +FILTER_CANCEL_OID_REQUEST SxNdisCancelOidRequest; + +FILTER_OID_REQUEST_COMPLETE SxNdisOidRequestComplete; + +FILTER_SEND_NET_BUFFER_LISTS SxNdisSendNetBufferLists; + +FILTER_RETURN_NET_BUFFER_LISTS SxNdisReturnNetBufferLists; + +FILTER_SEND_NET_BUFFER_LISTS_COMPLETE SxNdisSendNetBufferListsComplete; + +FILTER_RECEIVE_NET_BUFFER_LISTS SxNdisReceiveNetBufferLists; + +FILTER_CANCEL_SEND_NET_BUFFER_LISTS SxNdisCancelSendNetBufferLists; + +FILTER_STATUS SxNdisStatus; + +FILTER_NET_PNP_EVENT SxNdisNetPnPEvent; + +VOID +SxpNdisCompleteInternalOidRequest( + __in PSX_SWITCH_OBJECT Switch, + __in PNDIS_OID_REQUEST NdisRequest, + __in NDIS_STATUS Status + ); + + +// +// Some debug stuff. +// +#define DL_EXTRA_LOUD 20 +#define DL_VERY_LOUD 10 +#define DL_LOUD 8 +#define DL_INFO 6 +#define DL_TRACE 5 +#define DL_WARN 4 +#define DL_ERROR 2 +#define DL_FATAL 0 + +#if DBG + +extern ULONG SxDebugLevel; + +#define DEBUGP(lev, stmt) \ + { \ + if ((lev) <= SxDebugLevel) \ + { \ + DbgPrint("%S: ",SxExtServiceName); DbgPrint stmt; \ + } \ + } + +#else + +#define DEBUGP(lev, stmt) + +#endif + + diff --git a/network/ndis/extension/base/SxLibrary.c b/network/ndis/extension/base/SxLibrary.c new file mode 100644 index 00000000..ea2f53b6 --- /dev/null +++ b/network/ndis/extension/base/SxLibrary.c @@ -0,0 +1,839 @@ +/*++ + +Copyright (c) Microsoft Corporation. All Rights Reserved. + +Module Name: + + SxLibrary.c + +Abstract: + + This file contains the common library functions that can be used + by any extension using the SxBase library. + + +--*/ + +#include "precomp.h" + +VOID +SxLibSendNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendFlags, + _In_ ULONG NumInjectedNetBufferLists + ) +{ + BOOLEAN dispatch; + BOOLEAN sameSource; + ULONG sendCompleteFlags; + PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; + PNET_BUFFER_LIST curNbl, nextNbl; + ULONG numNbls = 0; + PNET_BUFFER_LIST dropNbl = NULL; + PNET_BUFFER_LIST *curDropNbl = &dropNbl; + NDIS_SWITCH_PORT_ID curSourcePort; + NDIS_STRING filterReason; + + dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags); + sameSource = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE); + + InterlockedAdd(&Switch->PendingInjectedNblCount, NumInjectedNetBufferLists); + KeMemoryBarrier(); + + if (Switch->DataFlowState != SxSwitchRunning) + { + RtlInitUnicodeString(&filterReason, L"Extension Paused"); + + sendCompleteFlags = (dispatch) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0; + sendCompleteFlags |= (sameSource) ? NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0; + + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); + + if (sameSource) + { + for (curNbl = NetBufferLists; curNbl != NULL; curNbl = curNbl->Next) + { + ++numNbls; + } + + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + fwdDetail->SourcePortId, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + numNbls, + NetBufferLists, + &filterReason); + + SxExtStartCompleteNetBufferListsIngress(Switch, + Switch->ExtensionContext, + NetBufferLists, + sendCompleteFlags); + } + else + { + curSourcePort = fwdDetail->SourcePortId; + for (curNbl = NetBufferLists; curNbl != NULL; curNbl = nextNbl) + { + nextNbl = curNbl->Next; + curNbl->Next = NULL; + + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); + + if(curSourcePort == fwdDetail->SourcePortId) + { + *curDropNbl = curNbl; + curDropNbl = &(curNbl->Next); + ++numNbls; + } + else + { + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + curSourcePort, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + numNbls, + dropNbl, + &filterReason); + + SxExtStartCompleteNetBufferListsIngress(Switch, + Switch->ExtensionContext, + dropNbl, + sendCompleteFlags); + + numNbls = 1; + dropNbl = curNbl; + curDropNbl = &(curNbl->Next); + curSourcePort = fwdDetail->SourcePortId; + } + } + + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + curSourcePort, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + numNbls, + dropNbl, + &filterReason); + + SxExtStartCompleteNetBufferListsIngress(Switch, + Switch->ExtensionContext, + dropNbl, + sendCompleteFlags); + } + + goto Cleanup; + } + + NdisFSendNetBufferLists(Switch->NdisFilterHandle, + NetBufferLists, + NDIS_DEFAULT_PORT_NUMBER, + SendFlags); + +Cleanup: + return; +} + + +VOID +SxLibSendNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG NumberOfNetBufferLists, + _In_ ULONG ReceiveFlags + ) +{ + BOOLEAN dispatch, sameSource; + NDIS_SWITCH_PORT_ID sourcePortId; + PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; + ULONG returnFlags; + NDIS_SWITCH_PORT_ID curSourcePort; + PNET_BUFFER_LIST curNbl, nextNbl; + ULONG numNbls; + PNET_BUFFER_LIST dropNbl = NULL; + PNET_BUFFER_LIST *curDropNbl = &dropNbl; + NDIS_STRING filterReason; + + dispatch = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags); + sameSource = NDIS_TEST_RECEIVE_FLAG(ReceiveFlags, NDIS_RECEIVE_FLAGS_SWITCH_SINGLE_SOURCE); + + if (Switch->DataFlowState != SxSwitchRunning) + { + RtlInitUnicodeString(&filterReason, L"Extension Paused"); + + returnFlags = (dispatch) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0; + returnFlags |= NDIS_RETURN_FLAGS_SWITCH_SINGLE_SOURCE; + + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); + + if (sameSource) + { + sourcePortId = fwdDetail->SourcePortId; + + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + sourcePortId, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + NumberOfNetBufferLists, + NetBufferLists, + &filterReason); + + SxExtStartCompleteNetBufferListsEgress(Switch, + Switch->ExtensionContext, + NetBufferLists, + returnFlags); + } + else + { + curSourcePort = fwdDetail->SourcePortId; + numNbls = 0; + for (curNbl = NetBufferLists; curNbl != NULL; curNbl = nextNbl) + { + nextNbl = curNbl->Next; + curNbl->Next = NULL; + + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); + + if(curSourcePort == fwdDetail->SourcePortId) + { + *curDropNbl = curNbl; + curDropNbl = &(curNbl->Next); + ++numNbls; + } + else + { + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + curSourcePort, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + numNbls, + dropNbl, + &filterReason); + + SxExtStartCompleteNetBufferListsEgress(Switch, + Switch->ExtensionContext, + dropNbl, + returnFlags); + + numNbls = 1; + dropNbl = curNbl; + curDropNbl = &(curNbl->Next); + curSourcePort = fwdDetail->SourcePortId; + } + } + + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( + Switch->NdisSwitchContext, + &SxExtensionGuid, + &SxExtensionFriendlyName, + curSourcePort, + NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, + numNbls, + dropNbl, + &filterReason); + + SxExtStartCompleteNetBufferListsEgress(Switch, + Switch->ExtensionContext, + dropNbl, + returnFlags); + } + + goto Cleanup; + } + + NdisFIndicateReceiveNetBufferLists(Switch->NdisFilterHandle, + NetBufferLists, + NDIS_DEFAULT_PORT_NUMBER, + NumberOfNetBufferLists, + ReceiveFlags); + +Cleanup: + return; +} + +VOID +SxLibCompleteNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG ReturnFlags + ) +{ + NdisFReturnNetBufferLists(Switch->NdisFilterHandle, + NetBufferLists, + ReturnFlags); +} + + +VOID +SxLibCompleteNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendCompleteFlags + ) +{ + NdisFSendNetBufferListsComplete(Switch->NdisFilterHandle, + NetBufferLists, + SendCompleteFlags); +} + +VOID +SxLibCompletedInjectedNetBufferLists( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ ULONG NumInjectedNetBufferLists + ) +{ + LONG subtract = -(LONG)NumInjectedNetBufferLists; + InterlockedAdd(&Switch->PendingInjectedNblCount, subtract); +} + + +NDIS_STATUS +SxLibIssueOidRequest( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_REQUEST_TYPE RequestType, + _In_ NDIS_OID Oid, + _In_opt_ PVOID InformationBuffer, + _In_ ULONG InformationBufferLength, + _In_ ULONG OutputBufferLength, + _In_ ULONG MethodId, + _In_ UINT Timeout, + _Out_ PULONG BytesNeeded + ) +{ + NDIS_STATUS status; + PSX_OID_REQUEST oidRequest; + PNDIS_OID_REQUEST ndisOidRequest; + ULONG bytesNeeded; + BOOLEAN asyncCompletion; + + status = NDIS_STATUS_SUCCESS; + oidRequest = NULL; + bytesNeeded = 0; + asyncCompletion = FALSE; + + NdisInterlockedIncrement(&Switch->PendingOidCount); + + if (Switch->ControlFlowState != SxSwitchAttached) + { + status = NDIS_STATUS_CLOSING; + goto Cleanup; + } + + // + // Dynamically allocate filter request so that we can handle asynchronous + // completion. + // + oidRequest = (PSX_OID_REQUEST)ExAllocatePoolWithTag(NonPagedPoolNx, + sizeof(SX_OID_REQUEST), + SxExtAllocationTag); + if (oidRequest == NULL) + { + goto Cleanup; + } + + NdisZeroMemory(oidRequest, sizeof(SX_OID_REQUEST)); + ndisOidRequest = &oidRequest->NdisOidRequest; + NdisInitializeEvent(&oidRequest->ReqEvent); + + ndisOidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; + ndisOidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; + ndisOidRequest->Header.Size = sizeof(NDIS_OID_REQUEST); + ndisOidRequest->RequestType = RequestType; + ndisOidRequest->Timeout = Timeout; + + switch (RequestType) + { + case NdisRequestQueryInformation: + ndisOidRequest->DATA.QUERY_INFORMATION.Oid = Oid; + ndisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer = + InformationBuffer; + ndisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = + InformationBufferLength; + break; + + case NdisRequestSetInformation: + ndisOidRequest->DATA.SET_INFORMATION.Oid = Oid; + ndisOidRequest->DATA.SET_INFORMATION.InformationBuffer = + InformationBuffer; + ndisOidRequest->DATA.SET_INFORMATION.InformationBufferLength = + InformationBufferLength; + break; + + case NdisRequestMethod: + ndisOidRequest->DATA.METHOD_INFORMATION.Oid = Oid; + ndisOidRequest->DATA.METHOD_INFORMATION.MethodId = MethodId; + ndisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer = + InformationBuffer; + ndisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength = + InformationBufferLength; + ndisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength = + OutputBufferLength; + break; + + default: + NT_ASSERT(FALSE); + break; + } + + ndisOidRequest->RequestId = (PVOID)SxExtOidRequestId; + status = NdisFOidRequest(Switch->NdisFilterHandle, ndisOidRequest); + + if (status == NDIS_STATUS_PENDING) + { + asyncCompletion = TRUE; + NdisWaitEvent(&oidRequest->ReqEvent, 0); + } + else + { + SxpNdisCompleteInternalOidRequest(Switch, ndisOidRequest, status); + } + + bytesNeeded = oidRequest->BytesNeeded; + status = oidRequest->Status; + +Cleanup: + + if (BytesNeeded != NULL) + { + *BytesNeeded = bytesNeeded; + } + + if (!asyncCompletion) + { + NdisInterlockedDecrement(&Switch->PendingOidCount); + } + + if (oidRequest != NULL) + { + ExFreePoolWithTag(oidRequest, SxExtAllocationTag); + } + + return status; +} + + +NDIS_STATUS +SxLibGetSwitchParametersUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _Out_ PNDIS_SWITCH_PARAMETERS SwitchParameters + ) +{ + NDIS_STATUS status; + + SwitchParameters->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1; + SwitchParameters->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + SwitchParameters->Header.Size = sizeof(NDIS_SWITCH_PARAMETERS); + + status = SxLibIssueOidRequest(Switch, + NdisRequestQueryInformation, + OID_SWITCH_PARAMETERS, + SwitchParameters, + sizeof(NDIS_SWITCH_PARAMETERS), + 0, + 0, + 0, + NULL); + + return status; +} + + +NDIS_STATUS +SxLibGetPortArrayUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _Out_ PNDIS_SWITCH_PORT_ARRAY *PortArray + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + ULONG BytesNeeded = 0; + PNDIS_SWITCH_PORT_ARRAY portArray = NULL; + ULONG arrayLength = 0; + + do + { + if (portArray != NULL) + { + ExFreePoolWithTag(portArray, SxExtAllocationTag); + } + + if (BytesNeeded != 0) + { + arrayLength = BytesNeeded; + portArray = ExAllocatePoolWithTag(NonPagedPoolNx, + arrayLength, + SxExtAllocationTag); + + if (portArray == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + + portArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1; + portArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + portArray->Header.Size = (USHORT)arrayLength; + } + + status = SxLibIssueOidRequest(Switch, + NdisRequestQueryInformation, + OID_SWITCH_PORT_ARRAY, + portArray, + arrayLength, + 0, + 0, + 0, + &BytesNeeded); + + } while(status == NDIS_STATUS_INVALID_LENGTH); + + *PortArray = portArray; +Cleanup: + if (status != NDIS_STATUS_SUCCESS && + portArray != NULL) + { + ExFreePoolWithTag(portArray, SxExtAllocationTag); + } + + return status; +} + + +NDIS_STATUS +SxLibGetNicArrayUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _Out_ PNDIS_SWITCH_NIC_ARRAY *NicArray + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + ULONG BytesNeeded = 0; + PNDIS_SWITCH_NIC_ARRAY nicArray = NULL; + ULONG arrayLength = 0; + + do + { + if (nicArray != NULL) + { + ExFreePoolWithTag(nicArray, SxExtAllocationTag); + } + + if (BytesNeeded != 0) + { + arrayLength = BytesNeeded; + nicArray = ExAllocatePoolWithTag(NonPagedPoolNx, + arrayLength, + SxExtAllocationTag); + + if (nicArray == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + + nicArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1; + nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + nicArray->Header.Size = (USHORT)arrayLength; + } + + status = SxLibIssueOidRequest(Switch, + NdisRequestQueryInformation, + OID_SWITCH_NIC_ARRAY, + nicArray, + arrayLength, + 0, + 0, + 0, + &BytesNeeded); + + } while(status == NDIS_STATUS_INVALID_LENGTH); + + *NicArray = nicArray; +Cleanup: + if (status != NDIS_STATUS_SUCCESS && + nicArray != NULL) + { + ExFreePoolWithTag(nicArray, SxExtAllocationTag); + } + + return status; +} + + +NDIS_STATUS +SxLibGetSwitchPropertyUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PROPERTY_TYPE PropertyType, + _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId, + _Outptr_ PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS *SwitchPropertyEnumParameters + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS propertyParameters; + ULONG bytesNeeded = 0; + PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL; + USHORT outputBufferLength = sizeof(NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS); + + propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + propertyParameters.Header.Revision = NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS_REVISION_1; + + propertyParameters.PropertyType = PropertyType; + propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1; + + // + // For Built-in properties, the ID is unnecessary. + // + if (PropertyId != NULL) + { + NdisMoveMemory(&propertyParameters.PropertyId, + PropertyId, + sizeof(NDIS_SWITCH_OBJECT_ID)); + } + else + { + ASSERT(PropertyType != NdisSwitchPropertyTypeCustom); + } + + outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, + outputBufferLength, + SxExtAllocationTag); + + if (outputBuffer == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + + do + { + if (bytesNeeded != 0) + { + ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); + + outputBufferLength = (USHORT)bytesNeeded; + outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, + outputBufferLength, + SxExtAllocationTag); + + if (outputBuffer == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + } + + if(outputBufferLength >= sizeof(propertyParameters)) + { + NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters)); + + } + + status = SxLibIssueOidRequest(Switch, + NdisRequestMethod, + OID_SWITCH_PROPERTY_ENUM, + outputBuffer, + sizeof(propertyParameters), + outputBufferLength, + 0, + 0, + &bytesNeeded); + + } while(status == NDIS_STATUS_INVALID_LENGTH); + +Cleanup: + if (status != NDIS_STATUS_SUCCESS && + outputBuffer != NULL) + { + ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); + outputBuffer = NULL; + } + + *SwitchPropertyEnumParameters = outputBuffer; + + return status; +} + + +NDIS_STATUS +SxLibGetPortPropertyUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PORT_ID PortId, + _In_ NDIS_SWITCH_PORT_PROPERTY_TYPE PropertyType, + _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId, + _Outptr_ PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS *PortPropertyEnumParameters + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS propertyParameters; + ULONG bytesNeeded = 0; + PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL; + USHORT outputBufferLength = sizeof(NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS); + + propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + propertyParameters.Header.Revision = NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS_REVISION_1; + + propertyParameters.PortId = PortId; + propertyParameters.PropertyType = PropertyType; + propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1; + + // + // For Built-in properties, the ID is unnecessary. + // + if (PropertyId != NULL) + { + NdisMoveMemory(&propertyParameters.PropertyId, + PropertyId, + sizeof(NDIS_SWITCH_OBJECT_ID)); + } + else + { + ASSERT(PropertyType != NdisSwitchPortPropertyTypeCustom); + } + + outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, + outputBufferLength, + SxExtAllocationTag); + + if (outputBuffer == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + + do + { + if (bytesNeeded != 0) + { + ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); + + outputBufferLength = (USHORT)bytesNeeded; + outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, + outputBufferLength, + SxExtAllocationTag); + + if (outputBuffer == NULL) + { + status = NDIS_STATUS_RESOURCES; + goto Cleanup; + } + } + + if(outputBufferLength >= sizeof(propertyParameters)) + { + outputBuffer->Header.Size = outputBufferLength; + NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters)); + } + + status = SxLibIssueOidRequest(Switch, + NdisRequestMethod, + OID_SWITCH_PORT_PROPERTY_ENUM, + outputBuffer, + sizeof(propertyParameters), + outputBufferLength, + 0, + 0, + &bytesNeeded); + + } while(status == NDIS_STATUS_INVALID_LENGTH); + +Cleanup: + if (status != NDIS_STATUS_SUCCESS && + outputBuffer != NULL) + { + ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); + outputBuffer = NULL; + } + + *PortPropertyEnumParameters = outputBuffer; + + return status; +} + + +VOID +SxLibRevokeVfUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PORT_ID PortId + ) +{ + SxLibIssueNicStatusIndicationUnsafe(Switch, + NDIS_STATUS_SWITCH_PORT_REMOVE_VF, + PortId, + NDIS_SWITCH_DEFAULT_NIC_INDEX, + TRUE, + NULL, + 0); +} + + +VOID +SxLibIssueNicStatusIndicationUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_STATUS StatusCode, + _In_ NDIS_SWITCH_PORT_ID PortId, + _In_ NDIS_SWITCH_NIC_INDEX NicIndex, + _In_ BOOLEAN IsDestination, + _In_opt_ PVOID StatusBuffer, + _In_ ULONG StatusBufferSize + ) +{ + NDIS_STATUS_INDICATION statusIndication; + NDIS_STATUS_INDICATION wrappedIndication; + NDIS_SWITCH_NIC_STATUS_INDICATION nicIndication; + + NdisZeroMemory(&wrappedIndication, sizeof(wrappedIndication)); + + wrappedIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; + wrappedIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; + wrappedIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; + + wrappedIndication.SourceHandle = Switch->NdisFilterHandle; + wrappedIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER; + + wrappedIndication.StatusCode = StatusCode; + wrappedIndication.StatusBuffer = StatusBuffer; + wrappedIndication.StatusBufferSize = StatusBufferSize; + + NdisZeroMemory(&nicIndication, sizeof(nicIndication)); + + nicIndication.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + nicIndication.Header.Revision = NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1; + nicIndication.Header.Size = NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1; + nicIndication.StatusIndication = &wrappedIndication; + + if (IsDestination) + { + nicIndication.DestinationPortId = PortId; + nicIndication.DestinationNicIndex = NicIndex; + } + else + { + nicIndication.SourcePortId = PortId; + nicIndication.SourceNicIndex = NicIndex; + } + + NdisZeroMemory(&statusIndication, sizeof(statusIndication)); + + 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; + + statusIndication.SourceHandle = Switch->NdisFilterHandle; + statusIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER; + + statusIndication.StatusCode = NDIS_STATUS_SWITCH_NIC_STATUS; + statusIndication.StatusBuffer = &nicIndication; + statusIndication.StatusBufferSize = sizeof(nicIndication); + + NdisFIndicateStatus(Switch->NdisFilterHandle, + &statusIndication); +} + diff --git a/network/ndis/extension/base/SxLibrary.h b/network/ndis/extension/base/SxLibrary.h new file mode 100644 index 00000000..2d9a30af --- /dev/null +++ b/network/ndis/extension/base/SxLibrary.h @@ -0,0 +1,464 @@ +/*++ + +Copyright (c) Microsoft Corporation. All Rights Reserved. + +Module Name: + + SxLibrary.h + +Abstract: + + This file contains the common library function headers that can be + used by any extension using the SxBase library. + + +--*/ + + +/*++ + +SxLibSendNetBufferListsIngress + +Routine Description: + This function is called to forward NBLs on ingress. + The extension MUST call this function, or call + SxLibCompleteNetBufferListsIngress for every NBL in NetBufferLists, + recieved in SxExtStartNetBufferListsIngress. + + This function can also be called to inject NBLs. + If there are NBLs in NetBufferLists that are initiated by the + extension, NumInjectedNetBufferLists must be the number of new NBLs. + +Arguments: + + Switch - the Switch context + + NetBufferLists - the NBLs to send + + SendFlags - the SendFlags equivalent to NDIS flags for + NdisFSendNetBufferLists + + NumInjectedNetBufferLists - the number of NBLs in NetBufferLists initiated + by the extension + +Return Value: + VOID + +--*/ +VOID +SxLibSendNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendFlags, + _In_ ULONG NumInjectedNetBufferLists + ); + + +/*++ + +SxLibSendNetBufferListsEgress + +Routine Description: + This function is called to forward NBLs on egress. + The extension MUST call this function, or call + SxLibCompleteNetBufferListsEgress for every NBL in NetBufferLists + recieved in SxExtStartNetBufferListsEgress. + +Arguments: + + Switch - the Switch context + + NetBufferLists - the NBLs to send + + NumberOfNetBufferLists - the number of NBLs in NetBufferLists + + ReceiveFlags - the ReceiveFlags equivalent to NDIS flags for + NdisFIndicateReceiveNetBufferLists + +Return Value: + VOID + +--*/ +VOID +SxLibSendNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG NumberOfNetBufferLists, + _In_ ULONG ReceiveFlags + ); + + +/*++ + +SxLibCompleteNetBufferListsEgress + +Routine Description: + This function is called to complete NBLs on egress. + The extension MUST call this function for all NBLs recieved + in SxExtStartCompleteNetBufferListsEgress. + +Arguments: + + Switch - the Switch context + + NetBufferLists - the NBLs to send + + ReturnFlags - the ReceiveFlags equivalent to NDIS flags for + NdisFReturnNetBufferLists + +Return Value: + VOID + +--*/ +VOID +SxLibCompleteNetBufferListsEgress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG ReturnFlags + ); + +/*++ + +SxLibCompleteNetBufferListsIngress + +Routine Description: + This function is called to complete NBLs on ingress. + The extension MUST call this function, or + SxLibCompletedInjectedNetBufferLists for all NBLs recieved in + SxExtStartCompleteNetBufferListsEgress. + +Arguments: + + Switch - the Switch context + + NetBufferLists - the NBLs to send + + SendCompleteFlags - the ReceiveFlags equivalent to NDIS flags for + NdisFSendNetBufferListsComplete + +Return Value: + VOID + +--*/ +VOID +SxLibCompleteNetBufferListsIngress( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ PNET_BUFFER_LIST NetBufferLists, + _In_ ULONG SendCompleteFlags + ); + + +/*++ + +SxLibCompletedInjectedNetBufferLists + +Routine Description: + This function is called after completing NBLs injected + by the extension. + +Arguments: + + Switch - the Switch context + + NumInjectedNetBufferLists - the number of NBLs completed + +Return Value: + VOID + +--*/ +VOID +SxLibCompletedInjectedNetBufferLists( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ ULONG NumInjectedNetBufferLists + ); + + +/*++ + +SxLibIssueOidRequest + +Routine Description: + + Utility routine that forms and sends an NDIS_OID_REQUEST to the + miniport, waits for it to complete, and returns status + to the caller. + + NOTE: this assumes that the calling routine ensures validity + of the filter handle until this returns. + + This function can only be called at PASSIVE_LEVEL. + +Arguments: + + Switch - pointer to our switch object. + + RequestType - NdisRequest[Set|Query|method]Information. + + Oid - the object being set/queried. + + InformationBuffer - data for the request. + + InformationBufferLength - length of the above. + + OutputBufferLength - valid only for method request. + + MethodId - valid only for method request. + + Timeout - The timeout in seconds for the OID. + + BytesNeeded - place to return bytes read/written. + +Return Value: + + NDIS_STATUS_*** + +--*/ +NDIS_STATUS +SxLibIssueOidRequest( + _In_ PSX_SWITCH_OBJECT SxSwitch, + _In_ NDIS_REQUEST_TYPE RequestType, + _In_ NDIS_OID Oid, + _In_opt_ PVOID InformationBuffer, + _In_ ULONG InformationBufferLength, + _In_ ULONG OutputBufferLength, + _In_ ULONG MethodId, + _In_ UINT Timeout, + _Out_ PULONG BytesNeeded + ); + + +/*++ + +SxLibGetSwitchParametersUnsafe + +Routine Description: + This function is called to get the current state of the switch. + +Arguments: + + Switch - the Switch context + + SwitchParameters - the returned switch parameters + +Return Value: + NDIS_STATUS_SUCCESS - if SwitchParameters was successfully returned + + NDIS_STATUS_*** - otherwise + +--*/ +NDIS_STATUS +SxLibGetSwitchParametersUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _Out_ PNDIS_SWITCH_PARAMETERS SwitchParameters + ); + + +/*++ + +SxLibGetPortArrayUnsafe + +Routine Description: + This function is called to get the current array + of ports. + + NOTE: It is necessary to synchonize this with SxExtPortCreate + and SxExtPortTeardown. + +Arguments: + + Switch - the Switch context + + PortArray - the returned port array + +Return Value: + NDIS_STATUS_SUCCESS - if PortArray was successfully allocated + and returned + + NDIS_STATUS_*** - otherwise + +--*/ +NDIS_STATUS +SxLibGetPortArrayUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _Out_ PNDIS_SWITCH_PORT_ARRAY *PortArray + ); + + +/*++ + +SxLibGetNicArrayUnsafe + +Routine Description: + This function is called to get the current array + of NICs. + + NOTE: It is necessary to synchonize this with SxExtNicConnect + and SxExtNicDisconnect. + +Arguments: + + Switch - the Switch context + + NicArray - the returned NIC array + +Return Value: + NDIS_STATUS_SUCCESS - if NicArray was successfully allocated + and returned + + NDIS_STATUS_*** - otherwise + +--*/ +NDIS_STATUS +SxLibGetNicArrayUnsafe( + _In_ PSX_SWITCH_OBJECT SxSwitch, + _Out_ PNDIS_SWITCH_NIC_ARRAY *NicArray + ); + +/*++ + +SxLibGetSwitchPropertyUnsafe + +Routine Description: + This function is called to get the current array of the switch + property queried. + + NOTE: It is necessary to synchonize this with SxExtAddSwitchProperty + and SxExtDeleteSwitchProperty. + +Arguments: + + Switch - the Switch context + + PropertyType - the PropertyType to query for + + PropertyId - the GUID of the property (from mof file) + + PropertyVersion - the version of the property + + SwitchPropertyEnumParameters - the returned property enum + +Return Value: + NDIS_STATUS_SUCCESS - if SwitchPropertyEnumParameters was + successfully allocated and returned + + NDIS_STATUS_*** - otherwise + +--*/ +NDIS_STATUS +SxLibGetSwitchPropertyUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PROPERTY_TYPE PropertyType, + _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId, + _Outptr_ PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS *SwitchPropertyEnumParameters + ); + +/*++ + +SxLibGetPortPropertyUnsafe + +Routine Description: + This function is called to get the current array of the switch + property queried. + + NOTE: It is necessary to synchonize this with SxExtAddPortProperty + and SxExtDeletePortProperty. + +Arguments: + + Switch - the Switch context + + PortId - the port to query from + + PropertyType - the PropertyType to query for + + PropertyId - the GUID of the property (from mof file) + + PortPropertyEnumParameters - the returned property enum + +Return Value: + NDIS_STATUS_SUCCESS - if PortPropertyEnumParameters was + successfully allocated and returned + + NDIS_STATUS_*** - otherwise + +--*/ +NDIS_STATUS +SxLibGetPortPropertyUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PORT_ID PortId, + _In_ NDIS_SWITCH_PORT_PROPERTY_TYPE PropertyType, + _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId, + _Outptr_ PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS *PortPropertyEnumParameters + ); + +/*++ + +SxLibRevokeVfUnsafe + +Routine Description: + This function is called revoke the VF assignment for the + given VM. + + NOTE: This must be synchonized with SxExtNicConnect and + SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic + must have been successfully called. + +Arguments: + + Switch - the Switch context + + PortId - the port the VM is connected to + +Return Value: + VOID + +--*/ +VOID +SxLibRevokeVfUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_SWITCH_PORT_ID PortId + ); + +/*++ + +SxLibIssueNicStatusIndicationUnsafe + +Routine Description: + This function is called issue a NIC status indication. + + NOTE: This must be synchonized with SxExtNicConnect and + SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic + must have been successfully called. + +Arguments: + + Switch - the Switch context + + StatusCode - the status code to indicate + + PortId - the port to indicate to/from + + NicIndex - the nic index to indicate to/from + + IsDestination - TRUE if PortId/NicIndex is destination info + FALSE if PortId/NicIndex is source info + + StatusBuffer - the StatusBuffer for the indication + + StatusBufferSize - the size of StatusBuffer + +Return Value: + VOID + +--*/ +VOID +SxLibIssueNicStatusIndicationUnsafe( + _In_ PSX_SWITCH_OBJECT Switch, + _In_ NDIS_STATUS StatusCode, + _In_ NDIS_SWITCH_PORT_ID PortId, + _In_ NDIS_SWITCH_NIC_INDEX NicIndex, + _In_ BOOLEAN IsDestination, + _In_opt_ PVOID StatusBuffer, + _In_ ULONG StatusBufferSize + ); + diff --git a/network/ndis/extension/base/precomp.h b/network/ndis/extension/base/precomp.h new file mode 100644 index 00000000..b0bd41c8 --- /dev/null +++ b/network/ndis/extension/base/precomp.h @@ -0,0 +1,11 @@ +// +// Copyright (c) Microsoft Corporation. All Rights Reserved. +// + +#include <ndis.h> +#include <netiodef.h> +#include <intsafe.h> +#include <ntintsafe.h> +#include "SxBase.h" +#include "SxApi.h" +#include "SxLibrary.h" diff --git a/network/ndis/extension/base/precompsrc.c b/network/ndis/extension/base/precompsrc.c new file mode 100644 index 00000000..5944cf51 --- /dev/null +++ b/network/ndis/extension/base/precompsrc.c @@ -0,0 +1 @@ +#include "precomp.h"
\ No newline at end of file diff --git a/network/ndis/extension/base/sxbase.vcxproj b/network/ndis/extension/base/sxbase.vcxproj new file mode 100644 index 00000000..4c81ea79 --- /dev/null +++ b/network/ndis/extension/base/sxbase.vcxproj @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{63FF1428-95CA-4751-A701-244D54A31BD9}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <SampleGuid>{8C4C832A-4638-47E9-B2AC-6FA6FC1D958B}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>sxbase</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>sxbase</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS630=1;NDIS_WDM=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="precompsrc.c"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Create</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="SxBase.c"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="SxLibrary.c"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/ndis/extension/base/sxbase.vcxproj.Filters b/network/ndis/extension/base/sxbase.vcxproj.Filters new file mode 100644 index 00000000..1291527a --- /dev/null +++ b/network/ndis/extension/base/sxbase.vcxproj.Filters @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{74637802-97A6-4EEE-A780-7AFC24D63060}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{7417E375-1992-4C4B-A4AB-C0C8E00F9AAA}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{73A4206C-20D4-4AB0-B133-03D222981702}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{CB4FE68B-83B4-4336-A241-94F6955D198A}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="precompsrc.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SxBase.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SxLibrary.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file |
