From ebecb965975de6f083d53249af08ecabc26e640c Mon Sep 17 00:00:00 2001 From: wj32 Date: Fri, 22 May 2009 02:50:49 +0000 Subject: [PATCH] improved synchronization methods, added UserHandle git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1311 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- .../Objects/DesktopHandle.cs | 2 +- .../Objects/ISynchronizable.cs | 4 +- .../Objects/KeyedEventHandle.cs | 64 +++++--- .../Objects/SemaphoreHandle.cs | 10 +- .../Objects/UserHandle.cs | 57 +++++++ .../Objects/Win32Handle.cs | 148 +++++++++++++----- .../Objects/WindowStationHandle.cs | 2 +- .../ProcessHacker.Native.csproj | 1 + 8 files changed, 218 insertions(+), 70 deletions(-) create mode 100644 trunk/ProcessHacker.Native/Objects/UserHandle.cs diff --git a/trunk/ProcessHacker.Native/Objects/DesktopHandle.cs b/trunk/ProcessHacker.Native/Objects/DesktopHandle.cs index 6cd5b9b5c..4445cd5e9 100644 --- a/trunk/ProcessHacker.Native/Objects/DesktopHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/DesktopHandle.cs @@ -28,7 +28,7 @@ using ProcessHacker.Native.Security; namespace ProcessHacker.Native.Objects { - public class DesktopHandle : Win32Handle + public class DesktopHandle : UserHandle { public static DesktopHandle GetCurrent() { diff --git a/trunk/ProcessHacker.Native/Objects/ISynchronizable.cs b/trunk/ProcessHacker.Native/Objects/ISynchronizable.cs index fdd029ced..8fad492ff 100644 --- a/trunk/ProcessHacker.Native/Objects/ISynchronizable.cs +++ b/trunk/ProcessHacker.Native/Objects/ISynchronizable.cs @@ -32,9 +32,11 @@ namespace ProcessHacker.Native.Objects { IntPtr Handle { get; } + NtStatus SignalAndWait(ISynchronizable waitObject); + NtStatus SignalAndWait(ISynchronizable waitObject, bool alertable); NtStatus SignalAndWait(ISynchronizable waitObject, bool alertable, long timeout); NtStatus Wait(); - NtStatus Wait(long timeout); + NtStatus Wait(bool alertable); NtStatus Wait(bool alertable, long timeout); } } diff --git a/trunk/ProcessHacker.Native/Objects/KeyedEventHandle.cs b/trunk/ProcessHacker.Native/Objects/KeyedEventHandle.cs index cd47a2040..478708cbd 100644 --- a/trunk/ProcessHacker.Native/Objects/KeyedEventHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/KeyedEventHandle.cs @@ -86,50 +86,66 @@ namespace ProcessHacker.Native.Objects : this(name, null, 0, access) { } - public void Release(IntPtr key, bool alertable, long timeout) + public NtStatus ReleaseKey(int key) + { + return this.ReleaseKey(key, -1); + } + + public NtStatus ReleaseKey(int key, long timeout) + { + return this.ReleaseKey(key, false, timeout); + } + + public NtStatus ReleaseKey(int key, bool alertable, long timeout) + { + return this.ReleaseKey(new IntPtr(key), alertable, timeout, true); + } + + public NtStatus ReleaseKey(IntPtr key, bool alertable, long timeout, bool relative) { NtStatus status; + long realTimeout = relative ? -timeout : timeout; - if ((status = Win32.NtReleaseKeyedEvent(this, key, alertable, ref timeout)) >= NtStatus.Error) + if ((status = Win32.NtReleaseKeyedEvent( + this, + key, + alertable, + ref realTimeout + )) >= NtStatus.Error) Win32.ThrowLastError(status); + + return status; } - public void Release(int key, bool alertable, long timeout) + public NtStatus WaitKey(int key) { - this.Release(new IntPtr(key), alertable, timeout); + return this.WaitKey(key, -1); } - public void Release(int key, long timeout) + public NtStatus WaitKey(int key, long timeout) { - this.Release(key, false, timeout); + return this.WaitKey(key, false, timeout); } - public void Release(int key) + public NtStatus WaitKey(int key, bool alertable, long timeout) { - this.Release(key, -1); + return this.WaitKey(new IntPtr(key), alertable, timeout, true); } - public void Wait(IntPtr key, bool alertable, long timeout) + public NtStatus WaitKey(IntPtr key, bool alertable, long timeout, bool relative) { NtStatus status; + long realTimeout = relative ? -timeout : timeout; - if ((status = Win32.NtWaitForKeyedEvent(this, key, alertable, ref timeout)) >= NtStatus.Error) + if ((status = Win32.NtWaitForKeyedEvent( + this, + key, + alertable, + ref realTimeout + )) >= NtStatus.Error) Win32.ThrowLastError(status); - } - public void Wait(int key, bool alertable, long timeout) - { - this.Wait(new IntPtr(key), alertable, timeout); - } - - public void Wait(int key, long timeout) - { - this.Wait(key, false, timeout); - } - - public void Wait(int key) - { - this.Wait(key, -1); + return status; } } } diff --git a/trunk/ProcessHacker.Native/Objects/SemaphoreHandle.cs b/trunk/ProcessHacker.Native/Objects/SemaphoreHandle.cs index 9e2d5cb07..b62ac786e 100644 --- a/trunk/ProcessHacker.Native/Objects/SemaphoreHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/SemaphoreHandle.cs @@ -104,6 +104,11 @@ namespace ProcessHacker.Native.Objects return sbi; } + public int Release() + { + return this.Release(1); + } + public int Release(int count) { NtStatus status; @@ -114,10 +119,5 @@ namespace ProcessHacker.Native.Objects return previousCount; } - - public int Release() - { - return this.Release(1); - } } } diff --git a/trunk/ProcessHacker.Native/Objects/UserHandle.cs b/trunk/ProcessHacker.Native/Objects/UserHandle.cs new file mode 100644 index 000000000..ed3de2d38 --- /dev/null +++ b/trunk/ProcessHacker.Native/Objects/UserHandle.cs @@ -0,0 +1,57 @@ +/* + * Process Hacker - + * USER handle + * + * Copyright (C) 2009 wj32 + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Text; +using ProcessHacker.Native.Api; +using ProcessHacker.Native.Security; + +namespace ProcessHacker.Native.Objects +{ + public abstract class UserHandle : Win32Handle + where TAccess : struct + { + protected UserHandle() + : base() + { } + + protected UserHandle(IntPtr handle, bool owned) + : base(handle, owned) + { } + + public override SecurityDescriptor GetSecurity() + { + return this.GetSecurity(SeObjectType.WindowObject); + } + + public override void SetSecurity(SecurityDescriptor securityDescriptor) + { + this.SetSecurity(SeObjectType.WindowObject, securityDescriptor); + } + + public override void SetSecurity(SecurityInformation securityInformation, SecurityDescriptor securityDescriptor) + { + this.SetSecurity(SeObjectType.WindowObject, securityInformation, securityDescriptor); + } + } +} diff --git a/trunk/ProcessHacker.Native/Objects/Win32Handle.cs b/trunk/ProcessHacker.Native/Objects/Win32Handle.cs index 626ee7aba..daf1ed2bd 100644 --- a/trunk/ProcessHacker.Native/Objects/Win32Handle.cs +++ b/trunk/ProcessHacker.Native/Objects/Win32Handle.cs @@ -28,13 +28,13 @@ using ProcessHacker.Native.Security; namespace ProcessHacker.Native.Objects { /// - /// Represents a generic Windows handle. + /// Represents a generic Windows handle which acts as a kernel handle by default. /// public class Win32Handle : Win32Handle { - public static NtStatus WaitAll(ISynchronizable[] objects, bool alertable, long timeout) + public static NtStatus WaitAll(ISynchronizable[] objects) { - return WaitForMultipleObjects(objects, WaitType.WaitAll, alertable, timeout); + return WaitAll(objects, long.MinValue); } public static NtStatus WaitAll(ISynchronizable[] objects, long timeout) @@ -42,19 +42,14 @@ namespace ProcessHacker.Native.Objects return WaitAll(objects, false, timeout); } - public static NtStatus WaitAll(ISynchronizable[] objects) + public static NtStatus WaitAll(ISynchronizable[] objects, bool alertable, long timeout) { - return WaitAll(objects, long.MinValue); + return WaitAll(objects, alertable, timeout, true); } - public static NtStatus WaitAny(ISynchronizable[] objects, bool alertable, long timeout) + public static NtStatus WaitAll(ISynchronizable[] objects, bool alertable, long timeout, bool relative) { - return WaitForMultipleObjects(objects, WaitType.WaitAny, alertable, timeout); - } - - public static NtStatus WaitAny(ISynchronizable[] objects, long timeout) - { - return WaitAny(objects, false, timeout); + return WaitForMultipleObjects(objects, WaitType.WaitAll, alertable, timeout, relative); } public static NtStatus WaitAny(ISynchronizable[] objects) @@ -62,10 +57,26 @@ namespace ProcessHacker.Native.Objects return WaitAny(objects, long.MinValue); } - private static NtStatus WaitForMultipleObjects(ISynchronizable[] objects, WaitType waitType, bool alertable, long timeout) + public static NtStatus WaitAny(ISynchronizable[] objects, long timeout) + { + return WaitAny(objects, false, timeout); + } + + public static NtStatus WaitAny(ISynchronizable[] objects, bool alertable, long timeout) + { + return WaitAny(objects, alertable, timeout, true); + } + + public static NtStatus WaitAny(ISynchronizable[] objects, bool alertable, long timeout, bool relative) + { + return WaitForMultipleObjects(objects, WaitType.WaitAny, alertable, timeout, relative); + } + + private static NtStatus WaitForMultipleObjects(ISynchronizable[] objects, WaitType waitType, bool alertable, long timeout, bool relative) { NtStatus status; IntPtr[] handles = new IntPtr[objects.Length]; + long realTimeout = relative ? -timeout : timeout; for (int i = 0; i < objects.Length; i++) handles[i] = objects[i].Handle; @@ -75,7 +86,7 @@ namespace ProcessHacker.Native.Objects handles, waitType, alertable, - ref timeout + ref realTimeout )) >= NtStatus.Error) Win32.ThrowLastError(status); @@ -129,7 +140,7 @@ namespace ProcessHacker.Native.Objects } /// - /// Represents a generic Windows handle. + /// Represents a generic Windows handle which acts as a kernel handle by default. /// public class Win32Handle : IDisposable, ISecurable, ISynchronizable where TAccess : struct @@ -285,13 +296,18 @@ namespace ProcessHacker.Native.Objects } public virtual SecurityDescriptor GetSecurity() + { + return this.GetSecurity(SeObjectType.KernelObject); + } + + protected SecurityDescriptor GetSecurity(SeObjectType objectType) { int result; IntPtr dummy, securityDescriptor; if ((result = Win32.GetSecurityInfo( this, - SeObjectType.KernelObject, + objectType, 0, out dummy, out dummy, out dummy, out dummy, out securityDescriptor @@ -336,6 +352,16 @@ namespace ProcessHacker.Native.Objects } public virtual void SetSecurity(SecurityDescriptor securityDescriptor) + { + this.SetSecurity(SeObjectType.KernelObject, securityDescriptor); + } + + public virtual void SetSecurity(SecurityInformation securityInformation, SecurityDescriptor securityDescriptor) + { + this.SetSecurity(SeObjectType.KernelObject, securityInformation, securityDescriptor); + } + + protected void SetSecurity(SeObjectType objectType, SecurityDescriptor securityDescriptor) { int result; IntPtr owner, group, dacl, sacl; @@ -353,7 +379,7 @@ namespace ProcessHacker.Native.Objects if ((result = Win32.SetSecurityInfo( this, - SeObjectType.KernelObject, + objectType, si, owner, group, @@ -363,7 +389,7 @@ namespace ProcessHacker.Native.Objects Win32.ThrowLastError(result); } - public virtual void SetSecurity(SecurityInformation securityInformation, SecurityDescriptor securityDescriptor) + protected void SetSecurity(SeObjectType objectType, SecurityInformation securityInformation, SecurityDescriptor securityDescriptor) { int result; IntPtr owner, group, dacl, sacl; @@ -376,7 +402,7 @@ namespace ProcessHacker.Native.Objects if ((result = Win32.SetSecurityInfo( this, - SeObjectType.KernelObject, + objectType, securityInformation, owner, group, @@ -386,12 +412,47 @@ namespace ProcessHacker.Native.Objects Win32.ThrowLastError(result); } + /// + /// Signals the object and waits for another. + /// + public virtual NtStatus SignalAndWait(ISynchronizable waitObject) + { + return this.SignalAndWait(waitObject, false); + } + + /// + /// Signals the object and waits for another. + /// + public virtual NtStatus SignalAndWait(ISynchronizable waitObject, bool alertable) + { + return this.SignalAndWait(waitObject, alertable, long.MinValue, false); + } + /// /// Signals the object and waits for another. /// public virtual NtStatus SignalAndWait(ISynchronizable waitObject, bool alertable, long timeout) { - return Win32.NtSignalAndWaitForSingleObject(this, waitObject.Handle, alertable, ref timeout); + return this.SignalAndWait(waitObject, alertable, timeout, true); + } + + /// + /// Signals the object and waits for another. + /// + public virtual NtStatus SignalAndWait(ISynchronizable waitObject, bool alertable, long timeout, bool relative) + { + NtStatus status; + long realTimeout = relative ? -timeout : timeout; + + if ((status = Win32.NtSignalAndWaitForSingleObject( + this, + waitObject.Handle, + alertable, + ref timeout + )) >= NtStatus.Error) + Win32.ThrowLastError(status); + + return status; } /// @@ -410,26 +471,16 @@ namespace ProcessHacker.Native.Objects /// public virtual NtStatus Wait(bool alertable) { - return this.Wait(alertable, long.MinValue); + return this.Wait(alertable, long.MinValue, false); } /// /// Waits for the object to be signaled. /// /// The timeout value. - public virtual NtStatus Wait(long timeout) + public NtStatus Wait(long timeout) { - return this.Wait(timeout, true); - } - - /// - /// Waits for the object to be signaled. - /// - /// The timeout value. - /// Whether the timeout value is relative. - public virtual NtStatus Wait(long timeout, bool relative) - { - return this.Wait(false, relative ? -timeout : timeout); + return this.Wait(false, timeout); } /// @@ -438,18 +489,39 @@ namespace ProcessHacker.Native.Objects /// /// Whether user-mode APCs can be delivered during the wait. /// - /// - /// Zero for no timeout (immediate return if the object is not signaled), - /// a negative relative timeout or a positive absolute timeout. - /// + /// The timeout value. public virtual NtStatus Wait(bool alertable, long timeout) + { + return this.Wait(alertable, timeout, true); + } + + /// + /// Waits for the object to be signaled. + /// + /// The timeout value. + /// Whether the timeout value is relative. + public NtStatus Wait(long timeout, bool relative) + { + return this.Wait(false, timeout, relative); + } + + /// + /// Waits for the object to be signaled. + /// + /// + /// Whether user-mode APCs can be delivered during the wait. + /// + /// The timeout value. + /// Whether the timeout value is relative. + public virtual NtStatus Wait(bool alertable, long timeout, bool relative) { NtStatus status; + long realTimeout = relative ? -timeout : timeout; if ((status = Win32.NtWaitForSingleObject( this, alertable, - ref timeout + ref realTimeout )) >= NtStatus.Error) Win32.ThrowLastError(status); diff --git a/trunk/ProcessHacker.Native/Objects/WindowStationHandle.cs b/trunk/ProcessHacker.Native/Objects/WindowStationHandle.cs index ac962c544..4fd99e986 100644 --- a/trunk/ProcessHacker.Native/Objects/WindowStationHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/WindowStationHandle.cs @@ -28,7 +28,7 @@ using ProcessHacker.Native.Security; namespace ProcessHacker.Native.Objects { - public class WindowStationHandle : Win32Handle + public class WindowStationHandle : UserHandle { public static WindowStationHandle GetCurrent() { diff --git a/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj b/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj index fbdf2ef57..51ed049f8 100644 --- a/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj +++ b/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj @@ -69,6 +69,7 @@ +