Author: ion Date: Wed May 23 17:35:25 2012 New Revision: 56651
URL: http://svn.reactos.org/svn/reactos?rev=56651&view=rev Log: [KERNEL32]: Formatting cleanups and annotations. [KERNEL32]: Simplify QueueWorkItem since the trampoline is in Rtl. [KERNEL32]: Add SxS support to QueueUserApc. [KERNEL32]: Add some extra sanity checks/assertions in certain places.
Modified: trunk/reactos/dll/win32/kernel32/client/thread.c
Modified: trunk/reactos/dll/win32/kernel32/client/thread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/t... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/thread.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/thread.c [iso-8859-1] Wed May 23 17:35:25 2012 @@ -8,15 +8,13 @@ * */
-/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/
#include <k32.h>
#define NDEBUG #include <debug.h>
-/* FIXME: NDK */ -#define HIGH_PRIORITY 31 #define SXS_SUPPORT_FIXME
typedef NTSTATUS (NTAPI *PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId); @@ -26,14 +24,15 @@ BasepNotifyCsrOfThread(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId);
-/* FUNCTIONS *****************************************************************/ +/* FUNCTIONS ******************************************************************/ + static LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo) { LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER; LPTOP_LEVEL_EXCEPTION_FILTER RealFilter; RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter); - + if (RealFilter != NULL) { _SEH2_TRY @@ -53,8 +52,8 @@ __declspec(noreturn) VOID WINAPI -BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter) +BaseThreadStartup(IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter) { /* Attempt to call the Thread Start Address */ _SEH2_TRY @@ -86,17 +85,58 @@ _SEH2_END; }
+VOID +NTAPI +BaseDispatchApc(IN PAPCFUNC ApcRoutine, + IN PVOID Data, + IN PACTIVATION_CONTEXT ActivationContext) +{ + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame; + + /* Setup the activation context */ + ActivationFrame.Size = sizeof(ActivationFrame); + ActivationFrame.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + + /* Check if caller wanted one */ + if (ActivationContext == INVALID_ACTIVATION_CONTEXT) + { + /* Do the APC directly */ + ApcRoutine((ULONG_PTR)Data); + return; + } + + /* Then activate it */ + RtlActivateActivationContextUnsafeFast(&ActivationFrame, ActivationContext); + + /* Call the routine under SEH */ + _SEH2_TRY + { + ApcRoutine((ULONG_PTR)Data); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + + } + _SEH2_END; + + /* Now de-activate and release the activation context */ + RtlDeactivateActivationContextUnsafeFast(&ActivationFrame); + RtlReleaseActivationContext(ActivationContext); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + /* * @implemented */ HANDLE WINAPI -CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, - DWORD dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId) +CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN DWORD dwStackSize, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter, + IN DWORD dwCreationFlags, + OUT LPDWORD lpThreadId) { /* Act as if we're going to create a remote thread in ourselves */ return CreateRemoteThread(NtCurrentProcess(), @@ -251,7 +291,7 @@ if (hProcess != NtCurrentProcess()) { PCSR_CREATE_REMOTE_THREAD CsrCreateRemoteThread; - + /* Get the direct CSRSRV export */ CsrCreateRemoteThread = (PCSR_CREATE_REMOTE_THREAD) GetProcAddress(GetModuleHandleA("csrsrv"), @@ -263,7 +303,7 @@ } } } - + if (!NT_SUCCESS(Status)) { ASSERT(FALSE); @@ -287,10 +327,15 @@ */ VOID WINAPI -ExitThread(DWORD uExitCode) +ExitThread(IN DWORD uExitCode) { NTSTATUS Status; ULONG LastThread; + PRTL_CRITICAL_SECTION LoaderLock; + + /* Make sure loader lock isn't held */ + LoaderLock = NtCurrentPeb()->LoaderLock; + if (LoaderLock) ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread);
/* * Terminate process if this is the last thread @@ -301,11 +346,7 @@ &LastThread, sizeof(LastThread), NULL); - if (NT_SUCCESS(Status) && LastThread) - { - /* Exit the Process */ - ExitProcess(uExitCode); - } + if ((NT_SUCCESS(Status)) && (LastThread)) ExitProcess(uExitCode);
/* Notify DLLs and TLS Callbacks of termination */ LdrShutdownThread(); @@ -316,7 +357,7 @@
/* We should never reach this place */ DPRINT1("It should not happen\n"); - while (TRUE) ; + while (TRUE); }
/* @@ -324,14 +365,14 @@ */ HANDLE WINAPI -OpenThread(DWORD dwDesiredAccess, - BOOL bInheritHandle, - DWORD dwThreadId) +OpenThread(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN DWORD dwThreadId) { NTSTATUS Status; HANDLE ThreadHandle; OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId ; + CLIENT_ID ClientId;
ClientId.UniqueProcess = 0; ClientId.UniqueThread = ULongToHandle(dwThreadId); @@ -390,11 +431,11 @@ */ BOOL NTAPI -GetThreadTimes(HANDLE hThread, - LPFILETIME lpCreationTime, - LPFILETIME lpExitTime, - LPFILETIME lpKernelTime, - LPFILETIME lpUserTime) +GetThreadTimes(IN HANDLE hThread, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) { KERNEL_USER_TIMES KernelUserTimes; NTSTATUS Status; @@ -407,7 +448,7 @@ if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); - return(FALSE); + return FALSE; }
*lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime; @@ -422,8 +463,8 @@ */ BOOL WINAPI -GetThreadContext(HANDLE hThread, - LPCONTEXT lpContext) +GetThreadContext(IN HANDLE hThread, + OUT LPCONTEXT lpContext) { NTSTATUS Status;
@@ -442,8 +483,8 @@ */ BOOL WINAPI -SetThreadContext(HANDLE hThread, - CONST CONTEXT *lpContext) +SetThreadContext(IN HANDLE hThread, + IN CONST CONTEXT *lpContext) { NTSTATUS Status;
@@ -462,8 +503,8 @@ */ BOOL WINAPI -GetExitCodeThread(HANDLE hThread, - LPDWORD lpExitCode) +GetExitCodeThread(IN HANDLE hThread, + OUT LPDWORD lpExitCode) { THREAD_BASIC_INFORMATION ThreadBasic; NTSTATUS Status; @@ -476,7 +517,7 @@ if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); - return(FALSE); + return FALSE; }
*lpExitCode = ThreadBasic.ExitStatus; @@ -488,7 +529,7 @@ */ DWORD WINAPI -ResumeThread(HANDLE hThread) +ResumeThread(IN HANDLE hThread) { ULONG PreviousResumeCount; NTSTATUS Status; @@ -508,24 +549,49 @@ */ BOOL WINAPI -TerminateThread(HANDLE hThread, - DWORD dwExitCode) -{ - NTSTATUS Status; - +TerminateThread(IN HANDLE hThread, + IN DWORD dwExitCode) +{ + NTSTATUS Status; + PRTL_CRITICAL_SECTION LoaderLock; + THREAD_BASIC_INFORMATION ThreadInfo; + + /* Check for invalid thread handle */ if (!hThread) { + /* Fail if one was passed */ SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
+ /* Get the loader lock */ + LoaderLock = NtCurrentPeb()->LoaderLock; + if (LoaderLock) + { + /* Get our TID */ + Status = NtQueryInformationThread(hThread, + ThreadBasicInformation, + &ThreadInfo, + sizeof(ThreadInfo), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Assert that we don't hold the loader lock */ + ASSERT(NtCurrentTeb()->ClientId.UniqueThread != ThreadInfo.ClientId.UniqueThread); + ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread); + } + } + + /* Now terminate the thread */ Status = NtTerminateThread(hThread, dwExitCode); if (!NT_SUCCESS(Status)) { - BaseSetLastNTError(Status); - return FALSE; - } - + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* All done */ return TRUE; }
@@ -534,7 +600,7 @@ */ DWORD WINAPI -SuspendThread(HANDLE hThread) +SuspendThread(IN HANDLE hThread) { ULONG PreviousSuspendCount; NTSTATUS Status; @@ -554,8 +620,8 @@ */ DWORD_PTR WINAPI -SetThreadAffinityMask(HANDLE hThread, - DWORD_PTR dwThreadAffinityMask) +SetThreadAffinityMask(IN HANDLE hThread, + IN DWORD_PTR dwThreadAffinityMask) { THREAD_BASIC_INFORMATION ThreadBasic; KAFFINITY AffinityMask; @@ -592,8 +658,8 @@ */ BOOL WINAPI -SetThreadPriority(HANDLE hThread, - int nPriority) +SetThreadPriority(IN HANDLE hThread, + IN int nPriority) { LONG Prio = nPriority; NTSTATUS Status; @@ -601,10 +667,12 @@ /* Check if values forcing saturation should be used */ if (Prio == THREAD_PRIORITY_TIME_CRITICAL) { + /* This is 16 */ Prio = (HIGH_PRIORITY + 1) / 2; } else if (Prio == THREAD_PRIORITY_IDLE) { + /* This is -16 */ Prio = -((HIGH_PRIORITY + 1) / 2); }
@@ -629,7 +697,7 @@ */ int WINAPI -GetThreadPriority(HANDLE hThread) +GetThreadPriority(IN HANDLE hThread) { THREAD_BASIC_INFORMATION ThreadBasic; NTSTATUS Status; @@ -700,7 +768,7 @@ ULONG PriorityBoost; NTSTATUS Status;
- PriorityBoost = (ULONG)bDisablePriorityBoost; + PriorityBoost = bDisablePriorityBoost != FALSE;
Status = NtSetInformationThread(hThread, ThreadPriorityBoost, @@ -756,8 +824,8 @@ */ DWORD WINAPI -SetThreadIdealProcessor(HANDLE hThread, - DWORD dwIdealProcessor) +SetThreadIdealProcessor(IN HANDLE hThread, + IN DWORD dwIdealProcessor) { NTSTATUS Status;
@@ -777,197 +845,171 @@ /* * @implemented */ -DWORD WINAPI -GetProcessIdOfThread(HANDLE Thread) -{ - THREAD_BASIC_INFORMATION ThreadBasic; - NTSTATUS Status; - - Status = NtQueryInformationThread(Thread, - ThreadBasicInformation, - &ThreadBasic, - sizeof(THREAD_BASIC_INFORMATION), - NULL); - if(!NT_SUCCESS(Status)) - { +DWORD +WINAPI +GetProcessIdOfThread(IN HANDLE Thread) +{ + THREAD_BASIC_INFORMATION ThreadBasic; + NTSTATUS Status; + + Status = NtQueryInformationThread(Thread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return HandleToUlong(ThreadBasic.ClientId.UniqueProcess); +} + +/* + * @implemented + */ +DWORD +WINAPI +GetThreadId(IN HANDLE Thread) +{ + THREAD_BASIC_INFORMATION ThreadBasic; + NTSTATUS Status; + + Status = NtQueryInformationThread(Thread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return HandleToUlong(ThreadBasic.ClientId.UniqueThread); +} + +/* + * @unimplemented + */ +LANGID +WINAPI +SetThreadUILanguage(IN LANGID LangId) +{ + UNIMPLEMENTED; + return NtCurrentTeb()->CurrentLocale; +} + +/* + * @implemented + */ +DWORD +WINAPI +QueueUserAPC(IN PAPCFUNC pfnAPC, + IN HANDLE hThread, + IN ULONG_PTR dwData) +{ + NTSTATUS Status; + ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo; + + /* Zero the activation context and query information on it */ + RtlZeroMemory(&ActCtxInfo, sizeof(ActCtxInfo)); + // WARNING!!! THIS IS USING THE WIN32 FLAG BECAUSE REACTOS CONTINUES TO BE A POS!!! /// + Status = RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, + NULL, + 0, + ActivationContextBasicInformation, + &ActCtxInfo, + sizeof(ActCtxInfo), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail due to SxS */ + DbgPrint("SXS: %s failing because RtlQueryInformationActivationContext()" + "returned status %08lx\n", __FUNCTION__, Status); + BaseSetLastNTError(Status); + return FALSE; + } + + /* Queue the APC */ + Status = NtQueueApcThread(hThread, + (PKNORMAL_ROUTINE)BaseDispatchApc, + pfnAPC, + (PVOID)dwData, + (ActCtxInfo.dwFlags & 1) ? + INVALID_ACTIVATION_CONTEXT : ActCtxInfo.hActCtx); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + /* All good */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes) +{ + UNIMPLEMENTED; + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetThreadIOPendingFlag(IN HANDLE hThread, + OUT PBOOL lpIOIsPending) +{ + ULONG IoPending; + NTSTATUS Status; + + /* Query the flag */ + Status = NtQueryInformationThread(hThread, + ThreadIsIoPending, + &IoPending, + sizeof(IoPending), + NULL); + if (NT_SUCCESS(Status)) + { + /* Return the flag */ + *lpIOIsPending = IoPending ? TRUE : FALSE; + return TRUE; + } + + /* Fail */ BaseSetLastNTError(Status); - return 0; - } - - return HandleToUlong(ThreadBasic.ClientId.UniqueProcess); -} - -/* - * @implemented - */ -DWORD WINAPI -GetThreadId(HANDLE Thread) -{ - THREAD_BASIC_INFORMATION ThreadBasic; - NTSTATUS Status; - - Status = NtQueryInformationThread(Thread, - ThreadBasicInformation, - &ThreadBasic, - sizeof(THREAD_BASIC_INFORMATION), - NULL); - if(!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - return 0; - } - - return HandleToUlong(ThreadBasic.ClientId.UniqueThread); -} - -/* - * @unimplemented - */ -LANGID WINAPI -SetThreadUILanguage(LANGID LangId) -{ - DPRINT1("SetThreadUILanguage(0x%4x) unimplemented!\n", LangId); - return LangId; -} - -static void CALLBACK -IntCallUserApc(PVOID Function, PVOID dwData, PVOID Argument3) -{ - PAPCFUNC pfnAPC = (PAPCFUNC)Function; - pfnAPC((ULONG_PTR)dwData); -} - -/* - * @implemented - */ -DWORD WINAPI -QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData) -{ - NTSTATUS Status; - - Status = NtQueueApcThread(hThread, IntCallUserApc, pfnAPC, - (PVOID)dwData, NULL); - if (!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - return 0; - } - - return 1; -} - -BOOL -WINAPI -SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes) -{ - STUB; return FALSE; }
- -/* - * @implemented - */ -BOOL WINAPI -GetThreadIOPendingFlag(HANDLE hThread, - PBOOL lpIOIsPending) -{ - ULONG IoPending; - NTSTATUS Status; - - if(lpIOIsPending == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - Status = NtQueryInformationThread(hThread, - ThreadIsIoPending, - (PVOID)&IoPending, - sizeof(IoPending), - NULL); - if(NT_SUCCESS(Status)) - { - *lpIOIsPending = ((IoPending != 0) ? TRUE : FALSE); - return TRUE; - } - - BaseSetLastNTError(Status); - return FALSE; -} - - -typedef struct _QUEUE_USER_WORKITEM_CONTEXT -{ - LPTHREAD_START_ROUTINE Function; - PVOID Context; -} QUEUE_USER_WORKITEM_CONTEXT, *PQUEUE_USER_WORKITEM_CONTEXT; - -static VOID -NTAPI -InternalWorkItemTrampoline(PVOID Context) -{ - QUEUE_USER_WORKITEM_CONTEXT Info; - - ASSERT(Context); - - /* Save the context to the stack */ - Info = *(volatile QUEUE_USER_WORKITEM_CONTEXT *)Context; - - /* Free the context before calling the callback. This avoids - a memory leak in case the thread dies... */ - RtlFreeHeap(RtlGetProcessHeap(), - 0, - Context); - - /* Call the real callback */ - Info.Function(Info.Context); -} - - -/* - * @implemented - */ -BOOL -WINAPI -QueueUserWorkItem( - LPTHREAD_START_ROUTINE Function, - PVOID Context, - ULONG Flags - ) -{ - PQUEUE_USER_WORKITEM_CONTEXT WorkItemContext; - NTSTATUS Status; - - /* Save the context for the trampoline function */ - WorkItemContext = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(*WorkItemContext)); - if (WorkItemContext == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - WorkItemContext->Function = Function; - WorkItemContext->Context = Context; - - /* NOTE: Don't use Function directly since the callback signature - differs. This might cause problems on certain platforms... */ - Status = RtlQueueWorkItem(InternalWorkItemTrampoline, - WorkItemContext, - Flags); - if (!NT_SUCCESS(Status)) - { - /* Free the allocated context in case of failure */ - RtlFreeHeap(RtlGetProcessHeap(), - 0, - WorkItemContext); - - BaseSetLastNTError(Status); - return FALSE; - } - +/* + * @implemented + */ +BOOL +WINAPI +QueueUserWorkItem(IN LPTHREAD_START_ROUTINE Function, + IN PVOID Context, + IN ULONG Flags) +{ + NTSTATUS Status; + + /* NOTE: Rtl needs to safely call the function using a trampoline */ + Status = RtlQueueWorkItem((WORKERCALLBACKFUNC)Function, Context, Flags); + if (!NT_SUCCESS(Status)) + { + /* Failed */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* All good */ return TRUE; }
@@ -1207,5 +1249,4 @@ return TRUE; }
- /* EOF */