mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 11:16:11 +00:00
[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. svn path=/trunk/; revision=56651
This commit is contained in:
parent
7b19834435
commit
7efa1d4b81
1 changed files with 251 additions and 210 deletions
|
@ -8,15 +8,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include <k32.h>
|
#include <k32.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
/* FIXME: NDK */
|
|
||||||
#define HIGH_PRIORITY 31
|
|
||||||
#define SXS_SUPPORT_FIXME
|
#define SXS_SUPPORT_FIXME
|
||||||
|
|
||||||
typedef NTSTATUS (NTAPI *PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId);
|
typedef NTSTATUS (NTAPI *PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId);
|
||||||
|
@ -26,7 +24,8 @@ WINAPI
|
||||||
BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
|
BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
|
||||||
IN PCLIENT_ID ClientId);
|
IN PCLIENT_ID ClientId);
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
static
|
static
|
||||||
LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
|
LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
|
||||||
{
|
{
|
||||||
|
@ -53,8 +52,8 @@ LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
|
||||||
__declspec(noreturn)
|
__declspec(noreturn)
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
BaseThreadStartup(IN LPTHREAD_START_ROUTINE lpStartAddress,
|
||||||
LPVOID lpParameter)
|
IN LPVOID lpParameter)
|
||||||
{
|
{
|
||||||
/* Attempt to call the Thread Start Address */
|
/* Attempt to call the Thread Start Address */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
|
@ -86,17 +85,58 @@ BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
||||||
_SEH2_END;
|
_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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HANDLE
|
HANDLE
|
||||||
WINAPI
|
WINAPI
|
||||||
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
DWORD dwStackSize,
|
IN DWORD dwStackSize,
|
||||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
IN LPTHREAD_START_ROUTINE lpStartAddress,
|
||||||
LPVOID lpParameter,
|
IN LPVOID lpParameter,
|
||||||
DWORD dwCreationFlags,
|
IN DWORD dwCreationFlags,
|
||||||
LPDWORD lpThreadId)
|
OUT LPDWORD lpThreadId)
|
||||||
{
|
{
|
||||||
/* Act as if we're going to create a remote thread in ourselves */
|
/* Act as if we're going to create a remote thread in ourselves */
|
||||||
return CreateRemoteThread(NtCurrentProcess(),
|
return CreateRemoteThread(NtCurrentProcess(),
|
||||||
|
@ -287,10 +327,15 @@ CreateRemoteThread(HANDLE hProcess,
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
ExitThread(DWORD uExitCode)
|
ExitThread(IN DWORD uExitCode)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG LastThread;
|
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
|
* Terminate process if this is the last thread
|
||||||
|
@ -301,11 +346,7 @@ ExitThread(DWORD uExitCode)
|
||||||
&LastThread,
|
&LastThread,
|
||||||
sizeof(LastThread),
|
sizeof(LastThread),
|
||||||
NULL);
|
NULL);
|
||||||
if (NT_SUCCESS(Status) && LastThread)
|
if ((NT_SUCCESS(Status)) && (LastThread)) ExitProcess(uExitCode);
|
||||||
{
|
|
||||||
/* Exit the Process */
|
|
||||||
ExitProcess(uExitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify DLLs and TLS Callbacks of termination */
|
/* Notify DLLs and TLS Callbacks of termination */
|
||||||
LdrShutdownThread();
|
LdrShutdownThread();
|
||||||
|
@ -316,7 +357,7 @@ ExitThread(DWORD uExitCode)
|
||||||
|
|
||||||
/* We should never reach this place */
|
/* We should never reach this place */
|
||||||
DPRINT1("It should not happen\n");
|
DPRINT1("It should not happen\n");
|
||||||
while (TRUE) ;
|
while (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -324,14 +365,14 @@ ExitThread(DWORD uExitCode)
|
||||||
*/
|
*/
|
||||||
HANDLE
|
HANDLE
|
||||||
WINAPI
|
WINAPI
|
||||||
OpenThread(DWORD dwDesiredAccess,
|
OpenThread(IN DWORD dwDesiredAccess,
|
||||||
BOOL bInheritHandle,
|
IN BOOL bInheritHandle,
|
||||||
DWORD dwThreadId)
|
IN DWORD dwThreadId)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
HANDLE ThreadHandle;
|
HANDLE ThreadHandle;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
CLIENT_ID ClientId ;
|
CLIENT_ID ClientId;
|
||||||
|
|
||||||
ClientId.UniqueProcess = 0;
|
ClientId.UniqueProcess = 0;
|
||||||
ClientId.UniqueThread = ULongToHandle(dwThreadId);
|
ClientId.UniqueThread = ULongToHandle(dwThreadId);
|
||||||
|
@ -390,11 +431,11 @@ GetCurrentThreadId(VOID)
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
NTAPI
|
NTAPI
|
||||||
GetThreadTimes(HANDLE hThread,
|
GetThreadTimes(IN HANDLE hThread,
|
||||||
LPFILETIME lpCreationTime,
|
OUT LPFILETIME lpCreationTime,
|
||||||
LPFILETIME lpExitTime,
|
OUT LPFILETIME lpExitTime,
|
||||||
LPFILETIME lpKernelTime,
|
OUT LPFILETIME lpKernelTime,
|
||||||
LPFILETIME lpUserTime)
|
OUT LPFILETIME lpUserTime)
|
||||||
{
|
{
|
||||||
KERNEL_USER_TIMES KernelUserTimes;
|
KERNEL_USER_TIMES KernelUserTimes;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -407,7 +448,7 @@ GetThreadTimes(HANDLE hThread,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
|
*lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
|
||||||
|
@ -422,8 +463,8 @@ GetThreadTimes(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
GetThreadContext(HANDLE hThread,
|
GetThreadContext(IN HANDLE hThread,
|
||||||
LPCONTEXT lpContext)
|
OUT LPCONTEXT lpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -442,8 +483,8 @@ GetThreadContext(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
SetThreadContext(HANDLE hThread,
|
SetThreadContext(IN HANDLE hThread,
|
||||||
CONST CONTEXT *lpContext)
|
IN CONST CONTEXT *lpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -462,8 +503,8 @@ SetThreadContext(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
GetExitCodeThread(HANDLE hThread,
|
GetExitCodeThread(IN HANDLE hThread,
|
||||||
LPDWORD lpExitCode)
|
OUT LPDWORD lpExitCode)
|
||||||
{
|
{
|
||||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -476,7 +517,7 @@ GetExitCodeThread(HANDLE hThread,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lpExitCode = ThreadBasic.ExitStatus;
|
*lpExitCode = ThreadBasic.ExitStatus;
|
||||||
|
@ -488,7 +529,7 @@ GetExitCodeThread(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
ResumeThread(HANDLE hThread)
|
ResumeThread(IN HANDLE hThread)
|
||||||
{
|
{
|
||||||
ULONG PreviousResumeCount;
|
ULONG PreviousResumeCount;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -508,24 +549,49 @@ ResumeThread(HANDLE hThread)
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
TerminateThread(HANDLE hThread,
|
TerminateThread(IN HANDLE hThread,
|
||||||
DWORD dwExitCode)
|
IN DWORD dwExitCode)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PRTL_CRITICAL_SECTION LoaderLock;
|
||||||
|
THREAD_BASIC_INFORMATION ThreadInfo;
|
||||||
|
|
||||||
|
/* Check for invalid thread handle */
|
||||||
if (!hThread)
|
if (!hThread)
|
||||||
{
|
{
|
||||||
|
/* Fail if one was passed */
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
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);
|
Status = NtTerminateThread(hThread, dwExitCode);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Fail */
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All done */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +600,7 @@ TerminateThread(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
SuspendThread(HANDLE hThread)
|
SuspendThread(IN HANDLE hThread)
|
||||||
{
|
{
|
||||||
ULONG PreviousSuspendCount;
|
ULONG PreviousSuspendCount;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -554,8 +620,8 @@ SuspendThread(HANDLE hThread)
|
||||||
*/
|
*/
|
||||||
DWORD_PTR
|
DWORD_PTR
|
||||||
WINAPI
|
WINAPI
|
||||||
SetThreadAffinityMask(HANDLE hThread,
|
SetThreadAffinityMask(IN HANDLE hThread,
|
||||||
DWORD_PTR dwThreadAffinityMask)
|
IN DWORD_PTR dwThreadAffinityMask)
|
||||||
{
|
{
|
||||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||||
KAFFINITY AffinityMask;
|
KAFFINITY AffinityMask;
|
||||||
|
@ -592,8 +658,8 @@ SetThreadAffinityMask(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
SetThreadPriority(HANDLE hThread,
|
SetThreadPriority(IN HANDLE hThread,
|
||||||
int nPriority)
|
IN int nPriority)
|
||||||
{
|
{
|
||||||
LONG Prio = nPriority;
|
LONG Prio = nPriority;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -601,10 +667,12 @@ SetThreadPriority(HANDLE hThread,
|
||||||
/* Check if values forcing saturation should be used */
|
/* Check if values forcing saturation should be used */
|
||||||
if (Prio == THREAD_PRIORITY_TIME_CRITICAL)
|
if (Prio == THREAD_PRIORITY_TIME_CRITICAL)
|
||||||
{
|
{
|
||||||
|
/* This is 16 */
|
||||||
Prio = (HIGH_PRIORITY + 1) / 2;
|
Prio = (HIGH_PRIORITY + 1) / 2;
|
||||||
}
|
}
|
||||||
else if (Prio == THREAD_PRIORITY_IDLE)
|
else if (Prio == THREAD_PRIORITY_IDLE)
|
||||||
{
|
{
|
||||||
|
/* This is -16 */
|
||||||
Prio = -((HIGH_PRIORITY + 1) / 2);
|
Prio = -((HIGH_PRIORITY + 1) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +697,7 @@ SetThreadPriority(HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
WINAPI
|
WINAPI
|
||||||
GetThreadPriority(HANDLE hThread)
|
GetThreadPriority(IN HANDLE hThread)
|
||||||
{
|
{
|
||||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -700,7 +768,7 @@ SetThreadPriorityBoost(IN HANDLE hThread,
|
||||||
ULONG PriorityBoost;
|
ULONG PriorityBoost;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PriorityBoost = (ULONG)bDisablePriorityBoost;
|
PriorityBoost = bDisablePriorityBoost != FALSE;
|
||||||
|
|
||||||
Status = NtSetInformationThread(hThread,
|
Status = NtSetInformationThread(hThread,
|
||||||
ThreadPriorityBoost,
|
ThreadPriorityBoost,
|
||||||
|
@ -756,8 +824,8 @@ GetThreadSelectorEntry(IN HANDLE hThread,
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
SetThreadIdealProcessor(HANDLE hThread,
|
SetThreadIdealProcessor(IN HANDLE hThread,
|
||||||
DWORD dwIdealProcessor)
|
IN DWORD dwIdealProcessor)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -777,8 +845,9 @@ SetThreadIdealProcessor(HANDLE hThread,
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI
|
DWORD
|
||||||
GetProcessIdOfThread(HANDLE Thread)
|
WINAPI
|
||||||
|
GetProcessIdOfThread(IN HANDLE Thread)
|
||||||
{
|
{
|
||||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -788,7 +857,7 @@ GetProcessIdOfThread(HANDLE Thread)
|
||||||
&ThreadBasic,
|
&ThreadBasic,
|
||||||
sizeof(THREAD_BASIC_INFORMATION),
|
sizeof(THREAD_BASIC_INFORMATION),
|
||||||
NULL);
|
NULL);
|
||||||
if(!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -800,8 +869,9 @@ GetProcessIdOfThread(HANDLE Thread)
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI
|
DWORD
|
||||||
GetThreadId(HANDLE Thread)
|
WINAPI
|
||||||
|
GetThreadId(IN HANDLE Thread)
|
||||||
{
|
{
|
||||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -811,7 +881,7 @@ GetThreadId(HANDLE Thread)
|
||||||
&ThreadBasic,
|
&ThreadBasic,
|
||||||
sizeof(THREAD_BASIC_INFORMATION),
|
sizeof(THREAD_BASIC_INFORMATION),
|
||||||
NULL);
|
NULL);
|
||||||
if(!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -823,151 +893,123 @@ GetThreadId(HANDLE Thread)
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
LANGID WINAPI
|
LANGID
|
||||||
SetThreadUILanguage(LANGID LangId)
|
WINAPI
|
||||||
|
SetThreadUILanguage(IN LANGID LangId)
|
||||||
{
|
{
|
||||||
DPRINT1("SetThreadUILanguage(0x%4x) unimplemented!\n", LangId);
|
UNIMPLEMENTED;
|
||||||
return LangId;
|
return NtCurrentTeb()->CurrentLocale;
|
||||||
}
|
|
||||||
|
|
||||||
static void CALLBACK
|
|
||||||
IntCallUserApc(PVOID Function, PVOID dwData, PVOID Argument3)
|
|
||||||
{
|
|
||||||
PAPCFUNC pfnAPC = (PAPCFUNC)Function;
|
|
||||||
pfnAPC((ULONG_PTR)dwData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI
|
DWORD
|
||||||
QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData)
|
WINAPI
|
||||||
|
QueueUserAPC(IN PAPCFUNC pfnAPC,
|
||||||
|
IN HANDLE hThread,
|
||||||
|
IN ULONG_PTR dwData)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
|
||||||
|
|
||||||
Status = NtQueueApcThread(hThread, IntCallUserApc, pfnAPC,
|
/* Zero the activation context and query information on it */
|
||||||
(PVOID)dwData, NULL);
|
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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
/* All good */
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
|
SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
|
||||||
{
|
{
|
||||||
STUB;
|
UNIMPLEMENTED;
|
||||||
return FALSE;
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
QueueUserWorkItem(
|
GetThreadIOPendingFlag(IN HANDLE hThread,
|
||||||
LPTHREAD_START_ROUTINE Function,
|
OUT PBOOL lpIOIsPending)
|
||||||
PVOID Context,
|
|
||||||
ULONG Flags
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
PQUEUE_USER_WORKITEM_CONTEXT WorkItemContext;
|
ULONG IoPending;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* Save the context for the trampoline function */
|
/* Query the flag */
|
||||||
WorkItemContext = RtlAllocateHeap(RtlGetProcessHeap(),
|
Status = NtQueryInformationThread(hThread,
|
||||||
0,
|
ThreadIsIoPending,
|
||||||
sizeof(*WorkItemContext));
|
&IoPending,
|
||||||
if (WorkItemContext == NULL)
|
sizeof(IoPending),
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
/* Return the flag */
|
||||||
return FALSE;
|
*lpIOIsPending = IoPending ? TRUE : FALSE;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkItemContext->Function = Function;
|
/* Fail */
|
||||||
WorkItemContext->Context = Context;
|
BaseSetLastNTError(Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* NOTE: Don't use Function directly since the callback signature
|
/*
|
||||||
differs. This might cause problems on certain platforms... */
|
* @implemented
|
||||||
Status = RtlQueueWorkItem(InternalWorkItemTrampoline,
|
*/
|
||||||
WorkItemContext,
|
BOOL
|
||||||
Flags);
|
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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Free the allocated context in case of failure */
|
/* Failed */
|
||||||
RtlFreeHeap(RtlGetProcessHeap(),
|
|
||||||
0,
|
|
||||||
WorkItemContext);
|
|
||||||
|
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,5 +1249,4 @@ TlsSetValue(IN DWORD Index,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue