Vanara/PInvoke/Avrt/Avrt.cs

526 lines
30 KiB
C#

namespace Vanara.PInvoke;
/// <summary>Functions from Avrt.dll.</summary>
public static partial class Avrt
{
private const string Lib_Avrt = "Avrt.dll";
/// <summary>The relative thread priority of this thread to other threads performing a similar task.</summary>
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvSetMmThreadPriority")]
public enum AVRT_PRIORITY
{
/// <summary>very low</summary>
AVRT_PRIORITY_VERYLOW = -2,
/// <summary>low</summary>
AVRT_PRIORITY_LOW,
/// <summary>normal</summary>
AVRT_PRIORITY_NORMAL,
/// <summary>high</summary>
AVRT_PRIORITY_HIGH,
/// <summary>critical</summary>
AVRT_PRIORITY_CRITICAL
}
/// <summary>Retrieves the system responsiveness setting used by the multimedia class scheduler service.</summary>
/// <param name="AvrtHandle">
/// A handle to the task. This handle is returned by the AvSetMmThreadCharacteristics or AvSetMmMaxThreadCharacteristics function.
/// </param>
/// <param name="SystemResponsivenessValue">The system responsiveness value. This value can range from 10 to 100 percent.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avquerysystemresponsiveness AVRTAPI BOOL AvQuerySystemResponsiveness(
// [in] HAVRT AvrtHandle, [out] PULONG SystemResponsivenessValue );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvQuerySystemResponsiveness")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvQuerySystemResponsiveness([In] HAVRT AvrtHandle, out uint SystemResponsivenessValue);
/// <summary>Indicates that a thread is no longer performing work associated with the specified task.</summary>
/// <param name="AvrtHandle">
/// A handle to the task. This handle is returned by the AvSetMmThreadCharacteristics or AvSetMmMaxThreadCharacteristics function.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// This function must be called from the same thread that called the AvSetMmThreadCharacteristics or AvSetMmMaxThreadCharacteristics
/// function to create the handle. Otherwise, the function will fail.
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrevertmmthreadcharacteristics AVRTAPI BOOL
// AvRevertMmThreadCharacteristics( [in] HAVRT AvrtHandle );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRevertMmThreadCharacteristics")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRevertMmThreadCharacteristics([In] HAVRT AvrtHandle);
/// <summary>
/// <para>Creates a thread ordering group.</para>
/// <para>
/// To prevent the server thread for the thread ordering group from being starved if higher priority client threads are running, use the
/// AvRtCreateThreadOrderingGroupEx function.
/// </para>
/// </summary>
/// <param name="Context">A pointer to a context handle.</param>
/// <param name="Period">
/// <para>
/// A pointer to a value, in 100-nanosecond increments, that specifies the period for the thread ordering group. Each thread in the
/// thread ordering group runs one time during this period. If all threads complete their execution before a period ends, all threads
/// wait until the remainder of the period elapses before any are executed again.
/// </para>
/// <para>
/// The possible values for this parameter depend on the platform, but this parameter can be as low as 500 microseconds or as high as
/// 0x1FFFFFFFFFFFFFFF. If this parameter is less than 500 microseconds, then it is set to 500 microseconds. If this parameter is greater
/// than the maximum, then it is set to 0x1FFFFFFFFFFFFFFF.
/// </para>
/// </param>
/// <param name="ThreadOrderingGuid">
/// <para>
/// A pointer to the unique identifier for the thread ordering group to be created. If this value is not unique to the thread ordering
/// service, the function fails.
/// </para>
/// <para>If the identifier is GUID_NULL on input, the thread ordering service generates and returns a unique identifier.</para>
/// </param>
/// <param name="Timeout">
/// <para>A pointer to a time-out value. All threads within the group should complete their execution within <c>Period</c> plus <c>Timeout</c>.</para>
/// <para>
/// If a thread fails to complete its processing within the period plus this time-out interval, it is removed from the thread ordering
/// group. If the parent fails to complete its processing within the period plus the time-out interval, the thread ordering group is destroyed.
/// </para>
/// <para>
/// The possible values for this parameter depend on the platform, but can be as low as 500 microseconds or as high as
/// 0x1FFFFFFFFFFFFFFF. If this parameter is less than 500 microseconds, then it is set to 500 microseconds. If this parameter is greater
/// than the maximum, then it is set to 0x1FFFFFFFFFFFFFFF.
/// </para>
/// <para>If this parameter is <c>NULL</c> or 0, the default is five times the value of <c>Period</c>.</para>
/// <para>
/// If this parameter is THREAD_ORDER_GROUP_INFINITE_TIMEOUT, the group is created with an infinite time-out interval. This can be useful
/// for debugging purposes.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// <para>If a thread ordering group with the specified identifier already exists, the function fails and sets the last error to ERROR_ALREADY_EXISTS.</para>
/// </returns>
/// <remarks>
/// <para>
/// The calling thread is considered to be the parent thread. Each thread ordering group has one parent thread. Each parent thread can
/// have zero or more predecessor threads and zero or more successor threads. A client thread can join a thread ordering group and
/// specify whether it is a predecessor or successor using the AvRtJoinThreadOrderingGroup function.
/// </para>
/// <para>
/// The parent thread encloses the code to be executed during each period within a loop that is controlled by the
/// AvRtWaitOnThreadOrderingGroup function.
/// </para>
/// <para>To delete the thread ordering group, call the AvRtDeleteThreadOrderingGroup function.</para>
/// <para>
/// A thread can create more than one thread ordering group and join more than one thread ordering group. However, a thread cannot join
/// the same thread ordering group more than one time.
/// </para>
/// <para>Examples</para>
/// <para>The following snippet creates a thread ordering group.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtcreatethreadorderinggroup AVRTAPI BOOL
// AvRtCreateThreadOrderingGroup( [out] PHANDLE Context, [in] PLARGE_INTEGER Period, [in, out] GUID *ThreadOrderingGuid, [in, optional]
// PLARGE_INTEGER Timeout );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtCreateThreadOrderingGroup")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtCreateThreadOrderingGroup(out HANDLE Context, in long Period, ref Guid ThreadOrderingGuid,
[In, Optional] in long Timeout);
/// <summary>Creates a thread ordering group and associates the server thread with a task.</summary>
/// <param name="Context">A pointer to a context handle.</param>
/// <param name="Period">
/// <para>
/// A pointer to a value, in 100-nanosecond increments, that specifies the period for the thread ordering group. Each thread in the
/// thread ordering group runs one time during this period. If all threads complete their execution before a period ends, all threads
/// wait until the remainder of the period elapses before any are executed again.
/// </para>
/// <para>
/// The possible values for this parameter depend on the platform, but this parameter can be as low as 500 microseconds or as high as
/// 0x1FFFFFFFFFFFFFFF. If this parameter is less than 500 microseconds, then it is set to 500 microseconds. If this parameter is greater
/// than the maximum, then it is set to 0x1FFFFFFFFFFFFFFF.
/// </para>
/// </param>
/// <param name="ThreadOrderingGuid">
/// <para>
/// A pointer to the unique identifier for the thread ordering group to be created. If this value is not unique to the thread ordering
/// service, the function fails.
/// </para>
/// <para>If the identifier is GUID_NULL on input, the thread ordering service generates and returns a unique identifier.</para>
/// </param>
/// <param name="Timeout">
/// <para>A pointer to a time-out value. All threads within the group should complete their execution within <c>Period</c> plus <c>Timeout</c>.</para>
/// <para>
/// If a thread fails to complete its processing within the period plus this time-out interval, it is removed from the thread ordering
/// group. If the parent fails to complete its processing within the period plus the time-out interval, the thread ordering group is destroyed.
/// </para>
/// <para>
/// The possible values for this parameter depend on the platform, but can be as low as 500 microseconds or as high as
/// 0x1FFFFFFFFFFFFFFF. If this parameter is less than 500 microseconds, then it is set to 500 microseconds. If this parameter is greater
/// than the maximum, then it is set to 0x1FFFFFFFFFFFFFFF.
/// </para>
/// <para>If this parameter is <c>NULL</c> or 0, the default is five times the value of <c>Period</c>.</para>
/// <para>
/// If this parameter is THREAD_ORDER_GROUP_INFINITE_TIMEOUT, the group is created with an infinite time-out interval. This can be useful
/// for debugging purposes.
/// </para>
/// </param>
/// <param name="TaskName">The name of the task.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// <para>If a thread ordering group with the specified identifier already exists, the function fails and sets the last error to ERROR_ALREADY_EXISTS.</para>
/// </returns>
/// <remarks>
/// <para>
/// The calling thread is considered to be the parent thread. Each thread ordering group has one parent thread. Each parent thread can
/// have zero or more predecessor threads and zero or more successor threads. A client thread can join a thread ordering group and
/// specify whether it is a predecessor or successor using the AvRtJoinThreadOrderingGroup function.
/// </para>
/// <para>
/// The parent thread encloses the code to be executed during each period within a loop that is controlled by the
/// AvRtWaitOnThreadOrderingGroup function.
/// </para>
/// <para>To delete the thread ordering group, call the AvRtDeleteThreadOrderingGroup function.</para>
/// <para>
/// A thread can create more than one thread ordering group and join more than one thread ordering group. However, a thread cannot join
/// the same thread ordering group more than one time.
/// </para>
/// <para>
/// The parent and client threads of a thread ordering group run at high priorities. However, the server thread that manages the thread
/// ordering group runs at normal priority. Therefore, there can be a delay switching from one client thread to another if there are
/// other high-priority threads running. The <c>TaskName</c> parameter of this function specifies the task to be associated with the
/// server thread.
/// </para>
/// <para>Examples</para>
/// <para>The following snippet creates a thread ordering group.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The avrt.h header defines AvRtCreateThreadOrderingGroupEx as an alias which automatically selects the ANSI or Unicode version of this
/// function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtcreatethreadorderinggroupexa AVRTAPI BOOL
// AvRtCreateThreadOrderingGroupExA( [out] PHANDLE Context, [in] PLARGE_INTEGER Period, [in, out] GUID *ThreadOrderingGuid, [in,
// optional] PLARGE_INTEGER Timeout, [in] LPCSTR TaskName );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtCreateThreadOrderingGroupExA")]
[DllImport(Lib_Avrt, SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtCreateThreadOrderingGroupEx(out HANDLE Context, in long Period, ref Guid ThreadOrderingGuid,
[In, Optional] in long Timeout, [MarshalAs(UnmanagedType.LPTStr)] string TaskName);
/// <summary>
/// Deletes the specified thread ordering group created by the caller. It cleans up resources for the thread ordering group, including
/// the context information, and returns.
/// </summary>
/// <param name="Context">
/// A context handle. This handle is returned by the AvRtCreateThreadOrderingGroup function when creating the group.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// This function can only be called successfully by the parent thread for the thread ordering group. If a thread other than the parent
/// thread calls this function, the function fails with a last error code of ERROR_INVALID_FUNCTION.
/// </para>
/// <para>If the parent thread times out and attempts to call this function, the function fails with a last error code of ERROR_INVALID_PARAMETER.</para>
/// <para>Examples</para>
/// <para>The following code deletes a thread ordering group.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtdeletethreadorderinggroup AVRTAPI BOOL
// AvRtDeleteThreadOrderingGroup( [in] HANDLE Context );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtDeleteThreadOrderingGroup")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtDeleteThreadOrderingGroup([In] HANDLE Context);
/// <summary>Joins client threads to a thread ordering group.</summary>
/// <param name="Context">A pointer to a context handle.</param>
/// <param name="ThreadOrderingGuid">A pointer to the unique identifier for the thread ordering group.</param>
/// <param name="Before">
/// The thread order. If this parameter is <c>TRUE</c>, the thread is a predecessor thread that is scheduled to run before the parent
/// thread. If this parameter is <c>FALSE</c>, the thread is a successor thread that is scheduled to run after the parent thread.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The thread encloses the code to be executed during each period within a loop that is controlled by the AvRtWaitOnThreadOrderingGroup function.
/// </para>
/// <para>
/// A thread can create more than one thread ordering group and join more than one thread ordering group. However, a thread cannot join
/// the same thread ordering group more than one time.
/// </para>
/// <para>The number of threads that can join a group is limited only by available system resources.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtjointhreadorderinggroup AVRTAPI BOOL AvRtJoinThreadOrderingGroup(
// [out] PHANDLE Context, [in] GUID *ThreadOrderingGuid, [in] BOOL Before );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtJoinThreadOrderingGroup")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtJoinThreadOrderingGroup(out HANDLE Context, in Guid ThreadOrderingGuid, [MarshalAs(UnmanagedType.Bool)] bool Before);
/// <summary>Enables client threads to leave a thread ordering group.</summary>
/// <param name="Context">A context handle. This handle is returned by the AvRtJoinThreadOrderingGroup function.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>The parent thread for a thread ordering group should not remove itself from the group.</para>
/// <para>If a thread times out and attempts to call this function, the function fails with a last error code of ERROR_INVALID_PARAMETER.</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtleavethreadorderinggroup AVRTAPI BOOL
// AvRtLeaveThreadOrderingGroup( [in] HANDLE Context );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtLeaveThreadOrderingGroup")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtLeaveThreadOrderingGroup([In] HANDLE Context);
/// <summary>Enables client threads of a thread ordering group to wait until they should execute.</summary>
/// <param name="Context">
/// A context handle. This handle is returned by the AvRtCreateThreadOrderingGroup or AvRtJoinThreadOrderingGroup function.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>When this function returns, the thread should complete its processing for the period and then call the function again.</para>
/// <para>
/// If the thread fails to complete its processing during the time-out interval specified by the parent thread when creating the group,
/// it is deleted from the thread ordering group. Therefore, when the thread finishes its processing loop, the next call to
/// <c>AvRtWaitOnThreadOrderingGroup</c> fails and the last error code is set to ERROR_ACCESS_DENIED.
/// </para>
/// <para>If the thread ordering group is deleted during the wait, this function eventually times out and return ERROR_ACCESS_DENIED.</para>
/// <para>Examples</para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avrtwaitonthreadorderinggroup AVRTAPI BOOL
// AvRtWaitOnThreadOrderingGroup( [in] HANDLE Context );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvRtWaitOnThreadOrderingGroup")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvRtWaitOnThreadOrderingGroup([In] HANDLE Context);
/// <summary>Associates the calling thread with the specified tasks.</summary>
/// <param name="FirstTask">
/// The name of the first task to be performed. This name must match the name of one of the subkeys of the following key
/// <c>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile\Tasks</c>.
/// </param>
/// <param name="SecondTask">
/// The name of the second task to be performed. This name must match the name of one of the subkeys of the following key
/// <c>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile\Tasks</c>.
/// </param>
/// <param name="TaskIndex">
/// The unique task identifier. The first time this function is called, this value must be 0 on input. The index value is returned on
/// output and can be used as input in subsequent calls.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns a handle to the task.</para>
/// <para>If the function fails, it returns 0. To retrieve extended error information, call GetLastError.</para>
/// <para>The following are possible error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>ERROR_INVALID_TASK_INDEX</c></term>
/// <term>Either <c>TaskIndex</c> is not 0 on the first call or is not recognized value (on subsequent calls).</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TASK_NAME</c></term>
/// <term>The specified task does not match any of the tasks stored in the registry.</term>
/// </item>
/// <item>
/// <term><c>ERROR_PRIVILEGE_NOT_HELD</c></term>
/// <term>The caller does not have sufficient privilege.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The resulting characteristics of the thread performing the tasks reflect the task with the highest priority.</para>
/// <para>When the task is completed, call the AvRevertMmThreadCharacteristics function.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The avrt.h header defines AvSetMmMaxThreadCharacteristics as an alias which automatically selects the ANSI or Unicode version of this
/// function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avsetmmmaxthreadcharacteristicsa AVRTAPI HANDLE
// AvSetMmMaxThreadCharacteristicsA( [in] LPCSTR FirstTask, [in] LPCSTR SecondTask, [in, out] LPDWORD TaskIndex );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvSetMmMaxThreadCharacteristicsA")]
[DllImport(Lib_Avrt, SetLastError = true, CharSet = CharSet.Auto)]
public static extern SafeHAVRT AvSetMmMaxThreadCharacteristics([MarshalAs(UnmanagedType.LPTStr)] string FirstTask,
[MarshalAs(UnmanagedType.LPTStr)] string SecondTask, ref uint TaskIndex);
/// <summary>Associates the calling thread with the specified task.</summary>
/// <param name="TaskName">
/// The name of the task to be performed. This name must match the name of one of the subkeys of the following key
/// <c>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile\Tasks</c>.
/// </param>
/// <param name="TaskIndex">
/// The unique task identifier. The first time this function is called, this value must be 0 on input. The index value is returned on
/// output and can be used as input in subsequent calls.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns a handle to the task.</para>
/// <para>If the function fails, it returns 0. To retrieve extended error information, call GetLastError.</para>
/// <para>The following are possible error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term><c>ERROR_INVALID_TASK_INDEX</c></term>
/// <term>Either <c>TaskIndex</c> is not 0 on the first call or is not recognized value (on subsequent calls).</term>
/// </item>
/// <item>
/// <term><c>ERROR_INVALID_TASK_NAME</c></term>
/// <term>The specified task does not match any of the tasks stored in the registry.</term>
/// </item>
/// <item>
/// <term><c>ERROR_PRIVILEGE_NOT_HELD</c></term>
/// <term>The caller does not have sufficient privilege.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>When the task is completed, call the AvRevertMmThreadCharacteristics function.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// The avrt.h header defines AvSetMmThreadCharacteristics as an alias which automatically selects the ANSI or Unicode version of this
/// function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not
/// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for
/// Function Prototypes.
/// </para>
/// </para>
/// </remarks>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avsetmmthreadcharacteristicsa AVRTAPI HANDLE
// AvSetMmThreadCharacteristicsA( [in] LPCSTR TaskName, [in, out] LPDWORD TaskIndex );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvSetMmThreadCharacteristicsA")]
[DllImport(Lib_Avrt, SetLastError = true, CharSet = CharSet.Auto)]
public static extern SafeHAVRT AvSetMmThreadCharacteristics([MarshalAs(UnmanagedType.LPTStr)] string TaskName, ref uint TaskIndex);
/// <summary>Adjusts the thread priority of the calling thread relative to other threads performing the same task.</summary>
/// <param name="AvrtHandle">
/// A handle to the task. This handle is returned by the AvSetMmThreadCharacteristics or AvSetMmMaxThreadCharacteristics function.
/// </param>
/// <param name="Priority">
/// <para>
/// The relative thread priority of this thread to other threads performing a similar task. This parameter can be one of the following values.
/// </para>
/// <para>AVRT_PRIORITY_CRITICAL (2)</para>
/// <para>AVRT_PRIORITY_HIGH (1)</para>
/// <para>AVRT_PRIORITY_LOW (-1)</para>
/// <para>AVRT_PRIORITY_NORMAL (0)</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
// https://learn.microsoft.com/en-us/windows/win32/api/avrt/nf-avrt-avsetmmthreadpriority AVRTAPI BOOL AvSetMmThreadPriority( [in] HANDLE
// AvrtHandle, [in] AVRT_PRIORITY Priority );
[PInvokeData("avrt.h", MSDNShortId = "NF:avrt.AvSetMmThreadPriority")]
[DllImport(Lib_Avrt, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AvSetMmThreadPriority([In] HAVRT AvrtHandle, [In] AVRT_PRIORITY Priority);
/// <summary>Provides a handle to an AvRt task.</summary>
[StructLayout(LayoutKind.Sequential)]
public readonly struct HAVRT : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="HAVRT"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public HAVRT(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="HAVRT"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static HAVRT NULL => new(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Implements the operator !.</summary>
/// <param name="h1">The handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !(HAVRT h1) => h1.IsNull;
/// <summary>Performs an explicit conversion from <see cref="HAVRT"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(HAVRT h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HAVRT"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HAVRT(IntPtr h) => new(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(HAVRT h1, HAVRT h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(HAVRT h1, HAVRT h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object? obj) => obj is HAVRT h && handle == h.handle;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HAVRT"/> that is disposed using <see cref="AvRevertMmThreadCharacteristics"/>.</summary>
public class SafeHAVRT : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeHAVRT"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHAVRT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeHAVRT"/> class.</summary>
private SafeHAVRT() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeHAVRT"/> to <see cref="HAVRT"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HAVRT(SafeHAVRT h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => AvRevertMmThreadCharacteristics((HAVRT)handle);
}
}