ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

thread.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.