mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 08:56:08 +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>
|
||||
|
||||
#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 @@ WINAPI
|
|||
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 @@ LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
|
|||
__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 @@ BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
|||
_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 @@ CreateRemoteThread(HANDLE hProcess,
|
|||
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 @@ CreateRemoteThread(HANDLE hProcess,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
|
@ -287,10 +327,15 @@ CreateRemoteThread(HANDLE hProcess,
|
|||
*/
|
||||
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 @@ ExitThread(DWORD uExitCode)
|
|||
&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 @@ ExitThread(DWORD uExitCode)
|
|||
|
||||
/* We should never reach this place */
|
||||
DPRINT1("It should not happen\n");
|
||||
while (TRUE) ;
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -324,14 +365,14 @@ ExitThread(DWORD uExitCode)
|
|||
*/
|
||||
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 @@ GetCurrentThreadId(VOID)
|
|||
*/
|
||||
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 @@ GetThreadTimes(HANDLE hThread,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
|
||||
|
@ -422,8 +463,8 @@ GetThreadTimes(HANDLE hThread,
|
|||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetThreadContext(HANDLE hThread,
|
||||
LPCONTEXT lpContext)
|
||||
GetThreadContext(IN HANDLE hThread,
|
||||
OUT LPCONTEXT lpContext)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -442,8 +483,8 @@ GetThreadContext(HANDLE hThread,
|
|||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetThreadContext(HANDLE hThread,
|
||||
CONST CONTEXT *lpContext)
|
||||
SetThreadContext(IN HANDLE hThread,
|
||||
IN CONST CONTEXT *lpContext)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -462,8 +503,8 @@ SetThreadContext(HANDLE hThread,
|
|||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetExitCodeThread(HANDLE hThread,
|
||||
LPDWORD lpExitCode)
|
||||
GetExitCodeThread(IN HANDLE hThread,
|
||||
OUT LPDWORD lpExitCode)
|
||||
{
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
|
@ -476,7 +517,7 @@ GetExitCodeThread(HANDLE hThread,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpExitCode = ThreadBasic.ExitStatus;
|
||||
|
@ -488,7 +529,7 @@ GetExitCodeThread(HANDLE hThread,
|
|||
*/
|
||||
DWORD
|
||||
WINAPI
|
||||
ResumeThread(HANDLE hThread)
|
||||
ResumeThread(IN HANDLE hThread)
|
||||
{
|
||||
ULONG PreviousResumeCount;
|
||||
NTSTATUS Status;
|
||||
|
@ -508,24 +549,49 @@ ResumeThread(HANDLE hThread)
|
|||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
TerminateThread(HANDLE hThread,
|
||||
DWORD dwExitCode)
|
||||
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))
|
||||
{
|
||||
/* Fail */
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -534,7 +600,7 @@ TerminateThread(HANDLE hThread,
|
|||
*/
|
||||
DWORD
|
||||
WINAPI
|
||||
SuspendThread(HANDLE hThread)
|
||||
SuspendThread(IN HANDLE hThread)
|
||||
{
|
||||
ULONG PreviousSuspendCount;
|
||||
NTSTATUS Status;
|
||||
|
@ -554,8 +620,8 @@ SuspendThread(HANDLE hThread)
|
|||
*/
|
||||
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 @@ SetThreadAffinityMask(HANDLE hThread,
|
|||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetThreadPriority(HANDLE hThread,
|
||||
int nPriority)
|
||||
SetThreadPriority(IN HANDLE hThread,
|
||||
IN int nPriority)
|
||||
{
|
||||
LONG Prio = nPriority;
|
||||
NTSTATUS Status;
|
||||
|
@ -601,10 +667,12 @@ SetThreadPriority(HANDLE hThread,
|
|||
/* 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 @@ SetThreadPriority(HANDLE hThread,
|
|||
*/
|
||||
int
|
||||
WINAPI
|
||||
GetThreadPriority(HANDLE hThread)
|
||||
GetThreadPriority(IN HANDLE hThread)
|
||||
{
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
|
@ -700,7 +768,7 @@ SetThreadPriorityBoost(IN HANDLE hThread,
|
|||
ULONG PriorityBoost;
|
||||
NTSTATUS Status;
|
||||
|
||||
PriorityBoost = (ULONG)bDisablePriorityBoost;
|
||||
PriorityBoost = bDisablePriorityBoost != FALSE;
|
||||
|
||||
Status = NtSetInformationThread(hThread,
|
||||
ThreadPriorityBoost,
|
||||
|
@ -756,8 +824,8 @@ GetThreadSelectorEntry(IN HANDLE hThread,
|
|||
*/
|
||||
DWORD
|
||||
WINAPI
|
||||
SetThreadIdealProcessor(HANDLE hThread,
|
||||
DWORD dwIdealProcessor)
|
||||
SetThreadIdealProcessor(IN HANDLE hThread,
|
||||
IN DWORD dwIdealProcessor)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -777,197 +845,171 @@ SetThreadIdealProcessor(HANDLE hThread,
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
DWORD WINAPI
|
||||
GetProcessIdOfThread(HANDLE Thread)
|
||||
DWORD
|
||||
WINAPI
|
||||
GetProcessIdOfThread(IN HANDLE Thread)
|
||||
{
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = NtQueryInformationThread(Thread,
|
||||
ThreadBasicInformation,
|
||||
&ThreadBasic,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return 0;
|
||||
}
|
||||
Status = NtQueryInformationThread(Thread,
|
||||
ThreadBasicInformation,
|
||||
&ThreadBasic,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HandleToUlong(ThreadBasic.ClientId.UniqueProcess);
|
||||
return HandleToUlong(ThreadBasic.ClientId.UniqueProcess);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
DWORD WINAPI
|
||||
GetThreadId(HANDLE Thread)
|
||||
DWORD
|
||||
WINAPI
|
||||
GetThreadId(IN HANDLE Thread)
|
||||
{
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
THREAD_BASIC_INFORMATION ThreadBasic;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = NtQueryInformationThread(Thread,
|
||||
ThreadBasicInformation,
|
||||
&ThreadBasic,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return 0;
|
||||
}
|
||||
Status = NtQueryInformationThread(Thread,
|
||||
ThreadBasicInformation,
|
||||
&ThreadBasic,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HandleToUlong(ThreadBasic.ClientId.UniqueThread);
|
||||
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
|
||||
LANGID
|
||||
WINAPI
|
||||
SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
|
||||
SetThreadUILanguage(IN LANGID LangId)
|
||||
{
|
||||
STUB;
|
||||
return FALSE;
|
||||
UNIMPLEMENTED;
|
||||
return NtCurrentTeb()->CurrentLocale;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @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
|
||||
DWORD
|
||||
WINAPI
|
||||
QueueUserWorkItem(
|
||||
LPTHREAD_START_ROUTINE Function,
|
||||
PVOID Context,
|
||||
ULONG Flags
|
||||
)
|
||||
QueueUserAPC(IN PAPCFUNC pfnAPC,
|
||||
IN HANDLE hThread,
|
||||
IN ULONG_PTR dwData)
|
||||
{
|
||||
PQUEUE_USER_WORKITEM_CONTEXT WorkItemContext;
|
||||
NTSTATUS Status;
|
||||
ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
|
||||
|
||||
/* 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);
|
||||
/* 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))
|
||||
{
|
||||
/* Free the allocated context in case of failure */
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
WorkItemContext);
|
||||
|
||||
/* 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 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 @@ TlsSetValue(IN DWORD Index,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue