using System;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
///
public const uint UMS_VERSION = 0x0100;
/// Flags used by UMS_SYSTEM_THREAD_INFORMATION.
[PInvokeData("winbase.h", MSDNShortId = "eecdc592-5046-47c3-a4c6-ecb10899db3c")]
public enum ThreadUmsFlags : uint
{
///
///
/// A bitfield that specifies a UMS scheduler thread. If IsUmsSchedulerThread is set, IsUmsWorkerThread must be clear.
///
///
IsUmsSchedulerThread = 0x1,
///
///
/// A bitfield that specifies a UMS worker thread. If IsUmsWorkerThread is set, IsUmsSchedulerThread must be clear.
///
///
IsUmsWorkerThread = 0x2,
}
///
/// Creates a user-mode scheduling (UMS) completion list.
///
///
/// A PUMS_COMPLETION_LIST variable. On output, this parameter receives a pointer to an empty UMS completion list.
///
///
/// If the function succeeds, it returns a nonzero value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory is available to create the completion list.
///
///
///
///
///
/// A completion list is associated with a UMS scheduler thread when the EnterUmsSchedulingMode function is called to create the
/// scheduler thread. The system queues newly created UMS worker threads to the completion list. It also queues previously blocked
/// UMS worker threads to the completion list when the threads are no longer blocked.
///
///
/// When an application's UmsSchedulerProc entry point function is called, the application's scheduler should retrieve items from the
/// completion list by calling DequeueUmsCompletionListItems.
///
///
/// Each completion list has an associated completion list event which is signaled whenever the system queues items to an empty list.
/// Use the GetUmsCompletionListEvent to obtain a handle to the event for a specified completion list.
///
///
/// When a completion list is no longer needed, use the DeleteUmsCompletionList to release the list. The list must be empty before it
/// can be released.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createumscompletionlist BOOL CreateUmsCompletionList(
// PUMS_COMPLETION_LIST *UmsCompletionList );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "6e77b793-a82e-4e23-8c8b-7aff79d69346")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateUmsCompletionList(out SafePUMS_COMPLETION_LIST UmsCompletionList);
///
/// Creates a user-mode scheduling (UMS) thread context to represent a UMS worker thread.
///
///
/// A PUMS_CONTEXT variable. On output, this parameter receives a pointer to a UMS thread context.
///
///
/// If the function succeeds, it returns a nonzero value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_NOT_ENOUGH_MEMORY
/// Not enough memory is available to create the UMS thread context.
///
///
///
///
///
/// A UMS thread context represents the state of a UMS worker thread. Thread contexts are used to specify UMS worker threads in
/// function calls.
///
///
/// A UMS worker thread is created by calling the CreateRemoteThreadEx function after using InitializeProcThreadAttributeList and
/// UpdateProcThreadAttribute to prepare a list of UMS attributes for the thread.
///
///
/// The underlying structures for a UMS thread context are managed by the system and should not be modified directly. To get and set
/// information about a UMS worker thread, use the QueryUmsThreadInformation and SetUmsThreadInformation functions.
///
/// After a UMS worker thread terminates, its thread context should be released by calling DeleteUmsThreadContext.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createumsthreadcontext BOOL CreateUmsThreadContext(
// PUMS_CONTEXT *lpUmsThread );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "b27ce81a-8463-46af-8acf-2de091f625df")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateUmsThreadContext(out SafePUMS_CONTEXT lpUmsThread);
///
/// Deletes the specified user-mode scheduling (UMS) completion list. The list must be empty.
///
///
/// A pointer to the UMS completion list to be deleted. The CreateUmsCompletionList function provides this pointer.
///
///
/// If the function succeeds, it returns a nonzero value.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// If the completion list is shared, the caller is responsible for ensuring that no active UMS thread holds a reference to the list
/// before deleting it.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deleteumscompletionlist BOOL DeleteUmsCompletionList(
// PUMS_COMPLETION_LIST UmsCompletionList );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "98124359-ddd1-468c-9f99-74dd3f631fa1")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteUmsCompletionList(PUMS_COMPLETION_LIST UmsCompletionList);
///
/// Deletes the specified user-mode scheduling (UMS) thread context. The thread must be terminated.
///
///
/// A pointer to the UMS thread context to be deleted. The CreateUmsThreadContext function provides this pointer.
///
///
/// If the function succeeds, it returns a nonzero value.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
/// A UMS thread context cannot be deleted until the associated thread has terminated.
///
/// When a UMS worker thread finishes running (for example, by returning from its thread entry point function), the system terminates
/// the thread, sets the termination status in the thread's UMS thread context, and queues the UMS thread context to the associated
/// completion list.
///
/// Any attempt to execute the UMS thread will fail because the thread is already terminated.
///
/// To check the termination status of a thread, the application's scheduler should call QueryUmsThreadInformation with the
/// UmsIsThreadTerminated information class.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deleteumsthreadcontext BOOL DeleteUmsThreadContext(
// PUMS_CONTEXT UmsThread );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "cdd118fc-f664-44ce-958d-857216ceb9a7")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteUmsThreadContext(PUMS_CONTEXT UmsThread);
///
/// Retrieves user-mode scheduling (UMS) worker threads from the specified UMS completion list.
///
///
/// A pointer to the completion list from which to retrieve worker threads.
///
///
///
/// The time-out interval for the retrieval operation, in milliseconds. The function returns if the interval elapses, even if no
/// worker threads are queued to the completion list.
///
///
/// If the WaitTimeOut parameter is zero, the completion list is checked for available worker threads without waiting for worker
/// threads to become available. If the WaitTimeOut parameter is INFINITE, the function's time-out interval never elapses. This is
/// not recommended, however, because it causes the function to block until one or more worker threads become available.
///
///
///
///
/// A pointer to a UMS_CONTEXT variable. On output, this parameter receives a pointer to the first UMS thread context in a list of
/// UMS thread contexts.
///
///
/// If no worker threads are available before the time-out specified by the WaitTimeOut parameter, this parameter is set to NULL.
///
///
///
/// If the function succeeds, it returns a nonzero value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_TIMEOUT
/// No threads became available before the specified time-out interval elapsed.
///
///
///
///
///
/// The system queues a UMS worker thread to a completion list when the worker thread is created or when a previously blocked worker
/// thread becomes unblocked. The DequeueUmsCompletionListItems function retrieves a pointer to a list of all thread contexts
/// in the specified completion list. The GetNextUmsListItem function can be used to pop UMS thread contexts off the list into the
/// scheduler's own ready thread queue. The scheduler is responsible for selecting threads to run based on priorities chosen by the application.
///
///
/// Do not run UMS threads directly from the list provided by DequeueUmsCompletionListItems, or run a thread transferred from
/// the list to the ready thread queue before the list is completely empty. This can cause unpredictable behavior in the application.
///
///
/// If more than one caller attempts to retrieve threads from a shared completion list, only the first caller retrieves the threads.
/// For subsequent callers, the DequeueUmsCompletionListItems function returns success but the UmsThreadList parameter is set
/// to NULL.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-dequeueumscompletionlistitems BOOL
// DequeueUmsCompletionListItems( PUMS_COMPLETION_LIST UmsCompletionList, DWORD WaitTimeOut, PUMS_CONTEXT *UmsThreadList );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "91499eb9-9fc5-4135-95f6-1bced78f1e07")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DequeueUmsCompletionListItems(PUMS_COMPLETION_LIST UmsCompletionList, uint WaitTimeOut, out PUMS_CONTEXT UmsThreadList);
///
/// Converts the calling thread into a user-mode scheduling (UMS) scheduler thread.
///
///
///
/// A pointer to a UMS_SCHEDULER_STARTUP_INFO structure that specifies UMS attributes for the thread, including a completion list and
/// a UmsSchedulerProc entry point function.
///
///
///
/// If the function succeeds, it returns a nonzero value.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// An application's UMS scheduler creates one UMS scheduler thread for each processor that will be used to run UMS threads. The
/// scheduler typically sets the affinity of the scheduler thread for a single processor, effectively reserving the processor for the
/// use of that scheduler thread. For more information about thread affinity, see Multiple Processors.
///
///
/// When a UMS scheduler thread is created, the system calls the UmsSchedulerProc entry point function specified with the
/// EnterUmsSchedulingMode function call. The application's scheduler is responsible for finishing any application-specific
/// initialization of the scheduler thread and selecting a UMS worker thread to run.
///
///
/// The application's scheduler selects a UMS worker thread to run by calling ExecuteUmsThread with the worker thread's UMS thread
/// context. The worker thread runs until it yields control by calling UmsThreadYield, blocks, or terminates. The scheduler thread is
/// then available to run another worker thread.
///
///
/// A scheduler thread should continue to run until all of its worker threads reach a natural stopping point: that is, all worker
/// threads have yielded, blocked, or terminated.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-enterumsschedulingmode BOOL EnterUmsSchedulingMode(
// PUMS_SCHEDULER_STARTUP_INFO SchedulerStartupInfo );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "792bd7fa-0ae9-4c38-a664-5fb3e3d0c52b")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnterUmsSchedulingMode(in UMS_SCHEDULER_STARTUP_INFO SchedulerStartupInfo);
///
/// Runs the specified UMS worker thread.
///
///
/// A pointer to the UMS thread context of the worker thread to run.
///
///
/// If the function succeeds, it does not return a value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error codes
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_RETRY
/// The specified UMS worker thread is temporarily locked by the system. The caller can retry the operation.
///
///
///
///
///
/// The ExecuteUmsThread function loads the state of the specified UMS worker thread over the state of the calling UMS
/// scheduler thread so that the worker thread can run. The worker thread runs until it yields by calling the UmsThreadYield
/// function, blocks, or terminates.
///
///
/// When a worker thread yields or blocks, the system calls the scheduler thread's UmsSchedulerProc entry point function. When a
/// previously blocked worker thread becomes unblocked, the system queues the worker thread to the completion list specified with the
/// UpdateProcThreadAttribute function when the worker thread was created.
///
///
/// The ExecuteUmsThread function does not return unless an error occurs. If the function returns ERROR_RETRY, the error is
/// transitory and the operation can be retried.
///
///
/// If the function returns an error other than ERROR_RETRY, the application's scheduler should check whether the thread is suspended
/// or terminated by calling QueryUmsThreadInformation with UmsThreadIsSuspended or UmsThreadIsTerminated,
/// respectively. Other possible errors include calling the function on a thread that is not a UMS scheduler thread, passing an
/// invalid UMS worker thread context, or specifying a worker thread that is already executing on another scheduler thread.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-executeumsthread BOOL ExecuteUmsThread( PUMS_CONTEXT
// UmsThread );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "e4265351-e8e9-4878-bd42-93258b4cd1a0")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ExecuteUmsThread(PUMS_CONTEXT UmsThread);
///
/// Returns the user-mode scheduling (UMS) thread context of the calling UMS thread.
///
///
/// The function returns a pointer to the UMS thread context of the calling thread.
/// If calling thread is not a UMS thread, the function returns NULL. To get extended error information, call GetLastError.
///
///
/// The GetCurrentUmsThread function can be called for a UMS scheduler thread or UMS worker thread.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcurrentumsthread PUMS_CONTEXT GetCurrentUmsThread( );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "f2e20816-919a-443d-96d3-94e98afc28f2")]
public static extern PUMS_CONTEXT GetCurrentUmsThread();
/// Returns the next user-mode scheduling (UMS) thread context in a list of thread contexts.
///
/// A pointer to a UMS context in a list of thread contexts. This list is retrieved by the DequeueUmsCompletionListItems function.
///
///
/// If the function succeeds, it returns a pointer to the next thread context in the list.
///
/// If there is no thread context after the context specified by the UmsContext parameter, the function returns NULL. To get extended
/// error information, call GetLastError.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getnextumslistitem PUMS_CONTEXT GetNextUmsListItem(
// PUMS_CONTEXT UmsContext );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "fb2c8420-12f4-4bd7-ac00-b53bab760db0")]
public static extern PUMS_CONTEXT GetNextUmsListItem(PUMS_CONTEXT UmsContext);
///
/// Retrieves a handle to the event associated with the specified user-mode scheduling (UMS) completion list.
///
///
/// A pointer to a UMS completion list. The CreateUmsCompletionList function provides this pointer.
///
///
///
/// A pointer to a HANDLE variable. On output, the UmsCompletionEvent parameter is set to a handle to the event associated with the
/// specified completion list.
///
///
///
/// If the function succeeds, it returns a nonzero value.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// The system signals a UMS completion list event when the system queues items to an empty completion list. A completion list event
/// handle can be used with any wait function that takes a handle to an event. When the event is signaled, an application typically
/// calls DequeueUmsCompletionListItems to retrieve the contents of the completion list.
///
///
/// The event handle remains valid until its completion list is deleted. Do not use the event handle to wait on a completion list
/// that has been deleted or is in the process of being deleted.
///
/// When the handle is no longer needed, use the CloseHandle function to close the handle.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getumscompletionlistevent BOOL GetUmsCompletionListEvent(
// PUMS_COMPLETION_LIST UmsCompletionList, PHANDLE UmsCompletionEvent );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "393f6e0a-fbea-4aa0-9c18-f96da18e61e9")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetUmsCompletionListEvent(PUMS_COMPLETION_LIST UmsCompletionList, out SafeEventHandle UmsCompletionEvent);
///
/// Queries whether the specified thread is a UMS scheduler thread, a UMS worker thread, or a non-UMS thread.
///
///
///
/// A handle to a thread. The thread handle must have the THREAD_QUERY_INFORMATION access right. For more information, see Thread
/// Security and Access Rights.
///
///
///
/// A pointer to an initialized UMS_SYSTEM_THREAD_INFORMATION structure that specifies the kind of thread for the query.
///
///
///
/// Returns TRUE if the specified thread matches the kind of thread specified by the SystemThreadInfo parameter. Otherwise, the
/// function returns FALSE.
///
///
///
///
/// The GetUmsSystemThreadInformation function is intended for use in debuggers, troubleshooting tools, and profiling
/// applications. For example, thread-isolated tracing or single-stepping through instructions might involve suspending all other
/// threads in the process. However, if the thread to be traced is a UMS worker thread, suspending UMS scheduler threads might cause
/// a deadlock because a UMS worker thread requires the intervention of a UMS scheduler thread in order to run. A debugger can call
/// GetUmsSystemThreadInformation for each thread that it might suspend to determine the kind of thread, and then suspend it
/// or not as needed for the code being debugged.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getumssystemthreadinformation BOOL
// GetUmsSystemThreadInformation( HANDLE ThreadHandle, PUMS_SYSTEM_THREAD_INFORMATION SystemThreadInfo );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "7c8347b6-6546-4ea9-9b2a-11794782f482")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetUmsSystemThreadInformation(HTHREAD ThreadHandle, ref UMS_SYSTEM_THREAD_INFORMATION SystemThreadInfo);
/// Retrieves information about the specified user-mode scheduling (UMS) worker thread.
/// A pointer to a UMS thread context.
/// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to retrieve.
///
///
/// A pointer to a buffer to receive the specified information. The required size of this buffer depends on the specified information class.
///
/// If the information class is UmsThreadContext or UmsThreadTeb, the buffer must be .
/// If the information class is UmsThreadIsSuspended or UmsThreadIsTerminated, the buffer must be .
///
/// The size of the UmsThreadInformation buffer, in bytes.
///
/// A pointer to a ULONG variable. On output, this parameter receives the number of bytes written to the UmsThreadInformation buffer.
///
///
/// If the function succeeds, it returns a nonzero value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_INFO_LENGTH_MISMATCH
/// The buffer is too small for the requested information.
///
/// -
/// ERROR_INVALID_INFO_CLASS
/// The specified information class is not supported.
///
///
///
///
///
/// The QueryUmsThreadInformation function retrieves information about the specified UMS worker thread such as its
/// application-defined context, its thread execution block (TEB), and whether the thread is suspended or terminated.
///
///
/// The underlying structures for UMS worker threads are managed by the system. Information that is not exposed through
/// QueryUmsThreadInformation should be considered reserved.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-queryumsthreadinformation BOOL QueryUmsThreadInformation(
// PUMS_CONTEXT UmsThread, UMS_THREAD_INFO_CLASS UmsThreadInfoClass, PVOID UmsThreadInformation, ULONG UmsThreadInformationLength,
// PULONG ReturnLength );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "5f694edf-ba5e-45a2-a938-5013edddcae2")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool QueryUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass, IntPtr UmsThreadInformation, uint UmsThreadInformationLength, out uint ReturnLength);
/// Retrieves information about the specified user-mode scheduling (UMS) worker thread.
/// The return type being requested.
/// A pointer to a UMS thread context.
/// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to retrieve.
/// The specified information of type .
///
///
/// The QueryUmsThreadInformation function retrieves information about the specified UMS worker thread such as its
/// application-defined context, its thread execution block (TEB), and whether the thread is suspended or terminated.
///
///
/// The underlying structures for UMS worker threads are managed by the system. Information that is not exposed through
/// QueryUmsThreadInformation should be considered reserved.
///
///
public static T QueryUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass) where T : struct
{
if (!CorrespondingTypeAttribute.CanGet(UmsThreadInfoClass, typeof(T))) throw new ArgumentException($"Cannot use {UmsThreadInfoClass} to retrieve a value of {typeof(T).Name}.");
if (!QueryUmsThreadInformation(UmsThread, UmsThreadInfoClass, IntPtr.Zero, 0, out var sz) && sz == 0)
Win32Error.ThrowLastError();
using (var mem = new SafeHGlobalHandle(sz))
{
if (!QueryUmsThreadInformation(UmsThread, UmsThreadInfoClass, mem, mem.Size, out sz))
Win32Error.ThrowLastError();
return typeof(T) == typeof(bool) ? (T)(object)(mem.ToStructure() != 0) : mem.ToStructure();
}
}
/// Sets application-specific context information for the specified user-mode scheduling (UMS) worker thread.
/// A pointer to a UMS thread context.
///
/// A UMS_THREAD_INFO_CLASS value that specifies the kind of information to set. This parameter must be UmsThreadUserContext.
///
/// A pointer to a buffer that contains the information to set.
/// The size of the UmsThreadInformation buffer, in bytes.
///
/// If the function succeeds, it returns a nonzero value.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible error values
/// include the following.
///
///
///
/// Return code
/// Description
///
/// -
/// ERROR_INFO_LENGTH_MISMATCH
/// The buffer size does not match the required size for the specified information class.
///
/// -
/// ERROR_INVALID_INFO_CLASS
/// The UmsThreadInfoClass parameter specifies an information class that is not supported.
///
///
///
///
///
/// The SetUmsThreadInformation function can be used to set an application-defined context for the specified UMS worker
/// thread. The context information can consist of anything the application might find useful to track, such as per-scheduler or
/// per-worker thread state. The underlying structures for UMS worker threads are managed by the system and should not be modified directly.
///
///
/// The QueryUmsThreadInformation function can be used to retrieve other exposed information about the specified thread, such as its
/// thread execution block (TEB) and whether the thread is suspended or terminated. Information that is not exposed through
/// QueryUmsThreadInformation should be considered reserved.
///
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setumsthreadinformation BOOL SetUmsThreadInformation(
// PUMS_CONTEXT UmsThread, UMS_THREAD_INFO_CLASS UmsThreadInfoClass, PVOID UmsThreadInformation, ULONG UmsThreadInformationLength );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "19f190fd-1f78-4bb6-93eb-73a5c522b44d")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetUmsThreadInformation(PUMS_CONTEXT UmsThread, RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass, IntPtr UmsThreadInformation, uint UmsThreadInformationLength);
///
/// Yields control to the user-mode scheduling (UMS) scheduler thread on which the calling UMS worker thread is running.
///
///
/// A parameter to pass to the scheduler thread's UmsSchedulerProc function.
///
///
/// If the function succeeds, it returns a nonzero value.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// A UMS worker thread calls the UmsThreadYield function to cooperatively yield control to the UMS scheduler thread on which
/// the worker thread is running. If a UMS worker thread never calls UmsThreadYield, the worker thread runs until it either
/// blocks or is terminated.
///
///
/// When control switches to the UMS scheduler thread, the system calls the associated scheduler entry point function with the reason
/// UmsSchedulerThreadYield and the ScheduleParam parameter specified by the worker thread in the UmsThreadYield call.
///
/// The application's scheduler is responsible for rescheduling the worker thread.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-umsthreadyield BOOL UmsThreadYield( PVOID SchedulerParam );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "d7c94ed5-9536-4c39-8658-27e4237cc9ba")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UmsThreadYield(IntPtr SchedulerParam);
/// Provides a handle to a completion list.
[StructLayout(LayoutKind.Sequential)]
public struct PUMS_COMPLETION_LIST : IHandle
{
private IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public PUMS_COMPLETION_LIST(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static PUMS_COMPLETION_LIST NULL => new PUMS_COMPLETION_LIST(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(PUMS_COMPLETION_LIST h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator PUMS_COMPLETION_LIST(IntPtr h) => new PUMS_COMPLETION_LIST(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(PUMS_COMPLETION_LIST h1, PUMS_COMPLETION_LIST h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(PUMS_COMPLETION_LIST h1, PUMS_COMPLETION_LIST h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is PUMS_COMPLETION_LIST h ? handle == h.handle : false;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
/// Provides a handle to a UMS context.
[StructLayout(LayoutKind.Sequential)]
public struct PUMS_CONTEXT : IHandle
{
private IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public PUMS_CONTEXT(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static PUMS_CONTEXT NULL => new PUMS_CONTEXT(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Gets a value indicating whether this instance is suspended.
/// true if this instance is suspended; otherwise, false.
public bool IsSuspended => QueryUmsThreadInformation(this, RTL_UMS_THREAD_INFO_CLASS.UmsThreadIsSuspended);
/// Gets a value indicating whether this instance is terminated.
/// true if this instance is terminated; otherwise, false.
public bool IsTerminated => QueryUmsThreadInformation(this, RTL_UMS_THREAD_INFO_CLASS.UmsThreadIsTerminated);
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(PUMS_CONTEXT h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator PUMS_CONTEXT(IntPtr h) => new PUMS_CONTEXT(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(PUMS_CONTEXT h1, PUMS_CONTEXT h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(PUMS_CONTEXT h1, PUMS_CONTEXT h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is PUMS_CONTEXT h ? handle == h.handle : false;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
///
/// Specifies attributes for a user-mode scheduling (UMS) scheduler thread. The EnterUmsSchedulingMode function uses this structure.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_ums_scheduler_startup_info typedef struct
// _UMS_SCHEDULER_STARTUP_INFO { ULONG UmsVersion; PUMS_COMPLETION_LIST CompletionList; PUMS_SCHEDULER_ENTRY_POINT SchedulerProc;
// PVOID SchedulerParam; } UMS_SCHEDULER_STARTUP_INFO, *PUMS_SCHEDULER_STARTUP_INFO;
[PInvokeData("winbase.h", MSDNShortId = "e3f7b1b7-d2b8-432d-bce7-3633292e855b")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct UMS_SCHEDULER_STARTUP_INFO
{
/// The UMS version for which the application was built. This parameter must be UMS_VERSION (0x0100).
public uint UmsVersion;
/// A pointer to a UMS completion list to associate with the calling thread.
public PUMS_COMPLETION_LIST CompletionList;
///
/// A pointer to an application-defined UmsSchedulerProc entry point function. The system calls this function when the calling
/// thread has been converted to UMS and is ready to run UMS worker threads. Subsequently, it calls this function when a UMS
/// worker thread running on the calling thread yields or blocks.
///
public RtlUmsSchedulerEntryPoint SchedulerProc;
/// An application-defined parameter to pass to the specified UmsSchedulerProc function.
public IntPtr SchedulerParam;
/// Initializes a new instance of the struct.
/// A pointer to an application-defined UmsSchedulerProc entry point function.
/// An application-defined parameter to pass to the specified UmsSchedulerProc function.
/// A pointer to a UMS completion list to associate with the calling thread.
public UMS_SCHEDULER_STARTUP_INFO(RtlUmsSchedulerEntryPoint schedulerProc, [Optional] IntPtr param, [Optional] PUMS_COMPLETION_LIST completionList)
{
UmsVersion = UMS_VERSION;
CompletionList = completionList;
SchedulerProc = schedulerProc;
SchedulerParam = param;
}
}
///
/// Specifies a UMS scheduler thread, UMS worker thread, or non-UMS thread. The GetUmsSystemThreadInformation function uses this structure.
///
///
/// If both IsUmsSchedulerThread and IsUmsWorkerThread are clear, the structure specifies a non-UMS thread.
///
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_ums_system_thread_information typedef struct
// _UMS_SYSTEM_THREAD_INFORMATION { ULONG UmsVersion; union { struct { ULONG IsUmsSchedulerThread : 1; ULONG IsUmsWorkerThread : 1; }
// DUMMYSTRUCTNAME; ULONG ThreadUmsFlags; } DUMMYUNIONNAME; } UMS_SYSTEM_THREAD_INFORMATION, *PUMS_SYSTEM_THREAD_INFORMATION;
[PInvokeData("winbase.h", MSDNShortId = "eecdc592-5046-47c3-a4c6-ecb10899db3c")]
[StructLayout(LayoutKind.Sequential)]
public struct UMS_SYSTEM_THREAD_INFORMATION
{
///
/// The UMS version. This member must be UMS_VERSION.
///
public uint UmsVersion;
/// A bitfield that specifies a UMS thread type.
public ThreadUmsFlags ThreadUmsFlags;
/// Gets a default instance of this structure with the fields pre-set to default values.
public static readonly UMS_SYSTEM_THREAD_INFORMATION Default = new UMS_SYSTEM_THREAD_INFORMATION { UmsVersion = UMS_VERSION };
}
///
/// Provides a to a UMS completion list that releases a created UmsCompletionList instance at disposal using DeleteUmsCompletionList.
///
public class SafePUMS_COMPLETION_LIST : 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 SafePUMS_COMPLETION_LIST(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// Initializes a new instance of the class.
private SafePUMS_COMPLETION_LIST() : base() { }
/// Converts to PUMS_COMPLETION_LIST.
/// Safe list.
public static implicit operator PUMS_COMPLETION_LIST(SafePUMS_COMPLETION_LIST l) => l.handle;
///
protected override bool InternalReleaseHandle() => DeleteUmsCompletionList(handle);
}
///
/// Provides a to a UMS thread context that releases a created UmsThreadContext instance at disposal using DeleteUmsThreadContext.
///
public class SafePUMS_CONTEXT : 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 SafePUMS_CONTEXT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// Initializes a new instance of the class.
private SafePUMS_CONTEXT() : base() { }
/// Converts to PUMS_CONTEXT.
/// Safe context.
public static implicit operator PUMS_CONTEXT(SafePUMS_CONTEXT c) => c.handle;
///
protected override bool InternalReleaseHandle() => DeleteUmsThreadContext(handle);
}
}
}