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
7 * Alex Ionescu (alex@relsoft.net)
12 /* INCLUDES *****************************************************************/
19 /* PRIVATE FUNCTIONS *******************************************************/
23 RtlpCreateUserStack(IN HANDLE hProcess
,
24 IN SIZE_T StackReserve OPTIONAL
,
25 IN SIZE_T StackCommit OPTIONAL
,
26 IN ULONG StackZeroBits OPTIONAL
,
27 OUT PINITIAL_TEB InitialTeb
)
30 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
31 PIMAGE_NT_HEADERS Headers
;
33 BOOLEAN UseGuard
= FALSE
;
37 /* Get some memory information */
38 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
40 sizeof(SYSTEM_BASIC_INFORMATION
),
42 if (!NT_SUCCESS(Status
)) return Status
;
44 /* Use the Image Settings if we are dealing with the current Process */
45 if (hProcess
== NtCurrentProcess())
47 /* Get the Image Headers */
48 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
49 if (!Headers
) return STATUS_INVALID_IMAGE_FORMAT
;
51 /* If we didn't get the parameters, find them ourselves */
52 if (!StackReserve
) StackReserve
= Headers
->OptionalHeader
.
54 if (!StackCommit
) StackCommit
= Headers
->OptionalHeader
.
59 /* Use the System Settings if needed */
60 if (!StackReserve
) StackReserve
= SystemBasicInfo
.AllocationGranularity
;
61 if (!StackCommit
) StackCommit
= SystemBasicInfo
.PageSize
;
64 /* Check if the commit is higher than the reserve*/
65 if (StackCommit
>= StackReserve
)
67 /* Grow the reserve beyond the commit, up to 1MB alignment */
68 StackReserve
= ROUND_UP(StackCommit
, 1024 * 1024);
71 /* Align everything to Page Size */
72 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
73 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
75 /* Reserve memory for the stack */
76 Status
= ZwAllocateVirtualMemory(hProcess
,
82 if (!NT_SUCCESS(Status
)) return Status
;
84 /* Now set up some basic Initial TEB Parameters */
85 InitialTeb
->PreviousStackBase
= NULL
;
86 InitialTeb
->PreviousStackLimit
= NULL
;
87 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
88 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
90 /* Update the Stack Position */
91 Stack
+= StackReserve
- StackCommit
;
93 /* Check if we will need a guard page */
94 if (StackReserve
> StackCommit
)
96 /* Remove a page to set as guard page */
97 Stack
-= SystemBasicInfo
.PageSize
;
98 StackCommit
+= SystemBasicInfo
.PageSize
;
102 /* Allocate memory for the stack */
103 Status
= ZwAllocateVirtualMemory(hProcess
,
109 if (!NT_SUCCESS(Status
)) return Status
;
111 /* Now set the current Stack Limit */
112 InitialTeb
->StackLimit
= (PVOID
)Stack
;
114 /* Create a guard page */
117 /* Attempt maximum space possible */
118 GuardPageSize
= SystemBasicInfo
.PageSize
;
119 Status
= ZwProtectVirtualMemory(hProcess
,
122 PAGE_GUARD
| PAGE_READWRITE
,
124 if (!NT_SUCCESS(Status
)) return Status
;
126 /* Update the Stack Limit keeping in mind the Guard Page */
127 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
+
132 return STATUS_SUCCESS
;
137 RtlpFreeUserStack(IN HANDLE Process
,
138 IN PINITIAL_TEB InitialTeb
)
144 Status
= ZwFreeVirtualMemory(Process
,
145 &InitialTeb
->AllocatedStackBase
,
149 /* Clear the initial TEB */
150 RtlZeroMemory(InitialTeb
, sizeof(INITIAL_TEB
));
154 /* FUNCTIONS ***************************************************************/
162 RtlSetThreadIsCritical(IN BOOLEAN NewValue
,
163 OUT PBOOLEAN OldValue OPTIONAL
,
164 IN BOOLEAN NeedBreaks
)
166 ULONG BreakOnTermination
;
168 /* Initialize to FALSE */
169 if (OldValue
) *OldValue
= FALSE
;
171 /* Fail, if the critical breaks flag is required but is not set */
173 !(NtCurrentPeb()->NtGlobalFlag
& FLG_ENABLE_SYSTEM_CRIT_BREAKS
))
175 return STATUS_UNSUCCESSFUL
;
178 /* Check if the caller wants the old value */
181 /* Query and return the old break on termination flag for the process */
182 ZwQueryInformationThread(NtCurrentThread(),
183 ThreadBreakOnTermination
,
187 *OldValue
= (BOOLEAN
)BreakOnTermination
;
190 /* Set the break on termination flag for the process */
191 BreakOnTermination
= NewValue
;
192 return ZwSetInformationThread(NtCurrentThread(),
193 ThreadBreakOnTermination
,
203 RtlCreateUserThread(IN HANDLE ProcessHandle
,
204 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
205 IN BOOLEAN CreateSuspended
,
206 IN ULONG StackZeroBits OPTIONAL
,
207 IN SIZE_T StackReserve OPTIONAL
,
208 IN SIZE_T StackCommit OPTIONAL
,
209 IN PTHREAD_START_ROUTINE StartAddress
,
210 IN PVOID Parameter OPTIONAL
,
211 OUT PHANDLE ThreadHandle OPTIONAL
,
212 OUT PCLIENT_ID ClientId OPTIONAL
)
217 INITIAL_TEB InitialTeb
;
218 OBJECT_ATTRIBUTES ObjectAttributes
;
221 /* First, we'll create the Stack */
222 Status
= RtlpCreateUserStack(ProcessHandle
,
227 if (!NT_SUCCESS(Status
)) return Status
;
229 /* Next, we'll set up the Initial Context */
230 RtlInitializeContext(ProcessHandle
,
234 InitialTeb
.StackBase
);
236 /* We are now ready to create the Kernel Thread Object */
237 InitializeObjectAttributes(&ObjectAttributes
,
242 Status
= ZwCreateThread(&Handle
,
250 if (!NT_SUCCESS(Status
))
253 RtlpFreeUserStack(ProcessHandle
, &InitialTeb
);
257 /* Return thread data */
259 *ThreadHandle
= Handle
;
262 if (ClientId
) *ClientId
= ThreadCid
;
265 /* Return success or the previous failure */
274 RtlExitUserThread(NTSTATUS Status
)
276 /* Call the Loader and tell him to notify the DLLs */
280 NtCurrentTeb()->FreeStackOnTermination
= TRUE
;
281 NtTerminateThread(NtCurrentThread(), Status
);
289 RtlFreeUserThreadStack(HANDLE ProcessHandle
,
293 THREAD_BASIC_INFORMATION ThreadBasicInfo
;
294 SIZE_T Dummy
, Size
= 0;
297 /* Query the Basic Info */
298 Status
= NtQueryInformationThread(ThreadHandle
,
299 ThreadBasicInformation
,
301 sizeof(THREAD_BASIC_INFORMATION
),
303 if (!NT_SUCCESS(Status
) || !ThreadBasicInfo
.TebBaseAddress
) return;
305 /* Get the deallocation stack */
306 Status
= NtReadVirtualMemory(ProcessHandle
,
307 &((PTEB
)ThreadBasicInfo
.TebBaseAddress
)->
312 if (!NT_SUCCESS(Status
) || !StackLocation
) return;
315 NtFreeVirtualMemory(ProcessHandle
, &StackLocation
, &Size
, MEM_RELEASE
);
323 return NtCurrentTeb();
328 RtlRemoteCall(IN HANDLE Process
,
331 IN ULONG ArgumentCount
,
333 IN BOOLEAN PassContext
,
334 IN BOOLEAN AlreadySuspended
)
337 return STATUS_NOT_IMPLEMENTED
;