msvcrtd: Fix _CrtDbgReport calling convention.
[wine.git] / dlls / kernel32 / thread.c
blobb6ca9f260f3fba54d328b69f8ac4b01e61005e33
1 /*
2 * Win32 threads
4 * Copyright 1996 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <sys/types.h>
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winternl.h"
38 #include "wine/exception.h"
39 #include "wine/library.h"
40 #include "wine/server.h"
41 #include "wine/debug.h"
43 #include "kernel_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(thread);
48 /***********************************************************************
49 * CreateThread (KERNEL32.@)
51 HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack, LPTHREAD_START_ROUTINE start,
52 LPVOID param, DWORD flags, LPDWORD id )
54 return CreateRemoteThread( GetCurrentProcess(),
55 sa, stack, start, param, flags, id );
58 /***************************************************************************
59 * CreateRemoteThread (KERNEL32.@)
61 HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
62 LPTHREAD_START_ROUTINE start, LPVOID param,
63 DWORD flags, DWORD *id )
65 return CreateRemoteThreadEx( hProcess, sa, stack, start, param, flags, NULL, id );
68 /***************************************************************************
69 * CreateRemoteThreadEx (KERNEL32.@)
71 * Creates a thread that runs in the address space of another process
73 * PARAMS
75 * RETURNS
76 * Success: Handle to the new thread.
77 * Failure: NULL. Use GetLastError() to find the error cause.
79 * BUGS
80 * Improper memory allocation: there's no ability to free new_thread_info
81 * in other process.
82 * Bad start address for RtlCreateUserThread because the library
83 * may be loaded at different address in other process.
85 HANDLE WINAPI CreateRemoteThreadEx( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
86 LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags,
87 LPPROC_THREAD_ATTRIBUTE_LIST attributes, DWORD *id )
89 HANDLE handle;
90 CLIENT_ID client_id;
91 NTSTATUS status;
92 SIZE_T stack_reserve = 0, stack_commit = 0;
94 if (attributes)
95 FIXME("thread attributes ignored\n");
97 if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
98 else stack_commit = stack;
100 status = RtlCreateUserThread( hProcess, NULL, TRUE,
101 NULL, stack_reserve, stack_commit,
102 (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
103 if (status == STATUS_SUCCESS)
105 if (id) *id = HandleToULong(client_id.UniqueThread);
106 if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
107 SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
108 if (!(flags & CREATE_SUSPENDED))
110 ULONG ret;
111 if (NtResumeThread( handle, &ret ))
113 NtClose( handle );
114 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
115 handle = 0;
119 else
121 SetLastError( RtlNtStatusToDosError(status) );
122 handle = 0;
124 return handle;
128 /***********************************************************************
129 * OpenThread [KERNEL32.@] Retrieves a handle to a thread from its thread id
131 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
133 NTSTATUS status;
134 HANDLE handle;
135 OBJECT_ATTRIBUTES attr;
136 CLIENT_ID cid;
138 attr.Length = sizeof(attr);
139 attr.RootDirectory = 0;
140 attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
141 attr.ObjectName = NULL;
142 attr.SecurityDescriptor = NULL;
143 attr.SecurityQualityOfService = NULL;
145 cid.UniqueProcess = 0; /* FIXME */
146 cid.UniqueThread = ULongToHandle(dwThreadId);
147 status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
148 if (status)
150 SetLastError( RtlNtStatusToDosError(status) );
151 handle = 0;
153 return handle;
157 /***********************************************************************
158 * ExitThread [KERNEL32.@] Ends a thread
160 * RETURNS
161 * None
163 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
165 RtlExitUserThread( code );
169 /**********************************************************************
170 * TerminateThread [KERNEL32.@] Terminates a thread
172 * RETURNS
173 * Success: TRUE
174 * Failure: FALSE
176 BOOL WINAPI TerminateThread( HANDLE handle, /* [in] Handle to thread */
177 DWORD exit_code) /* [in] Exit code for thread */
179 NTSTATUS status = NtTerminateThread( handle, exit_code );
180 if (status) SetLastError( RtlNtStatusToDosError(status) );
181 return !status;
185 /***********************************************************************
186 * FreeLibraryAndExitThread (KERNEL32.@)
188 void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
190 FreeLibrary(hLibModule);
191 ExitThread(dwExitCode);
195 /**********************************************************************
196 * GetExitCodeThread (KERNEL32.@)
198 * Gets termination status of thread.
200 * RETURNS
201 * Success: TRUE
202 * Failure: FALSE
204 BOOL WINAPI GetExitCodeThread(
205 HANDLE hthread, /* [in] Handle to thread */
206 LPDWORD exitcode) /* [out] Address to receive termination status */
208 THREAD_BASIC_INFORMATION info;
209 NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
210 &info, sizeof(info), NULL );
212 if (status)
214 SetLastError( RtlNtStatusToDosError(status) );
215 return FALSE;
217 if (exitcode) *exitcode = info.ExitStatus;
218 return TRUE;
222 /***********************************************************************
223 * SetThreadContext [KERNEL32.@] Sets context of thread.
225 * RETURNS
226 * Success: TRUE
227 * Failure: FALSE
229 BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
230 const CONTEXT *context ) /* [in] Address of context structure */
232 NTSTATUS status = NtSetContextThread( handle, context );
233 if (status) SetLastError( RtlNtStatusToDosError(status) );
234 return !status;
238 /***********************************************************************
239 * GetThreadContext [KERNEL32.@] Retrieves context of thread.
241 * RETURNS
242 * Success: TRUE
243 * Failure: FALSE
245 BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
246 CONTEXT *context ) /* [out] Address of context structure */
248 NTSTATUS status = NtGetContextThread( handle, context );
249 if (status) SetLastError( RtlNtStatusToDosError(status) );
250 return !status;
254 /**********************************************************************
255 * SuspendThread [KERNEL32.@] Suspends a thread.
257 * RETURNS
258 * Success: Previous suspend count
259 * Failure: 0xFFFFFFFF
261 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
263 DWORD ret;
264 NTSTATUS status = NtSuspendThread( hthread, &ret );
266 if (status)
268 ret = ~0U;
269 SetLastError( RtlNtStatusToDosError(status) );
271 return ret;
275 /**********************************************************************
276 * ResumeThread [KERNEL32.@] Resumes a thread.
278 * Decrements a thread's suspend count. When count is zero, the
279 * execution of the thread is resumed.
281 * RETURNS
282 * Success: Previous suspend count
283 * Failure: 0xFFFFFFFF
284 * Already running: 0
286 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
288 DWORD ret;
289 NTSTATUS status = NtResumeThread( hthread, &ret );
291 if (status)
293 ret = ~0U;
294 SetLastError( RtlNtStatusToDosError(status) );
296 return ret;
300 /**********************************************************************
301 * GetThreadPriority [KERNEL32.@] Returns priority for thread.
303 * RETURNS
304 * Success: Thread's priority level.
305 * Failure: THREAD_PRIORITY_ERROR_RETURN
307 INT WINAPI GetThreadPriority(
308 HANDLE hthread) /* [in] Handle to thread */
310 THREAD_BASIC_INFORMATION info;
311 NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
312 &info, sizeof(info), NULL );
314 if (status)
316 SetLastError( RtlNtStatusToDosError(status) );
317 return THREAD_PRIORITY_ERROR_RETURN;
319 return info.Priority;
323 /**********************************************************************
324 * SetThreadPriority [KERNEL32.@] Sets priority for thread.
326 * RETURNS
327 * Success: TRUE
328 * Failure: FALSE
330 BOOL WINAPI SetThreadPriority(
331 HANDLE hthread, /* [in] Handle to thread */
332 INT priority) /* [in] Thread priority level */
334 DWORD prio = priority;
335 NTSTATUS status;
337 status = NtSetInformationThread(hthread, ThreadBasePriority,
338 &prio, sizeof(prio));
340 if (status)
342 SetLastError( RtlNtStatusToDosError(status) );
343 return FALSE;
346 return TRUE;
350 /**********************************************************************
351 * GetThreadPriorityBoost [KERNEL32.@] Returns priority boost for thread.
353 * Always reports that priority boost is disabled.
355 * RETURNS
356 * Success: TRUE.
357 * Failure: FALSE
359 BOOL WINAPI GetThreadPriorityBoost(
360 HANDLE hthread, /* [in] Handle to thread */
361 PBOOL pstate) /* [out] pointer to var that receives the boost state */
363 if (pstate) *pstate = FALSE;
364 return TRUE;
368 /**********************************************************************
369 * SetThreadPriorityBoost [KERNEL32.@] Sets priority boost for thread.
371 * Priority boost is not implemented, but we return TRUE
372 * anyway because some games crash otherwise.
374 BOOL WINAPI SetThreadPriorityBoost(
375 HANDLE hthread, /* [in] Handle to thread */
376 BOOL disable) /* [in] TRUE to disable priority boost */
378 return TRUE;
382 /**********************************************************************
383 * SetThreadStackGuarantee (KERNEL32.@)
385 BOOL WINAPI SetThreadStackGuarantee(PULONG stacksize)
387 static int once;
388 if (once++ == 0)
389 FIXME("(%p): stub\n", stacksize);
390 return TRUE;
393 /***********************************************************************
394 * GetThreadGroupAffinity (KERNEL32.@)
396 BOOL WINAPI GetThreadGroupAffinity( HANDLE thread, GROUP_AFFINITY *affinity )
398 NTSTATUS status;
400 if (!affinity)
402 SetLastError( ERROR_INVALID_PARAMETER );
403 return FALSE;
406 status = NtQueryInformationThread( thread, ThreadGroupInformation,
407 affinity, sizeof(*affinity), NULL );
408 if (status)
410 SetLastError( RtlNtStatusToDosError(status) );
411 return FALSE;
414 return TRUE;
417 /***********************************************************************
418 * SetThreadGroupAffinity (KERNEL32.@)
420 BOOL WINAPI SetThreadGroupAffinity( HANDLE thread, const GROUP_AFFINITY *affinity_new,
421 GROUP_AFFINITY *affinity_old )
423 NTSTATUS status;
425 if (affinity_old && !GetThreadGroupAffinity( thread, affinity_old ))
426 return FALSE;
428 status = NtSetInformationThread( thread, ThreadGroupInformation,
429 affinity_new, sizeof(*affinity_new) );
430 if (status)
432 SetLastError( RtlNtStatusToDosError(status) );
433 return FALSE;
436 return TRUE;
439 /**********************************************************************
440 * SetThreadAffinityMask (KERNEL32.@)
442 DWORD_PTR WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD_PTR dwThreadAffinityMask )
444 NTSTATUS status;
445 THREAD_BASIC_INFORMATION tbi;
447 status = NtQueryInformationThread( hThread, ThreadBasicInformation,
448 &tbi, sizeof(tbi), NULL );
449 if (status)
451 SetLastError( RtlNtStatusToDosError(status) );
452 return 0;
454 status = NtSetInformationThread( hThread, ThreadAffinityMask,
455 &dwThreadAffinityMask,
456 sizeof(dwThreadAffinityMask));
457 if (status)
459 SetLastError( RtlNtStatusToDosError(status) );
460 return 0;
462 return tbi.AffinityMask;
466 /**********************************************************************
467 * SetThreadIdealProcessor [KERNEL32.@] Sets preferred processor for thread.
469 * RETURNS
470 * Success: Value of last call to SetThreadIdealProcessor
471 * Failure: -1
473 DWORD WINAPI SetThreadIdealProcessor(
474 HANDLE hThread, /* [in] Specifies the thread of interest */
475 DWORD dwIdealProcessor) /* [in] Specifies the new preferred processor */
477 FIXME("(%p): stub\n",hThread);
478 if (dwIdealProcessor > MAXIMUM_PROCESSORS)
480 SetLastError(ERROR_INVALID_PARAMETER);
481 return ~0u;
483 return 0;
486 /***********************************************************************
487 * SetThreadIdealProcessorEx (KERNEL32.@)
489 BOOL WINAPI SetThreadIdealProcessorEx( HANDLE thread, PROCESSOR_NUMBER *ideal, PROCESSOR_NUMBER *previous )
491 FIXME("(%p %p %p): stub\n", thread, ideal, previous);
492 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
493 return FALSE;
496 /***********************************************************************
497 * GetThreadSelectorEntry (KERNEL32.@)
499 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent )
501 THREAD_DESCRIPTOR_INFORMATION tdi;
502 NTSTATUS status;
504 tdi.Selector = sel;
505 status = NtQueryInformationThread( hthread, ThreadDescriptorTableEntry, &tdi, sizeof(tdi), NULL);
506 if (status)
508 SetLastError( RtlNtStatusToDosError(status) );
509 return FALSE;
511 *ldtent = tdi.Entry;
512 return TRUE;
516 /* callback for QueueUserAPC */
517 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
519 PAPCFUNC func = (PAPCFUNC)arg1;
520 func( arg2 );
523 /***********************************************************************
524 * QueueUserAPC (KERNEL32.@)
526 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
528 NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
530 if (status) SetLastError( RtlNtStatusToDosError(status) );
531 return !status;
534 /***********************************************************************
535 * QueueUserWorkItem (KERNEL32.@)
537 BOOL WINAPI QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags )
539 NTSTATUS status;
541 TRACE("(%p,%p,0x%08x)\n", Function, Context, Flags);
543 status = RtlQueueWorkItem( Function, Context, Flags );
545 if (status) SetLastError( RtlNtStatusToDosError(status) );
546 return !status;
549 /**********************************************************************
550 * GetThreadTimes [KERNEL32.@] Obtains timing information.
552 * RETURNS
553 * Success: TRUE
554 * Failure: FALSE
556 BOOL WINAPI GetThreadTimes(
557 HANDLE thread, /* [in] Specifies the thread of interest */
558 LPFILETIME creationtime, /* [out] When the thread was created */
559 LPFILETIME exittime, /* [out] When the thread was destroyed */
560 LPFILETIME kerneltime, /* [out] Time thread spent in kernel mode */
561 LPFILETIME usertime) /* [out] Time thread spent in user mode */
563 KERNEL_USER_TIMES kusrt;
564 NTSTATUS status;
566 status = NtQueryInformationThread(thread, ThreadTimes, &kusrt,
567 sizeof(kusrt), NULL);
568 if (status)
570 SetLastError( RtlNtStatusToDosError(status) );
571 return FALSE;
573 if (creationtime)
575 creationtime->dwLowDateTime = kusrt.CreateTime.u.LowPart;
576 creationtime->dwHighDateTime = kusrt.CreateTime.u.HighPart;
578 if (exittime)
580 exittime->dwLowDateTime = kusrt.ExitTime.u.LowPart;
581 exittime->dwHighDateTime = kusrt.ExitTime.u.HighPart;
583 if (kerneltime)
585 kerneltime->dwLowDateTime = kusrt.KernelTime.u.LowPart;
586 kerneltime->dwHighDateTime = kusrt.KernelTime.u.HighPart;
588 if (usertime)
590 usertime->dwLowDateTime = kusrt.UserTime.u.LowPart;
591 usertime->dwHighDateTime = kusrt.UserTime.u.HighPart;
594 return TRUE;
597 /**********************************************************************
598 * GetThreadId [KERNEL32.@]
600 * Retrieve the identifier of a thread.
602 * PARAMS
603 * Thread [I] The thread to retrieve the identifier of.
605 * RETURNS
606 * Success: Identifier of the target thread.
607 * Failure: 0
609 DWORD WINAPI GetThreadId(HANDLE Thread)
611 THREAD_BASIC_INFORMATION tbi;
612 NTSTATUS status;
614 TRACE("(%p)\n", Thread);
616 status = NtQueryInformationThread(Thread, ThreadBasicInformation, &tbi,
617 sizeof(tbi), NULL);
618 if (status)
620 SetLastError( RtlNtStatusToDosError(status) );
621 return 0;
624 return HandleToULong(tbi.ClientId.UniqueThread);
627 /**********************************************************************
628 * GetProcessIdOfThread [KERNEL32.@]
630 * Retrieve process identifier given thread belongs to.
632 * PARAMS
633 * Thread [I] The thread identifier.
635 * RETURNS
636 * Success: Process identifier
637 * Failure: 0
639 DWORD WINAPI GetProcessIdOfThread(HANDLE Thread)
641 THREAD_BASIC_INFORMATION tbi;
642 NTSTATUS status;
644 TRACE("(%p)\n", Thread);
646 status = NtQueryInformationThread(Thread, ThreadBasicInformation, &tbi,
647 sizeof(tbi), NULL);
648 if (status)
650 SetLastError( RtlNtStatusToDosError(status) );
651 return 0;
654 return HandleToULong(tbi.ClientId.UniqueProcess);
657 /***********************************************************************
658 * GetCurrentThread [KERNEL32.@] Gets pseudohandle for current thread
660 * RETURNS
661 * Pseudohandle for the current thread
663 #undef GetCurrentThread
664 HANDLE WINAPI GetCurrentThread(void)
666 return (HANDLE)~(ULONG_PTR)1;
670 #ifdef __i386__
672 /***********************************************************************
673 * SetLastError (KERNEL32.@)
675 /* void WINAPI SetLastError( DWORD error ); */
676 __ASM_STDCALL_FUNC( SetLastError, 4,
677 "movl 4(%esp),%eax\n\t"
678 ".byte 0x64\n\t"
679 "movl %eax,0x34\n\t"
680 "ret $4" )
682 /***********************************************************************
683 * GetLastError (KERNEL32.@)
685 /* DWORD WINAPI GetLastError(void); */
686 __ASM_STDCALL_FUNC( GetLastError, 0, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" )
688 /***********************************************************************
689 * GetCurrentProcessId (KERNEL32.@)
691 /* DWORD WINAPI GetCurrentProcessId(void) */
692 __ASM_STDCALL_FUNC( GetCurrentProcessId, 0, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" )
694 /***********************************************************************
695 * GetCurrentThreadId (KERNEL32.@)
697 /* DWORD WINAPI GetCurrentThreadId(void) */
698 __ASM_STDCALL_FUNC( GetCurrentThreadId, 0, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" )
700 /***********************************************************************
701 * GetProcessHeap (KERNEL32.@)
703 /* HANDLE WINAPI GetProcessHeap(void) */
704 __ASM_STDCALL_FUNC( GetProcessHeap, 0, ".byte 0x64\n\tmovl 0x30,%eax\n\tmovl 0x18(%eax),%eax\n\tret");
706 #elif defined(__x86_64__)
708 #ifdef __APPLE__
710 /***********************************************************************
711 * SetLastError (KERNEL32.@)
713 /* void WINAPI SetLastError( DWORD error ); */
714 __ASM_STDCALL_FUNC( SetLastError, 8, ".byte 0x65\n\tmovq 0x30,%rax\n\tmovl %ecx,0x68(%rax)\n\tret" );
716 /***********************************************************************
717 * GetLastError (KERNEL32.@)
719 /* DWORD WINAPI GetLastError(void); */
720 __ASM_STDCALL_FUNC( GetLastError, 0, ".byte 0x65\n\tmovq 0x30,%rax\n\tmovl 0x68(%rax),%eax\n\tret" );
722 /***********************************************************************
723 * GetCurrentProcessId (KERNEL32.@)
725 /* DWORD WINAPI GetCurrentProcessId(void) */
726 __ASM_STDCALL_FUNC( GetCurrentProcessId, 0, ".byte 0x65\n\tmovq 0x30,%rax\n\tmovl 0x40(%rax),%eax\n\tret" );
728 /***********************************************************************
729 * GetCurrentThreadId (KERNEL32.@)
731 /* DWORD WINAPI GetCurrentThreadId(void) */
732 __ASM_STDCALL_FUNC( GetCurrentThreadId, 0, ".byte 0x65\n\tmovq 0x30,%rax\n\tmovl 0x48(%rax),%eax\n\tret" );
734 /***********************************************************************
735 * GetProcessHeap (KERNEL32.@)
737 /* HANDLE WINAPI GetProcessHeap(void) */
738 __ASM_STDCALL_FUNC( GetProcessHeap, 0, ".byte 0x65\n\tmovq 0x30,%rax\n\tmovq 0x60(%rax),%rax\n\tmovq 0x30(%rax),%rax\n\tret");
740 #else
742 /***********************************************************************
743 * SetLastError (KERNEL32.@)
745 /* void WINAPI SetLastError( DWORD error ); */
746 __ASM_STDCALL_FUNC( SetLastError, 8, ".byte 0x65\n\tmovl %ecx,0x68\n\tret" );
748 /***********************************************************************
749 * GetLastError (KERNEL32.@)
751 /* DWORD WINAPI GetLastError(void); */
752 __ASM_STDCALL_FUNC( GetLastError, 0, ".byte 0x65\n\tmovl 0x68,%eax\n\tret" );
754 /***********************************************************************
755 * GetCurrentProcessId (KERNEL32.@)
757 /* DWORD WINAPI GetCurrentProcessId(void) */
758 __ASM_STDCALL_FUNC( GetCurrentProcessId, 0, ".byte 0x65\n\tmovl 0x40,%eax\n\tret" );
760 /***********************************************************************
761 * GetCurrentThreadId (KERNEL32.@)
763 /* DWORD WINAPI GetCurrentThreadId(void) */
764 __ASM_STDCALL_FUNC( GetCurrentThreadId, 0, ".byte 0x65\n\tmovl 0x48,%eax\n\tret" );
766 /***********************************************************************
767 * GetProcessHeap (KERNEL32.@)
769 /* HANDLE WINAPI GetProcessHeap(void) */
770 __ASM_STDCALL_FUNC( GetProcessHeap, 0, ".byte 0x65\n\tmovq 0x60,%rax\n\tmovq 0x30(%rax),%rax\n\tret");
772 #endif /* __APPLE__ */
774 #else /* __x86_64__ */
776 /**********************************************************************
777 * SetLastError (KERNEL32.@)
779 * Sets the last-error code.
781 * RETURNS
782 * Nothing.
784 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
786 NtCurrentTeb()->LastErrorValue = error;
789 /**********************************************************************
790 * GetLastError (KERNEL32.@)
792 * Get the last-error code.
794 * RETURNS
795 * last-error code.
797 DWORD WINAPI GetLastError(void)
799 return NtCurrentTeb()->LastErrorValue;
802 /***********************************************************************
803 * GetCurrentProcessId (KERNEL32.@)
805 * Get the current process identifier.
807 * RETURNS
808 * current process identifier
810 DWORD WINAPI GetCurrentProcessId(void)
812 return HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess);
815 /***********************************************************************
816 * GetCurrentThreadId (KERNEL32.@)
818 * Get the current thread identifier.
820 * RETURNS
821 * current thread identifier
823 DWORD WINAPI GetCurrentThreadId(void)
825 return HandleToULong(NtCurrentTeb()->ClientId.UniqueThread);
828 /***********************************************************************
829 * GetProcessHeap (KERNEL32.@)
831 HANDLE WINAPI GetProcessHeap(void)
833 return NtCurrentTeb()->Peb->ProcessHeap;
836 #endif /* __i386__ */
838 /*************************************************************************
839 * rtlmode_to_win32mode
841 static DWORD rtlmode_to_win32mode( DWORD rtlmode )
843 DWORD win32mode = 0;
845 if (rtlmode & 0x10)
846 win32mode |= SEM_FAILCRITICALERRORS;
847 if (rtlmode & 0x20)
848 win32mode |= SEM_NOGPFAULTERRORBOX;
849 if (rtlmode & 0x40)
850 win32mode |= SEM_NOOPENFILEERRORBOX;
852 return win32mode;
855 /***********************************************************************
856 * SetThreadErrorMode (KERNEL32.@)
858 * Set the thread local error mode.
860 * PARAMS
861 * mode [I] The new error mode, a bitwise or of SEM_FAILCRITICALERRORS,
862 * SEM_NOGPFAULTERRORBOX and SEM_NOOPENFILEERRORBOX.
863 * oldmode [O] Destination of the old error mode (may be NULL)
865 * RETURNS
866 * Success: TRUE
867 * Failure: FALSE, check GetLastError
869 BOOL WINAPI SetThreadErrorMode( DWORD mode, LPDWORD oldmode )
871 NTSTATUS status;
872 DWORD tmp = 0;
874 if (mode & ~(SEM_FAILCRITICALERRORS |
875 SEM_NOGPFAULTERRORBOX |
876 SEM_NOOPENFILEERRORBOX))
878 SetLastError( ERROR_INVALID_PARAMETER );
879 return FALSE;
882 if (mode & SEM_FAILCRITICALERRORS)
883 tmp |= 0x10;
884 if (mode & SEM_NOGPFAULTERRORBOX)
885 tmp |= 0x20;
886 if (mode & SEM_NOOPENFILEERRORBOX)
887 tmp |= 0x40;
889 status = RtlSetThreadErrorMode( tmp, oldmode );
890 if (status)
892 SetLastError( RtlNtStatusToDosError(status) );
893 return FALSE;
896 if (oldmode)
897 *oldmode = rtlmode_to_win32mode(*oldmode);
899 return TRUE;
902 /***********************************************************************
903 * GetThreadErrorMode (KERNEL32.@)
905 * Get the thread local error mode.
907 * PARAMS
908 * None.
910 * RETURNS
911 * The current thread local error mode.
913 DWORD WINAPI GetThreadErrorMode( void )
915 return rtlmode_to_win32mode( RtlGetThreadErrorMode() );
918 /***********************************************************************
919 * GetThreadUILanguage (KERNEL32.@)
921 * Get the current thread's language identifier.
923 * PARAMS
924 * None.
926 * RETURNS
927 * The current thread's language identifier.
929 LANGID WINAPI GetThreadUILanguage( void )
931 LANGID lang;
932 NtQueryDefaultUILanguage( &lang );
933 FIXME(": stub, returning default language.\n");
934 return lang;
937 /***********************************************************************
938 * GetThreadIOPendingFlag (KERNEL32.@)
940 BOOL WINAPI GetThreadIOPendingFlag( HANDLE thread, PBOOL io_pending )
942 NTSTATUS status;
944 TRACE("%p, %p\n", thread, io_pending);
946 status = NtQueryInformationThread( thread, ThreadIsIoPending,
947 io_pending, sizeof(*io_pending), NULL );
948 if (status)
950 SetLastError( RtlNtStatusToDosError(status) );
951 return FALSE;
953 return TRUE;
956 /***********************************************************************
957 * CallbackMayRunLong (KERNEL32.@)
959 BOOL WINAPI CallbackMayRunLong( TP_CALLBACK_INSTANCE *instance )
961 NTSTATUS status;
963 TRACE( "%p\n", instance );
965 status = TpCallbackMayRunLong( instance );
966 if (status)
968 SetLastError( RtlNtStatusToDosError(status) );
969 return FALSE;
972 return TRUE;
975 /***********************************************************************
976 * CreateThreadpool (KERNEL32.@)
978 PTP_POOL WINAPI CreateThreadpool( PVOID reserved )
980 TP_POOL *pool;
981 NTSTATUS status;
983 TRACE( "%p\n", reserved );
985 status = TpAllocPool( &pool, reserved );
986 if (status)
988 SetLastError( RtlNtStatusToDosError(status) );
989 return NULL;
992 return pool;
995 /***********************************************************************
996 * CreateThreadpoolCleanupGroup (KERNEL32.@)
998 PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup( void )
1000 TP_CLEANUP_GROUP *group;
1001 NTSTATUS status;
1003 TRACE( "\n" );
1005 status = TpAllocCleanupGroup( &group );
1006 if (status)
1008 SetLastError( RtlNtStatusToDosError(status) );
1009 return NULL;
1012 return group;
1015 /***********************************************************************
1016 * CreateThreadpoolIo (KERNEL32.@)
1018 PTP_IO WINAPI CreateThreadpoolIo( HANDLE handle, PTP_WIN32_IO_CALLBACK callback,
1019 PVOID userdata, TP_CALLBACK_ENVIRON *environment )
1021 FIXME("(%p, %p, %p, %p): stub\n", handle, callback, userdata, environment);
1022 return FALSE;
1025 /***********************************************************************
1026 * CreateThreadpoolTimer (KERNEL32.@)
1028 PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userdata,
1029 TP_CALLBACK_ENVIRON *environment )
1031 TP_TIMER *timer;
1032 NTSTATUS status;
1034 TRACE( "%p, %p, %p\n", callback, userdata, environment );
1036 status = TpAllocTimer( &timer, callback, userdata, environment );
1037 if (status)
1039 SetLastError( RtlNtStatusToDosError(status) );
1040 return NULL;
1043 return timer;
1046 /***********************************************************************
1047 * CreateThreadpoolWait (KERNEL32.@)
1049 PTP_WAIT WINAPI CreateThreadpoolWait( PTP_WAIT_CALLBACK callback, PVOID userdata,
1050 TP_CALLBACK_ENVIRON *environment )
1052 TP_WAIT *wait;
1053 NTSTATUS status;
1055 TRACE( "%p, %p, %p\n", callback, userdata, environment );
1057 status = TpAllocWait( &wait, callback, userdata, environment );
1058 if (status)
1060 SetLastError( RtlNtStatusToDosError(status) );
1061 return NULL;
1064 return wait;
1067 /***********************************************************************
1068 * CreateThreadpoolWork (KERNEL32.@)
1070 PTP_WORK WINAPI CreateThreadpoolWork( PTP_WORK_CALLBACK callback, PVOID userdata,
1071 TP_CALLBACK_ENVIRON *environment )
1073 TP_WORK *work;
1074 NTSTATUS status;
1076 TRACE( "%p, %p, %p\n", callback, userdata, environment );
1078 status = TpAllocWork( &work, callback, userdata, environment );
1079 if (status)
1081 SetLastError( RtlNtStatusToDosError(status) );
1082 return NULL;
1085 return work;
1088 /***********************************************************************
1089 * SetThreadpoolTimer (KERNEL32.@)
1091 VOID WINAPI SetThreadpoolTimer( TP_TIMER *timer, FILETIME *due_time,
1092 DWORD period, DWORD window_length )
1094 LARGE_INTEGER timeout;
1096 TRACE( "%p, %p, %u, %u\n", timer, due_time, period, window_length );
1098 if (due_time)
1100 timeout.u.LowPart = due_time->dwLowDateTime;
1101 timeout.u.HighPart = due_time->dwHighDateTime;
1104 TpSetTimer( timer, due_time ? &timeout : NULL, period, window_length );
1107 /***********************************************************************
1108 * SetThreadpoolWait (KERNEL32.@)
1110 VOID WINAPI SetThreadpoolWait( TP_WAIT *wait, HANDLE handle, FILETIME *due_time )
1112 LARGE_INTEGER timeout;
1114 TRACE( "%p, %p, %p\n", wait, handle, due_time );
1116 if (!handle)
1118 due_time = NULL;
1120 else if (due_time)
1122 timeout.u.LowPart = due_time->dwLowDateTime;
1123 timeout.u.HighPart = due_time->dwHighDateTime;
1126 TpSetWait( wait, handle, due_time ? &timeout : NULL );
1129 /***********************************************************************
1130 * TrySubmitThreadpoolCallback (KERNEL32.@)
1132 BOOL WINAPI TrySubmitThreadpoolCallback( PTP_SIMPLE_CALLBACK callback, PVOID userdata,
1133 TP_CALLBACK_ENVIRON *environment )
1135 NTSTATUS status;
1137 TRACE( "%p, %p, %p\n", callback, userdata, environment );
1139 status = TpSimpleTryPost( callback, userdata, environment );
1140 if (status)
1142 SetLastError( RtlNtStatusToDosError(status) );
1143 return FALSE;
1146 return TRUE;