Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthread.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * PURPOSE: Rtl user thread functions 00005 * FILE: lib/rtl/thread.c 00006 * PROGRAMERS: 00007 * Alex Ionescu (alex@relsoft.net) 00008 * Eric Kohl 00009 * KJK::Hyperion 00010 */ 00011 00012 /* INCLUDES *****************************************************************/ 00013 00014 #include <rtl.h> 00015 00016 #define NDEBUG 00017 #include <debug.h> 00018 00019 /* PRIVATE FUNCTIONS *******************************************************/ 00020 00021 NTSTATUS 00022 NTAPI 00023 RtlpCreateUserStack(IN HANDLE hProcess, 00024 IN SIZE_T StackReserve OPTIONAL, 00025 IN SIZE_T StackCommit OPTIONAL, 00026 IN ULONG StackZeroBits OPTIONAL, 00027 OUT PINITIAL_TEB InitialTeb) 00028 { 00029 NTSTATUS Status; 00030 SYSTEM_BASIC_INFORMATION SystemBasicInfo; 00031 PIMAGE_NT_HEADERS Headers; 00032 ULONG_PTR Stack = 0; 00033 BOOLEAN UseGuard = FALSE; 00034 ULONG Dummy; 00035 SIZE_T GuardPageSize; 00036 00037 /* Get some memory information */ 00038 Status = ZwQuerySystemInformation(SystemBasicInformation, 00039 &SystemBasicInfo, 00040 sizeof(SYSTEM_BASIC_INFORMATION), 00041 NULL); 00042 if (!NT_SUCCESS(Status)) return Status; 00043 00044 /* Use the Image Settings if we are dealing with the current Process */ 00045 if (hProcess == NtCurrentProcess()) 00046 { 00047 /* Get the Image Headers */ 00048 Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); 00049 00050 /* If we didn't get the parameters, find them ourselves */ 00051 if (!StackReserve) StackReserve = Headers->OptionalHeader. 00052 SizeOfStackReserve; 00053 if (!StackCommit) StackCommit = Headers->OptionalHeader. 00054 SizeOfStackCommit; 00055 } 00056 else 00057 { 00058 /* Use the System Settings if needed */ 00059 if (!StackReserve) StackReserve = SystemBasicInfo.AllocationGranularity; 00060 if (!StackCommit) StackCommit = SystemBasicInfo.PageSize; 00061 } 00062 00063 /* Align everything to Page Size */ 00064 StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity); 00065 StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize); 00066 00067 // FIXME: Remove once Guard Page support is here 00068 #if 1 00069 StackCommit = StackReserve; 00070 #endif 00071 00072 /* Reserve memory for the stack */ 00073 Status = ZwAllocateVirtualMemory(hProcess, 00074 (PVOID*)&Stack, 00075 StackZeroBits, 00076 &StackReserve, 00077 MEM_RESERVE, 00078 PAGE_READWRITE); 00079 if (!NT_SUCCESS(Status)) return Status; 00080 00081 /* Now set up some basic Initial TEB Parameters */ 00082 InitialTeb->PreviousStackBase = NULL; 00083 InitialTeb->PreviousStackLimit = NULL; 00084 InitialTeb->AllocatedStackBase = (PVOID)Stack; 00085 InitialTeb->StackBase = (PVOID)(Stack + StackReserve); 00086 00087 /* Update the Stack Position */ 00088 Stack += StackReserve - StackCommit; 00089 00090 /* Check if we will need a guard page */ 00091 if (StackReserve > StackCommit) 00092 { 00093 /* Remove a page to set as guard page */ 00094 Stack -= SystemBasicInfo.PageSize; 00095 StackCommit += SystemBasicInfo.PageSize; 00096 UseGuard = TRUE; 00097 } 00098 00099 /* Allocate memory for the stack */ 00100 Status = ZwAllocateVirtualMemory(hProcess, 00101 (PVOID*)&Stack, 00102 0, 00103 &StackCommit, 00104 MEM_COMMIT, 00105 PAGE_READWRITE); 00106 if (!NT_SUCCESS(Status)) return Status; 00107 00108 /* Now set the current Stack Limit */ 00109 InitialTeb->StackLimit = (PVOID)Stack; 00110 00111 /* Create a guard page */ 00112 if (UseGuard) 00113 { 00114 /* Attempt maximum space possible */ 00115 GuardPageSize = SystemBasicInfo.PageSize; 00116 Status = ZwProtectVirtualMemory(hProcess, 00117 (PVOID*)&Stack, 00118 &GuardPageSize, 00119 PAGE_GUARD | PAGE_READWRITE, 00120 &Dummy); 00121 if (!NT_SUCCESS(Status)) return Status; 00122 00123 /* Update the Stack Limit keeping in mind the Guard Page */ 00124 InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - 00125 GuardPageSize); 00126 } 00127 00128 /* We are done! */ 00129 return STATUS_SUCCESS; 00130 } 00131 00132 NTSTATUS 00133 NTAPI 00134 RtlpFreeUserStack(IN HANDLE Process, 00135 IN PINITIAL_TEB InitialTeb) 00136 { 00137 SIZE_T Dummy = 0; 00138 NTSTATUS Status; 00139 00140 /* Free the Stack */ 00141 Status = ZwFreeVirtualMemory(Process, 00142 &InitialTeb->AllocatedStackBase, 00143 &Dummy, 00144 MEM_RELEASE); 00145 00146 /* Clear the initial TEB */ 00147 RtlZeroMemory(InitialTeb, sizeof(INITIAL_TEB)); 00148 return Status; 00149 } 00150 00151 /* FUNCTIONS ***************************************************************/ 00152 00153 00154 /* 00155 * @implemented 00156 */ 00157 NTSTATUS 00158 NTAPI 00159 RtlSetThreadIsCritical(IN BOOLEAN NewValue, 00160 OUT PBOOLEAN OldValue OPTIONAL, 00161 IN BOOLEAN NeedBreaks) 00162 { 00163 ULONG BreakOnTermination; 00164 00165 /* Initialize to FALSE */ 00166 if (OldValue) *OldValue = FALSE; 00167 00168 /* Fail, if the critical breaks flag is required but is not set */ 00169 if ((NeedBreaks) && 00170 !(NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS)) 00171 { 00172 return STATUS_UNSUCCESSFUL; 00173 } 00174 00175 /* Check if the caller wants the old value */ 00176 if (OldValue) 00177 { 00178 /* Query and return the old break on termination flag for the process */ 00179 ZwQueryInformationThread(NtCurrentThread(), 00180 ThreadBreakOnTermination, 00181 &BreakOnTermination, 00182 sizeof(ULONG), 00183 NULL); 00184 *OldValue = (BOOLEAN)BreakOnTermination; 00185 } 00186 00187 /* Set the break on termination flag for the process */ 00188 BreakOnTermination = NewValue; 00189 return ZwSetInformationThread(NtCurrentThread(), 00190 ThreadBreakOnTermination, 00191 &BreakOnTermination, 00192 sizeof(ULONG)); 00193 } 00194 00195 /* 00196 @implemented 00197 */ 00198 NTSTATUS 00199 NTAPI 00200 RtlCreateUserThread(IN HANDLE ProcessHandle, 00201 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, 00202 IN BOOLEAN CreateSuspended, 00203 IN ULONG StackZeroBits OPTIONAL, 00204 IN SIZE_T StackReserve OPTIONAL, 00205 IN SIZE_T StackCommit OPTIONAL, 00206 IN PTHREAD_START_ROUTINE StartAddress, 00207 IN PVOID Parameter OPTIONAL, 00208 OUT PHANDLE ThreadHandle OPTIONAL, 00209 OUT PCLIENT_ID ClientId OPTIONAL) 00210 { 00211 NTSTATUS Status; 00212 HANDLE Handle; 00213 CLIENT_ID ThreadCid; 00214 INITIAL_TEB InitialTeb; 00215 OBJECT_ATTRIBUTES ObjectAttributes; 00216 CONTEXT Context; 00217 00218 /* First, we'll create the Stack */ 00219 Status = RtlpCreateUserStack(ProcessHandle, 00220 StackReserve, 00221 StackCommit, 00222 StackZeroBits, 00223 &InitialTeb); 00224 if (!NT_SUCCESS(Status)) return Status; 00225 00226 /* Next, we'll set up the Initial Context */ 00227 RtlInitializeContext(ProcessHandle, 00228 &Context, 00229 Parameter, 00230 StartAddress, 00231 InitialTeb.StackBase); 00232 00233 /* We are now ready to create the Kernel Thread Object */ 00234 InitializeObjectAttributes(&ObjectAttributes, 00235 NULL, 00236 0, 00237 NULL, 00238 SecurityDescriptor); 00239 Status = ZwCreateThread(&Handle, 00240 THREAD_ALL_ACCESS, 00241 &ObjectAttributes, 00242 ProcessHandle, 00243 &ThreadCid, 00244 &Context, 00245 &InitialTeb, 00246 CreateSuspended); 00247 if (!NT_SUCCESS(Status)) 00248 { 00249 /* Free the stack */ 00250 RtlpFreeUserStack(ProcessHandle, &InitialTeb); 00251 } 00252 else 00253 { 00254 /* Return thread data */ 00255 if (ThreadHandle) 00256 *ThreadHandle = Handle; 00257 else 00258 NtClose(Handle); 00259 if (ClientId) *ClientId = ThreadCid; 00260 } 00261 00262 /* Return success or the previous failure */ 00263 return Status; 00264 } 00265 00266 /* 00267 * @implemented 00268 */ 00269 VOID 00270 NTAPI 00271 RtlExitUserThread(NTSTATUS Status) 00272 { 00273 /* Call the Loader and tell him to notify the DLLs */ 00274 LdrShutdownThread(); 00275 00276 /* Shut us down */ 00277 NtCurrentTeb()->FreeStackOnTermination = TRUE; 00278 NtTerminateThread(NtCurrentThread(), Status); 00279 } 00280 00281 /* 00282 @implemented 00283 */ 00284 VOID 00285 NTAPI 00286 RtlFreeUserThreadStack(HANDLE ProcessHandle, 00287 HANDLE ThreadHandle) 00288 { 00289 NTSTATUS Status; 00290 THREAD_BASIC_INFORMATION ThreadBasicInfo; 00291 SIZE_T Dummy, Size = 0; 00292 PVOID StackLocation; 00293 00294 /* Query the Basic Info */ 00295 Status = NtQueryInformationThread(ThreadHandle, 00296 ThreadBasicInformation, 00297 &ThreadBasicInfo, 00298 sizeof(THREAD_BASIC_INFORMATION), 00299 NULL); 00300 if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return; 00301 00302 /* Get the deallocation stack */ 00303 Status = NtReadVirtualMemory(ProcessHandle, 00304 &((PTEB)ThreadBasicInfo.TebBaseAddress)-> 00305 DeallocationStack, 00306 &StackLocation, 00307 sizeof(PVOID), 00308 &Dummy); 00309 if (!NT_SUCCESS(Status) || !StackLocation) return; 00310 00311 /* Free it */ 00312 NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE); 00313 } 00314 00315 PTEB 00316 NTAPI 00317 _NtCurrentTeb(VOID) 00318 { 00319 /* Return the TEB */ 00320 return NtCurrentTeb(); 00321 } 00322 00323 NTSTATUS 00324 NTAPI 00325 RtlRemoteCall(IN HANDLE Process, 00326 IN HANDLE Thread, 00327 IN PVOID CallSite, 00328 IN ULONG ArgumentCount, 00329 IN PULONG Arguments, 00330 IN BOOLEAN PassContext, 00331 IN BOOLEAN AlreadySuspended) 00332 { 00333 UNIMPLEMENTED; 00334 return STATUS_NOT_IMPLEMENTED; 00335 } Generated on Sun May 27 2012 04:24:32 for ReactOS by
1.7.6.1
|