2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Rtl user thread functions
5 * FILE: lib/ntdll/rtl/thread.c
9 * 09/10/99: Cleanup and full stack support.
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <napi/i386/segment.h>
17 #include <ntdll/rtl.h>
20 #include <ntdll/ntdll.h>
23 /* FUNCTIONS ***************************************************************/
27 RtlCreateUserThread(HANDLE ProcessHandle
,
28 PSECURITY_DESCRIPTOR SecurityDescriptor
,
29 BOOLEAN CreateSuspended
,
33 PTHREAD_START_ROUTINE StartAddress
,
38 HANDLE LocalThreadHandle
;
39 CLIENT_ID LocalClientId
;
40 OBJECT_ATTRIBUTES ObjectAttributes
;
41 INITIAL_TEB InitialTeb
;
42 CONTEXT ThreadContext
;
49 /* initialize initial teb */
50 if ((StackCommit
!= NULL
) && (*StackCommit
> PAGESIZE
))
51 CommitSize
= *StackCommit
;
53 CommitSize
= PAGESIZE
;
55 if ((StackReserve
!= NULL
) && (*StackReserve
> 0x100000))
56 ReserveSize
= *StackReserve
;
58 ReserveSize
= 0x100000; /* 1MByte */
65 InitialTeb
.StackReserve
= NULL
;
66 Status
= NtAllocateVirtualMemory(ProcessHandle
,
67 &InitialTeb
.StackReserve
,
73 if (!NT_SUCCESS(Status
))
75 DPRINT("Error reserving stack space!\n");
79 DPRINT("StackReserved: %p ReservedSize: 0x%lx\n",
80 InitialTeb
.StackReserve
, ReserveSize
);
82 InitialTeb
.StackBase
= (PVOID
)(InitialTeb
.StackReserve
+ ReserveSize
);
83 InitialTeb
.StackCommit
= (PVOID
)(InitialTeb
.StackBase
- CommitSize
);
84 InitialTeb
.StackLimit
= (PVOID
)(InitialTeb
.StackCommit
- PAGESIZE
);
85 InitialTeb
.StackCommitMax
= (PVOID
)(InitialTeb
.StackReserve
+ PAGESIZE
);
87 DPRINT("StackBase: %p\n",
88 InitialTeb
.StackBase
);
90 /* Commit stack page */
91 Status
= NtAllocateVirtualMemory(ProcessHandle
,
92 &InitialTeb
.StackCommit
,
98 if (!NT_SUCCESS(Status
))
100 /* release the stack space */
101 NtFreeVirtualMemory(ProcessHandle
,
102 InitialTeb
.StackReserve
,
106 DPRINT("Error comitting stack page!\n");
110 DPRINT("StackCommit: %p CommitSize: 0x%lx\n",
111 InitialTeb
.StackCommit
, CommitSize
);
113 /* Commit guard page */
114 Status
= NtAllocateVirtualMemory(ProcessHandle
,
115 &InitialTeb
.StackLimit
,
121 if (!NT_SUCCESS(Status
))
123 /* release the stack space */
124 NtFreeVirtualMemory(ProcessHandle
,
125 InitialTeb
.StackReserve
,
129 DPRINT("Error comitting guard page!\n");
133 DPRINT("StackLimit: %p GuardSize: 0x%lx\n",
134 InitialTeb
.StackLimit
, GuardSize
);
136 /* initialize thread context */
137 RtlInitializeContext (ProcessHandle
,
143 /* create the thread */
144 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
145 ObjectAttributes
.RootDirectory
= NULL
;
146 ObjectAttributes
.ObjectName
= NULL
;
147 // ObjectAttributes.Attributes = 0;
148 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
149 ObjectAttributes
.SecurityDescriptor
= SecurityDescriptor
;
150 ObjectAttributes
.SecurityQualityOfService
= NULL
;
152 Status
= NtCreateThread(&LocalThreadHandle
,
161 if (!NT_SUCCESS(Status
))
163 /* release the stack space */
164 NtFreeVirtualMemory(ProcessHandle
,
165 InitialTeb
.StackReserve
,
169 DPRINT("Error creating thread!\n");
173 /* return committed stack size */
175 *StackCommit
= CommitSize
;
177 /* return reserved stack size */
179 *StackReserve
= ReserveSize
;
181 /* return thread handle */
183 *ThreadHandle
= LocalThreadHandle
;
185 /* return client id */
188 ClientId
->UniqueProcess
= LocalClientId
.UniqueProcess
;
189 ClientId
->UniqueThread
= LocalClientId
.UniqueThread
;
197 RtlInitializeContext(HANDLE ProcessHandle
,
200 PTHREAD_START_ROUTINE StartAddress
,
201 PINITIAL_TEB InitialTeb
)
207 memset (Context
, 0, sizeof(CONTEXT
));
209 Context
->Eip
= (LONG
)StartAddress
;
210 Context
->SegGs
= USER_DS
;
211 Context
->SegFs
= TEB_SELECTOR
;
212 Context
->SegEs
= USER_DS
;
213 Context
->SegDs
= USER_DS
;
214 Context
->SegCs
= USER_CS
;
215 Context
->SegSs
= USER_DS
;
216 Context
->Esp
= (ULONG
)InitialTeb
->StackBase
- 8;
217 Context
->EFlags
= (1<<1) + (1<<9);
219 /* prepare the thread stack for execution */
220 if (ProcessHandle
== NtCurrentProcess())
222 *((PULONG
)(InitialTeb
->StackBase
- 4)) = (ULONG
)Parameter
;
223 *((PULONG
)(InitialTeb
->StackBase
- 8)) = 0xdeadbeef;
227 Buffer
[0] = (ULONG
)Parameter
;
228 Buffer
[1] = 0xdeadbeef;
230 Status
= NtWriteVirtualMemory(ProcessHandle
,
231 (PVOID
)(InitialTeb
->StackBase
- 4),
238 return STATUS_SUCCESS
;
243 RtlFreeUserThreadStack (HANDLE ProcessHandle
, HANDLE ThreadHandle
)
245 THREAD_BASIC_INFORMATION ThreadInfo
;
252 Status
= NtQueryInformationThread (ThreadHandle
,
253 ThreadBasicInformation
,
255 sizeof(THREAD_BASIC_INFORMATION
),
257 if (!NT_SUCCESS(Status
))
260 if (ThreadInfo
.TebBaseAddress
== NULL
)
263 Teb
= (PNT_TEB
)ThreadInfo
.TebBaseAddress
;
264 Status
= NtReadVirtualMemory (ProcessHandle
,
265 &Teb
->DeallocationStack
,
269 if (!NT_SUCCESS(Status
))
272 if (StackBase
== NULL
)
276 Status
= NtFreeVirtualMemory (ProcessHandle
,