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
;
43 ULONG OldPageProtection
;
46 /* initialize initial teb */
47 if ((StackReserve
!= NULL
) && (*StackReserve
> 0x100000))
48 InitialTeb
.StackReserve
= *StackReserve
;
50 InitialTeb
.StackReserve
= 0x100000; /* 1MByte */
52 /* FIXME: use correct commit size */
54 if ((StackCommit
!= NULL
) && (*StackCommit
> PAGE_SIZE
))
55 InitialTeb
.StackCommit
= *StackCommit
;
57 InitialTeb
.StackCommit
= PAGE_SIZE
;
59 InitialTeb
.StackCommit
= InitialTeb
.StackReserve
- PAGE_SIZE
;
61 /* add size of guard page */
62 InitialTeb
.StackCommit
+= PAGE_SIZE
;
65 InitialTeb
.StackAllocate
= NULL
;
66 Status
= NtAllocateVirtualMemory(ProcessHandle
,
67 &InitialTeb
.StackAllocate
,
69 &InitialTeb
.StackReserve
,
72 if (!NT_SUCCESS(Status
))
74 DPRINT("Error reserving stack space!\n");
78 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
79 InitialTeb
.StackAllocate
, InitialTeb
.StackReserve
);
81 InitialTeb
.StackBase
= (PVOID
)((ULONG
)InitialTeb
.StackAllocate
+ InitialTeb
.StackReserve
);
82 InitialTeb
.StackLimit
= (PVOID
)((ULONG
)InitialTeb
.StackBase
- InitialTeb
.StackCommit
);
84 DPRINT("StackBase: %p StackCommit: 0x%lX\n",
85 InitialTeb
.StackBase
, InitialTeb
.StackCommit
);
88 Status
= NtAllocateVirtualMemory(ProcessHandle
,
89 &InitialTeb
.StackLimit
,
91 &InitialTeb
.StackCommit
,
94 if (!NT_SUCCESS(Status
))
96 /* release the stack space */
97 NtFreeVirtualMemory(ProcessHandle
,
98 InitialTeb
.StackAllocate
,
99 &InitialTeb
.StackReserve
,
102 DPRINT("Error comitting stack page!\n");
106 DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n",
107 InitialTeb
.StackLimit
,
108 InitialTeb
.StackCommit
);
110 /* Protect guard page */
111 Status
= NtProtectVirtualMemory(ProcessHandle
,
112 InitialTeb
.StackLimit
,
114 PAGE_GUARD
| PAGE_READWRITE
,
116 if (!NT_SUCCESS(Status
))
118 /* release the stack space */
119 NtFreeVirtualMemory(ProcessHandle
,
120 InitialTeb
.StackAllocate
,
121 &InitialTeb
.StackReserve
,
124 DPRINT("Error protecting guard page!\n");
128 /* initialize thread context */
129 RtlInitializeContext(ProcessHandle
,
135 /* create the thread */
136 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
137 ObjectAttributes
.RootDirectory
= NULL
;
138 ObjectAttributes
.ObjectName
= NULL
;
139 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
140 ObjectAttributes
.SecurityDescriptor
= SecurityDescriptor
;
141 ObjectAttributes
.SecurityQualityOfService
= NULL
;
143 Status
= NtCreateThread(&LocalThreadHandle
,
151 if (!NT_SUCCESS(Status
))
153 /* release the stack space */
154 NtFreeVirtualMemory(ProcessHandle
,
155 InitialTeb
.StackAllocate
,
156 &InitialTeb
.StackReserve
,
159 DPRINT("Error creating thread!\n");
163 /* return committed stack size */
165 *StackCommit
= InitialTeb
.StackCommit
;
167 /* return reserved stack size */
169 *StackReserve
= InitialTeb
.StackReserve
;
171 /* return thread handle */
173 *ThreadHandle
= LocalThreadHandle
;
175 /* return client id */
178 ClientId
->UniqueProcess
= LocalClientId
.UniqueProcess
;
179 ClientId
->UniqueThread
= LocalClientId
.UniqueThread
;
182 return(STATUS_SUCCESS
);
187 RtlInitializeContext(HANDLE ProcessHandle
,
190 PTHREAD_START_ROUTINE StartAddress
,
191 PINITIAL_TEB InitialTeb
)
197 memset (Context
, 0, sizeof(CONTEXT
));
198 Context
->Eip
= (LONG
)StartAddress
;
199 Context
->SegGs
= USER_DS
;
200 Context
->SegFs
= TEB_SELECTOR
;
201 Context
->SegEs
= USER_DS
;
202 Context
->SegDs
= USER_DS
;
203 Context
->SegCs
= USER_CS
;
204 Context
->SegSs
= USER_DS
;
205 Context
->Esp
= (ULONG
)InitialTeb
->StackBase
- 8;
206 Context
->EFlags
= (1<<1) + (1<<9);
208 /* prepare the thread stack for execution */
209 if (ProcessHandle
== NtCurrentProcess())
211 *((PULONG
)(InitialTeb
->StackBase
- 4)) = (ULONG
)Parameter
;
212 *((PULONG
)(InitialTeb
->StackBase
- 8)) = 0xdeadbeef;
216 Buffer
[0] = (ULONG
)Parameter
;
217 Buffer
[1] = 0xdeadbeef;
219 Status
= NtWriteVirtualMemory(ProcessHandle
,
220 (PVOID
)((ULONG
)InitialTeb
->StackBase
- 8),
227 return STATUS_SUCCESS
;
232 RtlFreeUserThreadStack(HANDLE ProcessHandle
,
235 THREAD_BASIC_INFORMATION ThreadInfo
;
242 Status
= NtQueryInformationThread(ThreadHandle
,
243 ThreadBasicInformation
,
245 sizeof(THREAD_BASIC_INFORMATION
),
247 if (!NT_SUCCESS(Status
))
250 if (ThreadInfo
.TebBaseAddress
== NULL
)
253 Teb
= (PTEB
)ThreadInfo
.TebBaseAddress
;
254 Status
= NtReadVirtualMemory(ProcessHandle
,
255 &Teb
->DeallocationStack
,
259 if (!NT_SUCCESS(Status
))
262 if (StackBase
== NULL
)
266 Status
= NtFreeVirtualMemory(ProcessHandle
,