ReactOS 0.4.16-dev-91-g764881a
thread.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Rtl user thread functions
5 * FILE: lib/rtl/thread.c
6 * PROGRAMERS:
7 * Alex Ionescu (alex@relsoft.net)
8 * Eric Kohl
9 * KJK::Hyperion
10 */
11
12/* INCLUDES *****************************************************************/
13
14#include <rtl.h>
15
16#define NDEBUG
17#include <debug.h>
18
19/* PRIVATE FUNCTIONS *******************************************************/
20
24 IN SIZE_T StackReserve OPTIONAL,
25 IN SIZE_T StackCommit OPTIONAL,
26 IN ULONG StackZeroBits OPTIONAL,
27 OUT PINITIAL_TEB InitialTeb)
28{
31 PIMAGE_NT_HEADERS Headers;
33 BOOLEAN UseGuard;
34 ULONG Dummy;
35 SIZE_T MinimumStackCommit, GuardPageSize;
36
37 /* Get some memory information */
41 NULL);
42 if (!NT_SUCCESS(Status)) return Status;
43
44 /* Use the Image Settings if we are dealing with the current Process */
46 {
47 /* Get the Image Headers */
48 Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
49 if (!Headers) return STATUS_INVALID_IMAGE_FORMAT;
50
51 /* If we didn't get the parameters, find them ourselves */
52 if (StackReserve == 0)
53 StackReserve = Headers->OptionalHeader.SizeOfStackReserve;
54 if (StackCommit == 0)
55 StackCommit = Headers->OptionalHeader.SizeOfStackCommit;
56
57 MinimumStackCommit = NtCurrentPeb()->MinimumStackCommit;
58 if ((MinimumStackCommit != 0) && (StackCommit < MinimumStackCommit))
59 {
60 StackCommit = MinimumStackCommit;
61 }
62 }
63 else
64 {
65 /* Use the System Settings if needed */
66 if (StackReserve == 0)
68 if (StackCommit == 0)
69 StackCommit = SystemBasicInfo.PageSize;
70 }
71
72 /* Check if the commit is higher than the reserve */
73 if (StackCommit >= StackReserve)
74 {
75 /* Grow the reserve beyond the commit, up to 1MB alignment */
76 StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
77 }
78
79 /* Align everything to Page Size */
80 StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
81 StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
82
83 /* Reserve memory for the stack */
84 Stack = 0;
85 Status = ZwAllocateVirtualMemory(ProcessHandle,
86 (PVOID*)&Stack,
87 StackZeroBits,
88 &StackReserve,
91 if (!NT_SUCCESS(Status)) return Status;
92
93 /* Now set up some basic Initial TEB Parameters */
94 InitialTeb->AllocatedStackBase = (PVOID)Stack;
95 InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
96 InitialTeb->PreviousStackBase = NULL;
97 InitialTeb->PreviousStackLimit = NULL;
98
99 /* Update the stack position */
100 Stack += StackReserve - StackCommit;
101
102 /* Check if we can add a guard page */
103 if (StackReserve >= StackCommit + SystemBasicInfo.PageSize)
104 {
106 StackCommit += SystemBasicInfo.PageSize;
107 UseGuard = TRUE;
108 }
109 else
110 {
111 UseGuard = FALSE;
112 }
113
114 /* Allocate memory for the stack */
115 Status = ZwAllocateVirtualMemory(ProcessHandle,
116 (PVOID*)&Stack,
117 0,
118 &StackCommit,
121 if (!NT_SUCCESS(Status))
122 {
123 GuardPageSize = 0;
124 ZwFreeVirtualMemory(ProcessHandle, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
125 return Status;
126 }
127
128 /* Now set the current Stack Limit */
129 InitialTeb->StackLimit = (PVOID)Stack;
130
131 /* Create a guard page if needed */
132 if (UseGuard)
133 {
134 GuardPageSize = SystemBasicInfo.PageSize;
136 (PVOID*)&Stack,
137 &GuardPageSize,
139 &Dummy);
140 if (!NT_SUCCESS(Status)) return Status;
141
142 /* Update the Stack Limit keeping in mind the Guard Page */
143 InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
144 GuardPageSize);
145 }
146
147 /* We are done! */
148 return STATUS_SUCCESS;
149}
150
151VOID
152NTAPI
154 IN PINITIAL_TEB InitialTeb)
155{
156 SIZE_T Dummy = 0;
157
158 /* Free the Stack */
159 ZwFreeVirtualMemory(ProcessHandle,
160 &InitialTeb->AllocatedStackBase,
161 &Dummy,
163
164 /* Clear the initial TEB */
165 RtlZeroMemory(InitialTeb, sizeof(*InitialTeb));
166}
167
168/* FUNCTIONS ***************************************************************/
169
170
171/*
172 * @implemented
173 */
177 OUT PBOOLEAN OldValue OPTIONAL,
178 IN BOOLEAN NeedBreaks)
179{
180 ULONG BreakOnTermination;
181
182 /* Initialize to FALSE */
183 if (OldValue) *OldValue = FALSE;
184
185 /* Fail, if the critical breaks flag is required but is not set */
186 if ((NeedBreaks) &&
188 {
189 return STATUS_UNSUCCESSFUL;
190 }
191
192 /* Check if the caller wants the old value */
193 if (OldValue)
194 {
195 /* Query and return the old break on termination flag for the process */
198 &BreakOnTermination,
199 sizeof(ULONG),
200 NULL);
201 *OldValue = (BOOLEAN)BreakOnTermination;
202 }
203
204 /* Set the break on termination flag for the process */
205 BreakOnTermination = NewValue;
206 return ZwSetInformationThread(NtCurrentThread(),
208 &BreakOnTermination,
209 sizeof(ULONG));
210}
211
212/*
213 @implemented
214*/
216NTAPI
219 IN BOOLEAN CreateSuspended,
220 IN ULONG StackZeroBits OPTIONAL,
221 IN SIZE_T StackReserve OPTIONAL,
222 IN SIZE_T StackCommit OPTIONAL,
223 IN PTHREAD_START_ROUTINE StartAddress,
225 OUT PHANDLE ThreadHandle OPTIONAL,
227{
230 CLIENT_ID ThreadCid;
231 INITIAL_TEB InitialTeb;
234
235 /* First, we'll create the Stack */
237 StackReserve,
238 StackCommit,
239 StackZeroBits,
240 &InitialTeb);
241 if (!NT_SUCCESS(Status)) return Status;
242
243 /* Next, we'll set up the Initial Context */
245 &Context,
246 Parameter,
247 StartAddress,
248 InitialTeb.StackBase);
249
250 /* We are now ready to create the Kernel Thread Object */
252 NULL,
253 0,
254 NULL,
260 &ThreadCid,
261 &Context,
262 &InitialTeb,
263 CreateSuspended);
264 if (!NT_SUCCESS(Status))
265 {
266 /* Free the stack */
267 RtlpFreeUserStack(ProcessHandle, &InitialTeb);
268 }
269 else
270 {
271 /* Return thread data */
272 if (ThreadHandle)
273 *ThreadHandle = Handle;
274 else
276 if (ClientId) *ClientId = ThreadCid;
277 }
278
279 /* Return success or the previous failure */
280 return Status;
281}
282
283/*
284 * @implemented
285 */
286VOID
287NTAPI
289{
290 /* Call the Loader and tell him to notify the DLLs */
292
293 /* Shut us down */
294 NtCurrentTeb()->FreeStackOnTermination = TRUE;
296}
297
298/*
299 @implemented
300*/
301VOID
302NTAPI
304 HANDLE ThreadHandle)
305{
307 THREAD_BASIC_INFORMATION ThreadBasicInfo;
308 SIZE_T Dummy, Size = 0;
309 PVOID StackLocation;
310
311 /* Query the Basic Info */
312 Status = NtQueryInformationThread(ThreadHandle,
314 &ThreadBasicInfo,
316 NULL);
317 if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return;
318
319 /* Get the deallocation stack */
321 &((PTEB)ThreadBasicInfo.TebBaseAddress)->
322 DeallocationStack,
323 &StackLocation,
324 sizeof(PVOID),
325 &Dummy);
326 if (!NT_SUCCESS(Status) || !StackLocation) return;
327
328 /* Free it */
330}
331
332PTEB
333NTAPI
335{
336 /* Return the TEB */
337 return NtCurrentTeb();
338}
339
341NTAPI
344 IN PVOID CallSite,
345 IN ULONG ArgumentCount,
346 IN PULONG Arguments,
347 IN BOOLEAN PassContext,
348 IN BOOLEAN AlreadySuspended)
349{
352}
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned char BOOLEAN
#define __cdecl
Definition: accygwin.h:79
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: debug.h:118
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
@ ThreadBreakOnTermination
Definition: compat.h:953
@ ThreadBasicInformation
Definition: compat.h:935
#define RtlImageNtHeader
Definition: compat.h:806
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
@ SystemBasicInformation
Definition: ntddk_ex.h:11
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
#define FLG_ENABLE_SYSTEM_CRIT_BREAKS
Definition: pstypes.h:78
NTSYSAPI void WINAPI LdrShutdownThread(void)
Definition: ldrinit.c:1082
#define NtCurrentTeb
static PVOID
Definition: thread.c:78
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID *BaseAddress, _In_ SIZE_T *NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection)
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _Out_ PVOID ThreadInformation, _In_ ULONG ThreadInformationLength, _Out_opt_ PULONG ReturnLength)
NTSYSAPI NTSTATUS NTAPI ZwCreateThread(_Out_ PHANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ HANDLE ProcessHandle, _Out_ PCLIENT_ID ClientId, _In_ PCONTEXT ThreadContext, _In_ PINITIAL_TEB UserStack, _In_ BOOLEAN CreateSuspended)
ULONG(NTAPI * PTHREAD_START_ROUTINE)(PVOID Parameter)
Definition: rtltypes.h:566
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1279
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define MEM_RESERVE
Definition: nt_native.h:1314
#define MEM_RELEASE
Definition: nt_native.h:1316
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_GUARD
Definition: nt_native.h:1310
ULONG NtGlobalFlag
Definition: init.c:54
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5230
NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
Definition: virtual.c:2816
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define BOOLEAN
Definition: pedump.c:73
SYSTEM_BASIC_INFORMATION SystemBasicInfo
Definition: perfdata.c:30
VOID NTAPI RtlInitializeContext(IN HANDLE ProcessHandle, OUT PCONTEXT ThreadContext, IN PVOID ThreadStartParam OPTIONAL, IN PTHREAD_START_ROUTINE ThreadStartAddress, IN PINITIAL_TEB InitialTeb)
Definition: thread.c:27
VOID NTAPI RtlFreeUserThreadStack(HANDLE ProcessHandle, HANDLE ThreadHandle)
Definition: thread.c:303
NTSTATUS __cdecl RtlSetThreadIsCritical(IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN NeedBreaks)
Definition: thread.c:176
VOID NTAPI RtlExitUserThread(NTSTATUS Status)
Definition: thread.c:288
PTEB NTAPI _NtCurrentTeb(VOID)
Definition: thread.c:334
NTSTATUS NTAPI RtlpCreateUserStack(IN HANDLE ProcessHandle, IN SIZE_T StackReserve OPTIONAL, IN SIZE_T StackCommit OPTIONAL, IN ULONG StackZeroBits OPTIONAL, OUT PINITIAL_TEB InitialTeb)
Definition: thread.c:23
NTSTATUS NTAPI RtlRemoteCall(IN HANDLE Process, IN HANDLE Thread, IN PVOID CallSite, IN ULONG ArgumentCount, IN PULONG Arguments, IN BOOLEAN PassContext, IN BOOLEAN AlreadySuspended)
Definition: thread.c:342
NTSTATUS NTAPI RtlCreateUserThread(IN HANDLE ProcessHandle, IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, IN BOOLEAN CreateSuspended, IN ULONG StackZeroBits OPTIONAL, IN SIZE_T StackReserve OPTIONAL, IN SIZE_T StackCommit OPTIONAL, IN PTHREAD_START_ROUTINE StartAddress, IN PVOID Parameter OPTIONAL, OUT PHANDLE ThreadHandle OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL)
Definition: thread.c:217
VOID NTAPI RtlpFreeUserStack(IN HANDLE ProcessHandle, IN PINITIAL_TEB InitialTeb)
Definition: thread.c:153
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
PVOID StackBase
Definition: pstypes.h:695
Definition: compat.h:836
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336
#define NtCurrentThread()