Vanara/PInvoke/QoS/Traffic.cs

2292 lines
108 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Generic;
using System.Linq;
using static Vanara.PInvoke.Qwave;
namespace Vanara.PInvoke;
/// <summary>Items from Traffic.dll.</summary>
public static partial class Traffic
{
/// <summary>The current traffic control version.</summary>
public const uint CURRENT_TCI_VERSION = 0x0002;
private const string Lib_Traffic = "traffic.dll";
private const int MAX_STRING_LENGTH = 256;
/// <summary>
/// <para>
/// The <c>ClAddFlowComplete</c> function is used by traffic control to notify the client of the completion of its previous call to the
/// TcAddFlow function.
/// </para>
/// <para>
/// The <c>ClAddFlowComplete</c> callback function is optional. If this function is not specified, TcAddFlow will block until it completes.
/// </para>
/// </summary>
/// <param name="ClFlowCtx">
/// Client providedflow context handle. This can be the container used to hold an arbitrary client-defined context for this instance of
/// the client. This value will be the same as the value provided by the client during its corresponding call to TcAddFlow.
/// </param>
/// <param name="Status">
/// <para>
/// Completion status for the TcAddFlow request. This value may be any of the return values possible for the <c>TcAddFlow</c> function,
/// with the exception of ERROR_SIGNAL_PENDING.
/// </para>
/// <para><c>Note</c> Use of the <c>ClAddFlowComplete</c> function requires administrative privilege.</para>
/// </param>
/// <returns>None</returns>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nc-traffic-tci_add_flow_complete_handler TCI_ADD_FLOW_COMPLETE_HANDLER
// TciAddFlowCompleteHandler; void TciAddFlowCompleteHandler( [in] HANDLE ClFlowCtx, [in] ULONG Status ) {...}
[PInvokeData("traffic.h", MSDNShortId = "NC:traffic.TCI_ADD_FLOW_COMPLETE_HANDLER")]
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
public delegate void TCI_ADD_FLOW_COMPLETE_HANDLER([In] IntPtr ClFlowCtx, Win32Error Status);
/// <summary>
/// <para>
/// The <c>ClDeleteFlowComplete</c> function is used by traffic control to notify the client of the completion of its previous call to
/// the TcDeleteFlow function.
/// </para>
/// <para>
/// The <c>ClDeleteFlowComplete</c> callback function is optional. If this function is not specified, TcDeleteFlow will block until it completes.
/// </para>
/// </summary>
/// <param name="ClFlowCtx">
/// Client providedflow context handle. This can be the container used to hold an arbitrary client-defined context for this instance of
/// the client. This value will be the same as the value provided by the client during its corresponding call to TcDeleteFlow.
/// </param>
/// <param name="Status">
/// <para>
/// Completion status for the TcDeleteFlow request. This value may be any of the return values possible for the <c>TcDeleteFlow</c>
/// function, with the exception of ERROR_SIGNAL_PENDING.
/// </para>
/// <para><c>Note</c> Use of the <c>ClDeleteFlowComplete</c> function requires administrative privilege.</para>
/// </param>
/// <returns>None</returns>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nc-traffic-tci_del_flow_complete_handler TCI_DEL_FLOW_COMPLETE_HANDLER
// TciDelFlowCompleteHandler; void TciDelFlowCompleteHandler( [in] HANDLE ClFlowCtx, [in] ULONG Status ) {...}
[PInvokeData("traffic.h", MSDNShortId = "NC:traffic.TCI_DEL_FLOW_COMPLETE_HANDLER")]
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
public delegate void TCI_DEL_FLOW_COMPLETE_HANDLER([In] IntPtr ClFlowCtx, Win32Error Status);
/// <summary>
/// <para>
/// The <c>ClModifyFlowComplete</c> function is used by traffic control to notify the client of the completion of its previous call to
/// the TcModifyFlow function.
/// </para>
/// <para>
/// The <c>ClModifyFlowComplete</c> callback function is optional. If this function is not specified, TcModifyFlow will block until it completes.
/// </para>
/// </summary>
/// <param name="ClFlowCtx">
/// Client providedflow context handle. This can be the container used to hold an arbitrary client-defined context for this instance of
/// the client. This value will be the same as the value provided by the client during its corresponding call to TcModifyFlow.
/// </param>
/// <param name="Status">
/// <para>
/// Completion status for the TcModifyFlow request. This value may be any of the return values possible for the <c>TcModifyFlow</c>
/// function, with the exception of ERROR_SIGNAL_PENDING.
/// </para>
/// <para><c>Note</c> Use of the <c>ClModifyFlowComplete</c> function requires administrative privilege.</para>
/// </param>
/// <returns>None</returns>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nc-traffic-tci_mod_flow_complete_handler TCI_MOD_FLOW_COMPLETE_HANDLER
// TciModFlowCompleteHandler; void TciModFlowCompleteHandler( [in] HANDLE ClFlowCtx, [in] ULONG Status ) {...}
[PInvokeData("traffic.h", MSDNShortId = "NC:traffic.TCI_MOD_FLOW_COMPLETE_HANDLER")]
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
public delegate void TCI_MOD_FLOW_COMPLETE_HANDLER([In] IntPtr ClFlowCtx, Win32Error Status);
/// <summary>
/// <para>
/// The <c>ClNotifyHandler</c> function is used by traffic control to notify the client of various traffic controlspecific events,
/// including the deletion of flows, changes in filter parameters, or the closing of an interface.
/// </para>
/// <para>The <c>ClNotifyHandler</c> callback function should be exposed by all clients using traffic control services.</para>
/// </summary>
/// <param name="ClRegCtx">
/// Client registration context, provided to traffic control by the client with the client's call to the TcRegisterClient function.
/// </param>
/// <param name="ClIfcCtx">
/// Client interface context, provided to traffic control by the client with the client's call to the TcOpenInterface function. Note that
/// during a TC_NOTIFY_IFC_UP event, <c>ClIfcCtx</c> is not available and will be set to <c>NULL</c>.
/// </param>
/// <param name="Event">Describes the notification event. See the Remarks section for a list of notification events.</param>
/// <param name="SubCode">Handle used to further qualify a notification event. See Note below for 64-bit for Windows programming issues.</param>
/// <param name="BufSize">Size of the buffer included with the notification event, in bytes.</param>
/// <param name="Buffer">Buffer containing the detailed event information associated with <c>Event</c> and <c>SubCode</c>.</param>
/// <returns>None</returns>
/// <remarks>
/// <para>
/// Notification events may require the traffic control client to take particular action or respond appropriately, for example, removing
/// filters or enumerating flows for affected interfaces.
/// </para>
/// <para>The following table describes the various notification events.</para>
/// <list type="table">
/// <listheader>
/// <term>Event</term>
/// <term>SubCode</term>
/// <term>Buffer contents</term>
/// <term>Remarks</term>
/// </listheader>
/// <item>
/// <term>TC_NOTIFY_IFC_UP</term>
/// <term>None</term>
/// <term>Interface name of the new interface</term>
/// <term>A new traffic control interface is coming up, and the list of addresses is indicated.</term>
/// </item>
/// <item>
/// <term>TC_NOTIFY_IFC_CLOSE</term>
/// <term>Reason for close</term>
/// <term>Interface name of the closed interface</term>
/// <term>
/// Indicates an interface that was opened by the client is being closed by the system. Note that the interface and its supported flows
/// and filters are closed by the system upon return from the notification handler. The client does not need to close the interface,
/// delete flows, or delete filters.
/// </term>
/// </item>
/// <item>
/// <term>TC_NOTIFY_IFC_CHANGE</term>
/// <term>None</term>
/// <term>New parameter value</term>
/// <term>
/// Used to notify clients that have registered for interface change notification through the <c>NotifyChange</c> parameter of the
/// TcQueryInterface function.
/// </term>
/// </item>
/// <item>
/// <term>TC_NOTIFY_PARAM_CHANGED</term>
/// <term>Pointer to the GUID for a traffic control parameter queried using the TcQueryInterface function.</term>
/// <term>New parameter value</term>
/// <term>This event is notified as a result of a change in a parameter previously queried with the <c>NotifyChange</c> flag set.</term>
/// </item>
/// <item>
/// <term>TC_NOTIFY_FLOW_CLOSE</term>
/// <term><c>ClFlowCtx</c></term>
/// <term/>
/// <term>Indicates system closure of a client-created flow. The system deletes all associated filters.</term>
/// </item>
/// </list>
/// <para><c>Note</c> Use of the <c>ClNotifyHandler</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nc-traffic-tci_notify_handler TCI_NOTIFY_HANDLER TciNotifyHandler; void
// TciNotifyHandler( [in] HANDLE ClRegCtx, [in] HANDLE ClIfcCtx, [in] ULONG Event, [in] HANDLE SubCode, [in] ULONG BufSize, [in] PVOID
// Buffer ) {...}
[PInvokeData("traffic.h", MSDNShortId = "NC:traffic.TCI_NOTIFY_HANDLER")]
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
public delegate void TCI_NOTIFY_HANDLER([In] IntPtr ClRegCtx, [In, Optional] IntPtr ClIfcCtx, TC_NOTIFY Event, [In] IntPtr SubCode,
uint BufSize, [In] IntPtr Buffer);
/// <summary>Describes the notification event.</summary>
[PInvokeData("traffic.h", MSDNShortId = "NC:traffic.TCI_NOTIFY_HANDLER")]
public enum TC_NOTIFY : uint
{
/// <summary>A new traffic control interface is coming up, and the list of addresses is indicated.</summary>
TC_NOTIFY_IFC_UP = 1,
/// <summary>
/// Indicates an interface that was opened by the client is being closed by the system. Note that the interface and its supported
/// flows and filters are closed by the system upon return from the notification handler. The client does not need to close the
/// interface, delete flows, or delete filters.
/// </summary>
TC_NOTIFY_IFC_CLOSE = 2,
/// <summary>
/// Used to notify clients that have registered for interface change notification through the NotifyChange parameter of the
/// TcQueryInterface function.
/// </summary>
TC_NOTIFY_IFC_CHANGE = 3,
/// <summary>This event is notified as a result of a change in a parameter previously queried with the NotifyChange flag set.</summary>
TC_NOTIFY_PARAM_CHANGED = 4,
/// <summary>Indicates system closure of a client-created flow. The system deletes all associated filters.</summary>
TC_NOTIFY_FLOW_CLOSE = 5,
}
/// <summary>
/// <para>
/// The <c>TcAddFilter</c> function associates a new filter with an existing flow that allows packets matching the filter to be directed
/// to the associated flow.
/// </para>
/// <para>
/// Filters include a pattern and a mask. The pattern specifies particular parameter values, while the mask specifies which parameters
/// and parameter subfields apply to a given filter. When a pattern/mask combination is applied to a set of packets, matching packets are
/// directed to the flow to which the corresponding filter is associated.
/// </para>
/// <para>
/// Traffic control returns a handle to the newly added filter, in the pFilterHandle parameter, by which clients can refer to the added
/// filter. Pending flows, such as those processing a TcAddFlow or TcModifyFlow request for which a callback routine has not been
/// completed, cannot have filters associated to them; only flows that have been completed and are stable can apply associated filters.
/// </para>
/// <para>
/// The relationship between filters and flows is many to one. Multiple filters can be applied to a single flow; however, a filter can
/// only apply to one flow. For example, flow A can have filters X, Y and Z applied to it, but as long as flow A is active, filters X, Y
/// and Z cannot apply to any other flows.
/// </para>
/// </summary>
/// <param name="FlowHandle">Handle for the flow, as received from a previous call to the TcAddFlow function.</param>
/// <param name="pGenericFilter">Pointer to a description of the filter to be installed.</param>
/// <param name="pFilterHandle">
/// Pointer to a buffer where traffic control returns the filter handle. This filter handle is used by the client in subsequent calls to
/// refer to the added filter.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The flow handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>A parameter is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_ADDRESS_TYPE</c></term>
/// <term>An invalid address type has been provided.</term>
/// </item>
/// <item>
/// <term><c>ERROR_DUPLICATE_FILTER</c></term>
/// <term>An identical filter exists on a flow on this interface.</term>
/// </item>
/// <item>
/// <term><c>ERROR_FILTER_CONFLICT</c></term>
/// <term>A conflicting filter exists on a flow on this interface.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT READY</c></term>
/// <term>The flow is either being installed, modified, or deleted, and is not in a state that accepts filters.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Filters can be of different types. They are typically used to filter packets belonging to different network layers. Filter types
/// installed on an interface generally correspond to the address types of the network layer addresses associated with the interface. The
/// address type should be specified in the filter structure.
/// </para>
/// <para>
/// Filters may be rejected for various reasons, including possible conflicts with the requested filter as well as filters already
/// associated with the flow. Error codes specific to traffic control are provided to help the user diagnose the reason behind a
/// rejection to the <c>TcAddFilter</c> function.
/// </para>
/// <para><c>Note</c> Use of the <c>TcAddFilter</c> function requires administrative privilege.</para>
/// <para>In Windows Vista, overlapping and identical filters can be created. In these situations, the more specific filter takes precedence.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcaddfilter ULONG TcAddFilter( [in] HANDLE FlowHandle, [in]
// PTC_GEN_FILTER pGenericFilter, [out] PHANDLE pFilterHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcAddFilter")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcAddFilter([In] HFLOW FlowHandle, in TC_GEN_FILTER pGenericFilter, out SafeHFILTER pFilterHandle);
/// <summary>
/// <para>
/// The <c>TcAddFlow</c> function adds a new flow on the specified interface. Note that the successful addition of a flow does not
/// necessarily indicate a change in the way traffic is handled; traffic handling changes are effected by attaching a filter to the added
/// flow, using the TcAddFilter function.
/// </para>
/// <para>
/// Traffic control clients that have registered an <c>AddFlowComplete</c> handler (a mechanism for allowing traffic control to call the
/// ClAddFlowComplete callback function in order to alert clients of completed flow additions) can expect a return value of
/// ERROR_SIGNAL_PENDING. For more information, see Traffic Control Objects.
/// </para>
/// </summary>
/// <param name="IfcHandle">
/// Handle associated with the interface on which the flow is to be added. This handle is obtained by a previous call to the
/// TcOpenInterface function.
/// </param>
/// <param name="ClFlowCtx">Client providedflow context handle. Used subsequently by traffic control when referring to the added flow.</param>
/// <param name="Flags">Reserved for future use. Must be set to zero.</param>
/// <param name="pGenericFlow">Pointer to a description of the flow being installed.</param>
/// <param name="pFlowHandle">
/// Pointer to a location into which traffic control will return the flow handle. This flow handle should be used in subsequent calls to
/// traffic control to refer to the installed flow.
/// </param>
/// <returns>
/// <para>
/// There are many reasons why a request to add a flow might be rejected. Error codes returned by traffic control from calls to
/// <c>TcAddFlow</c> are provided to aid in determining the reason for rejection.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_SIGNAL_PENDING</c></term>
/// <term>
/// The function is being executed asynchronously; the client will be called back through the client-exposed ClAddFlowComplete function
/// when the flow has been added or when the process has been completed.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The interface handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>A parameter is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SERVICE_TYPE</c></term>
/// <term>An unspecified or bad <c>INTSERV</c> service type has been provided.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TOKEN_RATE</c></term>
/// <term>An unspecified or bad TOKENRATE value has been provided.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PEAK_RATE</c></term>
/// <term>The PEAKBANDWIDTH value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SD_MODE</c></term>
/// <term>The SHAPEDISCARDMODE is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_QOS_PRIORITY</c></term>
/// <term>The priority value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TRAFFIC_CLASS</c></term>
/// <term>The traffic class value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NO_SYSTEM_RESOURCES</c></term>
/// <term>There are not enough resources to accommodate the requested flow.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TC_OBJECT_LENGTH_INVALID</c></term>
/// <term>Bad length specified for the TC objects.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_DIFFSERV_FLOW</c></term>
/// <term>Applies to Diffserv flows. Indicates that the QOS_DIFFSERV object was passed with an invalid parameter.</term>
/// </item>
/// <item>
/// <term><c>ERROR_DS_MAPPING_EXISTS</c></term>
/// <term>
/// Applies to Diffserv flows. Indicates that the QOS_DIFFSERV_RULE specified in TC_GEN_FLOW already applies to an existing flow on the interface.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SHAPE_RATE</c></term>
/// <term>The QOS_SHAPING_RATE object was passed with an invalid <c>ShapingRate</c> member.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_DS_CLASS</c></term>
/// <term>The QOS_DS_CLASS is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NETWORK_UNREACHABLE</c></term>
/// <term>The network cable is not plugged into the adapter.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If the <c>TcAddFlow</c> function returns ERROR_SIGNAL_PENDING, the ClAddFlowComplete function will be called on a different thread
/// than the thread that called the <c>TcAddFlow</c> function.
/// </para>
/// <para>
/// Only the addition of a filter will affect traffic control. However, the addition of a flow will cause resources to be committed
/// within traffic control components. This enables traffic control to prepare for handling traffic on the added flow.
/// </para>
/// <para>
/// Traffic control may delete a flow for various reasons, including the inability to accommodate the flow due to bandwidth restrictions,
/// and adjusted policy requirements. Clients are notified of deleted flows through the ClNotifyHandler callback function, with the
/// TC_NOTIFY_FLOW_CLOSE event.
/// </para>
/// <para><c>Note</c> Use of the <c>TcAddFlow</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcaddflow ULONG TcAddFlow( [in] HANDLE IfcHandle, [in] HANDLE
// ClFlowCtx, [in] ULONG Flags, [in] PTC_GEN_FLOW pGenericFlow, [out] PHANDLE pFlowHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcAddFlow")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcAddFlow([In] HIFC IfcHandle, [In] IntPtr ClFlowCtx, [Optional] uint Flags,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(VanaraCustomMarshaler<TC_GEN_FLOW>))]
TC_GEN_FLOW pGenericFlow, out SafeHFLOW pFlowHandle);
/// <summary>
/// The <c>TcCloseInterface</c> function closes an interface previously opened with a call to TcOpenInterface. All flows and filters on a
/// particular interface should be closed before closing the interface with a call to <c>TcCloseInterface</c>.
/// </summary>
/// <param name="IfcHandle">
/// Handle associated with the interface to be closed. This handle is obtained by a previous call to the TcOpenInterface function.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The interface handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TC_SUPPORTED_OBJECTS_EXIST</c></term>
/// <term>Not all flows have been deleted for this interface.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Regardless of whether <c>TcCloseInterface</c> is called, an interface will be closed following a TC_NOTIFY_IFC_CLOSE notification
/// event. If the <c>TcCloseInterface</c> function is called with the handle of an interface that has already been closed, the handle
/// will be invalidated and <c>TcCloseInterface</c> will return ERROR_INVALID_HANDLE.
/// </para>
/// <para><c>Note</c> Use of <c>TcCloseInterface</c> requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tccloseinterface ULONG TcCloseInterface( [in] HANDLE IfcHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcCloseInterface")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcCloseInterface([In] HIFC IfcHandle);
/// <summary>The <c>TcDeleteFilter</c> function deletes a filter previously added with the TcAddFilter function.</summary>
/// <param name="FilterHandle">Handle to the filter to be deleted, as received in a previous call to the TcAddFilter function.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The filter handle is invalid.</term>
/// </item>
/// </list>
/// <para><c>Note</c> Use of the <c>TcDeleteFilter</c> function requires administrative privilege.</para>
/// </returns>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcdeletefilter ULONG TcDeleteFilter( [in] HANDLE FilterHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcDeleteFilter")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcDeleteFilter([In] HFILTER FilterHandle);
/// <summary>
/// <para>
/// The <c>TcDeleteFlow</c> function deletes a flow that has been added with the TcAddFlow function. Clients should delete all filters
/// associated with a flow before deleting it, otherwise, an error will be returned and the function will not delete the flow.
/// </para>
/// <para>
/// Traffic control clients that have registered a <c>DeleteFlowComplete</c> handler (a mechanism for allowing traffic control to call
/// the ClDeleteFlowComplete callback function to alert clients of completed flow deletions) can expect a return value of ERROR_SIGNAL_PENDING.
/// </para>
/// </summary>
/// <param name="FlowHandle">Handle for the flow, as received from a previous call to the TcAddFlow function.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_SIGNAL_PENDING</c></term>
/// <term>
/// The function is being executed asynchronously; the client will be called back through the client-exposed ClDeleteFlowComplete
/// function when the flow has been added, or when the process has been completed.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The flow handle is invalid or <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_READY</c></term>
/// <term>Action performed on the flow by a previous function call to TcModifyFlow, TcDeleteFlow, or TcAddFlow has not yet completed.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TC_SUPPORTED_OBJECTS_EXIST</c></term>
/// <term>At least one filter associated with this flow exists.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If the <c>TcDeleteFlow</c> function returns ERROR_SIGNAL_PENDING, the ClDeleteFlowComplete function will be called on a different
/// thread than the thread that called the <c>TcDeleteFlow</c> function.
/// </para>
/// <para><c>Note</c> Use of the <c>TcDeleteFlow</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcdeleteflow ULONG TcDeleteFlow( [in] HANDLE FlowHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcDeleteFlow")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcDeleteFlow([In] HFLOW FlowHandle);
/// <summary>
/// The <c>TcDeregisterClient</c> function deregisters a client with the Traffic Control Interface (TCI). Before deregistering, a client
/// must delete each installed flow and filter with the TcDeleteFlow and TcDeleteFilter functions, and close all open interfaces with the
/// TcCloseInterface function, respectively.
/// </summary>
/// <param name="ClientHandle">Handle assigned to the client through the previous call to the TcRegisterClient function.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>Invalid interface handle, or the handle was set to <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TC_SUPPORTED_OBJECTS_EXIST</c></term>
/// <term>Interfaces are still open for this client. all interfaces must be closed to deregister a client.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Once a client calls <c>TcDeregisterClient</c>, the only traffic control function the client is allowed to call is TcRegisterClient.</para>
/// <para><c>Note</c> Use of the <c>TcDeregisterClient</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcderegisterclient ULONG TcDeregisterClient( [in] HANDLE
// ClientHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcDeregisterClient")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcDeregisterClient([In] HCLIENT ClientHandle);
/// <summary>
/// <para>The <c>TcEnumerateFlows</c> function enumerates installed flows and their associated filters on an interface.</para>
/// <para>
/// The process of returning flow enumeration often consists of multiple calls to the <c>TcEnumerateFlows</c> function. The process of
/// receiving flow information from <c>TcEnumerateFlows</c> can be compared to reading through a book in multiple sittings, where a
/// certain number of pages are read at one time, a bookmark is placed where reading stops, reading is resumed at the bookmark, and
/// continues until the book is finished.
/// </para>
/// <para>
/// The <c>TcEnumerateFlows</c> function fills the <c>Buffer</c> parameter with as many flow enumerations as the buffer can hold, then
/// returns a handle in the pEnumToken parameter that internally bookmarks where the enumeration stopped. Subsequent calls to
/// <c>TcEnumerateFlows</c> must then pass the returned <c>pEnumToken</c> value to instruct traffic control where to resume flow
/// enumeration information. When all flows have been enumerated, <c>pEnumToken</c> will be <c>NULL</c>.
/// </para>
/// </summary>
/// <param name="IfcHandle">
/// Handle associated with the interface on which flows are to be enumerated. This handle is obtained by a previous call to the
/// TcOpenInterface function.
/// </param>
/// <param name="pEnumHandle">
/// <para>Pointer to the enumeration token, used internally by traffic control to maintain returned flow information state.</para>
/// <para>
/// For input of the initial call to <c>TcEnumerateFlows</c>, <c>pEnumToken</c> should be set to <c>NULL</c>. For input on subsequent
/// calls, <c>pEnumToken</c> must be the value returned as the <c>pEnumToken</c> OUT parameter from the immediately preceding call to <c>TcEnumerateFlows</c>.
/// </para>
/// <para>For output, <c>pEnumToken</c> is the refreshed enumeration token that must be used in the following call to <c>TcEnumerateFlows</c>.</para>
/// </param>
/// <param name="pFlowCount">
/// Pointer to the number of requested or returned flows. For input, this parameter designates the number of requested flows or it can be
/// set to <c>0xFFFF</c> to request all flows. For output, <c>pFlowCount</c> returns the number of flows actually returned in <c>Buffer</c>.
/// </param>
/// <param name="pBufSize">
/// Pointer to the size of the client-provided buffer or the number of bytes used by traffic control. For input, points to the size of
/// <c>Buffer</c>, in bytes. For output, points to the actual amount of buffer space, in bytes, written or needed with flow enumerations.
/// </param>
/// <param name="Buffer">
/// Pointer to the buffer containing flow enumerations. See ENUMERATION_BUFFER for more information about flow enumerations.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>Invalid interface handle.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>One of the pointers is <c>NULL</c>, or <c>pFlowCount</c> or <c>pBufSize</c> are set to zero.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INSUFFICIENT_BUFFER</c></term>
/// <term>The buffer is too small to store even a single flow's information and attached filters.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_DATA</c></term>
/// <term>The enumeration token is no longer valid.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Do not request zero flows, or pass a buffer with a size equal to zero or pointer to a <c>NULL</c>.</para>
/// <para>
/// If an enumeration token pointer has been invalidated by traffic control (due to the deletion of a flow), continuing to enumerate
/// flows is not allowed, and the call will return ERROR_INVALID_DATA. Under this circumstance, the process of enumeration must start
/// over. This circumstance can occur when the next flow to be enumerated is deleted while enumeration is in progress.
/// </para>
/// <para>To get the total number of flows for a given interface, call TcQueryInterface and specify <c>GUID_QOS_FLOW_COUNT</c>.</para>
/// <para><c>Note</c> Use of the <c>TcEnumerateFlows</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcenumerateflows ULONG TcEnumerateFlows( [in] HANDLE IfcHandle,
// [in, out] PHANDLE pEnumHandle, [in, out] PULONG pFlowCount, [in, out] PULONG pBufSize, [out] PENUMERATION_BUFFER Buffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcEnumerateFlows")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcEnumerateFlows([In] HIFC IfcHandle, ref HFLOWENUM pEnumHandle, ref uint pFlowCount, ref uint pBufSize, [Out] IntPtr Buffer);
/// <summary>
/// <para>The <c>TcEnumerateFlows</c> function enumerates installed flows and their associated filters on an interface.</para>
/// <para>
/// The process of returning flow enumeration often consists of multiple calls to the <c>TcEnumerateFlows</c> function. The process of
/// receiving flow information from <c>TcEnumerateFlows</c> can be compared to reading through a book in multiple sittings, where a
/// certain number of pages are read at one time, a bookmark is placed where reading stops, reading is resumed at the bookmark, and
/// continues until the book is finished.
/// </para>
/// <para>
/// The <c>TcEnumerateFlows</c> function fills the <c>Buffer</c> parameter with as many flow enumerations as the buffer can hold, then
/// returns a handle in the pEnumToken parameter that internally bookmarks where the enumeration stopped. Subsequent calls to
/// <c>TcEnumerateFlows</c> must then pass the returned <c>pEnumToken</c> value to instruct traffic control where to resume flow
/// enumeration information. When all flows have been enumerated, <c>pEnumToken</c> will be <c>NULL</c>.
/// </para>
/// </summary>
/// <param name="IfcHandle">
/// Handle associated with the interface on which flows are to be enumerated. This handle is obtained by a previous call to the
/// TcOpenInterface function.
/// </param>
/// <param name="pFlowCount">The number of requested flows or it can be set to <c>0xFFFF</c> to request all flows.</param>
/// <returns>An allocated buffer with the <see cref="ENUMERATION_BUFFER"/> contents.</returns>
/// <remarks>
/// <para>Do not request zero flows.</para>
/// <para>
/// If an enumeration token pointer has been invalidated by traffic control (due to the deletion of a flow), continuing to enumerate
/// flows is not allowed, and the call will return ERROR_INVALID_DATA. Under this circumstance, the process of enumeration must start
/// over. This circumstance can occur when the next flow to be enumerated is deleted while enumeration is in progress.
/// </para>
/// <para>To get the total number of flows for a given interface, call TcQueryInterface and specify <c>GUID_QOS_FLOW_COUNT</c>.</para>
/// <para><c>Note</c> Use of the <c>TcEnumerateFlows</c> function requires administrative privilege.</para>
/// </remarks>
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcEnumerateFlows")]
public static ENUMERATION_BUFFER_MGD? TcEnumerateFlows(HIFC IfcHandle, uint pFlowCount = 0xFFFF)
{
HFLOWENUM hEnum = default;
uint bufSz = 1024, cnt;
SafeCoTaskMemHandle buf = new(bufSz);
Win32Error err;
do
{
cnt = pFlowCount;
buf.Size = bufSz;
err = TcEnumerateFlows(IfcHandle, ref hEnum, ref cnt, ref bufSz, buf);
} while (err == Win32Error.ERROR_INSUFFICIENT_BUFFER);
err.ThrowIfFailed();
return cnt > 0 ? new(buf) : default;
}
/// <summary>
/// The <c>TcEnumerateInterfaces</c> function enumerates all traffic controlenabled network interfaces. Clients are notified of
/// interface changes through the ClNotifyHandler function.
/// </summary>
/// <param name="ClientHandle">
/// Handle used by traffic control to identify the client. Clients receive handles when registering with traffic control through the
/// TcRegisterClient function.
/// </param>
/// <param name="pBufferSize">
/// Pointer to a value indicating the size of the buffer. For input, this value is the size of the buffer, in bytes, allocated by the
/// caller. For output, this value is the actual size of the buffer, in bytes, used or needed by traffic control. A value of zero on
/// output indicates that no traffic control interfaces are available, indicating that the QOS Packet Scheduler is not installed.
/// </param>
/// <param name="InterfaceBuffer">Pointer to the buffer containing the returned list of interface descriptors.</param>
/// <returns>
/// <para>Successful completion returns the device name of the interface.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The client handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>One of the parameters is <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INSUFFICIENT_BUFFER</c></term>
/// <term>
/// The buffer is too small to enumerate all interfaces. If this error is returned, the correct (required) size of the buffer is passed
/// back in <c>pBufferSize</c>.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The client calling the <c>TcEnumerateInterfaces</c> function must first allocate a buffer, then pass the buffer to traffic control
/// through <c>InterfaceBuffer</c>. Traffic control returns a pointer to an array of interface descriptors in <c>InterfaceBuffer</c>.
/// Each interface descriptor contains two elements:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The traffic control interface's identifying text string.</term>
/// </item>
/// <item>
/// <term>The network address list descriptor currently associated with the interface.</term>
/// </item>
/// </list>
/// <para>
/// The network address list descriptor includes the media type, as well as a list of network addresses. The media type determines how
/// the network address list should be interpreted:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// For connectionless media such as a LAN, the network address list contains all the protocol-specific addresses associated with the interface.
/// </term>
/// </item>
/// <item>
/// <term>For connection-oriented media such as a WAN, the network address list contains an even number of network addresses:</term>
/// </item>
/// </list>
/// <para><c>Note</c> Use of the <c>TcEnumerateInterfaces</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcenumerateinterfaces ULONG TcEnumerateInterfaces( [in] HANDLE
// ClientHandle, [in, out] PULONG pBufferSize, [out] PTC_IFC_DESCRIPTOR InterfaceBuffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcEnumerateInterfaces")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcEnumerateInterfaces([In] HCLIENT ClientHandle, ref uint pBufferSize, [Out] IntPtr InterfaceBuffer);
/// <summary>
/// The <c>TcEnumerateInterfaces</c> function enumerates all traffic controlenabled network interfaces. Clients are notified of
/// interface changes through the ClNotifyHandler function.
/// </summary>
/// <param name="ClientHandle">Handle used by traffic control to identify the client. Clients receive handles when registering with traffic control through the
/// TcRegisterClient function.</param>
/// <returns>
/// A sequence of <see cref="TC_IFC_DESCRIPTOR" /> structures with information about each interface.
/// </returns>
/// <remarks>
/// <para>
/// Each interface descriptor contains two elements:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The traffic control interface's identifying text string.</term>
/// </item>
/// <item>
/// <term>The network address list descriptor currently associated with the interface.</term>
/// </item>
/// </list>
/// <para>
/// The network address list descriptor includes the media type, as well as a list of network addresses. The media type determines how
/// the network address list should be interpreted:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// For connectionless media such as a LAN, the network address list contains all the protocol-specific addresses associated with the interface.
/// </term>
/// </item>
/// <item>
/// <term>
/// <para>For connection-oriented media such as a WAN, the network address list contains an even number of network addresses:</para>
/// <list type="bullet">
/// <item>
/// <term>The first address in each pair represents the local (source) address of the interface.</term>
/// </item>
/// <item>
/// <term>The second address in each pair represents the remote (destination) address of the interface.</term>
/// </item>
/// </list>
/// </term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> Use of the <c>TcEnumerateInterfaces</c> function requires administrative privilege.</para>
/// </remarks>
public static IEnumerable<TC_IFC_DESCRIPTOR> TcEnumerateInterfaces([In] HCLIENT ClientHandle)
{
uint sz = 1024 * 2;
SafeCoTaskMemHandle buf = new(sz);
Win32Error err;
do
{
buf.Size = sz;
err = TcEnumerateInterfaces(ClientHandle, ref sz, buf);
} while (err == Win32Error.ERROR_INSUFFICIENT_BUFFER);
err.ThrowIfFailed();
if (sz == 0)
yield break;
int offset = 0;
TC_IFC_DESCRIPTOR d = GetDesc(offset);
do
{
yield return d;
d = GetDesc(offset += (int)d.Length);
} while (d.Length > 0);
TC_IFC_DESCRIPTOR GetDesc(int offset)
{
var desc = buf.ToStructure<TC_IFC_DESCRIPTOR>(offset);
desc.AddressListDesc.AddressList = buf.ToStructure<NETWORK_ADDRESS_LIST>(offset + TC_IFC_DESCRIPTOR.NetAddrListOffset);
return desc;
}
}
/// <summary>
/// The <c>TcGetFlowName</c> function provides the name of a flow that has been created by the calling client. Flow properties and other
/// characteristics of flows are provided based on the name of a flow. Flow names can also be retrieved by a call to the TcEnumerateFlows function.
/// </summary>
/// <param name="FlowHandle">Handle for the flow.</param>
/// <param name="StrSize">Size of the string buffer provided in <c>pFlowName</c>.</param>
/// <param name="pFlowName">Pointer to the output buffer holding the flow name.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The flow handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>One of the parameters is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INSUFFICIENT_BUFFER</c></term>
/// <term>The buffer is too small to contain the results.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Use of the <c>TcGetFlowName</c> function requires administrative privilege.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The traffic.h header defines TcGetFlowName as an alias which automatically selects the ANSI or Unicode version of this function based
/// on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcgetflownamea ULONG TcGetFlowNameA( [in] HANDLE FlowHandle,
// [in] ULONG StrSize, [out] LPSTR pFlowName );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcGetFlowNameA")]
[DllImport(Lib_Traffic, SetLastError = false, CharSet = CharSet.Auto)]
public static extern Win32Error TcGetFlowName([In] HFLOW FlowHandle, uint StrSize, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder pFlowName);
/// <summary>
/// <para>
/// The <c>TcModifyFlow</c> function modifies an existing flow. When calling <c>TcModifyFlow</c>, new <c>Flowspec</c> parameters and any
/// traffic control objects should be filled.
/// </para>
/// <para>
/// Traffic control clients that have registered a ModifyFlowComplete handler (a mechanism for allowing traffic control to call the
/// ClModifyFlowComplete callback function in order to alert clients of completed flow modifications) can expect a return value of ERROR_SIGNAL_PENDING.
/// </para>
/// </summary>
/// <param name="FlowHandle">Handle for the flow, as received from a previous call to the TcAddFlow function.</param>
/// <param name="pGenericFlow">Pointer to a description of the flow modifications.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_SIGNAL_PENDING</c></term>
/// <term>
/// The function is being executed asynchronously; the client will be called back through the client-exposed ClModifyFlowComplete
/// function when the flow has been added, or when the process has been completed.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The interface handle is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_READY</c></term>
/// <term>Action performed on the flow by a previous function call to the TcAddFlow, TcModifyFlow, or TcDeleteFlow has not yet completed.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>A parameter is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SERVICE_TYPE</c></term>
/// <term>An unspecified or bad intserv service type has been provided.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TOKEN_RATE</c></term>
/// <term>An unspecified or bad <c>TokenRate</c> value has been provided.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PEAK_RATE</c></term>
/// <term>The <c>PeakBandwidth</c> value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SD_MODE</c></term>
/// <term>The <c>ShapeDiscardMode</c> is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_QOS_PRIORITY</c></term>
/// <term>The priority value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TRAFFIC_CLASS</c></term>
/// <term>The traffic class value is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NO_SYSTEM_RESOURCES</c></term>
/// <term>There are not enough resources to accommodate the requested flow.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TC_OBJECT_LENGTH_INVALID</c></term>
/// <term>Bad length specified for the TC objects.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_DIFFSERV_FLOW</c></term>
/// <term>Applies to Diffserv flows. Indicates that the QOS_DIFFSERV object was passed with an invalid parameter.</term>
/// </item>
/// <item>
/// <term><c>ERROR_DS_MAPPING_EXISTS</c></term>
/// <term>
/// Applies to Diffserv flows. Indicates that the QOS_DIFFSERV_RULE specified in TC_GEN_FLOW already applies to an existing flow on the interface.
/// </term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_SHAPE_RATE</c></term>
/// <term>The QOS_SHAPING_RATE was passed with an invalid ShapeRate.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_DS_CLASS</c></term>
/// <term>QOS_DS_CLASS is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NETWORK_UNREACHABLE</c></term>
/// <term>The network cable is not plugged into the adapter.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If the <c>TcModifyFlow</c> function returns ERROR_SIGNAL_PENDING, the ClModifyFlowComplete function will be called on a different
/// thread than the thread that called the <c>TcModifyFlow</c> function.
/// </para>
/// <para><c>Note</c> Use of the <c>TcModifyFlow</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcmodifyflow ULONG TcModifyFlow( [in] HANDLE FlowHandle, [in]
// PTC_GEN_FLOW pGenericFlow );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcModifyFlow")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcModifyFlow([In] HFLOW FlowHandle,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(VanaraCustomMarshaler<TC_GEN_FLOW>))]
TC_GEN_FLOW pGenericFlow);
/// <summary>
/// The <c>TcOpenInterface</c> function opens an interface. The <c>TcOpenInterface</c> function identifies and opens an interface based
/// on its text string, which is available from a call to TcEnumerateInterfaces. Once an interface is opened, the client must be prepared
/// to receive notification regarding the open interface, through traffic control's use of the interface context.
/// </summary>
/// <param name="pInterfaceName">
/// Pointer to the text string identifying the interface to be opened. This text string is part of the information returned in a previous
/// call to TcEnumerateInterfaces.
/// </param>
/// <param name="ClientHandle">
/// Handle used by traffic control to identify the client, obtained through the <c>pClientHandle</c> parameter of the client's call to TcRegisterClient.
/// </param>
/// <param name="ClIfcCtx">
/// Client's interfacecontext handle for the opened interface. Used as a callback parameter by traffic control when communicating with
/// the client about the opened interface. This can be a container to hold an arbitrary client-defined context for this instance of the interface.
/// </param>
/// <param name="pIfcHandle">
/// Pointer to the buffer where traffic control can return an interface handle. The interface handle returned to <c>pIfcHandle</c> must
/// be used by the client to identify the interface in subsequent calls to traffic control.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>One of the parameters is <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_FOUND</c></term>
/// <term>Traffic control failed to find an interface with the name provided in <c>pInterfaceName</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>The client handle is invalid.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Use of the <c>TcOpenInterface</c> function requires administrative privilege.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The traffic.h header defines TcOpenInterface as an alias which automatically selects the ANSI or Unicode version of this function
/// based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcopeninterfacew ULONG TcOpenInterfaceW( [in] LPWSTR
// pInterfaceName, [in] HANDLE ClientHandle, [in] HANDLE ClIfcCtx, [out] PHANDLE pIfcHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcOpenInterfaceW")]
[DllImport(Lib_Traffic, SetLastError = false, CharSet = CharSet.Auto)]
public static extern Win32Error TcOpenInterface([MarshalAs(UnmanagedType.LPTStr)] string pInterfaceName, [In] HCLIENT ClientHandle, [In] IntPtr ClIfcCtx, out SafeHIFC pIfcHandle);
/// <summary>
/// The <c>TcQueryFlow</c> function queries traffic control for the value of a specific flow parameter based on the name of the flow. The
/// name of a flow can be retrieved from the TcEnumerateFlows function or from the TcGetFlowName function.
/// </summary>
/// <param name="pFlowName">Name of the flow being queried.</param>
/// <param name="pGuidParam">
/// Pointer to the globally unique identifier (GUID) that corresponds to the flow parameter of interest. A list of traffic control's
/// GUIDs can be found in GUID.
/// </param>
/// <param name="pBufferSize">
/// Pointer to the size of the client-provided buffer or the number of bytes used by traffic control. For input, points to the size of
/// <c>Buffer</c>, in bytes. For output, points to the actual amount of buffer space written with returned flow-parameter data, in bytes.
/// </param>
/// <param name="Buffer">Pointer to the client-provided buffer in which the returned flow parameter is written.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>A parameter is invalid.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INSUFFICIENT_BUFFER</c></term>
/// <term>The provided buffer is too small to hold the results.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_SUPPORTED</c></term>
/// <term>The requested GUID is not supported.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_GUID_NOT_FOUND</c></term>
/// <term>The device did not register for this GUID.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_INSTANCE_NOT_FOUND</c></term>
/// <term>The instance name was not found, likely because the flow or the interface is in the process of being closed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Use of the <c>TcQueryFlow</c> function requires administrative privilege.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The traffic.h header defines TcQueryFlow as an alias which automatically selects the ANSI or Unicode version of this function based
/// on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcqueryflowa ULONG TcQueryFlowA( [in] LPSTR pFlowName, [in]
// LPGUID pGuidParam, [in, out] PULONG pBufferSize, [out] PVOID Buffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcQueryFlowA")]
[DllImport(Lib_Traffic, SetLastError = false, CharSet = CharSet.Auto)]
public static extern Win32Error TcQueryFlow([MarshalAs(UnmanagedType.LPTStr)] string pFlowName, in Guid pGuidParam, ref uint pBufferSize, [Out] IntPtr Buffer);
/// <summary>
/// The <c>TcQueryInterface</c> function queries traffic control for related per-interface parameters. A traffic control parameter is
/// queried by providing its globally unique identifier (GUID). Setting the <c>NotifyChange</c> parameter to <c>TRUE</c> enables event
/// notification on the specified GUID, after which notification events are sent to a client whenever the queried parameter changes.
/// GUIDs for which clients can request notification are found in the GUID entry; the column titled "Notification" denotes which GUIDs
/// are available for notification.
/// </summary>
/// <param name="IfcHandle">
/// Handle associated with the interface to be queried. This handle is obtained by a previous call to the TcOpenInterface function.
/// </param>
/// <param name="pGuidParam">
/// Pointer to the globally unique identifier (GUID) that corresponds to the traffic control parameter being queried.
/// </param>
/// <param name="NotifyChange">
/// Used to request notifications from traffic control for the parameter being queried. If <c>TRUE</c>, traffic control will notify the
/// client, through the ClNotifyHandler function, upon changes to the parameter corresponding to the GUID provided in <c>pGuidParam</c>.
/// Notifications are off by default.
/// </param>
/// <param name="pBufferSize">
/// Indicates the size of the buffer, in bytes. For input, this value is the size of the buffer allocated by the caller. For output, this
/// value is the actual size of the buffer, in bytes, used by traffic control.
/// </param>
/// <param name="Buffer">Pointer to a client-allocated buffer into which returned data will be written.</param>
/// <returns>
/// <para>
/// Note that, with regard to a requested notification state, only a return value of NO_ERROR will result in the application of the
/// requested notification state. If a return value other than NO_ERROR is returned from a call to the <c>TcQueryInterface</c> function,
/// the requested change in notification state will not be accepted.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>Invalid interface handle.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>Invalid or <c>NULL</c> parameter.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INSUFFICIENT_BUFFER</c></term>
/// <term>The buffer is too small to store the results.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_SUPPORTED</c></term>
/// <term>Querying for the GUID provided is not supported on the provided interface.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_GUID_NOT_FOUND</c></term>
/// <term>The device did not register for this GUID.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_INSTANCE_NOT_FOUND</c></term>
/// <term>The instance name was not found, likely because the interface is in the process of being closed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks><c>Note</c> Use of the <c>TcQueryInterface</c> function requires administrative privilege.</remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcqueryinterface ULONG TcQueryInterface( [in] HANDLE IfcHandle,
// [in] LPGUID pGuidParam, [in] BOOLEAN NotifyChange, [in, out] PULONG pBufferSize, [out] PVOID Buffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcQueryInterface")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcQueryInterface([In] HIFC IfcHandle, in Guid pGuidParam, [MarshalAs(UnmanagedType.U1)] bool NotifyChange, ref uint pBufferSize, [Out] IntPtr Buffer);
/// <summary>
/// <para>
/// The <c>TcRegisterClient</c> function is used to register a client with the traffic control interface (TCI). The
/// <c>TcRegisterClient</c> function must be the first function call a client makes to the TCI.
/// </para>
/// <para>
/// Client registration provides callback routines that allow the TCI to complete either client-initiated operations or asynchronous
/// events. Upon successful registration, the caller of the <c>TcRegisterClient</c> function must be ready to have any of its TCI
/// handlers called. See Entry Points Exposed by Clients of the Traffic Control Interface for more information.
/// </para>
/// </summary>
/// <param name="TciVersion">
/// Traffic control version expected by the client, included to ensure compatibility between traffic control and the client. Clients can
/// pass CURRENT_TCI_VERSION, defined in Traffic.h.
/// </param>
/// <param name="ClRegCtx">
/// Client registration context. <c>ClRegCtx</c> is returned when the client's notification handler function is called. This can be a
/// container to hold an arbitrary client-defined context for this instance of the interface.
/// </param>
/// <param name="ClientHandlerList">
/// Pointer to a list of client-supplied handlers. Client-supplied handlers are used for notification events and asynchronous
/// completions. Each completion routine is optional, with the exception of the notification handler. Setting the notification handler to
/// <c>NULL</c> will return an ERROR_INVALID_PARAMETER.
/// </param>
/// <param name="pClientHandle">Pointer to the buffer that traffic control uses to return a registration handle to the client.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The system is out of memory.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>One of the parameters is <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INCOMPATIBLE_TCI_VERSION</c></term>
/// <term>The TCI version is wrong.</term>
/// </item>
/// <item>
/// <term><c>ERROR_OPEN_FAILED</c></term>
/// <term>Traffic control failed to open a system device. The likely cause is insufficient privileges.</term>
/// </item>
/// <item>
/// <term><c>ERROR_TOO_MANY_CLIENTS</c></term>
/// <term>
/// Traffic Control was unable to register with the kernel component GPC. The likely cause is too many traffic control clients are
/// currently connected. <c>Windows 2000:</c> This value is not supported.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Some of the return codes can be found in tcerror.h.</para>
/// <para><c>Note</c> Use of the <c>TcRegisterClient</c> function requires administrative privilege.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcregisterclient ULONG TcRegisterClient( [in] ULONG TciVersion,
// [in] HANDLE ClRegCtx, [in] PTCI_CLIENT_FUNC_LIST ClientHandlerList, [out] PHANDLE pClientHandle );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcRegisterClient")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcRegisterClient(uint TciVersion, [In] IntPtr ClRegCtx,
in TCI_CLIENT_FUNC_LIST ClientHandlerList, out SafeHCLIENT pClientHandle);
/// <summary>The <c>TcSetFlow</c> function sets individual parameters for a given flow.</summary>
/// <param name="pFlowName">
/// Name of the flow being set. The value for this parameter is obtained by a previous call to the TcEnumerateFlows function or the
/// TcGetFlowName function.
/// </param>
/// <param name="pGuidParam">
/// Pointer to the globally unique identifier (GUID) that corresponds to the parameter to be set. A list of available GUIDs can be found
/// in GUID.
/// </param>
/// <param name="BufferSize">Size of the client-provided buffer, in bytes.</param>
/// <param name="Buffer">
/// Pointer to a client-provided buffer. Buffer must contain the value to which the traffic control parameter provided in
/// <c>pGuidParam</c> should be set.
/// </param>
/// <returns>
/// <para>The <c>TcSetFlow</c> function has the following return values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_READY</c></term>
/// <term>The flow is currently being modified.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_ENOUGH_MEMORY</c></term>
/// <term>The buffer size was insufficient for the GUID.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>Invalid parameter.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_SUPPORTED</c></term>
/// <term>Setting the GUID for the provided flow is not supported.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_INSTANCE_NOT_FOUND</c></term>
/// <term>The instance name was not found, likely due to the flow or the interface being in the process of being closed.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_GUID_NOT_FOUND</c></term>
/// <term>The device did not register for this GUID.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Use of the <c>TcSetFlow</c> function requires administrative privilege.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The traffic.h header defines TcSetFlow as an alias which automatically selects the ANSI or Unicode version of this function based on
/// the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not encoding-neutral
/// can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcsetflowa ULONG TcSetFlowA( [in] LPSTR pFlowName, [in] LPGUID
// pGuidParam, [in] ULONG BufferSize, [in] PVOID Buffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcSetFlowA")]
[DllImport(Lib_Traffic, SetLastError = false, CharSet = CharSet.Auto)]
public static extern Win32Error TcSetFlow([MarshalAs(UnmanagedType.LPTStr)] string pFlowName, in Guid pGuidParam, uint BufferSize, [In] IntPtr Buffer);
/// <summary>The <c>TcSetInterface</c> function sets individual parameters for a given interface.</summary>
/// <param name="IfcHandle">
/// Handle associated with the interface to be set. This handle is obtained by a previous call to the TcOpenInterface function.
/// </param>
/// <param name="pGuidParam">
/// Pointer to the globally unique identifier (GUID) that corresponds to the parameter to be set. A list of available GUIDs can be found
/// in GUID.
/// </param>
/// <param name="BufferSize">Size of the client-provided buffer, in bytes.</param>
/// <param name="Buffer">
/// Pointer to a client-provided buffer. <c>Buffer</c> must contain the value to which the traffic control parameter provided in
/// <c>pGuidParam</c> should be set.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>NO_ERROR</c></term>
/// <term>The function executed without errors.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_HANDLE</c></term>
/// <term>Invalid interface handle.</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_PARAMETER</c></term>
/// <term>Invalid parameter.</term>
/// </item>
/// <item>
/// <term><c>ERROR_NOT_SUPPORTED</c></term>
/// <term>Setting the GUID for the provided interface is not supported.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_INSTANCE_NOT_FOUND</c></term>
/// <term>The GUID is not available.</term>
/// </item>
/// <item>
/// <term><c>ERROR_WMI_GUID_NOT_FOUND</c></term>
/// <term>The device did not register for this GUID.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <c>Note</c> Use of the <c>TcSetInterface</c> function requires administrative privilege. The list of GUIDs that can be set is
/// explained in GUID.
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/nf-traffic-tcsetinterface ULONG TcSetInterface( [in] HANDLE IfcHandle,
// [in] LPGUID pGuidParam, [in] ULONG BufferSize, [in] PVOID Buffer );
[PInvokeData("traffic.h", MSDNShortId = "NF:traffic.TcSetInterface")]
[DllImport(Lib_Traffic, SetLastError = false, ExactSpelling = true)]
public static extern Win32Error TcSetInterface([In] HIFC IfcHandle, in Guid pGuidParam, uint BufferSize, [In] IntPtr Buffer);
/// <summary>
/// The <c>ADDRESS_LIST_DESCRIPTOR</c> structure provides network address descriptor information for a given interface. For
/// point-to-point media such as WAN connections, the list is a pair of addresses, the first of which is always the local or source
/// address, the second of which is the remote or destination address. Note that the members of <c>ADDRESS_LIST_DESCRIPTOR</c> are
/// defined in Ntddndis.h.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-address_list_descriptor typedef struct _ADDRESS_LIST_DESCRIPTOR
// { ULONG MediaType; NETWORK_ADDRESS_LIST AddressList; } ADDRESS_LIST_DESCRIPTOR, *PADDRESS_LIST_DESCRIPTOR;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._ADDRESS_LIST_DESCRIPTOR")]
[StructLayout(LayoutKind.Sequential)]
public struct ADDRESS_LIST_DESCRIPTOR
{
/// <summary>Media type of the interface.</summary>
public uint MediaType;
/// <summary>Pointer to the address list for the interface. The <c>NETWORK_ADDRESS_LIST</c> structure is defined in Ntddndis.h.</summary>
//[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(VanaraCustomMarshaler<SafeAnysizeStructMarshaler<NETWORK_ADDRESS_LIST>>), MarshalCookie = "AddressCount")]
public NETWORK_ADDRESS_LIST AddressList;
}
/// <summary>
/// The <c>ENUMERATION_BUFFER</c> structure contains information specific to a given flow, including flow name, the number of filters
/// associated with the flow, and an array of filters associated with the flow.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-enumeration_buffer typedef struct _ENUMERATION_BUFFER { ULONG
// Length; ULONG OwnerProcessId; USHORT FlowNameLength; WCHAR FlowName[MAX_STRING_LENGTH]; PTC_GEN_FLOW pFlow; ULONG NumberOfFilters;
// TC_GEN_FILTER GenericFilter[1]; } ENUMERATION_BUFFER, *PENUMERATION_BUFFER;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._ENUMERATION_BUFFER")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ENUMERATION_BUFFER
{
/// <summary>Number of bytes from the beginning of the <c>ENUMERATION_BUFFER</c> to the next <c>ENUMERATION_BUFFER</c>.</summary>
public uint Length;
/// <summary>Identifies the owner of the process.</summary>
public uint OwnerProcessId;
/// <summary>Specifies the length of the <c>FlowName</c> member.</summary>
public ushort FlowNameLength;
/// <summary>Array of WCHAR characters, of length <c>MAX_STRING_LENGTH</c>, that specifies the flow name.</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_STRING_LENGTH)]
public string FlowName;
/// <summary>
/// Pointer to the corresponding <see cref="TC_GEN_FLOW"/> structure. This structure is placed immediately after the array of
/// TC_GEN_FILTERS and is included in <c>Length</c>.
/// </summary>
public IntPtr pFlow;
/// <summary>The corresponding <see cref="TC_GEN_FLOW"/> structure.</summary>
public TC_GEN_FLOW Flow => pFlow.ToStructure<TC_GEN_FLOW>()!;
/// <summary>Specifies the number of filters associated with the flow.</summary>
public uint NumberOfFilters;
/// <summary>
/// <para>
/// Array of TC_GEN_FILTER structures. The number of elements in the array corresponds to the number of filters attached to the
/// specified flow. Note that in order to enumerate through the array of <c>TC_GEN_FILTER</c> structures, you need to increment the
/// pointer to the current <c>TC_GEN_FILTER</c> by using the following:
/// </para>
/// <para><c>sizeof(TC_GEN_FILTER) + 2 * [the pattern size of the current TC_GEN_FILTER structure].</c></para>
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public TC_GEN_FILTER[] GenericFilter;
}
/// <summary>
/// The <c>ENUMERATION_BUFFER</c> structure contains information specific to a given flow, including flow name, the number of filters
/// associated with the flow, and an array of filters associated with the flow.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-enumeration_buffer typedef struct _ENUMERATION_BUFFER { ULONG
// Length; ULONG OwnerProcessId; USHORT FlowNameLength; WCHAR FlowName[MAX_STRING_LENGTH]; PTC_GEN_FLOW pFlow; ULONG NumberOfFilters;
// TC_GEN_FILTER GenericFilter[1]; } ENUMERATION_BUFFER, *PENUMERATION_BUFFER;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._ENUMERATION_BUFFER")]
public class ENUMERATION_BUFFER_MGD
{
private ENUMERATION_BUFFER_MGD() => throw new NotImplementedException();
internal ENUMERATION_BUFFER_MGD(IntPtr ptr)
{
var buf = ptr.ToStructure<ENUMERATION_BUFFER>();
OwnerProcessId = buf.OwnerProcessId;
FlowName = buf.FlowName;
Flow = buf.Flow;
List<TC_GEN_FILTER_MGD_BASE> filters = new((int)buf.NumberOfFilters);
var fptr = ptr.Offset(Marshal.OffsetOf(typeof(ENUMERATION_BUFFER), "GenericFilter").ToInt64());
for (int i = 0; i < buf.NumberOfFilters; i++)
{
TC_GEN_FILTER f = fptr.ToStructure<TC_GEN_FILTER>();
filters.Add(f.AddressType switch
{
NDIS_PROTOCOL_ID.NDIS_PROTOCOL_ID_TCP_IP => new TC_GEN_FILTER_MGD<IP_PATTERN>(f),
NDIS_PROTOCOL_ID.NDIS_PROTOCOL_ID_IPX => new TC_GEN_FILTER_MGD<IPX_PATTERN>(f),
_ => new TC_GEN_FILTER_MGD_UNK(f),
});
fptr = fptr.Offset(Marshal.SizeOf(typeof(TC_GEN_FILTER)) + f.PatternSize * 2);
}
GenericFilter = filters;
}
/// <summary>Identifies the owner of the process.</summary>
public uint OwnerProcessId { get; }
/// <summary>Specifies the flow name.</summary>
public string FlowName { get; }
/// <summary>The corresponding <see cref="TC_GEN_FLOW"/> structure.</summary>
public TC_GEN_FLOW Flow { get; }
/// <summary>
/// List of TC_GEN_FILTER structures. The number of elements in the array corresponds to the number of filters attached to the
/// specified flow.
/// </summary>
public IReadOnlyList<TC_GEN_FILTER_MGD_BASE> GenericFilter { get; }
}
/// <summary>Provides a handle to a traffic control client.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct HCLIENT : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HCLIENT"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HCLIENT(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HCLIENT"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HCLIENT NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HCLIENT h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HCLIENT"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HCLIENT h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HCLIENT"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HCLIENT(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HCLIENT h1, HCLIENT h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HCLIENT h1, HCLIENT h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HCLIENT h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a handle to a traffic filter.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct HFILTER : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HFILTER"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HFILTER(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HFILTER"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HFILTER NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HFILTER h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HFILTER"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HFILTER h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HFILTER"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HFILTER(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HFILTER h1, HFILTER h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HFILTER h1, HFILTER h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HFILTER h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a handle to a traffic flow.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct HFLOW : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HFLOW"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HFLOW(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HFLOW"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HFLOW NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HFLOW h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HFLOW"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HFLOW h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HFLOW"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HFLOW(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HFLOW h1, HFLOW h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HFLOW h1, HFLOW h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HFLOW h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a handle to a flow enumeration.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct HFLOWENUM : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HFLOWENUM"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HFLOWENUM(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HFLOWENUM"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HFLOWENUM NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HFLOWENUM h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HFLOWENUM"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HFLOWENUM h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HFLOWENUM"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HFLOWENUM(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HFLOWENUM h1, HFLOWENUM h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HFLOWENUM h1, HFLOWENUM h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HFLOWENUM h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a handle to a traffic interface.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct HIFC : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HIFC"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HIFC(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HIFC"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HIFC NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HIFC h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HIFC"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HIFC h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HIFC"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HIFC(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HIFC h1, HIFC h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HIFC h1, HIFC h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HIFC h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>
/// The <c>IP_PATTERN</c> structure applies a specific pattern or corresponding mask for the IP protocol. The <c>IP_PATTERN</c> structure
/// designation is used by the traffic control interface in the application of packet filters.
/// </summary>
/// <remarks>The following macros are defined in Traffic.h to make it easier to reference the members of the union:</remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-ip_pattern typedef struct _IP_PATTERN { ULONG Reserved1; ULONG
// Reserved2; ULONG SrcAddr; ULONG DstAddr; union { struct { USHORT s_srcport; USHORT s_dstport; } S_un_ports; struct { UCHAR s_type;
// UCHAR s_code; USHORT filler; } S_un_icmp; ULONG S_Spi; } S_un; UCHAR ProtocolId; UCHAR Reserved3[3]; } IP_PATTERN, *PIP_PATTERN;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._IP_PATTERN")]
[StructLayout(LayoutKind.Sequential)]
public struct IP_PATTERN
{
/// <summary>Reserved for future use.</summary>
public uint Reserved1;
/// <summary>Reserved for future use.</summary>
public uint Reserved2;
/// <summary>Source address.</summary>
public uint SrcAddr;
/// <summary>Destination address.</summary>
public uint DstAddr;
/// <summary/>
public UNION S_un;
/// <summary>Protocol identifier.</summary>
public byte ProtocolId;
/// <summary>Reserved for future use.</summary>
public byte Reserved3_1, Reserved3_2, Reserved3_3;
/// <summary/>
[StructLayout(LayoutKind.Explicit)]
public struct UNION
{
/// <summary>Service provider interface.</summary>
[FieldOffset(0)]
public uint S_Spi;
/// <summary>Source port and destination port.</summary>
[FieldOffset(0)]
public PORTS S_un_ports;
/// <summary>ICMP message type and ICMP message code.</summary>
[FieldOffset(0)]
public ICMP S_un_icmp;
/// <summary>Source port and destination port.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct PORTS
{
/// <summary>The source port.</summary>
public ushort s_srcport;
/// <summary>The destination port.</summary>
public ushort s_dstport;
}
/// <summary>ICMP message type and ICMP message code.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct ICMP
{
/// <summary>The ICMP message type.</summary>
public byte s_type;
/// <summary>The ICMP message code.</summary>
public byte s_code;
/// <summary/>
public ushort filler;
}
}
/// <summary>The source port.</summary>
public ushort tcSrcPort { get => S_un.S_un_ports.s_srcport; set => S_un.S_un_ports.s_srcport = value; }
/// <summary>The destination port.</summary>
public ushort tcDstPort { get => S_un.S_un_ports.s_dstport; set => S_un.S_un_ports.s_dstport = value; }
/// <summary>The ICMP message type.</summary>
public byte tcIcmpType { get => S_un.S_un_icmp.s_type; set => S_un.S_un_icmp.s_type = value; }
/// <summary>The ICMP message code.</summary>
public byte tcIcmpCode { get => S_un.S_un_icmp.s_code; set => S_un.S_un_icmp.s_code = value; }
/// <summary>Service provider interface.</summary>
public uint tcSpi { get => S_un.S_Spi; set => S_un.S_Spi = value; }
}
/// <summary>
/// The <c>IPX_PATTERN</c> structure applies a specific pattern or corresponding mask for the IPX protocol. The <c>IPX_PATTERN</c>
/// structure designation is used by the traffic control interface in the application of packet filters.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-ipx_pattern typedef struct _IPX_PATTERN { struct { ULONG
// NetworkAddress; UCHAR NodeAddress[6]; USHORT Socket; } Src; __unnamed_struct_141c_4 Dest; } IPX_PATTERN, *PIPX_PATTERN;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._IPX_PATTERN")]
[StructLayout(LayoutKind.Sequential)]
public struct IPX_PATTERN
{
/// <summary/>
public IPX Src;
/// <summary/>
public IPX Dest;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct IPX
{
/// <summary/>
public uint NetworkAddress;
/// <summary/>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] NodeAddress;
/// <summary/>
public ushort Socket;
}
}
/// <summary>
/// The <c>TC_GEN_FILTER</c> structure creates a filter that matches a certain set of packet attributes or criteria, which can
/// subsequently be used to associate packets that meet the attribute criteria with a particular flow. The <c>TC_GEN_FILTER</c> structure
/// uses its <c>AddressType</c> member to indicate a specific filter type to apply to the filter.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-tc_gen_filter typedef struct _TC_GEN_FILTER { USHORT
// AddressType; ULONG PatternSize; PVOID Pattern; PVOID Mask; } TC_GEN_FILTER, *PTC_GEN_FILTER;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_GEN_FILTER")]
[StructLayout(LayoutKind.Sequential)]
public struct TC_GEN_FILTER
{
/// <summary>
/// Defines the filter type to be applied with the filter, as defined in Ntddndis.h. With the designation of a specific filter in
/// <c>AddressType</c>, the generic filter structure <c>TC_GEN_FILTER</c> provides a specific filter type.
/// </summary>
public NDIS_PROTOCOL_ID AddressType;
/// <summary>Size of the <c>Pattern</c> member, in bytes.</summary>
public uint PatternSize;
/// <summary>
/// Indicates the specific format of the pattern to be applied to the filter, such as IP_PATTERN. The pattern specifies which bits of
/// a given packet should be evaluated when determining whether a packet is included in the filter.
/// </summary>
public IntPtr Pattern;
/// <summary>
/// A bitmask applied to the bits designated in the <c>Pattern</c> member. The application of the <c>Mask</c> member to the
/// <c>Pattern</c> member determines which bits in the <c>Pattern</c> member are significant (should be applied to the filter
/// criteria). Note that the <c>Mask</c> member must be of the same type as the <c>Pattern</c> member.
/// </summary>
public IntPtr Mask;
/// <summary>Creates a <see cref="TC_GEN_FILTER"/> instance.</summary>
/// <typeparam name="T">The type of the pattern.</typeparam>
/// <param name="AddressType">The filter type to be applied with the filter.</param>
/// <param name="Pattern">Indicates the specific format of the pattern to be applied to the filter, such as IP_PATTERN.</param>
/// <param name="Mask">A bitmask applied to the bits designated in the <c>Pattern</c> member.</param>
/// <param name="memAlloc">The memory allocated too the <paramref name="Pattern"/> and <paramref name="Mask"/> fields.</param>
/// <returns>
/// A complete <see cref="TC_GEN_FILTER"/> instance. Do not dispose the value returned in <paramref name="memAlloc"/> until this
/// structure is no longer needed.
/// </returns>
public static TC_GEN_FILTER Create<T>(NDIS_PROTOCOL_ID AddressType, in T Pattern, in T Mask, out SafeHandle memAlloc) where T : struct
{
var sz = Marshal.SizeOf(typeof(T));
SafeNativeArray<T> parts = new(new T[] { Pattern, Mask });
memAlloc = parts;
var ptrs = parts.GetPointers();
return new TC_GEN_FILTER { AddressType = AddressType, PatternSize = (uint)sz, Pattern = ptrs[0], Mask = ptrs[1] };
}
}
/// <summary>
/// The <c>TC_GEN_FILTER</c> structure creates a filter that matches a certain set of packet attributes or criteria, which can
/// subsequently be used to associate packets that meet the attribute criteria with a particular flow. The <c>TC_GEN_FILTER</c> structure
/// uses its <c>AddressType</c> member to indicate a specific filter type to apply to the filter.
/// </summary>
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_GEN_FILTER")]
public class TC_GEN_FILTER_MGD_BASE
{
/// <summary>
/// Defines the filter type to be applied with the filter, as defined in Ntddndis.h. With the designation of a specific filter in
/// <c>AddressType</c>, the generic filter structure <c>TC_GEN_FILTER</c> provides a specific filter type.
/// </summary>
public NDIS_PROTOCOL_ID AddressType;
}
/// <summary>
/// The <c>TC_GEN_FILTER</c> structure creates a filter that matches a certain set of packet attributes or criteria, which can
/// subsequently be used to associate packets that meet the attribute criteria with a particular flow. The <c>TC_GEN_FILTER</c> structure
/// uses its <c>AddressType</c> member to indicate a specific filter type to apply to the filter.
/// </summary>
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_GEN_FILTER")]
public class TC_GEN_FILTER_MGD_UNK : TC_GEN_FILTER_MGD_BASE
{
/// <summary>
/// Indicates the specific format of the pattern to be applied to the filter, such as <see cref="IP_PATTERN"/>. The pattern specifies which bits of
/// a given packet should be evaluated when determining whether a packet is included in the filter.
/// </summary>
public byte[] Pattern;
/// <summary>
/// A bitmask applied to the bits designated in the <c>Pattern</c> member. The application of the <c>Mask</c> member to the
/// <c>Pattern</c> member determines which bits in the <c>Pattern</c> member are significant (should be applied to the filter
/// criteria). Note that the <c>Mask</c> member must be of the same type as the <c>Pattern</c> member.
/// </summary>
public byte[] Mask;
internal TC_GEN_FILTER_MGD_UNK(in TC_GEN_FILTER f)
{
AddressType = f.AddressType;
Pattern = f.Pattern.ToByteArray((int)f.PatternSize) ?? new byte[0];
Mask = f.Mask.ToByteArray((int)f.PatternSize) ?? new byte[0];
}
}
/// <summary>
/// The <c>TC_GEN_FILTER</c> structure creates a filter that matches a certain set of packet attributes or criteria, which can
/// subsequently be used to associate packets that meet the attribute criteria with a particular flow. The <c>TC_GEN_FILTER</c> structure
/// uses its <c>AddressType</c> member to indicate a specific filter type to apply to the filter.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-tc_gen_filter typedef struct _TC_GEN_FILTER { USHORT
// AddressType; ULONG PatternSize; PVOID Pattern; PVOID Mask; } TC_GEN_FILTER, *PTC_GEN_FILTER;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_GEN_FILTER")]
public class TC_GEN_FILTER_MGD<T> : TC_GEN_FILTER_MGD_BASE where T : struct
{
/// <summary>
/// Indicates the specific format of the pattern to be applied to the filter, such as IP_PATTERN. The pattern specifies which bits of
/// a given packet should be evaluated when determining whether a packet is included in the filter.
/// </summary>
public T Pattern;
/// <summary>
/// A bitmask applied to the bits designated in the <c>Pattern</c> member. The application of the <c>Mask</c> member to the
/// <c>Pattern</c> member determines which bits in the <c>Pattern</c> member are significant (should be applied to the filter
/// criteria). Note that the <c>Mask</c> member must be of the same type as the <c>Pattern</c> member.
/// </summary>
public T Mask;
internal TC_GEN_FILTER_MGD(in TC_GEN_FILTER f)
{
AddressType = f.AddressType;
Pattern = f.Pattern.ToStructure<T>();
Mask = f.Mask.ToStructure<T>();
}
}
/// <summary>
/// The <c>TC_GEN_FLOW</c> structure creates a generic flow for use with the traffic control interface. The flow is customized through
/// the members of this structure.
/// </summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-tc_gen_flow typedef struct _TC_GEN_FLOW { FLOWSPEC
// SendingFlowspec; FLOWSPEC ReceivingFlowspec; ULONG TcObjectsLength; QOS_OBJECT_HDR TcObjects[1]; } TC_GEN_FLOW, *PTC_GEN_FLOW;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_GEN_FLOW")]
public class TC_GEN_FLOW : IVanaraMarshaler
{
/// <summary>FLOWSPEC structure for the sending direction of the flow.</summary>
public FLOWSPEC SendingFlowspec;
/// <summary>FLOWSPEC structure for the receiving direction of the flow.</summary>
public FLOWSPEC ReceivingFlowspec;
/// <summary>
/// <para>
/// Buffer that contains an array of traffic control objects specific to the given flow. The <c>TcObjects</c> member can contain
/// objects from the list of currently supported objects. Definitions of these objects can be found in Qos.h and Traffic.h:
/// </para>
/// <para>QOS_DS_CLASS</para>
/// <para>QOS_TRAFFIC_CLASS</para>
/// <para>QOS_DIFFSERV</para>
/// <para>QOS_SD_MODE</para>
/// <para>QOS_SHAPING_RATE</para>
/// <para>QOS_OBJECT_END_OF_LIST</para>
/// </summary>
public IQoSObjectHdr[]? TcObjects;
SizeT IVanaraMarshaler.GetNativeSize() => Marshal.SizeOf(typeof(INT_TC_GEN_FLOW));
SafeAllocatedMemoryHandle IVanaraMarshaler.MarshalManagedToNative(object? managedObject)
{
if (managedObject is not TC_GEN_FLOW f)
throw new ArgumentException("Only objects of type TC_GEN_FLOW can be marshaled.");
int objLen = f.TcObjects?.Length ?? 0;
int objByteLen = f.TcObjects?.Sum(o => Marshal.SizeOf(o.GetType())) ?? 0;
SafeCoTaskMemStruct<INT_TC_GEN_FLOW> pFlow = new(new INT_TC_GEN_FLOW() { SendingFlowspec = f.SendingFlowspec, ReceivingFlowspec = f.ReceivingFlowspec, TcObjectsLength = objByteLen });
pFlow.Size += objByteLen;
if (objLen > 0)
{
var oPtr = pFlow.GetFieldAddress(nameof(TcObjects));
for (int i = 0; i < objLen; i++)
{
oPtr.Write(f.TcObjects![i]);
oPtr = oPtr.Offset(Marshal.SizeOf(f.TcObjects[i].GetType()));
}
}
return pFlow;
}
object? IVanaraMarshaler.MarshalNativeToManaged(IntPtr pNativeData, SizeT allocatedBytes)
{
var f = pNativeData.ToStructure<INT_TC_GEN_FLOW>(allocatedBytes);
TC_GEN_FLOW ret = new() { SendingFlowspec = f.SendingFlowspec, ReceivingFlowspec = f.ReceivingFlowspec, TcObjects = new IQoSObjectHdr[f.TcObjectsLength] };
var ptr = pNativeData.Offset(Marshal.OffsetOf(typeof(INT_TC_GEN_FLOW), nameof(TcObjects)).ToInt64());
for (int i = 0; i < f.TcObjectsLength; i++)
{
var e = ptr.Convert<QOS_OBJ_TYPE>(4);
var t = CorrespondingTypeAttribute.GetCorrespondingTypes(e).First()!;
ret.TcObjects[i] = (IQoSObjectHdr)Marshal.PtrToStructure(ptr, t)!;
}
return ret;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct INT_TC_GEN_FLOW
{
public FLOWSPEC SendingFlowspec;
public FLOWSPEC ReceivingFlowspec;
public int TcObjectsLength;
public QOS_OBJECT_HDR TcObjects;
}
}
/// <summary>The <c>TC_IFC_DESCRIPTOR</c> structure is an interface identifier used to enumerate interfaces.</summary>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-tc_ifc_descriptor typedef struct _TC_IFC_DESCRIPTOR { ULONG
// Length; LPWSTR pInterfaceName; LPWSTR pInterfaceID; ADDRESS_LIST_DESCRIPTOR AddressListDesc; } TC_IFC_DESCRIPTOR, *PTC_IFC_DESCRIPTOR;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TC_IFC_DESCRIPTOR")]
[StructLayout(LayoutKind.Sequential)]
public struct TC_IFC_DESCRIPTOR
{
/// <summary>Number of bytes from the beginning of the <c>TC_IFC_DESCRIPTOR</c> to the next <c>TC_IFC_DESCRIPTOR</c>.</summary>
public uint Length;
/// <summary>
/// Pointer to a zero-terminated Unicode string representing the name of the packet shaper interface. This name is used in subsequent
/// TC API calls to reference the interface.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pInterfaceName;
/// <summary>Pointer to a zero-terminated Unicode string naming the DeviceName of the interface.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pInterfaceID;
/// <summary>Network address list descriptor.</summary>
public ADDRESS_LIST_DESCRIPTOR AddressListDesc;
internal static readonly int NetAddrListOffset = Marshal.OffsetOf(typeof(TC_IFC_DESCRIPTOR), "AddressListDesc").ToInt32() + Marshal.OffsetOf(typeof(ADDRESS_LIST_DESCRIPTOR), "AddressList").ToInt32();
}
/// <summary>
/// The <c>TCI_CLIENT_FUNC_LIST</c> structure is used by the traffic control interface to register and then access client-callback
/// functions. Each member of <c>TCI_CLIENT_FUNC_LIST</c> is a pointer to the client providedcallback function.
/// </summary>
/// <remarks>Any member of the <c>TCI_CLIENT_FUNC_LIST</c> structure can be <c>NULL</c> except <c>ClNotifyHandler</c>.</remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/traffic/ns-traffic-tci_client_func_list typedef struct _TCI_CLIENT_FUNC_LIST {
// TCI_NOTIFY_HANDLER ClNotifyHandler; TCI_ADD_FLOW_COMPLETE_HANDLER ClAddFlowCompleteHandler; TCI_MOD_FLOW_COMPLETE_HANDLER
// ClModifyFlowCompleteHandler; TCI_DEL_FLOW_COMPLETE_HANDLER ClDeleteFlowCompleteHandler; } TCI_CLIENT_FUNC_LIST, *PTCI_CLIENT_FUNC_LIST;
[PInvokeData("traffic.h", MSDNShortId = "NS:traffic._TCI_CLIENT_FUNC_LIST")]
[StructLayout(LayoutKind.Sequential)]
public struct TCI_CLIENT_FUNC_LIST
{
/// <summary>Pointer to the client-callback function ClNotifyHandler.</summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public TCI_NOTIFY_HANDLER ClNotifyHandler;
/// <summary>Pointer to the client-callback function ClAddFlowComplete.</summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public TCI_ADD_FLOW_COMPLETE_HANDLER? ClAddFlowCompleteHandler;
/// <summary>Pointer to the client-callback function ClModifyFlowComplete.</summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public TCI_MOD_FLOW_COMPLETE_HANDLER? ClModifyFlowCompleteHandler;
/// <summary>Pointer to the client-callback function ClDeleteFlowComplete.</summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public TCI_DEL_FLOW_COMPLETE_HANDLER? ClDeleteFlowCompleteHandler;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HCLIENT"/> that is disposed using <see cref="TcDeregisterClient"/>.</summary>
public class SafeHCLIENT : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeHCLIENT"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHCLIENT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeHCLIENT"/> class.</summary>
private SafeHCLIENT() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeHCLIENT"/> to <see cref="HCLIENT"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HCLIENT(SafeHCLIENT h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => TcDeregisterClient(handle).Succeeded;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HFILTER"/> that is disposed using <see cref="TcDeleteFilter"/>.</summary>
public class SafeHFILTER : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeHFILTER"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHFILTER(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeHFILTER"/> class.</summary>
private SafeHFILTER() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeHFILTER"/> to <see cref="HFILTER"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HFILTER(SafeHFILTER h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => TcDeleteFilter(handle).Succeeded;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HFLOW"/> that is disposed using <see cref="TcDeleteFlow"/>.</summary>
public class SafeHFLOW : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeHFLOW"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHFLOW(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeHFLOW"/> class.</summary>
private SafeHFLOW() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeHFLOW"/> to <see cref="HFLOW"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HFLOW(SafeHFLOW h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => TcDeleteFlow(handle).Succeeded;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HIFC"/> that is disposed using <see cref="TcCloseInterface"/>.</summary>
public class SafeHIFC : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeHIFC"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHIFC(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeHIFC"/> class.</summary>
private SafeHIFC() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeHIFC"/> to <see cref="HIFC"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HIFC(SafeHIFC h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => TcCloseInterface(handle).Succeeded;
}
}