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 ((StackCommit
!= NULL
) && (*StackCommit
> PAGESIZE
))
48 InitialTeb
.StackCommit
= *StackCommit
;
50 InitialTeb
.StackCommit
= PAGESIZE
;
52 if ((StackReserve
!= NULL
) && (*StackReserve
> 0x100000))
53 InitialTeb
.StackReserve
= *StackReserve
;
55 InitialTeb
.StackReserve
= 0x100000; /* 1MByte */
57 /* add size of guard page */
58 InitialTeb
.StackCommit
+= PAGESIZE
;
61 InitialTeb
.StackAllocate
= NULL
;
62 Status
= NtAllocateVirtualMemory(ProcessHandle
,
63 &InitialTeb
.StackAllocate
,
65 &InitialTeb
.StackReserve
,
66 MEM_COMMIT
, //MEM_RESERVE,
68 if (!NT_SUCCESS(Status
))
70 DPRINT("Error reserving stack space!\n");
74 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
75 InitialTeb
.StackAllocate
, InitialTeb
.StackReserve
);
77 InitialTeb
.StackBase
= (PVOID
)((ULONG
)InitialTeb
.StackAllocate
+ InitialTeb
.StackReserve
);
78 InitialTeb
.StackLimit
= (PVOID
)((ULONG
)InitialTeb
.StackBase
- InitialTeb
.StackCommit
);
80 DPRINT("StackBase: %p StackCommit: 0x%lX\n",
81 InitialTeb
.StackBase
, InitialTeb
.StackCommit
);
84 Status
= NtAllocateVirtualMemory(ProcessHandle
,
85 &InitialTeb
.StackLimit
,
87 &InitialTeb
.StackCommit
,
90 if (!NT_SUCCESS(Status
))
92 /* release the stack space */
93 NtFreeVirtualMemory(ProcessHandle
,
94 InitialTeb
.StackAllocate
,
95 &InitialTeb
.StackReserve
,
98 DPRINT("Error comitting stack page!\n");
102 DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n",
103 InitialTeb
.StackLimit
,
104 InitialTeb
.StackCommit
);
106 /* Protect guard page */
107 Status
= NtProtectVirtualMemory(ProcessHandle
,
108 InitialTeb
.StackLimit
,
110 PAGE_GUARD
| PAGE_READWRITE
,
112 if (!NT_SUCCESS(Status
))
114 /* release the stack space */
115 NtFreeVirtualMemory(ProcessHandle
,
116 InitialTeb
.StackAllocate
,
117 &InitialTeb
.StackReserve
,
120 DPRINT("Error protecting guard page!\n");
124 /* initialize thread context */
125 RtlInitializeContext (ProcessHandle
,
131 /* create the thread */
132 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
133 ObjectAttributes
.RootDirectory
= NULL
;
134 ObjectAttributes
.ObjectName
= NULL
;
135 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
136 ObjectAttributes
.SecurityDescriptor
= SecurityDescriptor
;
137 ObjectAttributes
.SecurityQualityOfService
= NULL
;
139 Status
= NtCreateThread(&LocalThreadHandle
,
148 if (!NT_SUCCESS(Status
))
150 /* release the stack space */
151 NtFreeVirtualMemory(ProcessHandle
,
152 InitialTeb
.StackAllocate
,
153 &InitialTeb
.StackReserve
,
156 DPRINT("Error creating thread!\n");
160 /* return committed stack size */
162 *StackCommit
= InitialTeb
.StackCommit
;
164 /* return reserved stack size */
166 *StackReserve
= InitialTeb
.StackReserve
;
168 /* return thread handle */
170 *ThreadHandle
= LocalThreadHandle
;
172 /* return client id */
175 ClientId
->UniqueProcess
= LocalClientId
.UniqueProcess
;
176 ClientId
->UniqueThread
= LocalClientId
.UniqueThread
;
179 return(STATUS_SUCCESS
);
184 RtlInitializeContext(HANDLE ProcessHandle
,
187 PTHREAD_START_ROUTINE StartAddress
,
188 PINITIAL_TEB InitialTeb
)
194 memset (Context
, 0, sizeof(CONTEXT
));
195 Context
->Eip
= (LONG
)StartAddress
;
196 Context
->SegGs
= USER_DS
;
197 Context
->SegFs
= TEB_SELECTOR
;
198 Context
->SegEs
= USER_DS
;
199 Context
->SegDs
= USER_DS
;
200 Context
->SegCs
= USER_CS
;
201 Context
->SegSs
= USER_DS
;
202 Context
->Esp
= (ULONG
)InitialTeb
->StackBase
- 8;
203 Context
->EFlags
= (1<<1) + (1<<9);
205 /* prepare the thread stack for execution */
206 if (ProcessHandle
== NtCurrentProcess())
208 *((PULONG
)(InitialTeb
->StackBase
- 4)) = (ULONG
)Parameter
;
209 *((PULONG
)(InitialTeb
->StackBase
- 8)) = 0xdeadbeef;
213 Buffer
[0] = (ULONG
)Parameter
;
214 Buffer
[1] = 0xdeadbeef;
216 Status
= NtWriteVirtualMemory(ProcessHandle
,
217 (PVOID
)((ULONG
)InitialTeb
->StackBase
- 8),
224 return STATUS_SUCCESS
;
229 RtlFreeUserThreadStack(HANDLE ProcessHandle
,
232 THREAD_BASIC_INFORMATION ThreadInfo
;
239 Status
= NtQueryInformationThread(ThreadHandle
,
240 ThreadBasicInformation
,
242 sizeof(THREAD_BASIC_INFORMATION
),
244 if (!NT_SUCCESS(Status
))
247 if (ThreadInfo
.TebBaseAddress
== NULL
)
250 Teb
= (PTEB
)ThreadInfo
.TebBaseAddress
;
251 Status
= NtReadVirtualMemory(ProcessHandle
,
252 &Teb
->DeallocationStack
,
256 if (!NT_SUCCESS(Status
))
259 if (StackBase
== NULL
)
263 Status
= NtFreeVirtualMemory(ProcessHandle
,