From 3454e9d34f30e4e8dc6bd8649d5bfafcfcf05bb0 Mon Sep 17 00:00:00 2001 From: David Hall Date: Tue, 16 Jul 2019 11:53:20 -0600 Subject: [PATCH] Added unsafe CreateThread overload and changed PTHREAD_START_ROUTINE to ThreadProc --- PInvoke/Kernel32/DebugApi.cs | 25 ++++++---- PInvoke/Kernel32/ProcessThreadsApi.cs | 78 ++++++++++++++++++++++++++++-- PInvoke/Kernel32/ThreadPoolLegacyApiSet.cs | 2 +- PInvoke/Security/Authz/Authz.cs | 2 +- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/PInvoke/Kernel32/DebugApi.cs b/PInvoke/Kernel32/DebugApi.cs index 618d263a..b04d421d 100644 --- a/PInvoke/Kernel32/DebugApi.cs +++ b/PInvoke/Kernel32/DebugApi.cs @@ -11,8 +11,15 @@ namespace Vanara.PInvoke /// /// A pointer to a variable to be passed as the lpParameter parameter to the function pointed to by the lpCallbackAddress parameter. /// - /// Zero if successfull. Otherwise, returns an error code. - public delegate uint PTHREAD_START_ROUTINE(IntPtr lpThreadParameter); + /// Zero if successful. Otherwise, returns an error code. + public delegate uint ThreadProc(IntPtr lpThreadParameter); + + /// A pointer to the starting address of the thread. + /// + /// A pointer to a variable to be passed as the lpParameter parameter to the function pointed to by the lpCallbackAddress parameter. + /// + /// Zero if successful. Otherwise, returns an error code. + public unsafe delegate uint ThreadProcUnsafe(void* lpThreadParameter); /// The options to continue the thread that reported the debugging event. public enum DEBUG_CONTINUE : uint @@ -347,39 +354,39 @@ namespace Vanara.PInvoke /// [FieldOffset(0)] public CREATE_THREAD_DEBUG_INFO CreateThread; - + /// /// If the dwDebugEventCode is CREATE_PROCESS_DEBUG_EVENT (3), u.CreateProcessInfo specifies an CREATE_PROCESS_DEBUG_INFO structure. /// [FieldOffset(0)] public CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; - + /// /// If the dwDebugEventCode is EXIT_THREAD_DEBUG_EVENT (4), u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure. /// [FieldOffset(0)] public EXIT_THREAD_DEBUG_INFO ExitThread; - + /// /// If the dwDebugEventCode is EXIT_PROCESS_DEBUG_EVENT (5), u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure. /// [FieldOffset(0)] public EXIT_PROCESS_DEBUG_INFO ExitProcess; - + /// If the dwDebugEventCode is LOAD_DLL_DEBUG_EVENT (6), u.LoadDll specifies an LOAD_DLL_DEBUG_INFO structure. [FieldOffset(0)] public LOAD_DLL_DEBUG_INFO LoadDll; - + /// If the dwDebugEventCode is UNLOAD_DLL_DEBUG_EVENT (7), u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure. [FieldOffset(0)] public UNLOAD_DLL_DEBUG_INFO UnloadDll; - + /// /// If the dwDebugEventCode is OUTPUT_DEBUG_STRING_EVENT (8), u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure. /// [FieldOffset(0)] public OUTPUT_DEBUG_STRING_INFO DebugString; - + /// If the dwDebugEventCode is RIP_EVENT (9), u.RipInfo specifies an RIP_INFO structure. [FieldOffset(0)] public RIP_INFO RipInfo; diff --git a/PInvoke/Kernel32/ProcessThreadsApi.cs b/PInvoke/Kernel32/ProcessThreadsApi.cs index e97e327f..7f7a9c5b 100644 --- a/PInvoke/Kernel32/ProcessThreadsApi.cs +++ b/PInvoke/Kernel32/ProcessThreadsApi.cs @@ -1542,7 +1542,7 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("WinBase.h", MSDNShortId = "ms682437")] public static extern SafeHTHREAD CreateRemoteThread([In] HPROCESS hProcess, [In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, - PTHREAD_START_ROUTINE lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, out uint lpThreadId); + ThreadProc lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, out uint lpThreadId); /// /// Creates a thread that runs in the virtual address space of another process. @@ -1697,7 +1697,7 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("WinBase.h", MSDNShortId = "dd405484")] public static extern SafeHTHREAD CreateRemoteThreadEx([In] HPROCESS hProcess, [In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, - PTHREAD_START_ROUTINE lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, SafeProcThreadAttributeList lpAttributeList, + ThreadProc lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, SafeProcThreadAttributeList lpAttributeList, out uint lpThreadId); /// @@ -1772,7 +1772,7 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("WinBase.h", MSDNShortId = "dd405484")] public static extern SafeHTHREAD CreateRemoteThreadEx([In] HPROCESS hProcess, [In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, - PTHREAD_START_ROUTINE lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, [Optional] IntPtr lpAttributeList, + ThreadProc lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, [Optional] IntPtr lpAttributeList, out uint lpThreadId); /// @@ -1992,9 +1992,79 @@ namespace Vanara.PInvoke // LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("WinBase.h", MSDNShortId = "ms682453")] - public static extern SafeHTHREAD CreateThread([In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, PTHREAD_START_ROUTINE lpStartAddress, + public static extern SafeHTHREAD CreateThread([In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, ThreadProc lpStartAddress, [In, Optional] IntPtr lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, out uint lpThreadId); + /// + /// Creates a thread to execute within the virtual address space of the calling process. + /// To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function. + /// + /// + /// + /// A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child + /// processes. If lpThreadAttributes is NULL, the handle cannot be inherited. + /// + /// + /// The lpSecurityDescriptor member of the structure specifies a security descriptor for the new thread. If lpThreadAttributes + /// is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the + /// primary token of the creator. + /// + /// + /// + /// The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new + /// thread uses the default size for the executable. For more information, see Thread Stack Size. + /// + /// + /// A pointer to the application-defined function to be executed by the thread. This pointer represents the starting address of the + /// thread. For more information on the thread function, see ThreadProc. + /// + /// A pointer to a variable to be passed to the thread. + /// + /// The flags that control the creation of the thread. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// 0 + /// The thread runs immediately after creation. + /// + /// + /// CREATE_SUSPENDED0x00000004 + /// The thread is created in a suspended state, and does not run until the ResumeThread function is called. + /// + /// + /// STACK_SIZE_PARAM_IS_A_RESERVATION0x00010000 + /// + /// The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies + /// the commit size. + /// + /// + /// + /// + /// + /// + /// A pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned. + /// + /// + /// If the function succeeds, the return value is a handle to the new thread. + /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. + /// + /// Note that CreateThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address + /// is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start + /// address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of + /// CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs). + /// + /// + // HANDLE WINAPI CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ + // LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx + [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("WinBase.h", MSDNShortId = "ms682453")] + public static extern unsafe SafeHTHREAD CreateThread([In, Optional] SECURITY_ATTRIBUTES lpThreadAttributes, [Optional] SizeT dwStackSize, ThreadProcUnsafe lpStartAddress, + [In, Optional] void* lpParameter, [Optional] CREATE_THREAD_FLAGS dwCreationFlags, out uint lpThreadId); + /// Deletes the specified list of attributes for process and thread creation. /// The attribute list. This list is created by the . /// This function does not return a value. diff --git a/PInvoke/Kernel32/ThreadPoolLegacyApiSet.cs b/PInvoke/Kernel32/ThreadPoolLegacyApiSet.cs index 9fc39d5e..32f4e691 100644 --- a/PInvoke/Kernel32/ThreadPoolLegacyApiSet.cs +++ b/PInvoke/Kernel32/ThreadPoolLegacyApiSet.cs @@ -331,7 +331,7 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("WinBase.h", MSDNShortId = "ms684957")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool QueueUserWorkItem(PTHREAD_START_ROUTINE Function, [In] IntPtr Context, WT Flags); + public static extern bool QueueUserWorkItem(ThreadProc Function, [In] IntPtr Context, WT Flags); /// /// Directs a wait thread in the thread pool to wait on the object. The wait thread queues the specified callback function to the diff --git a/PInvoke/Security/Authz/Authz.cs b/PInvoke/Security/Authz/Authz.cs index b2233b86..a05b6302 100644 --- a/PInvoke/Security/Authz/Authz.cs +++ b/PInvoke/Security/Authz/Authz.cs @@ -1841,7 +1841,7 @@ namespace Vanara.PInvoke [DllImport(Lib.Authz, SetLastError = true, ExactSpelling = true)] [PInvokeData("authz.h", MSDNShortId = "B0675BB3-62FA-462E-8DFB-55C47576DFEC")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AuthzRegisterCapChangeNotification(out SafeAUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE phCapChangeSubscription, PTHREAD_START_ROUTINE pfnCapChangeCallback, IntPtr pCallbackContext); + public static extern bool AuthzRegisterCapChangeNotification(out SafeAUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE phCapChangeSubscription, ThreadProc pfnCapChangeCallback, IntPtr pCallbackContext); /// /// The AuthzRegisterSecurityEventSource function registers a security event source with the Local Security Authority (LSA).