using Microsoft.Win32.SafeHandles; using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class Kernel32 { /// Optional actions. [Flags] public enum DUPLICATE_HANDLE_OPTIONS : uint { /// Closes the source handle. This occurs regardless of any error status returned. DUPLICATE_CLOSE_SOURCE = 0x00000001, /// Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle. DUPLICATE_SAME_ACCESS = 0x00000002, } /// A set of bit flags that specify properties of the object handle. [Flags] public enum HANDLE_FLAG { /// None. NONE = 0, /// /// If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the /// object handle. /// HANDLE_FLAG_INHERIT = 1, /// If this flag is set, calling the CloseHandle function will not close the object handle. HANDLE_FLAG_PROTECT_FROM_CLOSE = 2 } /// Closes an open object handle. /// A valid handle to an open object. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// If the application is running under a debugger, the function will throw an exception if it receives either a handle value that is /// not valid or a pseudo-handle value. This can happen if you close a handle twice, or if you call CloseHandle on a handle /// returned by the FindFirstFile function instead of calling the FindClose function. /// /// // BOOL WINAPI CloseHandle( _In_ HANDLE hObject); https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [PInvokeData("Winbase.h", MSDNShortId = "ms724211")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); /// Compares two object handles to determine if they refer to the same underlying kernel object. /// The first object handle to compare. /// The second object handle to compare. /// /// A Boolean value that indicates if the two handles refer to the same underlying kernel object. TRUE if the same, otherwise FALSE. /// // BOOL WINAPI CompareObjectHandles( _In_ HANDLE hFirstObjectHandle, _In_ HANDLE hSecondObjectHandle); https://msdn.microsoft.com/en-us/library/windows/desktop/mt438733(v=vs.85).aspx [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)] [PInvokeData("Handleapi.h", MSDNShortId = "mt438733")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CompareObjectHandles(IntPtr hFirstObjectHandle, IntPtr hSecondObjectHandle); /// Determines if two object handles refer to the same underlying kernel object. /// The first object handle to compare. /// The second object handle to compare. /// if the two handles refer to the same underlying kernel object; otherwise. public static bool Equals(this IKernelHandle h1, IKernelHandle h2) => CompareObjectHandles(h1.DangerousGetHandle(), h2?.DangerousGetHandle() ?? IntPtr.Zero); /// Duplicates an object handle. /// /// The handle to be duplicated. This is an open object handle that is valid in the context of the source process. For a list of /// objects whose handles can be duplicated, see the following Remarks section. /// /// /// A variable that indicates whether the handle is inheritable. If TRUE, the duplicate handle can be inherited by new /// processes created by the target process. If FALSE, the new handle cannot be inherited. /// /// /// Optional actions. This parameter can be zero, or any combination of the following values. /// /// /// /// Value /// Meaning /// /// /// DUPLICATE_CLOSE_SOURCE0x00000001 /// Closes the source handle. This occurs regardless of any error status returned. /// /// /// DUPLICATE_SAME_ACCESS0x00000002 /// Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle. /// /// /// /// /// /// /// The access requested for the new handle. For the flags that can be specified for each object type, see the following Remarks section. /// /// /// This parameter is ignored if the dwOptions parameter specifies the DUPLICATE_SAME_ACCESS flag. Otherwise, the flags that can be /// specified depend on the type of object whose handle is to be duplicated. /// /// /// /// The duplicate handle. This handle value is valid in the context of the target process. /// /// If hSourceHandle is a pseudo handle returned by GetCurrentProcess or GetCurrentThread, DuplicateHandle /// converts it to a real handle to a process or thread, respectively. /// /// public static IntPtr Duplicate(this IKernelHandle hSourceHandle, bool bInheritHandle = true, DUPLICATE_HANDLE_OPTIONS dwOptions = DUPLICATE_HANDLE_OPTIONS.DUPLICATE_SAME_ACCESS, uint dwDesiredAccess = 0) => DuplicateHandle(GetCurrentProcess(), hSourceHandle.DangerousGetHandle(), GetCurrentProcess(), out var h, dwDesiredAccess, bInheritHandle, dwOptions) ? h : IntPtr.Zero; /// Duplicates an object handle. /// /// A handle to the process with the handle to be duplicated. /// The handle must have the PROCESS_DUP_HANDLE access right. For more information, see Process Security and Access Rights. /// /// /// The handle to be duplicated. This is an open object handle that is valid in the context of the source process. For a list of /// objects whose handles can be duplicated, see the following Remarks section. /// /// /// A handle to the process that is to receive the duplicated handle. The handle must have the PROCESS_DUP_HANDLE access right. /// /// /// A pointer to a variable that receives the duplicate handle. This handle value is valid in the context of the target process. /// /// If hSourceHandle is a pseudo handle returned by GetCurrentProcess or GetCurrentThread, DuplicateHandle /// converts it to a real handle to a process or thread, respectively. /// /// /// If lpTargetHandle is NULL, the function duplicates the handle, but does not return the duplicate handle value to the /// caller. This behavior exists only for backward compatibility with previous versions of this function. You should not use this /// feature, as you will lose system resources until the target process terminates. /// /// /// /// /// The access requested for the new handle. For the flags that can be specified for each object type, see the following Remarks section. /// /// /// This parameter is ignored if the dwOptions parameter specifies the DUPLICATE_SAME_ACCESS flag. Otherwise, the flags that can be /// specified depend on the type of object whose handle is to be duplicated. /// /// /// /// A variable that indicates whether the handle is inheritable. If TRUE, the duplicate handle can be inherited by new /// processes created by the target process. If FALSE, the new handle cannot be inherited. /// /// /// Optional actions. This parameter can be zero, or any combination of the following values. /// /// /// /// Value /// Meaning /// /// /// DUPLICATE_CLOSE_SOURCE0x00000001 /// Closes the source handle. This occurs regardless of any error status returned. /// /// /// DUPLICATE_SAME_ACCESS0x00000002 /// Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle. /// /// /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI DuplicateHandle( _In_ HANDLE hSourceProcessHandle, _In_ HANDLE hSourceHandle, _In_ HANDLE hTargetProcessHandle, _Out_ // LPHANDLE lpTargetHandle, _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwOptions); https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("Winbase.h", MSDNShortId = "ms724251")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DuplicateHandle([In] HPROCESS hSourceProcessHandle, [In] IntPtr hSourceHandle, [In] HPROCESS hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, DUPLICATE_HANDLE_OPTIONS dwOptions); /// Retrieves certain properties of an object handle. /// /// A handle to an object whose information is to be retrieved. /// /// You can specify a handle to one of the following types of objects: access token, console input buffer, console screen buffer, /// event, file, file mapping, job, mailslot, mutex, pipe, printer, process, registry key, semaphore, serial communication device, /// socket, thread, or waitable timer. /// /// /// /// /// A pointer to a variable that receives a set of bit flags that specify properties of the object handle or 0. The following values /// are defined. /// /// /// /// /// Value /// Meaning /// /// /// HANDLE_FLAG_INHERIT0x00000001 /// /// If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the /// object handle. /// /// /// /// HANDLE_FLAG_PROTECT_FROM_CLOSE0x00000002 /// If this flag is set, calling the CloseHandle function will not close the object handle. /// /// /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI GetHandleInformation( _In_ HANDLE hObject, _Out_ LPDWORD lpdwFlags); https://msdn.microsoft.com/en-us/library/windows/desktop/ms724329(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("Winbase.h", MSDNShortId = "ms724329")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetHandleInformation([In] IntPtr hObject, out HANDLE_FLAG lpdwFlags); /// Retrieves certain properties of an object handle. /// A handle to an object whose information is to be retrieved. /// A variable that receives a set of bit flags that specify properties of the object handle public static HANDLE_FLAG GetInformation(this IKernelHandle hObj) => GetHandleInformation(hObj.DangerousGetHandle(), out var flag) ? flag : 0; /// Sets certain properties of an object handle. /// /// A handle to an object whose information is to be set. /// /// You can specify a handle to one of the following types of objects: access token, console input buffer, console screen buffer, /// event, file, file mapping, job, mailslot, mutex, pipe, printer, process, registry key, semaphore, serial communication device, /// socket, thread, or waitable timer. /// /// /// /// A mask that specifies the bit flags to be changed. Use the same constants shown in the description of dwFlags. /// /// /// /// Set of bit flags that specifies properties of the object handle. This parameter can be 0 or one or more of the following values. /// /// /// /// /// Value /// Meaning /// /// /// HANDLE_FLAG_INHERIT0x00000001 /// /// If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the /// object handle. /// /// /// /// HANDLE_FLAG_PROTECT_FROM_CLOSE0x00000002 /// If this flag is set, calling the CloseHandle function will not close the object handle. /// /// /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI SetHandleInformation( _In_ HANDLE hObject, _In_ DWORD dwMask, _In_ DWORD dwFlags);// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724935(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("Winbase.h", MSDNShortId = "ms724935")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetHandleInformation([In] IntPtr hObject, HANDLE_FLAG dwMask, HANDLE_FLAG dwFlags); /// Provides a to a handle that releases a created HANDLE instance at disposal using CloseHandle. public abstract class SafeKernelHandle : SafeHANDLE, IKernelHandle { /// Initializes a new instance of the class. protected SafeKernelHandle() : base() { } /// 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). /// protected SafeKernelHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// protected override bool InternalReleaseHandle() => CloseHandle(handle); } /// Provides a to a synchronization object that is automatically disposed using CloseHandle. /// public abstract class SafeSyncHandle : SafeKernelHandle, ISyncHandle { /// Initializes a new instance of the class. protected SafeSyncHandle() : base() { } /// 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). /// protected SafeSyncHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Performs an implicit conversion from to . /// The SafeSyncHandle instance. /// The result of the conversion. public static implicit operator SafeWaitHandle(SafeSyncHandle h) => new SafeWaitHandle(h.handle, false); } } }