diff --git a/PInvoke/Kernel32/HandleApi.cs b/PInvoke/Kernel32/HandleApi.cs
index e680fb52..a3f50ca8 100644
--- a/PInvoke/Kernel32/HandleApi.cs
+++ b/PInvoke/Kernel32/HandleApi.cs
@@ -2,136 +2,363 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
+using System.Threading;
-namespace Vanara.PInvoke
+namespace Vanara.PInvoke;
+
+public static partial class Kernel32
{
- public static partial class Kernel32
+ /// Optional actions.
+ [Flags]
+ public enum DUPLICATE_HANDLE_OPTIONS : uint
{
- /// 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,
+ /// 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,
- }
+ /// 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,
+ /// 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, 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
- }
+ /// 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);
+ /// 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);
- /// Closes an open object handle.
- /// The type of the handle.
- /// The 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.
- ///
- /// 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.
- ///
- ///
- [PInvokeData("Winbase.h", MSDNShortId = "ms724211")]
- public static bool CloseHandle(THandle handle) where THandle : struct, IKernelHandle => CloseHandle(handle.DangerousGetHandle());
+ /// Closes an open object handle.
+ /// The type of the handle.
+ /// The 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.
+ ///
+ /// 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.
+ ///
+ ///
+ [PInvokeData("Winbase.h", MSDNShortId = "ms724211")]
+ public static bool CloseHandle(THandle handle) where THandle : struct, IKernelHandle => CloseHandle(handle.DangerousGetHandle());
- /// 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);
+ /// 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);
+ /// 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.
+ /// 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 = default) =>
+ DuplicateHandle(GetCurrentProcess(), hSourceHandle.DangerousGetHandle(), GetCurrentProcess(), out var h, dwDesiredAccess, bInheritHandle, dwOptions) ? h : IntPtr.Zero;
+
+ /// Duplicates an object handle.
+ /// The type of the handle.
+ /// The type of the access value (enum or uint).
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ /// 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_SOURCE 0x00000001
+ /// Closes the source handle. This occurs regardless of any error status returned.
+ ///
+ /// -
+ /// DUPLICATE_SAME_ACCESS 0x00000002
+ /// Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 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 THandle Duplicate(this THandle hSourceHandle, TAccess dwDesiredAccess, bool bInheritHandle = true, DUPLICATE_HANDLE_OPTIONS dwOptions = DUPLICATE_HANDLE_OPTIONS.DUPLICATE_SAME_ACCESS)
+ where THandle : SafeKernelHandle where TAccess : struct, IConvertible =>
+ Win32Error.ThrowLastErrorIfFalse(SafeKernelHandle.DuplicateHandle(hSourceHandle, out var ret, dwDesiredAccess, default, default, bInheritHandle, dwOptions)) ? ret : default;
+
+ /// 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).
///
- ///
- /// 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 = default) =>
- DuplicateHandle(GetCurrentProcess(), hSourceHandle.DangerousGetHandle(), GetCurrentProcess(), out var h, dwDesiredAccess, bInheritHandle, dwOptions) ? h : IntPtr.Zero;
+ protected SafeKernelHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// Duplicates an object handle.
/// The type of the handle.
@@ -140,71 +367,18 @@ namespace Vanara.PInvoke
/// 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.
///
- ///
- ///
- /// 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_SOURCE 0x00000001
- /// Closes the source handle. This occurs regardless of any error status returned.
- ///
- /// -
- /// DUPLICATE_SAME_ACCESS 0x00000002
- /// Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.
- ///
- ///
- ///
- ///
- ///
- /// 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 THandle Duplicate(this THandle hSourceHandle, TAccess dwDesiredAccess, bool bInheritHandle = true, DUPLICATE_HANDLE_OPTIONS dwOptions = DUPLICATE_HANDLE_OPTIONS.DUPLICATE_SAME_ACCESS)
- where THandle : SafeKernelHandle where TAccess : struct, IConvertible =>
- Win32Error.ThrowLastErrorIfFalse(SafeKernelHandle.DuplicateHandle(hSourceHandle, out var ret, dwDesiredAccess, default, default, bInheritHandle, dwOptions)) ? ret : default;
-
- /// 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.
+ ///
+ /// 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.
+ /// 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.
///
///
///
@@ -212,10 +386,17 @@ namespace Vanara.PInvoke
/// 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.
+ /// 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 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.
+ ///
+ ///
+ /// A handle to the process that is to receive the duplicated handle. The handle must have the PROCESS_DUP_HANDLE access right.
+ ///
///
/// 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.
@@ -243,218 +424,66 @@ namespace Vanara.PInvoke
/// 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
+ public static bool DuplicateHandle(THandle hSourceHandle, out THandle lpTargetHandle, TAccess dwDesiredAccess,
+ HPROCESS hSourceProcessHandle = default, HPROCESS hTargetProcessHandle = default, bool bInheritHandle = false, DUPLICATE_HANDLE_OPTIONS dwOptions = 0)
+ where THandle : SafeKernelHandle where TAccess : struct, IConvertible
{
- /// 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) { }
-
- /// Duplicates an object handle.
- /// The type of the handle.
- /// The type of the access value (enum or uint).
- ///
- /// 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 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 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.
- ///
- ///
- /// A handle to the process that is to receive the duplicated handle. The handle must have the PROCESS_DUP_HANDLE access right.
- ///
- ///
- /// 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.
- ///
- public static bool DuplicateHandle(THandle hSourceHandle, out THandle lpTargetHandle, TAccess dwDesiredAccess,
- HPROCESS hSourceProcessHandle = default, HPROCESS hTargetProcessHandle = default, bool bInheritHandle = false, DUPLICATE_HANDLE_OPTIONS dwOptions = 0)
- where THandle : SafeKernelHandle where TAccess : struct, IConvertible
- {
- var ret = Kernel32.DuplicateHandle(hSourceProcessHandle == default ? GetCurrentProcess() : hSourceProcessHandle, hSourceHandle.DangerousGetHandle(),
- hTargetProcessHandle == default ? GetCurrentProcess() : hTargetProcessHandle, out IntPtr h, Convert.ToUInt32(dwDesiredAccess), bInheritHandle, dwOptions);
- lpTargetHandle = (THandle)Activator.CreateInstance(typeof(THandle), h, true);
- return ret;
- }
-
- ///
- protected override bool InternalReleaseHandle() => CloseHandle(handle);
+ var ret = Kernel32.DuplicateHandle(hSourceProcessHandle == default ? GetCurrentProcess() : hSourceProcessHandle, hSourceHandle.DangerousGetHandle(),
+ hTargetProcessHandle == default ? GetCurrentProcess() : hTargetProcessHandle, out IntPtr h, Convert.ToUInt32(dwDesiredAccess), bInheritHandle, dwOptions);
+ lpTargetHandle = (THandle)Activator.CreateInstance(typeof(THandle), h, true);
+ return ret;
}
- /// Provides a to a synchronization object that is automatically disposed using CloseHandle.
- ///
- public abstract class SafeSyncHandle : SafeKernelHandle, ISyncHandle
+ ///
+ 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);
+
+ /// Waits until this object is in the signaled state or the time-out interval elapses.
+ ///
+ ///
+ /// The time-out interval, in milliseconds. If a nonzero value is specified, the function waits until the object is signaled or
+ /// the interval elapses. If is zero, the function does not enter a wait state if the object is not
+ /// signaled; it always returns immediately. If is INFINITE, the function will return only when
+ /// the object is signaled.
+ ///
+ ///
+ /// Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2: The
+ /// value does include time spent in low-power states. For example, the timeout does keep counting down
+ /// while the computer is asleep.
+ ///
+ ///
+ /// Windows 8, Windows Server 2012, Windows 8.1, Windows Server 2012 R2, Windows 10 and Windows Server 2016: The value does not include time spent in low-power states. For example, the timeout does not keep counting down
+ /// while the computer is asleep.
+ ///
+ ///
+ /// if the current instance receives a signal; otherwise, .
+ /// The wait completed because a thread exited without releasing a mutex.
+ public bool Wait(uint msec = INFINITE) => WaitForSingleObject(ThrowIfDisposed(this), msec) switch
{
- /// 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);
- }
+ WAIT_STATUS.WAIT_OBJECT_0 => true,
+ WAIT_STATUS.WAIT_TIMEOUT => false,
+ WAIT_STATUS.WAIT_ABANDONED => throw new AbandonedMutexException(),
+ _ => throw Win32Error.GetLastError().GetException(),
+ };
}
}
\ No newline at end of file