kernel32: Move thread functions to kernelbase.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-08-08 14:25:50 +02:00
parent adac42bad6
commit 0116660dd8
6 changed files with 558 additions and 735 deletions

View File

@ -316,8 +316,8 @@
@ stdcall CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr)
# @ stub CreateProcessInternalWSecure
@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall CreateRemoteThread(long ptr long ptr long long ptr)
@ stdcall CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr)
@ stdcall -import CreateRemoteThread(long ptr long ptr long long ptr)
@ stdcall -import CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr)
@ stdcall CreateSemaphoreA(ptr long long str)
@ stdcall CreateSemaphoreExA(ptr long long str long long)
@ stdcall -import CreateSemaphoreExW(ptr long long wstr long long)
@ -328,7 +328,7 @@
# @ stub CreateSymbolicLinkTransactedW
@ stdcall CreateSymbolicLinkW(wstr wstr long)
@ stdcall CreateTapePartition(long long long long)
@ stdcall CreateThread(ptr long ptr long long ptr)
@ stdcall -import CreateThread(ptr long ptr long long ptr)
@ stdcall CreateThreadpool(ptr)
@ stdcall CreateThreadpoolCleanupGroup()
@ stdcall CreateThreadpoolIo(ptr ptr ptr ptr)
@ -437,7 +437,7 @@
@ stdcall EscapeCommFunction(long long)
@ stdcall -arch=x86_64 ExecuteUmsThread(ptr)
@ stdcall ExitProcess(long)
@ stdcall ExitThread(long)
@ stdcall ExitThread(long) ntdll.RtlExitUserThread
@ stub ExitVDM
@ stdcall ExpandEnvironmentStringsA(str ptr long)
@ stdcall ExpandEnvironmentStringsW(wstr ptr long)
@ -635,7 +635,7 @@
@ stdcall GetCurrentProcessorNumberEx(ptr) ntdll.RtlGetCurrentProcessorNumberEx
@ stdcall -norelay GetCurrentThread() KERNEL32_GetCurrentThread
@ stdcall -norelay GetCurrentThreadId() KERNEL32_GetCurrentThreadId
@ stdcall GetCurrentThreadStackLimits(ptr ptr)
@ stdcall -import GetCurrentThreadStackLimits(ptr ptr)
@ stdcall -arch=x86_64 GetCurrentUmsThread()
@ stdcall GetDateFormatA(long long ptr str ptr long)
@ stdcall GetDateFormatEx(wstr long ptr wstr ptr long wstr)
@ -666,7 +666,7 @@
# @ stub GetEraNameCountedString
@ stdcall GetErrorMode()
@ stdcall GetExitCodeProcess(long ptr)
@ stdcall GetExitCodeThread(long ptr)
@ stdcall -import GetExitCodeThread(long ptr)
@ stdcall GetExpandedNameA(str ptr)
@ stdcall GetExpandedNameW(wstr ptr)
@ stdcall GetFileAttributesA(str)
@ -783,7 +783,7 @@
@ stdcall -norelay GetProcessHeap() KERNEL32_GetProcessHeap
@ stdcall GetProcessHeaps(long ptr)
@ stdcall GetProcessId(long)
@ stdcall GetProcessIdOfThread(long)
@ stdcall -import GetProcessIdOfThread(long)
@ stdcall GetProcessIoCounters(long ptr)
@ stdcall GetProcessMitigationPolicy(long long ptr long)
@ stdcall GetProcessPreferredUILanguages(long ptr ptr ptr)
@ -846,18 +846,19 @@
@ stdcall GetTempFileNameW(wstr wstr long ptr)
@ stdcall GetTempPathA(long ptr)
@ stdcall GetTempPathW(long ptr)
@ stdcall GetThreadContext(long ptr)
@ stdcall GetThreadErrorMode()
@ stdcall GetThreadGroupAffinity(long ptr)
@ stdcall GetThreadId(ptr)
@ stdcall -import GetThreadContext(long ptr)
@ stdcall -import GetThreadErrorMode()
@ stdcall -import GetThreadGroupAffinity(long ptr)
@ stdcall -import GetThreadIOPendingFlag(long ptr)
@ stdcall -import GetThreadId(ptr)
# @ stub GetThreadIdealProcessorEx
@ stdcall GetThreadIOPendingFlag(long ptr)
@ stdcall GetThreadLocale()
@ stdcall GetThreadPreferredUILanguages(long ptr ptr ptr)
@ stdcall GetThreadPriority(long)
@ stdcall GetThreadPriorityBoost(long ptr)
@ stdcall -import GetThreadPriority(long)
@ stdcall -import GetThreadPriorityBoost(long ptr)
@ stdcall GetThreadSelectorEntry(long long ptr)
@ stdcall GetThreadTimes(long ptr ptr ptr ptr)
@ stdcall -import GetThreadTimes(long ptr ptr ptr ptr)
@ stdcall -import GetThreadUILanguage()
@ stdcall GetTickCount()
@ stdcall -ret64 GetTickCount64()
@ stdcall GetTimeFormatA(long long ptr str ptr long)
@ -865,7 +866,6 @@
@ stdcall GetTimeFormatW(long long ptr wstr ptr long)
@ stdcall GetTimeZoneInformation(ptr)
@ stdcall GetTimeZoneInformationForYear(long ptr ptr)
@ stdcall GetThreadUILanguage()
# @ stub GetUILanguageInfo
@ stdcall -arch=x86_64 GetUmsCompletionListEvent(ptr ptr)
# @ stub -arch=x86_64 GetUmsSystemThreadInformation
@ -1129,7 +1129,7 @@
@ stdcall OpenProfileUserMapping()
@ stdcall OpenSemaphoreA(long long str)
@ stdcall -import OpenSemaphoreW(long long wstr)
@ stdcall OpenThread(long long long)
@ stdcall -import OpenThread(long long long)
# @ stub OpenThreadToken
@ stdcall -i386 OpenVxDHandle(long)
@ stdcall OpenWaitableTimerA(long long str)
@ -1179,7 +1179,7 @@
@ stdcall -arch=x86_64 QueryUmsThreadInformation(ptr long ptr long ptr)
@ stdcall QueryUnbiasedInterruptTime(ptr)
@ stub QueryWin31IniFilesMappedToRegistry
@ stdcall QueueUserAPC(ptr long long)
@ stdcall -import QueueUserAPC(ptr long long)
@ stdcall QueueUserWorkItem(ptr ptr long)
@ stdcall RaiseException(long long long ptr)
# @ stub RaiseFailFastException
@ -1284,7 +1284,7 @@
@ stdcall ResolveDelayLoadedAPI(ptr ptr ptr ptr ptr long) ntdll.LdrResolveDelayLoadedAPI
@ stdcall ResolveLocaleName(wstr ptr long)
@ stdcall RestoreLastError(long) ntdll.RtlRestoreLastWin32Error
@ stdcall ResumeThread(long)
@ stdcall -import ResumeThread(long)
@ cdecl -arch=arm,arm64,x86_64 RtlAddFunctionTable(ptr long long) ntdll.RtlAddFunctionTable
@ stdcall -norelay RtlCaptureContext(ptr) ntdll.RtlCaptureContext
@ stdcall RtlCaptureStackBackTrace(long long ptr ptr) ntdll.RtlCaptureStackBackTrace
@ -1446,17 +1446,17 @@
@ stdcall SetTapePosition(ptr long long long long long)
@ stdcall SetTermsrvAppInstallMode(long)
@ stdcall SetThreadAffinityMask(long long)
@ stdcall SetThreadContext(long ptr)
@ stdcall SetThreadErrorMode(long ptr)
@ stdcall -import SetThreadContext(long ptr)
@ stdcall -import SetThreadErrorMode(long ptr)
@ stdcall SetThreadExecutionState(long)
@ stdcall SetThreadGroupAffinity(long ptr ptr)
@ stdcall SetThreadIdealProcessor(long long)
@ stdcall SetThreadIdealProcessorEx(long ptr ptr)
@ stdcall -import SetThreadGroupAffinity(long ptr ptr)
@ stdcall -import SetThreadIdealProcessor(long long)
@ stdcall -import SetThreadIdealProcessorEx(long ptr ptr)
@ stdcall SetThreadLocale(long)
@ stdcall SetThreadPreferredUILanguages(long ptr ptr)
@ stdcall SetThreadPriority(long long)
@ stdcall SetThreadPriorityBoost(long long)
@ stdcall SetThreadStackGuarantee(ptr)
@ stdcall -import SetThreadPriority(long long)
@ stdcall -import SetThreadPriorityBoost(long long)
@ stdcall -import SetThreadStackGuarantee(ptr)
# @ stub SetThreadToken
@ stdcall SetThreadUILanguage(long)
# @ stub SetThreadpoolStackInformation
@ -1489,15 +1489,15 @@
# @ stub SortGetHandle
# @ stub StartThreadpoolIo
@ stdcall SubmitThreadpoolWork(ptr) ntdll.TpPostWork
@ stdcall SuspendThread(long)
@ stdcall -import SuspendThread(long)
@ stdcall SwitchToFiber(ptr)
@ stdcall SwitchToThread()
@ stdcall -import SwitchToThread()
@ stdcall SystemTimeToFileTime(ptr ptr)
@ stdcall SystemTimeToTzSpecificLocalTime (ptr ptr ptr)
# @ stub SystemTimeToTzSpecificLocalTimeEx
@ stdcall TerminateJobObject(long long)
@ stdcall TerminateProcess(long long)
@ stdcall TerminateThread(long long)
@ stdcall -import TerminateThread(long long)
@ stdcall TermsrvAppInstallMode()
@ stdcall Thread32First(long ptr)
@ stdcall Thread32Next(long ptr)

