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