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/…
==============================================================================
--- 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 */