View File

@ -83,15 +83,6 @@ static BOOL get_open_object_attributes( OBJECT_ATTRIBUTES *attr, UNICODE_STRING
return TRUE;
}
/***********************************************************************
* SwitchToThread (KERNEL32.@)
*/
BOOL WINAPI SwitchToThread(void)
{
return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
}
static HANDLE normalize_handle_if_console(HANDLE handle)
{
if ((handle == (HANDLE)STD_INPUT_HANDLE) ||

View File

@ -46,143 +46,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(thread);
/***********************************************************************
* CreateThread (KERNEL32.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack, LPTHREAD_START_ROUTINE start,
LPVOID param, DWORD flags, LPDWORD id )
{
return CreateRemoteThread( GetCurrentProcess(),
sa, stack, start, param, flags, id );
}
/***************************************************************************
* CreateRemoteThread (KERNEL32.@)
*/
HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, DWORD *id )
{
return CreateRemoteThreadEx( hProcess, sa, stack, start, param, flags, NULL, id );
}
/***************************************************************************
* CreateRemoteThreadEx (KERNEL32.@)
*
* Creates a thread that runs in the address space of another process
*
* PARAMS
*
* RETURNS
* Success: Handle to the new thread.
* Failure: NULL. Use GetLastError() to find the error cause.
*
* BUGS
* Improper memory allocation: there's no ability to free new_thread_info
* in other process.
* Bad start address for RtlCreateUserThread because the library
* may be loaded at different address in other process.
*/
HANDLE WINAPI CreateRemoteThreadEx( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags,
LPPROC_THREAD_ATTRIBUTE_LIST attributes, DWORD *id )
{
HANDLE handle;
CLIENT_ID client_id;
NTSTATUS status;
SIZE_T stack_reserve = 0, stack_commit = 0;
if (attributes)
FIXME("thread attributes ignored\n");
if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
else stack_commit = stack;
status = RtlCreateUserThread( hProcess, sa ? sa->lpSecurityDescriptor : NULL, TRUE,
NULL, stack_reserve, stack_commit,
(PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
if (status == STATUS_SUCCESS)
{
if (id) *id = HandleToULong(client_id.UniqueThread);
if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
if (!(flags & CREATE_SUSPENDED))
{
ULONG ret;
if (NtResumeThread( handle, &ret ))
{
NtClose( handle );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
handle = 0;
}
}
}
else
{
SetLastError( RtlNtStatusToDosError(status) );
handle = 0;
}
return handle;
}
/***********************************************************************
* OpenThread [KERNEL32.@] Retrieves a handle to a thread from its thread id
*/
HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
{
NTSTATUS status;
HANDLE handle;
OBJECT_ATTRIBUTES attr;
CLIENT_ID cid;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
attr.ObjectName = NULL;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
cid.UniqueProcess = 0;
cid.UniqueThread = ULongToHandle(dwThreadId);
status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
handle = 0;
}
return handle;
}
/***********************************************************************
* ExitThread [KERNEL32.@] Ends a thread
*
* RETURNS
* None
*/
void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
{
RtlExitUserThread( code );
}
/**********************************************************************
* TerminateThread [KERNEL32.@] Terminates a thread
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI TerminateThread( HANDLE handle, /* [in] Handle to thread */
DWORD exit_code) /* [in] Exit code for thread */
{
NTSTATUS status = NtTerminateThread( handle, exit_code );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/***********************************************************************
* FreeLibraryAndExitThread (KERNEL32.@)
*/
@ -193,49 +56,6 @@ void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
}
/**********************************************************************
* GetExitCodeThread (KERNEL32.@)
*
* Gets termination status of thread.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI GetExitCodeThread(
HANDLE hthread, /* [in] Handle to thread */
LPDWORD exitcode) /* [out] Address to receive termination status */
{
THREAD_BASIC_INFORMATION info;
NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
&info, sizeof(info), NULL );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (exitcode) *exitcode = info.ExitStatus;
return TRUE;
}
/***********************************************************************
* SetThreadContext [KERNEL32.@] Sets context of thread.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
const CONTEXT *context ) /* [in] Address of context structure */
{
NTSTATUS status = NtSetContextThread( handle, context );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/***********************************************************************
* Wow64SetThreadContext [KERNEL32.@]
*/
@ -253,22 +73,6 @@ BOOL WINAPI Wow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context)
return !status;
}
/***********************************************************************
* GetThreadContext [KERNEL32.@] Retrieves context of thread.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
CONTEXT *context ) /* [out] Address of context structure */
{
NTSTATUS status = NtGetContextThread( handle, context );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/***********************************************************************
* Wow64GetThreadContext [KERNEL32.@]
*/
@ -287,191 +91,6 @@ BOOL WINAPI Wow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context)
}
/**********************************************************************
* SuspendThread [KERNEL32.@] Suspends a thread.
*
* RETURNS
* Success: Previous suspend count
* Failure: 0xFFFFFFFF
*/
DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
{
DWORD ret;
NTSTATUS status = NtSuspendThread( hthread, &ret );
if (status)
{
ret = ~0U;
SetLastError( RtlNtStatusToDosError(status) );
}
return ret;
}
/**********************************************************************
* ResumeThread [KERNEL32.@] Resumes a thread.
*
* Decrements a thread's suspend count. When count is zero, the
* execution of the thread is resumed.
*
* RETURNS
* Success: Previous suspend count
* Failure: 0xFFFFFFFF
* Already running: 0
*/
DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
{
DWORD ret;
NTSTATUS status = NtResumeThread( hthread, &ret );
if (status)
{
ret = ~0U;
SetLastError( RtlNtStatusToDosError(status) );
}
return ret;
}
/**********************************************************************
* GetThreadPriority [KERNEL32.@] Returns priority for thread.
*
* RETURNS
* Success: Thread's priority level.
* Failure: THREAD_PRIORITY_ERROR_RETURN
*/
INT WINAPI GetThreadPriority(
HANDLE hthread) /* [in] Handle to thread */
{
THREAD_BASIC_INFORMATION info;
NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
&info, sizeof(info), NULL );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return THREAD_PRIORITY_ERROR_RETURN;
}
return info.Priority;
}
/**********************************************************************
* SetThreadPriority [KERNEL32.@] Sets priority for thread.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI SetThreadPriority(
HANDLE hthread, /* [in] Handle to thread */
INT priority) /* [in] Thread priority level */
{
DWORD prio = priority;
NTSTATUS status;
status = NtSetInformationThread(hthread, ThreadBasePriority,
&prio, sizeof(prio));
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
return TRUE;
}
/**********************************************************************
* GetThreadPriorityBoost [KERNEL32.@] Returns priority boost for thread.
*
* Always reports that priority boost is disabled.
*
* RETURNS
* Success: TRUE.
* Failure: FALSE
*/
BOOL WINAPI GetThreadPriorityBoost(
HANDLE hthread, /* [in] Handle to thread */
PBOOL pstate) /* [out] pointer to var that receives the boost state */
{
if (pstate) *pstate = FALSE;
return TRUE;
}
/**********************************************************************
* SetThreadPriorityBoost [KERNEL32.@] Sets priority boost for thread.
*
* Priority boost is not implemented, but we return TRUE
* anyway because some games crash otherwise.
*/
BOOL WINAPI SetThreadPriorityBoost(
HANDLE hthread, /* [in] Handle to thread */
BOOL disable) /* [in] TRUE to disable priority boost */
{
return TRUE;
}
/**********************************************************************
* SetThreadStackGuarantee (KERNEL32.@)
*/
BOOL WINAPI SetThreadStackGuarantee(PULONG stacksize)
{
static int once;
if (once++ == 0)
FIXME("(%p): stub\n", stacksize);
return TRUE;
}
/***********************************************************************
* GetThreadGroupAffinity (KERNEL32.@)
*/
BOOL WINAPI GetThreadGroupAffinity( HANDLE thread, GROUP_AFFINITY *affinity )
{
NTSTATUS status;
if (!affinity)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
status = NtQueryInformationThread( thread, ThreadGroupInformation,
affinity, sizeof(*affinity), NULL );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
return TRUE;
}
/***********************************************************************
* SetThreadGroupAffinity (KERNEL32.@)
*/
BOOL WINAPI SetThreadGroupAffinity( HANDLE thread, const GROUP_AFFINITY *affinity_new,
GROUP_AFFINITY *affinity_old )
{
NTSTATUS status;
if (affinity_old && !GetThreadGroupAffinity( thread, affinity_old ))
return FALSE;
status = NtSetInformationThread( thread, ThreadGroupInformation,
affinity_new, sizeof(*affinity_new) );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
return TRUE;
}
/**********************************************************************
* SetThreadAffinityMask (KERNEL32.@)
*/
@ -499,36 +118,6 @@ DWORD_PTR WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD_PTR dwThreadAffini
}
/**********************************************************************
* SetThreadIdealProcessor [KERNEL32.@] Sets preferred processor for thread.
*
* RETURNS
* Success: Value of last call to SetThreadIdealProcessor
* Failure: -1
*/
DWORD WINAPI SetThreadIdealProcessor(
HANDLE hThread, /* [in] Specifies the thread of interest */
DWORD dwIdealProcessor) /* [in] Specifies the new preferred processor */
{
FIXME("(%p): stub\n",hThread);
if (dwIdealProcessor > MAXIMUM_PROCESSORS)
{
SetLastError(ERROR_INVALID_PARAMETER);
return ~0u;
}
return 0;
}
/***********************************************************************
* SetThreadIdealProcessorEx (KERNEL32.@)
*/
BOOL WINAPI SetThreadIdealProcessorEx( HANDLE thread, PROCESSOR_NUMBER *ideal, PROCESSOR_NUMBER *previous )
{
FIXME("(%p %p %p): stub\n", thread, ideal, previous);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* GetThreadSelectorEntry (KERNEL32.@)
*/
@ -549,24 +138,6 @@ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldten
}
/* callback for QueueUserAPC */
static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
{
PAPCFUNC func = (PAPCFUNC)arg1;
func( arg2 );
}
/***********************************************************************
* QueueUserAPC (KERNEL32.@)
*/
DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
{
NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/***********************************************************************
* QueueUserWorkItem (KERNEL32.@)
*/
@ -582,114 +153,6 @@ BOOL WINAPI QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, U
return !status;
}
/**********************************************************************
* GetThreadTimes [KERNEL32.@] Obtains timing information.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI GetThreadTimes(
HANDLE thread, /* [in] Specifies the thread of interest */
LPFILETIME creationtime, /* [out] When the thread was created */
LPFILETIME exittime, /* [out] When the thread was destroyed */
LPFILETIME kerneltime, /* [out] Time thread spent in kernel mode */
LPFILETIME usertime) /* [out] Time thread spent in user mode */
{
KERNEL_USER_TIMES kusrt;
NTSTATUS status;
status = NtQueryInformationThread(thread, ThreadTimes, &kusrt,
sizeof(kusrt), NULL);
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (creationtime)
{
creationtime->dwLowDateTime = kusrt.CreateTime.u.LowPart;
creationtime->dwHighDateTime = kusrt.CreateTime.u.HighPart;
}
if (exittime)
{
exittime->dwLowDateTime = kusrt.ExitTime.u.LowPart;
exittime->dwHighDateTime = kusrt.ExitTime.u.HighPart;
}
if (kerneltime)
{
kerneltime->dwLowDateTime = kusrt.KernelTime.u.LowPart;
kerneltime->dwHighDateTime = kusrt.KernelTime.u.HighPart;
}
if (usertime)
{
usertime->dwLowDateTime = kusrt.UserTime.u.LowPart;
usertime->dwHighDateTime = kusrt.UserTime.u.HighPart;
}
return TRUE;
}
/**********************************************************************
* GetThreadId [KERNEL32.@]
*
* Retrieve the identifier of a thread.
*
* PARAMS
* Thread [I] The thread to retrieve the identifier of.
*
* RETURNS
* Success: Identifier of the target thread.
* Failure: 0
*/
DWORD WINAPI GetThreadId(HANDLE Thread)
{
THREAD_BASIC_INFORMATION tbi;
NTSTATUS status;
TRACE("(%p)\n", Thread);
status = NtQueryInformationThread(Thread, ThreadBasicInformation, &tbi,
sizeof(tbi), NULL);
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return 0;
}
return HandleToULong(tbi.ClientId.UniqueThread);
}
/**********************************************************************
* GetProcessIdOfThread [KERNEL32.@]
*
* Retrieve process identifier given thread belongs to.
*
* PARAMS
* Thread [I] The thread identifier.
*
* RETURNS
* Success: Process identifier
* Failure: 0
*/
DWORD WINAPI GetProcessIdOfThread(HANDLE Thread)
{
THREAD_BASIC_INFORMATION tbi;
NTSTATUS status;
TRACE("(%p)\n", Thread);
status = NtQueryInformationThread(Thread, ThreadBasicInformation, &tbi,
sizeof(tbi), NULL);
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return 0;
}
return HandleToULong(tbi.ClientId.UniqueProcess);
}
/***********************************************************************
* GetCurrentThread [KERNEL32.@] Gets pseudohandle for current thread
*
@ -701,15 +164,6 @@ HANDLE WINAPI KERNEL32_GetCurrentThread(void)
return (HANDLE)~(ULONG_PTR)1;
}
/***********************************************************************
* GetCurrentThreadStackLimits (KERNEL32.@)
*/
void WINAPI GetCurrentThreadStackLimits(ULONG_PTR *low, ULONG_PTR *high)
{
*low = (ULONG_PTR)NtCurrentTeb()->DeallocationStack;
*high = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase;
}
/**********************************************************************
* SetLastError (KERNEL32.@)
*
@ -770,124 +224,6 @@ HANDLE WINAPI KERNEL32_GetProcessHeap(void)
return NtCurrentTeb()->Peb->ProcessHeap;
}
/*************************************************************************
* rtlmode_to_win32mode
*/
static DWORD rtlmode_to_win32mode( DWORD rtlmode )
{
DWORD win32mode = 0;
if (rtlmode & 0x10)
win32mode |= SEM_FAILCRITICALERRORS;
if (rtlmode & 0x20)
win32mode |= SEM_NOGPFAULTERRORBOX;
if (rtlmode & 0x40)
win32mode |= SEM_NOOPENFILEERRORBOX;
return win32mode;
}
/***********************************************************************
* SetThreadErrorMode (KERNEL32.@)
*
* Set the thread local error mode.
*
* PARAMS
* mode [I] The new error mode, a bitwise or of SEM_FAILCRITICALERRORS,
* SEM_NOGPFAULTERRORBOX and SEM_NOOPENFILEERRORBOX.
* oldmode [O] Destination of the old error mode (may be NULL)
*
* RETURNS
* Success: TRUE
* Failure: FALSE, check GetLastError
*/
BOOL WINAPI SetThreadErrorMode( DWORD mode, LPDWORD oldmode )
{
NTSTATUS status;
DWORD tmp = 0;
if (mode & ~(SEM_FAILCRITICALERRORS |
SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (mode & SEM_FAILCRITICALERRORS)
tmp |= 0x10;
if (mode & SEM_NOGPFAULTERRORBOX)
tmp |= 0x20;
if (mode & SEM_NOOPENFILEERRORBOX)
tmp |= 0x40;
status = RtlSetThreadErrorMode( tmp, oldmode );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (oldmode)
*oldmode = rtlmode_to_win32mode(*oldmode);
return TRUE;
}
/***********************************************************************
* GetThreadErrorMode (KERNEL32.@)
*
* Get the thread local error mode.
*
* PARAMS
* None.
*
* RETURNS
* The current thread local error mode.
*/
DWORD WINAPI GetThreadErrorMode( void )
{
return rtlmode_to_win32mode( RtlGetThreadErrorMode() );
}
/***********************************************************************
* GetThreadUILanguage (KERNEL32.@)
*
* Get the current thread's language identifier.
*
* PARAMS
* None.
*
* RETURNS
* The current thread's language identifier.
*/
LANGID WINAPI GetThreadUILanguage( void )
{
LANGID lang;
NtQueryDefaultUILanguage( &lang );
FIXME(": stub, returning default language.\n");
return lang;
}
/***********************************************************************
* GetThreadIOPendingFlag (KERNEL32.@)
*/
BOOL WINAPI GetThreadIOPendingFlag( HANDLE thread, PBOOL io_pending )
{
NTSTATUS status;
TRACE("%p, %p\n", thread, io_pending);
status = NtQueryInformationThread( thread, ThreadIsIoPending,
io_pending, sizeof(*io_pending), NULL );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
return TRUE;
}
/***********************************************************************
* CallbackMayRunLong (KERNEL32.@)
*/

View File

@ -11,4 +11,5 @@ C_SRCS = \
security.c \
string.c \
sync.c \
thread.c \
version.c

View File

@ -211,8 +211,8 @@
@ stdcall CreateProcessInternalA(long str str ptr ptr long long ptr str ptr ptr ptr) kernel32.CreateProcessInternalA
@ stdcall CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr) kernel32.CreateProcessInternalW
@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr) kernel32.CreateProcessW
@ stdcall CreateRemoteThread(long ptr long ptr long long ptr) kernel32.CreateRemoteThread
@ stdcall CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr) kernel32.CreateRemoteThreadEx
@ stdcall CreateRemoteThread(long ptr long ptr long long ptr)
@ stdcall CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr)
@ stdcall CreateRestrictedToken(long long long ptr long ptr long ptr ptr)
@ stdcall CreateSemaphoreExW(ptr long long wstr long long)
@ stdcall CreateSemaphoreW(ptr long long wstr)
@ -222,7 +222,7 @@
# @ stub CreateStateLock
# @ stub CreateStateSubcontainer
@ stdcall CreateSymbolicLinkW(wstr wstr long) kernel32.CreateSymbolicLinkW
@ stdcall CreateThread(ptr long ptr long long ptr) kernel32.CreateThread
@ stdcall CreateThread(ptr long ptr long long ptr)
@ stdcall CreateThreadpool(ptr) kernel32.CreateThreadpool
@ stdcall CreateThreadpoolCleanupGroup() kernel32.CreateThreadpoolCleanupGroup
@ stdcall CreateThreadpoolIo(ptr ptr ptr ptr) kernel32.CreateThreadpoolIo
@ -395,7 +395,7 @@
# @ stub FreeGPOListInternalA
# @ stub FreeGPOListInternalW
@ stdcall FreeLibrary(long) kernel32.FreeLibrary
@ stdcall FreeLibraryAndExitThread(long long) kernel32.FreeLibraryAndExitThread
@ stdcall FreeLibraryAndExitThread(long long)
@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
@ stdcall FreeResource(long)
@ stdcall FreeSid(ptr)
@ -469,9 +469,9 @@
@ stdcall GetCurrentProcessorNumber() ntdll.NtGetCurrentProcessorNumber
@ stdcall GetCurrentProcessorNumberEx(ptr) ntdll.RtlGetCurrentProcessorNumberEx
# @ stub GetCurrentTargetPlatformContext
@ stdcall -norelay GetCurrentThread() kernel32.GetCurrentThread
@ stdcall -norelay GetCurrentThreadId() kernel32.GetCurrentThreadId
@ stdcall GetCurrentThreadStackLimits(ptr ptr) kernel32.GetCurrentThreadStackLimits
@ stdcall -norelay GetCurrentThread() kernelbase_GetCurrentThread
@ stdcall -norelay GetCurrentThreadId() kernelbase_GetCurrentThreadId
@ stdcall GetCurrentThreadStackLimits(ptr ptr)
@ stdcall GetDateFormatA(long long ptr str ptr long) kernel32.GetDateFormatA
@ stdcall GetDateFormatEx(wstr long ptr wstr ptr long wstr) kernel32.GetDateFormatEx
@ stdcall GetDateFormatW(long long ptr wstr ptr long) kernel32.GetDateFormatW
@ -500,7 +500,7 @@
@ stub GetEraNameCountedString
@ stdcall GetErrorMode() kernel32.GetErrorMode
@ stdcall GetExitCodeProcess(long ptr) kernel32.GetExitCodeProcess
@ stdcall GetExitCodeThread(long ptr) kernel32.GetExitCodeThread
@ stdcall GetExitCodeThread(long ptr)
@ stub GetFallbackDisplayName
@ stdcall GetFileAttributesA(str) kernel32.GetFileAttributesA
@ stdcall GetFileAttributesExA(str long ptr) kernel32.GetFileAttributesExA
@ -627,7 +627,7 @@
@ stdcall -norelay GetProcessHeap() kernel32.GetProcessHeap
@ stdcall GetProcessHeaps(long ptr) kernel32.GetProcessHeaps
@ stdcall GetProcessId(long) kernel32.GetProcessId
@ stdcall GetProcessIdOfThread(long) kernel32.GetProcessIdOfThread
@ stdcall GetProcessIdOfThread(long)
# @ stub GetProcessImageFileNameA
# @ stub GetProcessImageFileNameW
# @ stub GetProcessInformation
@ -711,21 +711,21 @@
@ stdcall GetTempFileNameW(wstr wstr long ptr) kernel32.GetTempFileNameW
@ stdcall GetTempPathA(long ptr) kernel32.GetTempPathA
@ stdcall GetTempPathW(long ptr) kernel32.GetTempPathW
@ stdcall GetThreadContext(long ptr) kernel32.GetThreadContext
@ stdcall GetThreadContext(long ptr)
# @ stub GetThreadDescription
@ stdcall GetThreadErrorMode() kernel32.GetThreadErrorMode
@ stdcall GetThreadGroupAffinity(long ptr) kernel32.GetThreadGroupAffinity
@ stdcall GetThreadIOPendingFlag(long ptr) kernel32.GetThreadIOPendingFlag
@ stdcall GetThreadId(ptr) kernel32.GetThreadId
@ stdcall GetThreadErrorMode()
@ stdcall GetThreadGroupAffinity(long ptr)
@ stdcall GetThreadIOPendingFlag(long ptr)
@ stdcall GetThreadId(ptr)
# @ stub GetThreadIdealProcessorEx
# @ stub GetThreadInformation
@ stdcall GetThreadLocale() kernel32.GetThreadLocale
@ stdcall GetThreadPreferredUILanguages(long ptr ptr ptr) kernel32.GetThreadPreferredUILanguages
@ stdcall GetThreadPriority(long) kernel32.GetThreadPriority
@ stdcall GetThreadPriorityBoost(long ptr) kernel32.GetThreadPriorityBoost
@ stdcall GetThreadPriority(long)
@ stdcall GetThreadPriorityBoost(long ptr)
# @ stub GetThreadSelectedCpuSets
@ stdcall GetThreadTimes(long ptr ptr ptr ptr) kernel32.GetThreadTimes
@ stdcall GetThreadUILanguage() kernel32.GetThreadUILanguage
@ stdcall GetThreadTimes(long ptr ptr ptr ptr)
@ stdcall GetThreadUILanguage()
@ stdcall GetTickCount() kernel32.GetTickCount
@ stdcall -ret64 GetTickCount64() kernel32.GetTickCount64
@ stdcall GetTimeFormatA(long long ptr str ptr long) kernel32.GetTimeFormatA
@ -1000,7 +1000,7 @@
# @ stub OpenStateExplicit
# @ stub OpenStateExplicitForUserSid
# @ stub OpenStateExplicitForUserSidString
@ stdcall OpenThread(long long long) kernel32.OpenThread
@ stdcall OpenThread(long long long)
@ stdcall OpenThreadToken(long long long ptr)
@ stdcall OpenWaitableTimerW(long long wstr)
@ stdcall OutputDebugStringA(str) kernel32.OutputDebugStringA
@ -1220,7 +1220,7 @@
# @ stub QueryVirtualMemoryInformation
# @ stub QueryWorkingSet
# @ stub QueryWorkingSetEx
@ stdcall QueueUserAPC(ptr long long) kernel32.QueueUserAPC
@ stdcall QueueUserAPC(ptr long long)
@ stdcall QueueUserWorkItem(ptr ptr long) kernel32.QueueUserWorkItem
# @ stub QuirkGetData
# @ stub QuirkGetData2
@ -1348,7 +1348,7 @@
# @ stub ResolveDelayLoadsFromDll
@ stdcall ResolveLocaleName(wstr ptr long) kernel32.ResolveLocaleName
@ stdcall RestoreLastError(long) ntdll.RtlRestoreLastWin32Error
@ stdcall ResumeThread(long) kernel32.ResumeThread
@ stdcall ResumeThread(long)
@ stdcall RevertToSelf()
# @ stub RsopLoggingEnabledInternal
# @ stub SHCoCreateInstance
@ -1478,19 +1478,19 @@
@ stdcall SetSystemFileCacheSize(long long long) kernel32.SetSystemFileCacheSize
@ stdcall SetSystemTime(ptr) kernel32.SetSystemTime
@ stdcall SetSystemTimeAdjustment(long long) kernel32.SetSystemTimeAdjustment
@ stdcall SetThreadContext(long ptr) kernel32.SetThreadContext
@ stdcall SetThreadContext(long ptr)
# @ stub SetThreadDescription
@ stdcall SetThreadErrorMode(long ptr) kernel32.SetThreadErrorMode
@ stdcall SetThreadGroupAffinity(long ptr ptr) kernel32.SetThreadGroupAffinity
@ stdcall SetThreadIdealProcessor(long long) kernel32.SetThreadIdealProcessor
@ stdcall SetThreadIdealProcessorEx(long ptr ptr) kernel32.SetThreadIdealProcessorEx
@ stdcall SetThreadErrorMode(long ptr)
@ stdcall SetThreadGroupAffinity(long ptr ptr)
@ stdcall SetThreadIdealProcessor(long long)
@ stdcall SetThreadIdealProcessorEx(long ptr ptr)
# @ stub SetThreadInformation
@ stdcall SetThreadLocale(long) kernel32.SetThreadLocale
@ stdcall SetThreadPreferredUILanguages(long ptr ptr) kernel32.SetThreadPreferredUILanguages
@ stdcall SetThreadPriority(long long) kernel32.SetThreadPriority
@ stdcall SetThreadPriorityBoost(long long) kernel32.SetThreadPriorityBoost
@ stdcall SetThreadPriority(long long)
@ stdcall SetThreadPriorityBoost(long long)
# @ stub SetThreadSelectedCpuSets
@ stdcall SetThreadStackGuarantee(ptr) kernel32.SetThreadStackGuarantee
@ stdcall SetThreadStackGuarantee(ptr)
@ stdcall SetThreadToken(ptr ptr)
@ stdcall SetThreadUILanguage(long) kernel32.SetThreadUILanguage
@ stub SetThreadpoolStackInformation
@ -1588,15 +1588,15 @@
@ stdcall SubmitThreadpoolWork(ptr) ntdll.TpPostWork
# @ stub SubscribeEdpEnabledStateChange
# @ stub SubscribeStateChangeNotification
@ stdcall SuspendThread(long) kernel32.SuspendThread
@ stdcall SuspendThread(long)
@ stdcall SwitchToFiber(ptr) kernel32.SwitchToFiber
@ stdcall SwitchToThread() kernel32.SwitchToThread
@ stdcall SwitchToThread()
@ stdcall SystemTimeToFileTime(ptr ptr) kernel32.SystemTimeToFileTime
@ stdcall SystemTimeToTzSpecificLocalTime(ptr ptr ptr) kernel32.SystemTimeToTzSpecificLocalTime
@ stub SystemTimeToTzSpecificLocalTimeEx
@ stdcall TerminateProcess(long long) kernel32.TerminateProcess
# @ stub TerminateProcessOnMemoryExhaustion
@ stdcall TerminateThread(long long) kernel32.TerminateThread
@ stdcall TerminateThread(long long)
@ stdcall TlsAlloc() kernel32.TlsAlloc
@ stdcall TlsFree(long) kernel32.TlsFree
@ stdcall TlsGetValue(long) kernel32.TlsGetValue

