using System; using System.Runtime.InteropServices; using ProcessHacker.Native.Api; using ProcessHacker.Native.Security; namespace ProcessHacker.Native.Objects { public sealed class TimerHandle : NativeHandle { /// /// Creates a timer. /// /// The desired access to the timer. /// /// The type of timer; synchronization timers will be reset once waiting threads are released. /// /// A handle to the timer. public static TimerHandle Create(TimerAccess access, TimerType type) { return Create(access, null, type); } /// /// Creates a timer. /// /// The desired access to the timer. /// A name for the timer in the object manager namespace. /// /// The type of timer; synchronization timers will be reset once waiting threads are released. /// /// A handle to the timer. public static TimerHandle Create(TimerAccess access, string name, TimerType type) { return Create(access, name, 0, null, type); } /// /// Creates a timer. /// /// The desired access to the timer. /// A name for the timer in the object manager namespace. /// The flags to use when creating the object. /// The directory in which to place the timer. This can be null. /// /// The type of timer; synchronization timers will be reset once waiting threads are released. /// /// A handle to the timer. public static TimerHandle Create(TimerAccess access, string name, ObjectFlags objectFlags, DirectoryHandle rootDirectory, TimerType type) { NtStatus status; ObjectAttributes oa = new ObjectAttributes(name, objectFlags, rootDirectory); IntPtr handle; try { if ((status = Win32.NtCreateTimer(out handle, access, ref oa, type)) >= NtStatus.Error) Win32.Throw(status); } finally { oa.Dispose(); } return new TimerHandle(handle, true); } public static TimerHandle FromHandle(IntPtr handle) { return new TimerHandle(handle, false); } private TimerApcRoutine _routine; private TimerHandle(IntPtr handle, bool owned) : base(handle, owned) { } public TimerHandle(string name, ObjectFlags objectFlags, DirectoryHandle rootDirectory, TimerAccess access) { NtStatus status; ObjectAttributes oa = new ObjectAttributes(name, objectFlags, rootDirectory); IntPtr handle; try { if ((status = Win32.NtOpenTimer(out handle, access, ref oa)) >= NtStatus.Error) Win32.Throw(status); } finally { oa.Dispose(); } this.Handle = handle; } public TimerHandle(string name, TimerAccess access) : this(name, 0, null, access) { } /// /// Cancels the timer, preventing it from being signaled. /// /// The state of the timer (whether it is signaled). public bool Cancel() { NtStatus status; bool currentState; if ((status = Win32.NtCancelTimer(this, out currentState)) >= NtStatus.Error) Win32.Throw(status); return currentState; } /// /// Gets information about the timer. /// public TimerBasicInformation GetBasicInformation() { NtStatus status; TimerBasicInformation tbi; int retLength; if ((status = Win32.NtQueryTimer(this, TimerInformationClass.TimerBasicInformation, out tbi, Marshal.SizeOf(typeof(TimerBasicInformation)), out retLength)) >= NtStatus.Error) Win32.Throw(status); return tbi; } /// /// Sets the timer. /// /// The time at which the timer is to be signaled. /// /// The time interval for periodic signaling of the timer, in milliseconds. /// Specify 0 for no periodic signaling. /// /// The state of the timer (whether it is signaled). public bool Set(DateTime dueTime, int period) { return this.Set(dueTime.ToFileTime(), false, null, IntPtr.Zero, period); } /// /// Sets the timer. /// /// A relative due time, in 100ns units. /// /// The time interval for periodic signaling of the timer, in milliseconds. /// Specify 0 for no periodic signaling. /// /// The state of the timer (whether it is signaled). public bool Set(long dueTime, int period) { return this.Set(dueTime, null, period); } /// /// Sets the timer. /// /// A relative due time, in 100ns units. /// A routine to call when the timer is signaled. /// /// The time interval for periodic signaling of the timer, in milliseconds. /// Specify 0 for no periodic signaling. /// /// The state of the timer (whether it is signaled). public bool Set(long dueTime, TimerApcRoutine routine, int period) { return this.Set(dueTime, true, routine, IntPtr.Zero, period); } /// /// Sets the timer. /// /// A due time, in 100ns units. /// Whether the due time is relative. /// A routine to call when the timer is signaled. /// A value to pass to the timer callback routine. /// /// The time interval for periodic signaling of the timer, in milliseconds. /// Specify 0 for no periodic signaling. /// /// The state of the timer (whether it is signaled). public bool Set(long dueTime, bool relative, TimerApcRoutine routine, IntPtr context, int period) { return this.Set(dueTime, relative, routine, context, false, period); } /// /// Sets the timer. /// /// A due time, in 100ns units. /// Whether the due time is relative. /// A routine to call when the timer is signaled. /// A value to pass to the timer callback routine. /// /// Whether the power manager should restore the system when the timer is signaled. /// /// /// The time interval for periodic signaling of the timer, in milliseconds. /// Specify 0 for no periodic signaling. /// /// The state of the timer (whether it is signaled). public bool Set(long dueTime, bool relative, TimerApcRoutine routine, IntPtr context, bool resume, int period) { NtStatus status; long realDueTime = relative ? -dueTime : dueTime; bool previousState; // Keep the APC routine alive. _routine = routine; if ((status = Win32.NtSetTimer( this, ref realDueTime, routine, context, resume, period, out previousState )) >= NtStatus.Error) Win32.Throw(status); return previousState; } } }