using System.Threading; using QOS_FLOWID = System.UInt32; namespace Vanara.PInvoke; /// Items from Qwave.dll. public static partial class Qwave { /// /// If you are unsure what bandwidth value you need but expect to use very little use QOS_OUTGOING_DEFAULT_MINIMUM_BANDWIDTH. The system /// will allocate you a small amount of bandwidth for your operations. /// public const ulong QOS_OUTGOING_DEFAULT_MINIMUM_BANDWIDTH = 0xFFFFFFFF; /// Flags used by . [PInvokeData("qos2.h")] public enum QOS_FLOW_TYPE { /// /// If specified, the QoS subsystem will not gather data about the network path for this flow. As a result, functions which rely on /// bandwidth estimation techniques will not be available. For example, this would block QOSQueryFlow with an Operation value of /// QOSQueryFlowFundamentals and QOSNotifyFlow with an Operation value of QOSNotifyCongested, QOSNotifyUncongested, and QOSNotifyAvailable. /// QOS_NON_ADAPTIVE_FLOW = 0x00000002 } /// The QOS_FLOWRATE_REASON enumeration indicates the reason for a change in a flow's bandwidth. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_flowrate_reason typedef enum _QOS_FLOWRATE_REASON { // QOSFlowRateNotApplicable = 0, QOSFlowRateContentChange = 1, QOSFlowRateCongestion = 2, QOSFlowRateHigherContentEncoding = 3, // QOSFlowRateUserCaused = 4 } QOS_FLOWRATE_REASON, *PQOS_FLOWRATE_REASON; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_FLOWRATE_REASON")] public enum QOS_FLOWRATE_REASON { /// /// Value: /// 0 /// Indicates that there has not been a change in the flow. /// QOSFlowRateNotApplicable, /// /// Value: /// 1 /// Indicates that the content of a flow has changed. /// QOSFlowRateContentChange, /// /// Value: /// 2 /// Indicates that the flow has changed due to congestion. /// QOSFlowRateCongestion, /// /// Value: /// 3 /// QOSFlowRateHigherContentEncoding, /// /// Value: /// 4 /// Indicates that the user has caused the flow to change. /// QOSFlowRateUserCaused, } /// /// The QOS_NOTIFY_FLOW enumeration specifies the circumstances that must be present for the QOSNotifyFlow function to send a notification. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_notify_flow typedef enum _QOS_NOTIFY_FLOW { QOSNotifyCongested = // 0, QOSNotifyUncongested = 1, QOSNotifyAvailable = 2 } QOS_NOTIFY_FLOW, *PQOS_NOTIFY_FLOW; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_NOTIFY_FLOW")] public enum QOS_NOTIFY_FLOW { /// /// Value: /// 0 /// /// Notifications will be sent when congestion is detected. If the flow is currently congested, a notification may be sent immediately. /// /// QOSNotifyCongested, /// /// Value: /// 1 /// /// Notifications will be sent when the flow is not congested. If the flow is currently uncongested, a notification may be sent immediately. /// /// QOSNotifyUncongested, /// /// Value: /// 2 /// /// Notifications will be sent when the flow's available capacity is sufficient to allow upgrading its bandwidth to a specified capacity. /// /// QOSNotifyAvailable, } /// The QOS_QUERY_FLOW enumeration indicates the type of information a QOSQueryFlow function will request. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_query_flow typedef enum _QOS_QUERY_FLOW { // QOSQueryFlowFundamentals = 0, QOSQueryPacketPriority = 1, QOSQueryOutgoingRate = 2 } QOS_QUERY_FLOW, *PQOS_QUERY_FLOW; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_QUERY_FLOW")] public enum QOS_QUERY_FLOW { /// /// Value: /// 0 /// /// Indicates an information request for the flow fundamentals. This information includes bottleneck bandwidth, available bandwidth, /// and the average Round Trip Time (RTT) /// /// [CorrespondingType(typeof(QOS_FLOW_FUNDAMENTALS))] QOSQueryFlowFundamentals, /// /// Value: /// 1 /// Indicates a request for information detailing the QoS priority being added to flow packets. /// [CorrespondingType(typeof(QOS_PACKET_PRIORITY))] QOSQueryPacketPriority, /// /// Value: /// 2 /// Indicates a request for the flow rate specified during the creation of an agreement with the QoS subsystem via the /// QOSSetFlow /// function. /// [CorrespondingType(typeof(ulong))] QOSQueryOutgoingRate, } /// Flags used by . [PInvokeData("qos2.h")] public enum QOS_QUERYFLOW { /// /// The QOS subsystem will only return fresh, not cached, data. If fresh data is unavailable, it will try to obtain such data, at the /// expense of possibly taking more time. If this is not possible, the call will fail with the error code ERROR_RETRY. /// This flag is only applicable when the Operation parameter is set to QOSQueryFlowFundamentals. /// QOS_QUERYFLOW_FRESH = 0x00000001 } /// The QOS_SET_FLOW enumeration indicates what is being changed about a flow. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_set_flow typedef enum _QOS_SET_FLOW { QOSSetTrafficType = 0, // QOSSetOutgoingRate = 1, QOSSetOutgoingDSCPValue = 2 } QOS_SET_FLOW, *PQOS_SET_FLOW; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_SET_FLOW")] public enum QOS_SET_FLOW { /// /// Value: /// 0 /// Indicates that the traffic type of the flow will change. /// QOSSetTrafficType, /// /// Value: /// 1 /// Indicates that the flow rate will change. /// QOSSetOutgoingRate, /// /// Value: /// 2 /// Windows 7, Windows Server 2008 R2, and later: Indicates that the outgoing DSCP value will change. /// /// Note This setting requires the calling application be a member of the Administrators or the Network Configuration /// Operators group. /// /// QOSSetOutgoingDSCPValue, } /// The QOS_SHAPING enumeration defines the shaping behavior of a flow. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_shaping typedef enum _QOS_SHAPING { QOSShapeOnly = 0, // QOSShapeAndMark = 1, QOSUseNonConformantMarkings = 2 } QOS_SHAPING, *PQOS_SHAPING; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_SHAPING")] public enum QOS_SHAPING { /// /// Value: /// 0 /// /// Indicates that the Windows packet scheduler (Pacer) will be used to enforce the requested flow rate. Data packets that exceed the /// rate are delayed until appropriate in order to maintain the specified flow rate. If the network supports prioritization, packets /// will always receive conformant priority values when QOSShapeFlow is specified. /// /// QOSShapeOnly, /// /// Value: /// 1 /// /// Indicates that the Windows Scheduler will be used to enforce the requested flow rate. Data packets exceeding the rate are delayed /// accordingly. Packets receive conformant priority values. /// /// QOSShapeAndMark, /// /// Value: /// 2 /// /// Indicates that the flow rate requested will not be enforced. Data packets that would exceed the flow rate will receive a priority /// that indicates they are non-conformant. This may lead to lost and reordered packets. /// /// QOSUseNonConformantMarkings, } /// /// The QOS_TRAFFIC_TYPE enumeration defines the various traffic types. Each flow has a single traffic type. This allows the QOS /// subsystem to apply user-specified policies to each type. /// /// /// 802.1p tags are added to sent traffic only when the following conditions are met: /// /// /// QOSAddSocketToFlow is called without the QOS_NON_ADAPTIVE_FLOW flag /// /// /// The destination host is on the local link and not across a router /// /// /// The qWAVE subsystem has determined that 802.1p tagged packets are not discarded by a network element on the end-to-end path /// /// /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ne-qos2-qos_traffic_type typedef enum _QOS_TRAFFIC_TYPE { // QOSTrafficTypeBestEffort = 0, QOSTrafficTypeBackground = 1, QOSTrafficTypeExcellentEffort = 2, QOSTrafficTypeAudioVideo = 3, // QOSTrafficTypeVoice = 4, QOSTrafficTypeControl = 5 } QOS_TRAFFIC_TYPE, *PQOS_TRAFFIC_TYPE; [PInvokeData("qos2.h", MSDNShortId = "NE:qos2._QOS_TRAFFIC_TYPE")] public enum QOS_TRAFFIC_TYPE { /// /// Value: /// 0 /// Flow traffic has the same network priority as regular traffic not associated with QOS. /// /// This traffic type is the same as not specifying priority, and as a result, the DSCP mark and 802.1p tag are not added to sent traffic. /// /// QOSTrafficTypeBestEffort, /// /// Value: /// 1 /// Flow traffic has a network priority lower than that of /// QOSTrafficTypeBestEffort /// . This traffic type could be used for traffic of an application doing data backup. /// Sent traffic will contain a DSCP mark with a value of 0x08 and an 802.1p tag with a value of 2. /// QOSTrafficTypeBackground, /// /// Value: /// 2 /// Flow traffic has a network priority higher than /// QOSTrafficTypeBestEffort /// , yet lower than /// QOSTrafficTypeAudioVideo /// . This traffic type should be used for data traffic that is more important than normal end-user scenarios, such as email. /// Sent traffic will contain a DSCP mark with value of 0x28 and 802.1p tag with a value of 5. /// QOSTrafficTypeExcellentEffort, /// /// Value: /// 3 /// Flow traffic has a network priority higher than /// QOSTrafficTypeExcellentEffort /// , yet lower than /// QOSTrafficTypeVoice /// . This traffic type should be used for A/V streaming scenarios such as MPEG2 streaming. /// Sent traffic will contain a DSCP mark with a value of 0x28 and an 802.1p tag with a value of 5. /// QOSTrafficTypeAudioVideo, /// /// Value: /// 4 /// Flow traffic has a network priority higher than /// QOSTrafficTypeAudioVideo /// , yet lower than /// QOSTrafficTypeControl /// . This traffic type should be used for realtime voice streams such as VOIP. /// Sent traffic will contain a DSCP mark with a value of 0x38 and an 802.1p tag with a value of 7. /// QOSTrafficTypeVoice, /// /// Value: /// 5 /// /// Flow traffic has the highest network priority. This traffic type should only be used for the most critical of data. For example, /// it may be used for data carrying user inputs. /// /// Sent traffic will contain a DSCP mark with a value of 0x38 and an 802.1p tag with a value of 7. /// QOSTrafficTypeControl, } /// API to calculate the impact of IP and protocol header overhead on a data rate. /// /// Address family used to create the socket. Please review the socket and WSASocket documentation. This should be AF_INET or AF_INET6 /// /// /// Protocol type used to create the socket. Please review the socket and WSASocket documentation. This should be IPPROTO_TCP or IPPROTO_UDP /// /// This is the expected packet size of your data stream. /// Your dataRate in bits/s. /// /// This call will return the data rate, in bits/s, augmented by the overhead on each packet given the address family and the protocol /// you've created your socket with. /// /// /// Note on targetDataPacketSize: /// /// If you're using a TCP socket on IPv4 and will be making large sends then you would expect the data packet size to be 1460 bytes: /// Ethernet has an MTU of 1500 bytes and that the overhead of an IPv4 header is typically 20 bytes while a TCP header is also 20 bytes. /// /// /// If you're using a UDP socket and your packet size varies, you may wish to pass in a reasonnable minimal value. This would adjust your /// rate for the worst case. /// /// The value 0 is an invalid parameter which will result in a division by 0. /// [PInvokeData("qos2.h")] public static ulong QOS_ADD_OVERHEAD(ADDRESS_FAMILY af, IPPROTO protocol, uint targetDataPacketSize, ulong dataRate) { // Calculate the header overhead ulong overhead = (ulong)QOS_HEADER_OVERHEAD(af, protocol); // Convert overhead and dataRate to bits overhead *= 8; targetDataPacketSize *= 8; // The adjustment is: // // (dataRate ) returnRate = dataRate + (-------------------- * overhead ) (targetDataPacketSize ) // // For each packet we expect to see go out, we need to add the overhead return dataRate + dataRate * overhead / targetDataPacketSize; } /// API to calculate the impact of IP and protocol header overhead on a data rate. /// /// Address family used to create the socket. Please review the socket and WSASocket documentation. This should be AF_INET or AF_INET6 /// /// /// Protocol type used to create the socket. Please review the socket and WSASocket documentation. This should be IPPROTO_TCP or IPPROTO_UDP /// /// This is the expected packet size of your data stream. /// Your dataRate in bits/s. /// /// This call will return the data rate, in bits/s, reduced by the overhead on each packet given the address family and the protocol /// you've created your socket with. /// /// /// Note on targetDataPacketSize: /// /// If you're using a TCP socket on IPv4 and will be making large sends then you would expect the data packet size to be 1460 bytes: /// Ethernet has an MTU of 1500 bytes and that the overhead of an IPv4 header is typically 20 bytes while a TCP header is also 20 bytes. /// /// /// If you're using a UDP socket and your packet size varies, you may wish to pass in a reasonnable minimal value. This would adjust your /// rate for the worst case. /// /// [PInvokeData("qos2.h")] public static ulong QOS_SUBTRACT_OVERHEAD(ADDRESS_FAMILY af, IPPROTO protocol, uint targetDataPacketSize, ulong dataRate) { // Calculate the header overhead ulong overhead = (ulong)QOS_HEADER_OVERHEAD(af, protocol); // Convert overhead and dataRate to bits overhead *= 8; targetDataPacketSize *= 8; // The adjustment is: // // (dataRate ) returnRate = dataRate - (------------------------------- * overhead ) (targetDataPacketSize + overhead ) // // For each packet we expect to see go out, we need to add the overhead return dataRate - dataRate * overhead / (targetDataPacketSize + overhead); } /// The QOSAddSocketToFlow function adds a new flow for traffic. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Identifies the socket that the application will use to flow traffic. /// /// /// Pointer to a sockaddr structure that contains the destination IP address to which the application will send traffic. The sockaddr /// structure must specify a destination port. /// /// /// /// DestAddr is optional if the socket is already connected. If this parameter is specified, the remote IP address and port must /// match those used in the socket's connect call. /// /// /// If the socket is not connected, this parameter must be specified. If the socket is already connected, this parameter does not need to /// be specified. In this case, if the parameter is still specified, the destination host and port must match what was specified during /// the socket connect call. /// /// /// Since, under TCP, the socket connect call can be delayed, QOSAddSocketToFlow can be called before a connection is established, /// passing in the remote system's IP address and port number in the DestAddr parameter. /// /// /// /// /// A QOS_TRAFFIC_TYPE constant that specifies the type of traffic for which this flow will be used. /// /// Optional flag values. /// /// /// Value /// Meaning /// /// /// QOS_NON_ADAPTIVE_FLOW /// /// If specified, the QoS subsystem will not gather data about the network path for this flow. As a result, functions which rely on /// bandwidth estimation techniques will not be available. For example, this would block QOSQueryFlow with an Operation value of /// QOSQueryFlowFundamentals and QOSNotifyFlow with an Operation value of QOSNotifyCongested, /// QOSNotifyUncongested, and QOSNotifyAvailable. /// /// /// /// /// /// /// Pointer to a buffer that receives a flow identifier. On input, this value must be 0. On output, the buffer contains a flow identifier /// if the call succeeds. /// /// If a socket is being added to an existing flow, this parameter will be the identifier of that flow. /// /// An application can make use of this parameter if multiple sockets used can share the same QoS flow properties. The QoS subsystem, /// then does not have to incur the overhead of provisioning new flows for subsequent sockets with the same properties. Note that only /// non-adaptive flows can have multiple sockets attached to an existing flow. /// /// A QOS_FLOWID is an unsigned 32-bit integer. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_CONNECTION_REFUSED /// The remote system refused the network connection. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The request is not supported. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// /// /// /// The use of IPv4/v6 mixed addresses is not supported in qWAVE. The address specified by the DestAddr parameter must be either /// IPv4 or IPv6. /// /// /// If there is a requirement for network experiments over a specific network interface, the socket must be bound to that particular /// interface. Otherwise the most appropriate interface for the experiment, as indicated by the network stack, is assigned by the qWAVE subsystem. /// /// /// Network traffic associated with this flow is not affected by making this call alone. For example, packet prioritization does not /// occur immediately. /// /// /// There are two categories of applications that use this function: adaptive and non-adaptive. An adaptive application makes use of /// notifications and information in the QOS_FLOW_FUNDAMENTALS structure for adapting to network changes such as congestion. The qWAVE /// service uses Link Layer Topology Discovery (LLTD) QoS extensions for adaptive flows which can be present on the destination device. /// /// /// After calling this function adaptive A/V applications should call the QOSSetFlow function with an Operation value of /// QOSSetFlowRate to affect network traffic. /// /// /// A non-adaptive application either does not adapt to changing network characteristics or is sending traffic to an endpoint that does /// not support adaptive capabilities as indicated by ERROR_NOT_SUPPORTED. /// /// /// Non-adaptive applications, or adaptive applications making non-adaptive flows, should call this function with the /// QOS_NON_ADAPTIVE_FLOW flag. After calling this function A/V applications should call the QOSSetFlow function with a /// Operation. QOSSetFlow does not need to be called unless shaping is desired. /// /// Examples /// /// The following code illustrates the use of QOSAddSocketFromFlow. The QOSCreateHandle function is also shown to provide /// information on initialization of parameters used by QOSAddSocketFromFlow. /// /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// The Winsock2.h header file must be included to use WSAGetLastError and other Winsock functions. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosaddsockettoflow ExternC BOOL QOSAddSocketToFlow( [in] HANDLE // QOSHandle, [in] SOCKET Socket, [in, optional] PSOCKADDR DestAddr, [in] QOS_TRAFFIC_TYPE TrafficType, [in, optional] DWORD Flags, [in, // out] PQOS_FLOWID FlowId ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSAddSocketToFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSAddSocketToFlow([In] HQOS QOSHandle, [In] SOCKET Socket, [In] SOCKADDR DestAddr, [In] QOS_TRAFFIC_TYPE TrafficType, [In, Optional] QOS_FLOW_TYPE Flags, ref QOS_FLOWID FlowId); /// The QOSAddSocketToFlow function adds a new flow for traffic. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Identifies the socket that the application will use to flow traffic. /// /// /// Pointer to a sockaddr structure that contains the destination IP address to which the application will send traffic. The sockaddr /// structure must specify a destination port. /// /// /// /// DestAddr is optional if the socket is already connected. If this parameter is specified, the remote IP address and port must /// match those used in the socket's connect call. /// /// /// If the socket is not connected, this parameter must be specified. If the socket is already connected, this parameter does not need to /// be specified. In this case, if the parameter is still specified, the destination host and port must match what was specified during /// the socket connect call. /// /// /// Since, under TCP, the socket connect call can be delayed, QOSAddSocketToFlow can be called before a connection is established, /// passing in the remote system's IP address and port number in the DestAddr parameter. /// /// /// /// /// A QOS_TRAFFIC_TYPE constant that specifies the type of traffic for which this flow will be used. /// /// Optional flag values. /// /// /// Value /// Meaning /// /// /// QOS_NON_ADAPTIVE_FLOW /// /// If specified, the QoS subsystem will not gather data about the network path for this flow. As a result, functions which rely on /// bandwidth estimation techniques will not be available. For example, this would block QOSQueryFlow with an Operation value of /// QOSQueryFlowFundamentals and QOSNotifyFlow with an Operation value of QOSNotifyCongested, /// QOSNotifyUncongested, and QOSNotifyAvailable. /// /// /// /// /// /// /// Pointer to a buffer that receives a flow identifier. On input, this value must be 0. On output, the buffer contains a flow identifier /// if the call succeeds. /// /// If a socket is being added to an existing flow, this parameter will be the identifier of that flow. /// /// An application can make use of this parameter if multiple sockets used can share the same QoS flow properties. The QoS subsystem, /// then does not have to incur the overhead of provisioning new flows for subsequent sockets with the same properties. Note that only /// non-adaptive flows can have multiple sockets attached to an existing flow. /// /// A QOS_FLOWID is an unsigned 32-bit integer. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_CONNECTION_REFUSED /// The remote system refused the network connection. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The request is not supported. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// /// /// /// The use of IPv4/v6 mixed addresses is not supported in qWAVE. The address specified by the DestAddr parameter must be either /// IPv4 or IPv6. /// /// /// If there is a requirement for network experiments over a specific network interface, the socket must be bound to that particular /// interface. Otherwise the most appropriate interface for the experiment, as indicated by the network stack, is assigned by the qWAVE subsystem. /// /// /// Network traffic associated with this flow is not affected by making this call alone. For example, packet prioritization does not /// occur immediately. /// /// /// There are two categories of applications that use this function: adaptive and non-adaptive. An adaptive application makes use of /// notifications and information in the QOS_FLOW_FUNDAMENTALS structure for adapting to network changes such as congestion. The qWAVE /// service uses Link Layer Topology Discovery (LLTD) QoS extensions for adaptive flows which can be present on the destination device. /// /// /// After calling this function adaptive A/V applications should call the QOSSetFlow function with an Operation value of /// QOSSetFlowRate to affect network traffic. /// /// /// A non-adaptive application either does not adapt to changing network characteristics or is sending traffic to an endpoint that does /// not support adaptive capabilities as indicated by ERROR_NOT_SUPPORTED. /// /// /// Non-adaptive applications, or adaptive applications making non-adaptive flows, should call this function with the /// QOS_NON_ADAPTIVE_FLOW flag. After calling this function A/V applications should call the QOSSetFlow function with a /// Operation. QOSSetFlow does not need to be called unless shaping is desired. /// /// Examples /// /// The following code illustrates the use of QOSAddSocketFromFlow. The QOSCreateHandle function is also shown to provide /// information on initialization of parameters used by QOSAddSocketFromFlow. /// /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// The Winsock2.h header file must be included to use WSAGetLastError and other Winsock functions. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosaddsockettoflow ExternC BOOL QOSAddSocketToFlow( [in] HANDLE // QOSHandle, [in] SOCKET Socket, [in, optional] PSOCKADDR DestAddr, [in] QOS_TRAFFIC_TYPE TrafficType, [in, optional] DWORD Flags, [in, // out] PQOS_FLOWID FlowId ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSAddSocketToFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSAddSocketToFlow([In] HQOS QOSHandle, [In] SOCKET Socket, [In, Optional] IntPtr DestAddr, [In] QOS_TRAFFIC_TYPE TrafficType, [In, Optional] QOS_FLOW_TYPE Flags, ref QOS_FLOWID FlowId); /// The QOSCancel function cancels a pending overlapped operation, like QOSSetFlow. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Pointer to the OVERLAPPED structure used in the operation to be canceled. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The Overlapped parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// /// /// This function would never be called with a NULLOverlapped parameter. /// /// Successfully canceled operations complete normal completion mechanisms and return ERROR_OPERATION_ABORTED as their completion /// return code. /// /// /// Closing a handle with the QOSCloseHandle will automatically abort all pending operations issued with that handle. If the handle is /// closed while a QOSCancel is still in progress, the call will complete with ERROR_OPERATION_ABORTED as the return code. /// /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qoscancel ExternC BOOL QOSCancel( [in] HANDLE QOSHandle, [in] // LPOVERLAPPED Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSCancel")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSCancel([In] HQOS QOSHandle, in NativeOverlapped Overlapped); /// The QOSCloseHandle function closes a handle returned by the QOSCreateHandle function. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is 0. To get extended error information, call GetLastError. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_PARAMETER /// The QOSHandle parameter is invalid. /// /// /// /// /// /// All flows added on the handle being closed are immediately removed from the system. Any traffic going out of a socket used to create /// these flows will no longer be marked with priority values. Any pending operations on these flows are immediately completed with ERROR_ABORTED. /// /// /// If any clients were being tracked through the handle being closed by a previous call to the QOSStartTrackingClient function, /// QOSCloseHandle indicates that the application is no longer using the client endpoint. /// /// Examples /// The following "CleanUpQos" function illustrates the use of QOSRemoveSocketFromFlow and QOSCloseHandle: /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// The Winsock2.h header file must be included to use Winsock defined identifiers or functions. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosclosehandle ExternC BOOL QOSCloseHandle( [in] HANDLE QOSHandle ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSCloseHandle")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSCloseHandle([In] HQOS QOSHandle); /// /// /// This function initializes the QOS subsystem and the QOSHandle parameter. The QOSHandle parameter is used when calling /// other QOS functions. QOSCreateHandle must be called before any other functions. /// /// QOSCloseHandle closes handles created by this function. /// /// /// Pointer to a QOS_VERSION structure that indicates the version of QOS being used. The MajorVersion member must be set to 1, and /// the MinorVersion member must be set to 0. /// /// Pointer to a variable that receives a QOS handle. This handle is used when calling other QOS functions. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_GEN_FAILURE /// /// Internal logic error. Initialization failed. For example, if the host goes into sleep or standby mode, all existing handles and flows /// are rendered invalid. /// /// /// /// ERROR_INVALID_PARAMETER /// The QOSHandle parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_RESOURCE_DISABLED /// /// A resource required by the service is unavailable. This error may be returned if the user has not enabled the firewall exception for /// the qWAVE service. /// /// /// /// ERROR_SERVICE_DEPENDENCY_FAIL /// One of the dependencies of this service is unavailable. The qWAVE service could not be started. /// /// /// /// /// /// Every process intending to use qWAVE must first call QOSCreateHandle. The handle returned can be used for performing /// overlapped I/O. For example, this handle can be associated with an I/O completion port (IOCP) to receive overlapped completion /// notifications. This function can be called multiple times to obtain multiple handles although a single handle is sufficient for most applications. /// /// /// If a machine enters a power save mode that interrupts connectivity such as sleep or standby, existing and active network experiments /// such as QOSStartTrackingClient must be reinitiated. This recreation of the flow mirrors the cleanup and creation activities also /// necessary for existing sockets. A new handle must be created, and the flow must be recreated and readmitted. /// /// Examples /// /// The following code illustrates function use and required parameter initializations. Actual values will vary depending on QoS version. /// /// Winsock.h must be included to use the WSAGetLastError function. /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qoscreatehandle ExternC BOOL QOSCreateHandle( [in] PQOS_VERSION // Version, [out] PHANDLE QOSHandle ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSCreateHandle")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSCreateHandle(in QOS_VERSION Version, out HQOS QOSHandle); /// /// /// This function initializes the QOS subsystem and the QOSHandle parameter. The QOSHandle parameter is used when calling /// other QOS functions. QOSCreateHandle must be called before any other functions. /// /// QOSCloseHandle closes handles created by this function. /// /// Pointer to a variable that receives a safe QOS handle. This handle is used when calling other QOS functions. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_GEN_FAILURE /// /// Internal logic error. Initialization failed. For example, if the host goes into sleep or standby mode, all existing handles and flows /// are rendered invalid. /// /// /// /// ERROR_INVALID_PARAMETER /// The QOSHandle parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_RESOURCE_DISABLED /// /// A resource required by the service is unavailable. This error may be returned if the user has not enabled the firewall exception for /// the qWAVE service. /// /// /// /// ERROR_SERVICE_DEPENDENCY_FAIL /// One of the dependencies of this service is unavailable. The qWAVE service could not be started. /// /// /// /// /// /// Every process intending to use qWAVE must first call QOSCreateHandle. The handle returned can be used for performing /// overlapped I/O. For example, this handle can be associated with an I/O completion port (IOCP) to receive overlapped completion /// notifications. This function can be called multiple times to obtain multiple handles although a single handle is sufficient for most applications. /// /// /// If a machine enters a power save mode that interrupts connectivity such as sleep or standby, existing and active network experiments /// such as QOSStartTrackingClient must be reinitiated. This recreation of the flow mirrors the cleanup and creation activities also /// necessary for existing sockets. A new handle must be created, and the flow must be recreated and readmitted. /// /// Examples /// /// The following code illustrates function use and required parameter initializations. Actual values will vary depending on QoS version. /// /// Winsock.h must be included to use the WSAGetLastError function. /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qoscreatehandle ExternC BOOL QOSCreateHandle( [in] PQOS_VERSION // Version, [out] PHANDLE QOSHandle ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSCreateHandle")] public static bool QOSCreateHandle(out SafeHQOS QOSHandle) { bool ret = QOSCreateHandle(new QOS_VERSION() { MajorVersion = 1 }, out HQOS h); QOSHandle = new((IntPtr)h, ret); return ret; } /// The QOSEnumerateFlows function enumerates all existing flows. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Indicates the size of the Buffer parameter, in bytes. /// On function return, if successful, this parameter will specify the number of bytes copied into Buffer. /// /// If this call fails with ERROR_INSUFFICIENT_BUFFER, this parameter will indicate the minimum required Buffer size in /// order to successfully complete this operation. /// /// /// Pointer to an array of QOS_FlowId flow identifiers. A QOS_FlowId is an unsigned 32-bit integer. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INSUFFICIENT_BUFFER /// /// Buffer is too small. On output, Size will contain the minimum required buffer size. This function should then be called again /// with a buffer of the indicated size. /// /// /// /// ERROR_INVALID_PARAMETER /// The DestAddr parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// /// /// Successfully calling this function requires administrative privileges /// /// Calling the QOSEnumerateFlows function retrieves a list of QOS_FlowId s currently active on the QOS subsystem. These /// QOS_FlowId s could then be used to call the QOSQueryFlow function in order to gain more information on individual flows. /// /// /// This function has call-twice semantics. First call to get the Buffer size, then call again (with an appropriately sized /// Buffer if the first call failed with ERROR_INSUFFICIENT_BUFFER) to retrieve the list of flows. The second call may fail /// again with ERROR_INSUFFICIENT_BUFFER if new flows ere added since the first call. /// /// Flows from another process cannot be modified. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosenumerateflows ExternC BOOL QOSEnumerateFlows( [in] HANDLE // QOSHandle, [in, out] PULONG Size, [out] PVOID Buffer ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSEnumerateFlows")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSEnumerateFlows([In] HQOS QOSHandle, ref uint Size, [Out] IntPtr Buffer); /// The QOSEnumerateFlows function enumerates all existing flows. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// An array of QOS_FLOWID flow identifiers expressed as . /// /// Successfully calling this function requires administrative privileges /// /// Calling the QOSEnumerateFlows function retrieves a list of QOS_FlowId s currently active on the QOS subsystem. These /// QOS_FlowId s could then be used to call the QOSQueryFlow function in order to gain more information on individual flows. /// /// Flows from another process cannot be modified. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosenumerateflows ExternC BOOL QOSEnumerateFlows( [in] HANDLE // QOSHandle, [in, out] PULONG Size, [out] PVOID Buffer ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSEnumerateFlows")] public static QOS_FLOWID[] QOSEnumerateFlows([In] HQOS QOSHandle) { uint sz = 256; using SafeCoTaskMemHandle mem = new(sz); while (true) { if (!QOSEnumerateFlows(QOSHandle, ref sz, mem)) { Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); mem.Size = sz; } else { return mem.ToArray((int)sz / sizeof(uint)); } } } /// /// The QOSNotifyFlow function registers the calling application to receive a notification about changes in network /// characteristics, such as congestion. Notifications may also be sent when a desired throughput is able to be achieved. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Specifies the flow identifier from which the application wishes to receive notifications. A QOS_FLOWID is an unsigned 32-bit integer. /// /// A QOS_NOTIFY_FLOW value that indicates what the type of notification being requested. /// /// Indicates the size of the Buffer parameter, in bytes. /// On function return, if successful, this parameter will specify the number of bytes copied into Buffer. /// /// If this call fails with ERROR_INSUFFICIENT_BUFFER, this parameter will indicate the minimum required Buffer size in /// order to successfully complete this operation. /// /// /// /// Pointer to a UINT64 that indicates the bandwidth at which point a notification will be sent. This parameter is only used if the /// Operation parameter is set to QOSNotifyAvailable. For the QOSNotifyCongested and QOSNotifyUncongested /// options, this parameter must be set to NULL on input. /// /// Reserved for future use. This parameter must be set to 0. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be se to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, a return value of nonzero is sent when the conditions set by the Operation parameter are met. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// Indicates that notification request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The QOS subsystem has determined that the operation requested could not be completed on the network path specified. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// ERROR_ALREADY_EXISTS /// There is already a request for notifications of the same type pending on this flow. /// /// /// /// This function may be called asynchronously. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosnotifyflow ExternC BOOL QOSNotifyFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_NOTIFY_FLOW Operation, [in, out, optional] PULONG Size, [in, out] PVOID Buffer, DWORD Flags, [out, // optional] LPOVERLAPPED Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSNotifyFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSNotifyFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_NOTIFY_FLOW Operation, ref uint Size, [In, Out, Optional] IntPtr Buffer, [Optional] uint Flags, ref NativeOverlapped Overlapped); /// /// The QOSNotifyFlow function registers the calling application to receive a notification about changes in network /// characteristics, such as congestion. Notifications may also be sent when a desired throughput is able to be achieved. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Specifies the flow identifier from which the application wishes to receive notifications. A QOS_FLOWID is an unsigned 32-bit integer. /// /// A QOS_NOTIFY_FLOW value that indicates what the type of notification being requested. /// /// Indicates the size of the Buffer parameter, in bytes. /// On function return, if successful, this parameter will specify the number of bytes copied into Buffer. /// /// If this call fails with ERROR_INSUFFICIENT_BUFFER, this parameter will indicate the minimum required Buffer size in /// order to successfully complete this operation. /// /// /// /// Pointer to a UINT64 that indicates the bandwidth at which point a notification will be sent. This parameter is only used if the /// Operation parameter is set to QOSNotifyAvailable. For the QOSNotifyCongested and QOSNotifyUncongested /// options, this parameter must be set to NULL on input. /// /// Reserved for future use. This parameter must be set to 0. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be se to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, a return value of nonzero is sent when the conditions set by the Operation parameter are met. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// Indicates that notification request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The QOS subsystem has determined that the operation requested could not be completed on the network path specified. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// ERROR_ALREADY_EXISTS /// There is already a request for notifications of the same type pending on this flow. /// /// /// /// This function may be called asynchronously. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosnotifyflow ExternC BOOL QOSNotifyFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_NOTIFY_FLOW Operation, [in, out, optional] PULONG Size, [in, out] PVOID Buffer, DWORD Flags, [out, // optional] LPOVERLAPPED Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSNotifyFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSNotifyFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_NOTIFY_FLOW Operation, ref uint Size, [In, Out, Optional] IntPtr Buffer, [Optional] uint Flags, [Optional] IntPtr Overlapped); /// /// The QOSNotifyFlow function registers the calling application to receive a notification about changes in network /// characteristics, such as congestion. Notifications may also be sent when a desired throughput is able to be achieved. /// /// The type of . /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Specifies the flow identifier from which the application wishes to receive notifications. A QOS_FLOWID is an unsigned 32-bit integer. /// /// A QOS_NOTIFY_FLOW value that indicates what the type of notification being requested. /// The value. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be se to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, a return value of nonzero is sent when the conditions set by the Operation parameter are met. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// Indicates that notification request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The QOS subsystem has determined that the operation requested could not be completed on the network path specified. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// ERROR_ALREADY_EXISTS /// There is already a request for notifications of the same type pending on this flow. /// /// /// /// This function may be called asynchronously. [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSNotifyFlow")] public static bool QOSNotifyFlow([In] HQOS QOSHandle, [In] uint FlowId, [In] QOS_NOTIFY_FLOW Operation, T value, ref NativeOverlapped Overlapped) where T : unmanaged { unsafe { uint sz = (uint)sizeof(T); return QOSNotifyFlow(QOSHandle, FlowId, Operation, ref sz, (IntPtr)(void*)&value, 0, ref Overlapped); } } /// /// The QOSNotifyFlow function registers the calling application to receive a notification about changes in network /// characteristics, such as congestion. Notifications may also be sent when a desired throughput is able to be achieved. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Specifies the flow identifier from which the application wishes to receive notifications. A QOS_FLOWID is an unsigned 32-bit integer. /// /// A QOS_NOTIFY_FLOW value that indicates what the type of notification being requested. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be se to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, a return value of nonzero is sent when the conditions set by the Operation parameter are met. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// Indicates that notification request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The QOS subsystem has determined that the operation requested could not be completed on the network path specified. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// ERROR_ALREADY_EXISTS /// There is already a request for notifications of the same type pending on this flow. /// /// /// /// This function may be called asynchronously. [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSNotifyFlow")] public static bool QOSNotifyFlow([In] HQOS QOSHandle, [In] uint FlowId, [In] QOS_NOTIFY_FLOW Operation, ref NativeOverlapped Overlapped) { uint sz = 0; return QOSNotifyFlow(QOSHandle, FlowId, Operation, ref sz, IntPtr.Zero, 0, ref Overlapped); } /// /// The QOSQueryFlow function requests information about a specific flow added to the QoS subsystem. This function may be called asynchronously. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Specifies a flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// Specifies which type of flow information is being queried. This parameter specifies what structure the Buffer will contain. /// /// /// Value /// Meaning /// /// /// QOSQueryFlowFundamentals /// Buffer will contain a QOS_FLOW_FUNDAMENTALS structure. /// /// /// QOSQueryPacketPriority /// Buffer will contain a QOS_PACKET_PRIORITY structure. /// /// /// QOSQueryOutgoingRate /// /// Buffer will contain a UINT64 value that indicates the flow rate specified when requesting the contract, in bits per second. /// /// /// /// /// /// Indicates the size of the Buffer parameter, in bytes. /// On function return, if successful, this parameter will specify the number of bytes copied into Buffer. /// /// If this call fails with ERROR_INSUFFICIENT_BUFFER, this parameter will indicate the minimum required Buffer size in /// order to successfully complete this operation. /// /// /// Pointer to the structure specified by the value of the Operation parameter. /// /// Flags pertaining to the data being returned. /// /// /// Value /// Meaning /// /// /// QOS_QUERYFLOW_FRESH /// /// The QOS subsystem will only return fresh, not cached, data. If fresh data is unavailable, it will try to obtain such data, at the /// expense of possibly taking more time. If this is not possible, the call will fail with the error code ERROR_RETRY. This flag /// is only applicable when the Operation parameter is set to QOSQueryFlowFundamentals. /// /// /// /// /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be set to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_TIMEOUT /// The request to the QOS subsystem timed out before enough useful information could be gathered. /// /// /// ERROR_INSUFFICIENT_BUFFER /// /// The buffer length as specified by the Size parameter is not sufficient for the queried data. The Size parameter now /// contains the minimum required size. /// /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter or Buffer size is insufficient. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_IO_PENDING /// Indicates that the update flow request was successfully initiated. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_NO_DATA /// The is no valid data to be returned. /// /// /// ERROR_RETRY /// /// There is currently insufficient data about networking conditions to answer the query. This is typically a transient state where qWAVE /// has erred on the side of caution as it awaits more data before ascertaining the state of the network. /// /// /// /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosqueryflow ExternC BOOL QOSQueryFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_QUERY_FLOW Operation, [in, out] PULONG Size, [out] PVOID Buffer, [in, optional] DWORD Flags, [out, // optional] LPOVERLAPPED Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSQueryFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSQueryFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_QUERY_FLOW Operation, ref uint Size, [Out] IntPtr Buffer, [In, Optional] QOS_QUERYFLOW Flags, out NativeOverlapped Overlapped); /// /// The QOSQueryFlow function requests information about a specific flow added to the QoS subsystem. This function may be called asynchronously. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Specifies a flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// Specifies which type of flow information is being queried. This parameter specifies what structure the Buffer will contain. /// /// /// Value /// Meaning /// /// /// QOSQueryFlowFundamentals /// Buffer will contain a QOS_FLOW_FUNDAMENTALS structure. /// /// /// QOSQueryPacketPriority /// Buffer will contain a QOS_PACKET_PRIORITY structure. /// /// /// QOSQueryOutgoingRate /// /// Buffer will contain a UINT64 value that indicates the flow rate specified when requesting the contract, in bits per second. /// /// /// /// /// /// Indicates the size of the Buffer parameter, in bytes. /// On function return, if successful, this parameter will specify the number of bytes copied into Buffer. /// /// If this call fails with ERROR_INSUFFICIENT_BUFFER, this parameter will indicate the minimum required Buffer size in /// order to successfully complete this operation. /// /// /// Pointer to the structure specified by the value of the Operation parameter. /// /// Flags pertaining to the data being returned. /// /// /// Value /// Meaning /// /// /// QOS_QUERYFLOW_FRESH /// /// The QOS subsystem will only return fresh, not cached, data. If fresh data is unavailable, it will try to obtain such data, at the /// expense of possibly taking more time. If this is not possible, the call will fail with the error code ERROR_RETRY. This flag /// is only applicable when the Operation parameter is set to QOSQueryFlowFundamentals. /// /// /// /// /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be set to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_TIMEOUT /// The request to the QOS subsystem timed out before enough useful information could be gathered. /// /// /// ERROR_INSUFFICIENT_BUFFER /// /// The buffer length as specified by the Size parameter is not sufficient for the queried data. The Size parameter now /// contains the minimum required size. /// /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter or Buffer size is insufficient. /// /// /// ERROR_NOT_FOUND /// Invalid FlowId specified. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_IO_PENDING /// Indicates that the update flow request was successfully initiated. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_NO_DATA /// The is no valid data to be returned. /// /// /// ERROR_RETRY /// /// There is currently insufficient data about networking conditions to answer the query. This is typically a transient state where qWAVE /// has erred on the side of caution as it awaits more data before ascertaining the state of the network. /// /// /// /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosqueryflow ExternC BOOL QOSQueryFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_QUERY_FLOW Operation, [in, out] PULONG Size, [out] PVOID Buffer, [in, optional] DWORD Flags, [out, // optional] LPOVERLAPPED Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSQueryFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSQueryFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_QUERY_FLOW Operation, ref uint Size, [Out] IntPtr Buffer, [In, Optional] QOS_QUERYFLOW Flags, [Optional] IntPtr Overlapped); /// /// The QOSQueryFlow function requests information about a specific flow added to the QoS subsystem. This function may be called asynchronously. /// /// The type of the out. /// Handle to the QOS subsystem returned by QOSCreateHandle. /// Specifies a flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// Specifies which type of flow information is being queried. This parameter specifies what structure the Buffer will contain. /// /// /// Value /// Meaning /// /// /// QOSQueryFlowFundamentals /// Buffer will contain a QOS_FLOW_FUNDAMENTALS structure. /// /// /// QOSQueryPacketPriority /// Buffer will contain a QOS_PACKET_PRIORITY structure. /// /// /// QOSQueryOutgoingRate /// /// Buffer will contain a UINT64 value that indicates the flow rate specified when requesting the contract, in bits per second. /// /// /// /// /// /// If set to the QOS subsystem will only return fresh, not cached, data. If fresh data is unavailable, it will /// try to obtain such data, at the expense of possibly taking more time. If this is not possible, the call will fail with the error code /// ERROR_RETRY. This flag is only applicable when the Operation parameter is set to QOSQueryFlowFundamentals. /// /// The structure specified by the value of the Operation parameter and . [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSQueryFlow")] [return: MarshalAs(UnmanagedType.Bool)] public static TOut QOSQueryFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_QUERY_FLOW Operation, bool fresh = false) where TOut : struct { if (!CorrespondingTypeAttribute.CanGet(Operation, typeof(TOut))) throw new InvalidCastException(); using var mem = new SafeCoTaskMemStruct(); uint sz = mem.Size; Win32Error.ThrowLastErrorIfFalse(QOSQueryFlow(QOSHandle, FlowId, Operation, ref sz, mem, fresh ? QOS_QUERYFLOW.QOS_QUERYFLOW_FRESH : 0, IntPtr.Zero)); return mem.Value; } /// /// The QOSRemoveSocketFromFlow function notifies the QOS subsystem that a previously added flow has been terminated by the /// application, and that the subsystem must update its internal information accordingly. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Socket to be removed from the flow. /// /// Only flows created with the QOS_NON_ADAPTIVE_FLOW flag may have multiple sockets added to the same flow. By passing the /// Socket parameter in this call, each socket can be removed individually. If the Socket parameter is not passed, the /// entire flow will be destroyed. If only one socket was attached to the flow, passing this socket as a parameter to this function and /// passing NULL as a socket are equivalent calls. /// /// /// A flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// Reserved for future use. This parameter must be set to 0. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_NOT_FOUND /// The FlowId parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient system resources to carry out the operation. /// /// /// ERROR_OPERATION_ABORTED /// The request was blocked. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// /// /// /// Calling the QOSCloseHandle function immediately aborts all pending operations and flows added by that handle. If a handle is closed /// while a QOSRemoveSocketFromFlow call is still progress, the call will complete with ERROR_OPERATION_ABORTED. /// /// Examples /// /// The following code snippet demonstrates the use of QOSRemoveSocketFromFlow, QOSStopTrackingClient, and QOSCloseHandle /// in an application function used for "cleaning up" QoS resources. See QOSCreateHandle function for information on initialization of parameters. /// /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// Note The winsock2.h header file must be included to use WSAGetLastError and other Winsock functions. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosremovesocketfromflow ExternC BOOL QOSRemoveSocketFromFlow( [in] // HANDLE QOSHandle, [in, optional] SOCKET Socket, [in] QOS_FLOWID FlowId, DWORD Flags ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSRemoveSocketFromFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSRemoveSocketFromFlow([In] HQOS QOSHandle, [In, Optional] SOCKET Socket, [In] QOS_FLOWID FlowId, [Optional] uint Flags); /// /// The QOSSetFlow function is called by an application to request the QOS subsystem to prioritize the application's packets and /// change the flow traffic. This function is also used to notify the QoS subsystem of a flow change: for example, if the flow rate is /// changed in order to account for network congestion, or if the QoS priority value requires adjustment for transferring or streaming /// different types of content over a single persistent socket connection. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// A flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// /// A QOS_SET_FLOW enumerated type that identifies what will be changed in the flow. This parameter specifies what structure the /// Buffer will contain. /// /// /// /// Value /// Meaning /// /// /// QOSSetTrafficType 0 /// The traffic type of the flow will be changed. The Buffer will contain a pointer to a QOS_TRAFFIC_TYPE constant. /// /// /// QOSSetOutgoingRate 1 /// The flow rate will be changed. The Buffer will contain a pointer to a QOS_FLOWRATE_OUTGOING structure. /// /// /// QOSSetOutgoingDSCPValue 2 /// /// Windows 7, Windows Server 2008 R2, and later: The outgoing DSCP value will be changed. The Buffer will contain a pointer to a /// DWORD value that defines the arbitrary DSCP value. /// /// /// /// /// The size of the Buffer parameter, in bytes. /// Pointer to the structure specified by the value of the Operation parameter. /// Reserved for future use. This parameter must be set to 0. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be set to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// The update flow request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_ACCESS_DENIED /// The calling application does not have sufficient privileges for the requested operation. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NETWORK_BUSY /// The requested flow properties were not available on this path. /// /// /// ERROR_NOT_FOUND /// The FlowId parameter specified cannot be found. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_RETRY /// /// There is currently insufficient data about networking conditions to answer the query. This is typically a transient state where qWAVE /// has erred on the side of caution as it awaits more data before ascertaining the state of the network. /// /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// /// /// /// If QOSStartTrackingClient has not already been called, calling QOSSetFlow will cause the QOS subsystem to perform the following. /// /// /// /// Discover whether the end-to-end network path supports prioritization. /// /// /// /// Track end-to-end network characteristics by way of network experiments. These experiments do not place any noteworthy stress on the network. /// /// /// /// /// If QOSSetFlow returns ERROR_NETWORK_BUSY there is insufficient bandwidth for the specified flow rate and network /// priority cannot be granted. The application can still transmit a data stream but the flow will not receive priority marking. Ideally /// an application would not attempt to stream at the requested rate if there is insufficient bandwidth. If ERROR_NETWORK_BUSY is /// returned the following safe strategy is available: /// /// /// /// /// Query the QoS subsystem with QOSNotifyFlow in order to determine the current available bandwidth and begin to stream at the received /// lower rate with priority if the network supports it. /// /// /// /// /// Request notification with QOSNotifyFlow for when the originally desired amount of bandwidth is available. When notification is /// received call QOSSetFlow with the new bandwidth request and send at the new rate again with prioritization if supported. /// /// /// /// This function may optionally be called asynchronously. /// Examples /// /// The following code snippet demonstrates the use of QOSSetFlow in an application. Input parameters QOSHandle, FlowId, /// FlowId, QOSSetOutgoingRate, and sizeof( QoSOutgoingFlowrate) must be previously initialized by other QoS /// functions and calculations within the application. /// /// Other QoS function examples that show initialization of parameters include QOSCreateHandle, QOSAddSocketToFlow, and QOSQueryFlow. /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qossetflow ExternC BOOL QOSSetFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_SET_FLOW Operation, [in] ULONG Size, [in] PVOID Buffer, DWORD Flags, [out, optional] LPOVERLAPPED // Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSSetFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSSetFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_SET_FLOW Operation, uint Size, [In] IntPtr Buffer, [Optional] uint Flags, out NativeOverlapped Overlapped); /// /// The QOSSetFlow function is called by an application to request the QOS subsystem to prioritize the application's packets and /// change the flow traffic. This function is also used to notify the QoS subsystem of a flow change: for example, if the flow rate is /// changed in order to account for network congestion, or if the QoS priority value requires adjustment for transferring or streaming /// different types of content over a single persistent socket connection. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// A flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// /// A QOS_SET_FLOW enumerated type that identifies what will be changed in the flow. This parameter specifies what structure the /// Buffer will contain. /// /// /// /// Value /// Meaning /// /// /// QOSSetTrafficType 0 /// The traffic type of the flow will be changed. The Buffer will contain a pointer to a QOS_TRAFFIC_TYPE constant. /// /// /// QOSSetOutgoingRate 1 /// The flow rate will be changed. The Buffer will contain a pointer to a QOS_FLOWRATE_OUTGOING structure. /// /// /// QOSSetOutgoingDSCPValue 2 /// /// Windows 7, Windows Server 2008 R2, and later: The outgoing DSCP value will be changed. The Buffer will contain a pointer to a /// DWORD value that defines the arbitrary DSCP value. /// /// /// /// /// The size of the Buffer parameter, in bytes. /// Pointer to the structure specified by the value of the Operation parameter. /// Reserved for future use. This parameter must be set to 0. /// /// Pointer to an OVERLAPPED structure used for asynchronous output. This must be set to NULL if this function is not being called asynchronously. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// The update flow request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_ACCESS_DENIED /// The calling application does not have sufficient privileges for the requested operation. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NETWORK_BUSY /// The requested flow properties were not available on this path. /// /// /// ERROR_NOT_FOUND /// The FlowId parameter specified cannot be found. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_RETRY /// /// There is currently insufficient data about networking conditions to answer the query. This is typically a transient state where qWAVE /// has erred on the side of caution as it awaits more data before ascertaining the state of the network. /// /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// /// /// /// If QOSStartTrackingClient has not already been called, calling QOSSetFlow will cause the QOS subsystem to perform the following. /// /// /// /// Discover whether the end-to-end network path supports prioritization. /// /// /// /// Track end-to-end network characteristics by way of network experiments. These experiments do not place any noteworthy stress on the network. /// /// /// /// /// If QOSSetFlow returns ERROR_NETWORK_BUSY there is insufficient bandwidth for the specified flow rate and network /// priority cannot be granted. The application can still transmit a data stream but the flow will not receive priority marking. Ideally /// an application would not attempt to stream at the requested rate if there is insufficient bandwidth. If ERROR_NETWORK_BUSY is /// returned the following safe strategy is available: /// /// /// /// /// Query the QoS subsystem with QOSNotifyFlow in order to determine the current available bandwidth and begin to stream at the received /// lower rate with priority if the network supports it. /// /// /// /// /// Request notification with QOSNotifyFlow for when the originally desired amount of bandwidth is available. When notification is /// received call QOSSetFlow with the new bandwidth request and send at the new rate again with prioritization if supported. /// /// /// /// This function may optionally be called asynchronously. /// Examples /// /// The following code snippet demonstrates the use of QOSSetFlow in an application. Input parameters QOSHandle, FlowId, /// FlowId, QOSSetOutgoingRate, and sizeof( QoSOutgoingFlowrate) must be previously initialized by other QoS /// functions and calculations within the application. /// /// Other QoS function examples that show initialization of parameters include QOSCreateHandle, QOSAddSocketToFlow, and QOSQueryFlow. /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qossetflow ExternC BOOL QOSSetFlow( [in] HANDLE QOSHandle, [in] // QOS_FLOWID FlowId, [in] QOS_SET_FLOW Operation, [in] ULONG Size, [in] PVOID Buffer, DWORD Flags, [out, optional] LPOVERLAPPED // Overlapped ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSSetFlow")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSSetFlow([In] HQOS QOSHandle, [In] QOS_FLOWID FlowId, [In] QOS_SET_FLOW Operation, uint Size, [In] IntPtr Buffer, [Optional] uint Flags, [Optional] IntPtr Overlapped); /// /// The QOSSetFlow function is called by an application to request the QOS subsystem to prioritize the application's packets and /// change the flow traffic. This function is also used to notify the QoS subsystem of a flow change: for example, if the flow rate is /// changed in order to account for network congestion, or if the QoS priority value requires adjustment for transferring or streaming /// different types of content over a single persistent socket connection. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// A flow identifier. A QOS_FLOWID is an unsigned 32-bit integer. /// /// /// A QOS_SET_FLOW enumerated type that identifies what will be changed in the flow. This parameter specifies what structure the /// Buffer will contain. /// /// /// /// Value /// Meaning /// /// /// QOSSetTrafficType 0 /// The traffic type of the flow will be changed. The Buffer will contain a pointer to a QOS_TRAFFIC_TYPE constant. /// /// /// QOSSetOutgoingRate 1 /// The flow rate will be changed. The Buffer will contain a pointer to a QOS_FLOWRATE_OUTGOING structure. /// /// /// QOSSetOutgoingDSCPValue 2 /// /// Windows 7, Windows Server 2008 R2, and later: The outgoing DSCP value will be changed. The Buffer will contain a pointer to a /// DWORD value that defines the arbitrary DSCP value. /// /// /// /// /// The structure specified by the value of the Operation parameter. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_ACCESS_DISABLED_BY_POLICY /// /// The QoS subsystem is currently configured by policy to not allow this operation on the network path between this host and the /// destination host. For example, the default policy prevents qWAVE experiments from running to off-link destinations. /// /// /// /// ERROR_IO_PENDING /// The update flow request was successfully received. Results will be returned during overlapped completion. /// /// /// ERROR_ACCESS_DENIED /// The calling application does not have sufficient privileges for the requested operation. /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The FlowId parameter is invalid. /// /// /// ERROR_NETWORK_BUSY /// The requested flow properties were not available on this path. /// /// /// ERROR_NOT_FOUND /// The FlowId parameter specified cannot be found. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// A memory allocation failed. /// /// /// ERROR_NOT_SUPPORTED /// /// The operation being performed requires information that the QoS subsystem does not have. Obtaining this information on this network /// is currently not supported. For example, bandwidth estimations cannot be obtained on a network path where the destination host is off-link. /// /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// ERROR_RETRY /// /// There is currently insufficient data about networking conditions to answer the query. This is typically a transient state where qWAVE /// has erred on the side of caution as it awaits more data before ascertaining the state of the network. /// /// /// /// ERROR_UNEXP_NET_ERR /// The network connection with the remote host failed. /// /// /// /// /// /// If QOSStartTrackingClient has not already been called, calling QOSSetFlow will cause the QOS subsystem to perform the following. /// /// /// /// Discover whether the end-to-end network path supports prioritization. /// /// /// /// Track end-to-end network characteristics by way of network experiments. These experiments do not place any noteworthy stress on the network. /// /// /// /// /// If QOSSetFlow returns ERROR_NETWORK_BUSY there is insufficient bandwidth for the specified flow rate and network /// priority cannot be granted. The application can still transmit a data stream but the flow will not receive priority marking. Ideally /// an application would not attempt to stream at the requested rate if there is insufficient bandwidth. If ERROR_NETWORK_BUSY is /// returned the following safe strategy is available: /// /// /// /// /// Query the QoS subsystem with QOSNotifyFlow in order to determine the current available bandwidth and begin to stream at the received /// lower rate with priority if the network supports it. /// /// /// /// /// Request notification with QOSNotifyFlow for when the originally desired amount of bandwidth is available. When notification is /// received call QOSSetFlow with the new bandwidth request and send at the new rate again with prioritization if supported. /// /// /// /// This function may optionally be called asynchronously. /// Examples /// /// The following code snippet demonstrates the use of QOSSetFlow in an application. Input parameters QOSHandle, FlowId, /// FlowId, QOSSetOutgoingRate, and sizeof( QoSOutgoingFlowrate) must be previously initialized by other QoS /// functions and calculations within the application. /// /// Other QoS function examples that show initialization of parameters include QOSCreateHandle, QOSAddSocketToFlow, and QOSQueryFlow. /// See the Windows SDK for a complete sample code listing. SDK folder: Samples\NetDs\GQos\Qos2 /// [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSSetFlow")] public static bool QOSSetFlow([In] HQOS QOSHandle, [In] uint FlowId, [In] QOS_SET_FLOW Operation, T value) where T : unmanaged { unsafe { uint sz = (uint)sizeof(T); return QOSSetFlow(QOSHandle, FlowId, Operation, sz, (IntPtr)(void*)&value, 0, default); } } /// /// The QOSStartTrackingClient function notifies the QOS subsystem of the existence of a new client. Calling this function /// increases the likelihood that the QOS subsystem will have gathered sufficient information on the network path to assist when calling /// QOSSetFlow to set the flow. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// A pointer to a sockaddr structure that contains the IP address of the client device. Clients are identified by their IP address and /// address family. Any port number specified in the sockaddr structure will be ignored. /// /// Reserved for future use. Must be set to 0. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The DestAddr parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDED /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_NOT_SUPPORTED /// The request is not supported. /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// ERROR_HOST_UNREACHABLE /// The network location cannot be reached. /// /// /// /// /// /// On receipt of a QOSStartTrackingClient call the QoS subsystem begins gathering information about the client such as the QoS /// capabilities and available bandwidth on the end-to-end path. /// /// /// An application should call this function as soon as it becomes aware of a client device that may need QoS flow. For example this /// function should be called when a media player device first connects to a media server application. /// /// /// Network experiments performed by QOSStartTrackingClient do not introduce noteworthy load on the network even if no stream is /// started for a long period of time. The qWAVE service dynamically adjusts experiment traffic based on QoS subsystem activity. /// /// Link Layer Topology Discovery (LLTD) must be implemented on the sink PC or device for this function to work. /// Examples /// /// The following code illustrates function use, handling a common exception, and required parameter initializations. Actual parameter /// values can vary depending on QoS version. The Winsock2.h header file must be included to use Winsock defined identifiers or functions. /// /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosstarttrackingclient ExternC BOOL QOSStartTrackingClient( [in] // HANDLE QOSHandle, [in] PSOCKADDR DestAddr, DWORD Flags ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSStartTrackingClient")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSStartTrackingClient([In] HQOS QOSHandle, [In] SOCKADDR DestAddr, [Optional] uint Flags); /// /// The QOSStopTrackingClient function notifies the QoS subsystem to stop tracking a client that has previously used the /// QOSStartTrackingClient function. If a flow is currently in progress, this function will not affect it. /// /// Handle to the QOS subsystem returned by QOSCreateHandle. /// /// Pointer to a sockaddr structure that contains the IP address of the client device. Clients are identified by their IP address and /// address family. A port number is not required and will be ignored. /// /// Reserved for future use. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is 0. To get extended error information, call GetLastError. Some possible error codes follow. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The QOSHandle parameter is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The DestAddr parameter is invalid. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Indicates that a memory allocation failed. /// /// /// ERROR_NO_SYSTEM_RESOURCES /// There are insufficient resources to carry out the operation. /// /// /// ERROR_IO_DEVICE /// The request could not be performed because of an I/O device error. /// /// /// ERROR_DEVICE_REINITIALIZATION_NEEDER /// /// The indicated device requires reinitialization due to hardware errors. The application should clean up and call QOSCreateHandle again. /// /// /// /// ERROR_ADAP_HDW_ERR /// A network adapter hardware error occurred. /// /// /// /// /// The Winsock2.h header file must be included to use Winsock defined identifiers or functions. /// Examples /// The following code shows this function called in an application setting. See QOSStartTrackingClient for parameter information. /// // https://learn.microsoft.com/en-us/windows/win32/api/qos2/nf-qos2-qosstoptrackingclient ExternC BOOL QOSStopTrackingClient( [in] HANDLE // QOSHandle, [in] PSOCKADDR DestAddr, DWORD Flags ); [PInvokeData("qos2.h", MSDNShortId = "NF:qos2.QOSStopTrackingClient")] [DllImport(Lib_Qwave, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool QOSStopTrackingClient([In] HQOS QOSHandle, [In] SOCKADDR DestAddr, [Optional] uint Flags); private static int QOS_HEADER_OVERHEAD(ADDRESS_FAMILY af, IPPROTO protocol) => (af == ADDRESS_FAMILY.AF_INET ? 20 : 40) + (protocol == IPPROTO.IPPROTO_TCP ? 20 : 8); /// Provides a handle to a QOS session. [PInvokeData("qos2.h")] [StructLayout(LayoutKind.Sequential)] public struct HQOS : IHandle { private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HQOS(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HQOS NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Implements the operator !. /// The handle. /// The result of the operator. public static bool operator !(HQOS h1) => h1.IsNull; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HQOS h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HQOS(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HQOS h1, HQOS h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HQOS h1, HQOS h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HQOS h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// The QOS_FLOW_FUNDAMENTALS structure contains basic information about a flow. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flow_fundamentals typedef struct _QOS_FLOW_FUNDAMENTALS { BOOL // BottleneckBandwidthSet; UINT64 BottleneckBandwidth; BOOL AvailableBandwidthSet; UINT64 AvailableBandwidth; BOOL RTTSet; UINT32 RTT; } // QOS_FLOW_FUNDAMENTALS, *PQOS_FLOW_FUNDAMENTALS; [PInvokeData("qos2.h", MSDNShortId = "NS:qos2._QOS_FLOW_FUNDAMENTALS")] [StructLayout(LayoutKind.Sequential)] public struct QOS_FLOW_FUNDAMENTALS { /// This Boolean value is set to TRUE if the BottleneckBandwidth field contains a value. [MarshalAs(UnmanagedType.Bool)] public bool BottleneckBandwidthSet; /// Indicates the maximum end-to-end link capacity between the source and sink device, in bits. public ulong BottleneckBandwidth; /// Set to TRUE if the AvailableBandwidth field contains a value. [MarshalAs(UnmanagedType.Bool)] public bool AvailableBandwidthSet; /// /// Indicates how much bandwidth is available for submitting traffic on the end-to-end network path between the source and sink /// device, in bits. /// public ulong AvailableBandwidth; /// Set to TRUE if the RTT field contains a value. [MarshalAs(UnmanagedType.Bool)] public bool RTTSet; /// Measures the round-trip time between the source and sink device, in microseconds. public uint RTT; } /// The QOS_FLOWRATE_OUTGOING structure is used to set flow rate information in the QOSSetFlow function. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing typedef struct _QOS_FLOWRATE_OUTGOING { UINT64 // Bandwidth; QOS_SHAPING ShapingBehavior; QOS_FLOWRATE_REASON Reason; } QOS_FLOWRATE_OUTGOING, *PQOS_FLOWRATE_OUTGOING; [PInvokeData("qos2.h", MSDNShortId = "NS:qos2._QOS_FLOWRATE_OUTGOING")] [StructLayout(LayoutKind.Sequential)] public struct QOS_FLOWRATE_OUTGOING { /// /// The rate at which data should be sent, in units of bits per second. /// /// Note Traffic on the network is measured at the IP level, and not at the application level. The rate that is specified /// should account for the IP and protocol headers. /// /// public ulong Bandwidth; /// A QOS_SHAPING constant that defines the shaping behavior of the flow. public QOS_SHAPING ShapingBehavior; /// A QOS_FLOWRATE_REASON constant that indicates the reason for a flow rate change. public QOS_FLOWRATE_REASON Reason; } /// The QOS_PACKET_PRIORITY structure that indicates the priority of the flow traffic. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_packet_priority typedef struct _QOS_PACKET_PRIORITY { ULONG // ConformantDSCPValue; ULONG NonConformantDSCPValue; ULONG ConformantL2Value; ULONG NonConformantL2Value; } QOS_PACKET_PRIORITY, *PQOS_PACKET_PRIORITY; [PInvokeData("qos2.h", MSDNShortId = "NS:qos2._QOS_PACKET_PRIORITY")] [StructLayout(LayoutKind.Sequential)] public struct QOS_PACKET_PRIORITY { /// Differential Services Code Point (DSCP) mark used for flow traffic that conforms to the specified flow rate. public uint ConformantDSCPValue; /// /// DSCP marking used for flow traffic that exceeds the specified flow rate. Non-conformant DSCP values are only applicable only if /// QOS_SHAPING has a value of QOSUseNonConformantMarkings. /// public uint NonConformantDSCPValue; /// /// Layer-2 (L2) tag used for flow traffic that conforms to the specified flow rate. L2 tags will not be added to packets if the /// end-to-end path between source and sink does not support them. /// public uint ConformantL2Value; /// /// L2 tag used for flow traffic that exceeds the specified flow rate. Non-conformant L2 values are only applicable if QOS_SHAPING /// has a value of QOSUseNonConformantMarkings. /// public uint NonConformantL2Value; } /// The QOS_VERSION structure indicates the version of the QOS protocol. // https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_version typedef struct _QOS_VERSION { USHORT MajorVersion; USHORT // MinorVersion; } QOS_VERSION, *PQOS_VERSION; [PInvokeData("qos2.h", MSDNShortId = "NS:qos2._QOS_VERSION")] [StructLayout(LayoutKind.Sequential)] public struct QOS_VERSION { /// Major version of the QOS protocol. public ushort MajorVersion; /// Minor version of the QOS protocol. public ushort MinorVersion; } /// Provides a for that is disposed using . public class SafeHQOS : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHQOS(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHQOS() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HQOS(SafeHQOS h) => h.handle; /// protected override bool InternalReleaseHandle() => QOSCloseHandle(handle); } }