495
dlls/kernelbase/thread.c Normal file
View File

@ -0,0 +1,495 @@
/*
* Win32 threads
*
* Copyright 1996 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "kernelbase.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(thread);
/***********************************************************************
* Threads
***********************************************************************/
static DWORD rtlmode_to_win32mode( DWORD rtlmode )
{
DWORD win32mode = 0;
if (rtlmode & 0x10) win32mode |= SEM_FAILCRITICALERRORS;
if (rtlmode & 0x20) win32mode |= SEM_NOGPFAULTERRORBOX;
if (rtlmode & 0x40) win32mode |= SEM_NOOPENFILEERRORBOX;
return win32mode;
}
/***************************************************************************
* CreateRemoteThread (kernelbase.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH CreateRemoteThread( HANDLE process, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, DWORD *id )
{
return CreateRemoteThreadEx( process, sa, stack, start, param, flags, NULL, id );
}
/***************************************************************************
* CreateRemoteThreadEx (kernelbase.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH CreateRemoteThreadEx( HANDLE process, SECURITY_ATTRIBUTES *sa,
SIZE_T stack, LPTHREAD_START_ROUTINE start,
LPVOID param, DWORD flags,
LPPROC_THREAD_ATTRIBUTE_LIST attributes, DWORD *id )
{
HANDLE handle;
CLIENT_ID client_id;
NTSTATUS status;
SIZE_T stack_reserve = 0, stack_commit = 0;
if (attributes) FIXME("thread attributes ignored\n");
if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
else stack_commit = stack;
status = RtlCreateUserThread( process, sa ? sa->lpSecurityDescriptor : NULL, TRUE,
NULL, stack_reserve, stack_commit,
(PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
if (status == STATUS_SUCCESS)
{
if (id) *id = HandleToULong( client_id.UniqueThread );
if (sa && sa->nLength >= sizeof(*sa) && sa->bInheritHandle)
SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
if (!(flags & CREATE_SUSPENDED))
{
ULONG ret;
if (NtResumeThread( handle, &ret ))
{
NtClose( handle );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
handle = 0;
}
}
}
else
{
SetLastError( RtlNtStatusToDosError(status) );
handle = 0;
}
return handle;
}
/***********************************************************************
* CreateThread (kernelbase.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, LPDWORD id )
{
return CreateRemoteThread( GetCurrentProcess(), sa, stack, start, param, flags, id );
}
/***********************************************************************
* FreeLibraryAndExitThread (kernelbase.@)
*/
void WINAPI DECLSPEC_HOTPATCH FreeLibraryAndExitThread( HINSTANCE module, DWORD exit_code )
{
FreeLibrary( module );
RtlExitUserThread( exit_code );
}
/***********************************************************************
* GetCurrentThreadStackLimits (kernelbase.@)
*/
void WINAPI DECLSPEC_HOTPATCH GetCurrentThreadStackLimits( ULONG_PTR *low, ULONG_PTR *high )
{
*low = (ULONG_PTR)NtCurrentTeb()->DeallocationStack;
*high = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase;
}
/***********************************************************************
* GetCurrentThread (kernelbase.@)
*/
HANDLE WINAPI kernelbase_GetCurrentThread(void)
{
return (HANDLE)~(ULONG_PTR)1;
}
/***********************************************************************
* GetCurrentThreadId (kernelbase.@)
*/
DWORD WINAPI kernelbase_GetCurrentThreadId(void)
{
return HandleToULong( NtCurrentTeb()->ClientId.UniqueThread );
}
/**********************************************************************
* GetExitCodeThread (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeThread( HANDLE thread, LPDWORD exit_code )
{
THREAD_BASIC_INFORMATION info;
NTSTATUS status = NtQueryInformationThread( thread, ThreadBasicInformation,
&info, sizeof(info), NULL );
if (!status && exit_code) *exit_code = info.ExitStatus;
return set_ntstatus( status );
}
/**********************************************************************
* GetProcessIdOfThread (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH GetProcessIdOfThread( HANDLE thread )
{
THREAD_BASIC_INFORMATION tbi;
if (!set_ntstatus( NtQueryInformationThread( thread, ThreadBasicInformation, &tbi, sizeof(tbi), NULL)))
return 0;
return HandleToULong( tbi.ClientId.UniqueProcess );
}
/***********************************************************************
* GetThreadContext (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadContext( HANDLE thread, CONTEXT *context )
{
return set_ntstatus( NtGetContextThread( thread, context ));
}
/***********************************************************************
* GetThreadErrorMode (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH GetThreadErrorMode(void)
{
return rtlmode_to_win32mode( RtlGetThreadErrorMode() );
}
/***********************************************************************
* GetThreadGroupAffinity (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadGroupAffinity( HANDLE thread, GROUP_AFFINITY *affinity )
{
if (!affinity)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return set_ntstatus( NtQueryInformationThread( thread, ThreadGroupInformation,
affinity, sizeof(*affinity), NULL ));
}
/***********************************************************************
* GetThreadIOPendingFlag (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadIOPendingFlag( HANDLE thread, PBOOL pending )
{
return set_ntstatus( NtQueryInformationThread( thread, ThreadIsIoPending,
pending, sizeof(*pending), NULL ));
}
/**********************************************************************
* GetThreadId (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH GetThreadId( HANDLE thread )
{
THREAD_BASIC_INFORMATION tbi;
if (!set_ntstatus( NtQueryInformationThread( thread, ThreadBasicInformation, &tbi, sizeof(tbi), NULL)))
return 0;
return HandleToULong( tbi.ClientId.UniqueThread );
}
/**********************************************************************
* GetThreadPriority (kernelbase.@)
*/
INT WINAPI DECLSPEC_HOTPATCH GetThreadPriority( HANDLE thread )
{
THREAD_BASIC_INFORMATION info;
if (!set_ntstatus( NtQueryInformationThread( thread, ThreadBasicInformation,
&info, sizeof(info), NULL )))
return THREAD_PRIORITY_ERROR_RETURN;
return info.Priority;
}
/**********************************************************************
* GetThreadPriorityBoost (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadPriorityBoost( HANDLE thread, BOOL *state )
{
if (state) *state = FALSE;
return TRUE;
}
/**********************************************************************
* GetThreadTimes (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadTimes( HANDLE thread, LPFILETIME creationtime, LPFILETIME exittime,
LPFILETIME kerneltime, LPFILETIME usertime )
{
KERNEL_USER_TIMES times;
NTSTATUS status = NtQueryInformationThread( thread, ThreadTimes, &times, sizeof(times), NULL);
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (creationtime)
{
creationtime->dwLowDateTime = times.CreateTime.u.LowPart;
creationtime->dwHighDateTime = times.CreateTime.u.HighPart;
}
if (exittime)
{
exittime->dwLowDateTime = times.ExitTime.u.LowPart;
exittime->dwHighDateTime = times.ExitTime.u.HighPart;
}
if (kerneltime)
{
kerneltime->dwLowDateTime = times.KernelTime.u.LowPart;
kerneltime->dwHighDateTime = times.KernelTime.u.HighPart;
}
if (usertime)
{
usertime->dwLowDateTime = times.UserTime.u.LowPart;
usertime->dwHighDateTime = times.UserTime.u.HighPart;
}
return TRUE;
}
/***********************************************************************
* GetThreadUILanguage (kernelbase.@)
*/
LANGID WINAPI DECLSPEC_HOTPATCH GetThreadUILanguage(void)
{
LANGID lang;
FIXME(": stub, returning default language.\n");
NtQueryDefaultUILanguage( &lang );
return lang;
}
/***********************************************************************
* OpenThread (kernelbase.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH OpenThread( DWORD access, BOOL inherit, DWORD id )
{
HANDLE handle;
OBJECT_ATTRIBUTES attr;
CLIENT_ID cid;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = inherit ? OBJ_INHERIT : 0;
attr.ObjectName = NULL;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
cid.UniqueProcess = 0;
cid.UniqueThread = ULongToHandle( id );
if (!set_ntstatus( NtOpenThread( &handle, access, &attr, &cid ))) handle = 0;
return handle;
}
/* callback for QueueUserAPC */
static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
{
PAPCFUNC func = (PAPCFUNC)arg1;
func( arg2 );
}
/***********************************************************************
* QueueUserAPC (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH QueueUserAPC( PAPCFUNC func, HANDLE thread, ULONG_PTR data )
{
return set_ntstatus( NtQueueApcThread( thread, call_user_apc, (ULONG_PTR)func, data, 0 ));
}
/**********************************************************************
* ResumeThread (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH ResumeThread( HANDLE thread )
{
DWORD ret;
if (!set_ntstatus( NtResumeThread( thread, &ret ))) ret = ~0U;
return ret;
}
/***********************************************************************
* SetThreadContext (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadContext( HANDLE thread, const CONTEXT *context )
{
return set_ntstatus( NtSetContextThread( thread, context ));
}
/***********************************************************************
* SetThreadErrorMode (kernelbase.@)
*/
BOOL WINAPI SetThreadErrorMode( DWORD mode, DWORD *old )
{
NTSTATUS status;
DWORD new = 0;
if (mode & ~(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (mode & SEM_FAILCRITICALERRORS) new |= 0x10;
if (mode & SEM_NOGPFAULTERRORBOX) new |= 0x20;
if (mode & SEM_NOOPENFILEERRORBOX) new |= 0x40;
status = RtlSetThreadErrorMode( new, old );
if (!status && old) *old = rtlmode_to_win32mode( *old );
return set_ntstatus( status );
}
/***********************************************************************
* SetThreadGroupAffinity (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadGroupAffinity( HANDLE thread, const GROUP_AFFINITY *new,
GROUP_AFFINITY *old )
{
if (old && !GetThreadGroupAffinity( thread, old )) return FALSE;
return set_ntstatus( NtSetInformationThread( thread, ThreadGroupInformation, new, sizeof(*new) ));
}
/**********************************************************************
* SetThreadIdealProcessor (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH SetThreadIdealProcessor( HANDLE thread, DWORD proc )
{
FIXME( "(%p %u): stub\n", thread, proc );
if (proc > MAXIMUM_PROCESSORS)
{
SetLastError( ERROR_INVALID_PARAMETER );
return ~0u;
}
return 0;
}
/***********************************************************************
* SetThreadIdealProcessorEx (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadIdealProcessorEx( HANDLE thread, PROCESSOR_NUMBER *ideal,
PROCESSOR_NUMBER *previous )
{
FIXME( "(%p %p %p): stub\n", thread, ideal, previous );
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
/**********************************************************************
* SetThreadPriority (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadPriority( HANDLE thread, INT priority )
{
DWORD prio = priority;
return set_ntstatus( NtSetInformationThread( thread, ThreadBasePriority, &prio, sizeof(prio) ));
}
/**********************************************************************
* SetThreadPriorityBoost (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadPriorityBoost( HANDLE thread, BOOL disable )
{
return TRUE;
}
/**********************************************************************
* SetThreadStackGuarantee (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadStackGuarantee( ULONG *size )
{
static int once;
if (once++ == 0) FIXME("(%p): stub\n", size);
return TRUE;
}
/**********************************************************************
* SuspendThread (kernelbase.@)
*/
DWORD WINAPI DECLSPEC_HOTPATCH SuspendThread( HANDLE thread )
{
DWORD ret;
if (!set_ntstatus( NtSuspendThread( thread, &ret ))) ret = ~0U;
return ret;
}
/***********************************************************************
* SwitchToThread (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SwitchToThread(void)
{
return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
}
/**********************************************************************
* TerminateThread (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH TerminateThread( HANDLE handle, DWORD exit_code )
{
return set_ntstatus( NtTerminateThread( handle, exit_code ));
}