ReactOS  0.4.14-dev-342-gdc047f9
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 
22 NTAPI
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;
32  ULONG_PTR Stack;
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  {
105  Stack -= SystemBasicInfo.PageSize;
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,
119  MEM_COMMIT,
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 
151 VOID
152 NTAPI
154  IN PINITIAL_TEB InitialTeb)
155 {
156  SIZE_T Dummy = 0;
157 
158  /* Free the Stack */
159  ZwFreeVirtualMemory(ProcessHandle,
160  &InitialTeb->AllocatedStackBase,
161  &Dummy,
162  MEM_RELEASE);
163 
164  /* Clear the initial TEB */
165  RtlZeroMemory(InitialTeb, sizeof(*InitialTeb));
166 }
167 
168 /* FUNCTIONS ***************************************************************/
169 
170 
171 /*
172  * @implemented
173  */
174 NTSTATUS
175 __cdecl
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 */
215 NTSTATUS
216 NTAPI
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 {
229  HANDLE Handle;
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
275  NtClose(Handle);
276  if (ClientId) *ClientId = ThreadCid;
277  }
278 
279  /* Return success or the previous failure */
280  return Status;
281 }
282 
283 /*
284  * @implemented
285  */
286 VOID
287 NTAPI
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 */
301 VOID
302 NTAPI
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,
315  sizeof(THREAD_BASIC_INFORMATION),
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 
332 PTEB
333 NTAPI
335 {
336  /* Return the TEB */
337  return NtCurrentTeb();
338 }
339 
340 NTSTATUS
341 NTAPI
343  IN HANDLE Thread,
344  IN PVOID CallSite,
345  IN ULONG ArgumentCount,
346  IN PULONG Arguments,
347  IN BOOLEAN PassContext,
348  IN BOOLEAN AlreadySuspended)
349 {
351  return STATUS_NOT_IMPLEMENTED;
352 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:38
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define TRUE
Definition: types.h:120
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
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
#define __cdecl
Definition: accygwin.h:79
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
_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:182
#define PAGE_GUARD
Definition: nt_native.h:1310
LONG NTSTATUS
Definition: precomp.h:26
#define NtCurrentThread()
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
static PVOID
Definition: thread.c:83
_In_ PVOID Parameter
Definition: ldrtypes.h:241
#define FLG_ENABLE_SYSTEM_CRIT_BREAKS
Definition: pstypes.h:78
#define MEM_COMMIT
Definition: nt_native.h:1313
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
NTSTATUS __cdecl RtlSetThreadIsCritical(IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN NeedBreaks)
Definition: thread.c:176
ULONG(NTAPI * PTHREAD_START_ROUTINE)(PVOID Parameter)
Definition: rtltypes.h:562
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define MEM_RESERVE
Definition: nt_native.h:1314
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
PVOID StackBase
Definition: pstypes.h:678
PTEB NTAPI _NtCurrentTeb(VOID)
Definition: thread.c:334
#define NtCurrentProcess()
Definition: nt_native.h:1657
VOID NTAPI RtlpFreeUserStack(IN HANDLE ProcessHandle, IN PINITIAL_TEB InitialTeb)
Definition: thread.c:153
_In_ HANDLE Handle
Definition: extypes.h:390
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:345
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
SYSTEM_BASIC_INFORMATION SystemBasicInfo
Definition: perfdata.c:45
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
Definition: virtual.c:2691
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
char * PBOOLEAN
Definition: retypes.h:11
VOID NTAPI RtlExitUserThread(NTSTATUS Status)
Definition: thread.c:288
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
Definition: compat.h:492
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
#define NtCurrentPeb()
Definition: FLS.c:20
unsigned int * PULONG
Definition: retypes.h:1
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
#define RtlImageNtHeader
Definition: compat.h:465
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _Out_ PVOID ThreadInformation, _In_ ULONG ThreadInformationLength, _Out_opt_ PULONG ReturnLength)
#define MEM_RELEASE
Definition: nt_native.h:1316
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:39
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
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
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI LdrShutdownThread(VOID)
Definition: ldrinit.c:1078
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
VOID NTAPI RtlFreeUserThreadStack(HANDLE ProcessHandle, HANDLE ThreadHandle)
Definition: thread.c:303
return STATUS_SUCCESS
Definition: btrfs.c:2938
ULONG NtGlobalFlag
Definition: init.c:51
NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID *BaseAddress, _In_ SIZE_T *NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection)
#define PAGE_READWRITE
Definition: nt_native.h:1304
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)
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5090
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68