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  * FILE:            lib/kernel32/thread/thread.c
00005  * PURPOSE:         Thread functions
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  *                  Ariadne ( ariadne@xs4all.nl)
00008  *
00009  */
00010 
00011 /* INCLUDES *******************************************************************/
00012 
00013 #include <k32.h>
00014 
00015 #define NDEBUG
00016 #include <debug.h>
00017 
00018 #define SXS_SUPPORT_FIXME
00019 
00020 typedef NTSTATUS (NTAPI *PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId);
00021 
00022 NTSTATUS
00023 WINAPI
00024 BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
00025                        IN PCLIENT_ID ClientId);
00026 
00027 /* FUNCTIONS ******************************************************************/
00028 
00029 static
00030 LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
00031 {
00032    LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
00033    LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
00034    RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
00035 
00036    if (RealFilter != NULL)
00037    {
00038       _SEH2_TRY
00039       {
00040          ExceptionDisposition = RealFilter(ExceptionInfo);
00041       }
00042       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00043       {
00044          ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
00045       }
00046       _SEH2_END;
00047    }
00048 
00049    return ExceptionDisposition;
00050 }
00051 
00052 __declspec(noreturn)
00053 VOID
00054 WINAPI
00055 BaseThreadStartup(IN LPTHREAD_START_ROUTINE lpStartAddress,
00056                   IN LPVOID lpParameter)
00057 {
00058     /* Attempt to call the Thread Start Address */
00059     _SEH2_TRY
00060     {
00061         /* Legacy check which is still used today for Win32 threads */
00062         if (NtCurrentTeb()->NtTib.Version == (30 << 8)) // OS/2 V3.0 ("Cruiser")
00063         {
00064             /* This registers the termination port with CSRSS */
00065             if (!BaseRunningInServerProcess) CsrNewThread();
00066         }
00067 
00068         /* Get the exit code from the Thread Start */
00069         ExitThread((lpStartAddress)((PVOID)lpParameter));
00070     }
00071     _SEH2_EXCEPT(BaseThreadExceptionFilter(_SEH2_GetExceptionInformation()))
00072     {
00073         /* Get the Exit code from the SEH Handler */
00074         if (!BaseRunningInServerProcess)
00075         {
00076             /* Kill the whole process, usually */
00077             ExitProcess(_SEH2_GetExceptionCode());
00078         }
00079         else
00080         {
00081             /* If running inside CSRSS, kill just this thread */
00082             ExitThread(_SEH2_GetExceptionCode());
00083         }
00084     }
00085     _SEH2_END;
00086 }
00087 
00088 VOID
00089 NTAPI
00090 BaseDispatchApc(IN PAPCFUNC ApcRoutine,
00091                 IN PVOID Data,
00092                 IN PACTIVATION_CONTEXT ActivationContext)
00093 {
00094     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame;
00095 
00096     /* Setup the activation context */
00097     ActivationFrame.Size = sizeof(ActivationFrame);
00098     ActivationFrame.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
00099 
00100     /* Check if caller wanted one */
00101     if (ActivationContext == INVALID_ACTIVATION_CONTEXT)
00102     {
00103         /* Do the APC directly */
00104         ApcRoutine((ULONG_PTR)Data);
00105         return;
00106     }
00107 
00108     /* Then activate it */
00109     RtlActivateActivationContextUnsafeFast(&ActivationFrame, ActivationContext);
00110 
00111     /* Call the routine under SEH */
00112     _SEH2_TRY
00113     {
00114         ApcRoutine((ULONG_PTR)Data);
00115     }
00116     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00117     {
00118 
00119     }
00120     _SEH2_END;
00121 
00122     /* Now de-activate and release the activation context */
00123     RtlDeactivateActivationContextUnsafeFast(&ActivationFrame);
00124     RtlReleaseActivationContext(ActivationContext);
00125 }
00126 
00127 /* PUBLIC FUNCTIONS ***********************************************************/
00128 
00129 /*
00130  * @implemented
00131  */
00132 HANDLE
00133 WINAPI
00134 CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
00135              IN DWORD dwStackSize,
00136              IN LPTHREAD_START_ROUTINE lpStartAddress,
00137              IN LPVOID lpParameter,
00138              IN DWORD dwCreationFlags,
00139              OUT LPDWORD lpThreadId)
00140 {
00141     /* Act as if we're going to create a remote thread in ourselves */
00142     return CreateRemoteThread(NtCurrentProcess(),
00143                               lpThreadAttributes,
00144                               dwStackSize,
00145                               lpStartAddress,
00146                               lpParameter,
00147                               dwCreationFlags,
00148                               lpThreadId);
00149 }
00150 
00151 /*
00152  * @implemented
00153  */
00154 HANDLE
00155 WINAPI
00156 CreateRemoteThread(HANDLE hProcess,
00157                    LPSECURITY_ATTRIBUTES lpThreadAttributes,
00158                    DWORD dwStackSize,
00159                    LPTHREAD_START_ROUTINE lpStartAddress,
00160                    LPVOID lpParameter,
00161                    DWORD dwCreationFlags,
00162                    LPDWORD lpThreadId)
00163 {
00164     NTSTATUS Status;
00165     INITIAL_TEB InitialTeb;
00166     CONTEXT Context;
00167     CLIENT_ID ClientId;
00168     OBJECT_ATTRIBUTES LocalObjectAttributes;
00169     POBJECT_ATTRIBUTES ObjectAttributes;
00170     HANDLE hThread;
00171     ULONG Dummy;
00172 
00173     DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
00174             ": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess,
00175             dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
00176 
00177     /* Clear the Context */
00178     RtlZeroMemory(&Context, sizeof(CONTEXT));
00179 
00180     /* Write PID */
00181     ClientId.UniqueProcess = hProcess;
00182 
00183     /* Create the Stack */
00184     Status = BaseCreateStack(hProcess,
00185                               dwStackSize,
00186                               dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
00187                               dwStackSize : 0,
00188                               &InitialTeb);
00189     if(!NT_SUCCESS(Status))
00190     {
00191         BaseSetLastNTError(Status);
00192         return NULL;
00193     }
00194 
00195     /* Create Initial Context */
00196     BaseInitializeContext(&Context,
00197                            lpParameter,
00198                            lpStartAddress,
00199                            InitialTeb.StackBase,
00200                            1);
00201 
00202     /* initialize the attributes for the thread object */
00203     ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
00204                                                     lpThreadAttributes,
00205                                                     NULL);
00206 
00207     /* Create the Kernel Thread Object */
00208     Status = NtCreateThread(&hThread,
00209                             THREAD_ALL_ACCESS,
00210                             ObjectAttributes,
00211                             hProcess,
00212                             &ClientId,
00213                             &Context,
00214                             &InitialTeb,
00215                             TRUE);
00216     if(!NT_SUCCESS(Status))
00217     {
00218         BaseFreeThreadStack(hProcess, &InitialTeb);
00219         BaseSetLastNTError(Status);
00220         return NULL;
00221     }
00222 
00223     /* Are we in the same process? */
00224     if (hProcess == NtCurrentProcess())
00225     {
00226         PTEB Teb;
00227         PVOID ActivationContextStack = NULL;
00228         THREAD_BASIC_INFORMATION ThreadBasicInfo;
00229 #ifndef SXS_SUPPORT_FIXME
00230         ACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
00231         ULONG_PTR Cookie;
00232 #endif
00233         ULONG retLen;
00234 
00235         /* Get the TEB */
00236         Status = NtQueryInformationThread(hThread,
00237                                           ThreadBasicInformation,
00238                                           &ThreadBasicInfo,
00239                                           sizeof(ThreadBasicInfo),
00240                                           &retLen);
00241         if (NT_SUCCESS(Status))
00242         {
00243             /* Allocate the Activation Context Stack */
00244             Status = RtlAllocateActivationContextStack(&ActivationContextStack);
00245         }
00246 
00247         if (NT_SUCCESS(Status))
00248         {
00249             Teb = ThreadBasicInfo.TebBaseAddress;
00250 
00251             /* Save it */
00252             Teb->ActivationContextStackPointer = ActivationContextStack;
00253 #ifndef SXS_SUPPORT_FIXME
00254             /* Query the Context */
00255             Status = RtlQueryInformationActivationContext(1,
00256                                                           0,
00257                                                           NULL,
00258                                                           ActivationContextBasicInformation,
00259                                                           &ActivationCtxInfo,
00260                                                           sizeof(ActivationCtxInfo),
00261                                                           &retLen);
00262             if (NT_SUCCESS(Status))
00263             {
00264                 /* Does it need to be activated? */
00265                 if (!ActivationCtxInfo.hActCtx)
00266                 {
00267                     /* Activate it */
00268                     Status = RtlActivateActivationContext(1,
00269                                                           ActivationCtxInfo.hActCtx,
00270                                                           &Cookie);
00271                     if (!NT_SUCCESS(Status))
00272                         DPRINT1("RtlActivateActivationContext failed %x\n", Status);
00273                 }
00274             }
00275             else
00276                 DPRINT1("RtlQueryInformationActivationContext failed %x\n", Status);
00277 #endif
00278         }
00279         else
00280             DPRINT1("RtlAllocateActivationContextStack failed %x\n", Status);
00281     }
00282 
00283     /* Notify CSR */
00284     if (!BaseRunningInServerProcess)
00285     {
00286         Status = BasepNotifyCsrOfThread(hThread, &ClientId);
00287     }
00288     else
00289     {
00290         DPRINT("Server thread in Server. Handle: %lx\n", hProcess);
00291         if (hProcess != NtCurrentProcess())
00292         {
00293             PCSR_CREATE_REMOTE_THREAD CsrCreateRemoteThread;
00294 
00295             /* Get the direct CSRSRV export */
00296             CsrCreateRemoteThread = (PCSR_CREATE_REMOTE_THREAD)
00297                                     GetProcAddress(GetModuleHandleA("csrsrv"),
00298                                                    "CsrCreateRemoteThread");
00299             if (CsrCreateRemoteThread)
00300             {
00301                 /* Call it instead of going through LPC */
00302                 Status = CsrCreateRemoteThread(hThread, &ClientId);
00303             }
00304         }
00305     }
00306 
00307     if (!NT_SUCCESS(Status))
00308     {
00309         ASSERT(FALSE);
00310     }
00311 
00312     /* Success */
00313     if(lpThreadId) *lpThreadId = HandleToUlong(ClientId.UniqueThread);
00314 
00315     /* Resume it if asked */
00316     if (!(dwCreationFlags & CREATE_SUSPENDED))
00317     {
00318         NtResumeThread(hThread, &Dummy);
00319     }
00320 
00321     /* Return handle to thread */
00322     return hThread;
00323 }
00324 
00325 /*
00326  * @implemented
00327  */
00328 VOID
00329 WINAPI
00330 ExitThread(IN DWORD uExitCode)
00331 {
00332     NTSTATUS Status;
00333     ULONG LastThread;
00334     PRTL_CRITICAL_SECTION LoaderLock;
00335 
00336     /* Make sure loader lock isn't held */
00337     LoaderLock = NtCurrentPeb()->LoaderLock;
00338     if (LoaderLock) ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread);
00339 
00340     /*
00341      * Terminate process if this is the last thread
00342      * of the current process
00343      */
00344     Status = NtQueryInformationThread(NtCurrentThread(),
00345                                       ThreadAmILastThread,
00346                                       &LastThread,
00347                                       sizeof(LastThread),
00348                                       NULL);
00349     if ((NT_SUCCESS(Status)) && (LastThread)) ExitProcess(uExitCode);
00350 
00351     /* Notify DLLs and TLS Callbacks of termination */
00352     LdrShutdownThread();
00353 
00354     /* Tell the Kernel to free the Stack */
00355     NtCurrentTeb()->FreeStackOnTermination = TRUE;
00356     NtTerminateThread(NULL, uExitCode);
00357 
00358     /* We should never reach this place */
00359     DPRINT1("It should not happen\n");
00360     while (TRUE);
00361 }
00362 
00363 /*
00364  * @implemented
00365  */
00366 HANDLE
00367 WINAPI
00368 OpenThread(IN DWORD dwDesiredAccess,
00369            IN BOOL bInheritHandle,
00370            IN DWORD dwThreadId)
00371 {
00372     NTSTATUS Status;
00373     HANDLE ThreadHandle;
00374     OBJECT_ATTRIBUTES ObjectAttributes;
00375     CLIENT_ID ClientId;
00376 
00377     ClientId.UniqueProcess = 0;
00378     ClientId.UniqueThread = ULongToHandle(dwThreadId);
00379 
00380     InitializeObjectAttributes(&ObjectAttributes,
00381                                NULL,
00382                                (bInheritHandle ? OBJ_INHERIT : 0),
00383                                NULL,
00384                                NULL);
00385 
00386     Status = NtOpenThread(&ThreadHandle,
00387                           dwDesiredAccess,
00388                           &ObjectAttributes,
00389                           &ClientId);
00390     if (!NT_SUCCESS(Status))
00391     {
00392         BaseSetLastNTError(Status);
00393         return NULL;
00394     }
00395 
00396     return ThreadHandle;
00397 }
00398 
00399 /*
00400  * @implemented
00401  */
00402 PTEB
00403 GetTeb(VOID)
00404 {
00405     return NtCurrentTeb();
00406 }
00407 
00408 /*
00409  * @implemented
00410  */
00411 BOOL
00412 WINAPI
00413 SwitchToThread(VOID)
00414 {
00415     return NtYieldExecution() != STATUS_NO_YIELD_PERFORMED;
00416 }
00417 
00418 
00419 /*
00420  * @implemented
00421  */
00422 DWORD
00423 WINAPI
00424 GetCurrentThreadId(VOID)
00425 {
00426     return HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
00427 }
00428 
00429 /*
00430  * @implemented
00431  */
00432 BOOL
00433 NTAPI
00434 GetThreadTimes(IN HANDLE hThread,
00435                OUT LPFILETIME lpCreationTime,
00436                OUT LPFILETIME lpExitTime,
00437                OUT LPFILETIME lpKernelTime,
00438                OUT LPFILETIME lpUserTime)
00439 {
00440     KERNEL_USER_TIMES KernelUserTimes;
00441     NTSTATUS Status;
00442 
00443     Status = NtQueryInformationThread(hThread,
00444                                       ThreadTimes,
00445                                       &KernelUserTimes,
00446                                       sizeof(KERNEL_USER_TIMES),
00447                                       NULL);
00448     if (!NT_SUCCESS(Status))
00449     {
00450         BaseSetLastNTError(Status);
00451         return FALSE;
00452     }
00453 
00454     *lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
00455     *lpExitTime = *(LPFILETIME)&KernelUserTimes.ExitTime;
00456     *lpKernelTime = *(LPFILETIME)&KernelUserTimes.KernelTime;
00457     *lpUserTime = *(LPFILETIME)&KernelUserTimes.UserTime;
00458     return TRUE;
00459 }
00460 
00461 /*
00462  * @implemented
00463  */
00464 BOOL
00465 WINAPI
00466 GetThreadContext(IN HANDLE hThread,
00467                  OUT LPCONTEXT lpContext)
00468 {
00469     NTSTATUS Status;
00470 
00471     Status = NtGetContextThread(hThread, lpContext);
00472     if (!NT_SUCCESS(Status))
00473     {
00474         BaseSetLastNTError(Status);
00475         return FALSE;
00476     }
00477 
00478     return TRUE;
00479 }
00480 
00481 /*
00482  * @implemented
00483  */
00484 BOOL
00485 WINAPI
00486 SetThreadContext(IN HANDLE hThread,
00487                  IN CONST CONTEXT *lpContext)
00488 {
00489     NTSTATUS Status;
00490 
00491     Status = NtSetContextThread(hThread, (PCONTEXT)lpContext);
00492     if (!NT_SUCCESS(Status))
00493     {
00494         BaseSetLastNTError(Status);
00495         return FALSE;
00496     }
00497 
00498     return TRUE;
00499 }
00500 
00501 /*
00502  * @implemented
00503  */
00504 BOOL
00505 WINAPI
00506 GetExitCodeThread(IN HANDLE hThread,
00507                   OUT LPDWORD lpExitCode)
00508 {
00509     THREAD_BASIC_INFORMATION ThreadBasic;
00510     NTSTATUS Status;
00511 
00512     Status = NtQueryInformationThread(hThread,
00513                                       ThreadBasicInformation,
00514                                       &ThreadBasic,
00515                                       sizeof(THREAD_BASIC_INFORMATION),
00516                                       NULL);
00517     if (!NT_SUCCESS(Status))
00518     {
00519         BaseSetLastNTError(Status);
00520         return FALSE;
00521     }
00522 
00523     *lpExitCode = ThreadBasic.ExitStatus;
00524     return TRUE;
00525 }
00526 
00527 /*
00528  * @implemented
00529  */
00530 DWORD
00531 WINAPI
00532 ResumeThread(IN HANDLE hThread)
00533 {
00534     ULONG PreviousResumeCount;
00535     NTSTATUS Status;
00536 
00537     Status = NtResumeThread(hThread, &PreviousResumeCount);
00538     if (!NT_SUCCESS(Status))
00539     {
00540         BaseSetLastNTError(Status);
00541         return -1;
00542     }
00543 
00544     return PreviousResumeCount;
00545 }
00546 
00547 /*
00548  * @implemented
00549  */
00550 BOOL
00551 WINAPI
00552 TerminateThread(IN HANDLE hThread,
00553                 IN DWORD dwExitCode)
00554 {
00555     NTSTATUS Status;
00556     PRTL_CRITICAL_SECTION LoaderLock;
00557     THREAD_BASIC_INFORMATION ThreadInfo;
00558 
00559     /* Check for invalid thread handle */
00560     if (!hThread)
00561     {
00562         /* Fail if one was passed */
00563         SetLastError(ERROR_INVALID_HANDLE);
00564         return FALSE;
00565     }
00566 
00567     /* Get the loader lock */
00568     LoaderLock = NtCurrentPeb()->LoaderLock;
00569     if (LoaderLock)
00570     {
00571         /* Get our TID */
00572         Status = NtQueryInformationThread(hThread,
00573                                           ThreadBasicInformation,
00574                                           &ThreadInfo,
00575                                           sizeof(ThreadInfo),
00576                                           NULL);
00577         if (!NT_SUCCESS(Status))
00578         {
00579             /* Assert that we don't hold the loader lock */
00580             ASSERT(NtCurrentTeb()->ClientId.UniqueThread != ThreadInfo.ClientId.UniqueThread);
00581             ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread);
00582         }
00583     }
00584 
00585     /* Now terminate the thread */
00586     Status = NtTerminateThread(hThread, dwExitCode);
00587     if (!NT_SUCCESS(Status))
00588     {
00589         /* Fail */
00590         BaseSetLastNTError(Status);
00591         return FALSE;
00592     }
00593 
00594     /* All done */
00595     return TRUE;
00596 }
00597 
00598 /*
00599  * @implemented
00600  */
00601 DWORD
00602 WINAPI
00603 SuspendThread(IN HANDLE hThread)
00604 {
00605     ULONG PreviousSuspendCount;
00606     NTSTATUS Status;
00607 
00608     Status = NtSuspendThread(hThread, &PreviousSuspendCount);
00609     if (!NT_SUCCESS(Status))
00610     {
00611         BaseSetLastNTError(Status);
00612         return -1;
00613     }
00614 
00615     return PreviousSuspendCount;
00616 }
00617 
00618 /*
00619  * @implemented
00620  */
00621 DWORD_PTR
00622 WINAPI
00623 SetThreadAffinityMask(IN HANDLE hThread,
00624                       IN DWORD_PTR dwThreadAffinityMask)
00625 {
00626     THREAD_BASIC_INFORMATION ThreadBasic;
00627     KAFFINITY AffinityMask;
00628     NTSTATUS Status;
00629 
00630     AffinityMask = (KAFFINITY)dwThreadAffinityMask;
00631 
00632     Status = NtQueryInformationThread(hThread,
00633                                       ThreadBasicInformation,
00634                                       &ThreadBasic,
00635                                       sizeof(THREAD_BASIC_INFORMATION),
00636                                       NULL);
00637     if (!NT_SUCCESS(Status))
00638     {
00639         BaseSetLastNTError(Status);
00640         return 0;
00641     }
00642 
00643     Status = NtSetInformationThread(hThread,
00644                                     ThreadAffinityMask,
00645                                     &AffinityMask,
00646                                     sizeof(KAFFINITY));
00647     if (!NT_SUCCESS(Status))
00648     {
00649         BaseSetLastNTError(Status);
00650         ThreadBasic.AffinityMask = 0;
00651     }
00652 
00653     return ThreadBasic.AffinityMask;
00654 }
00655 
00656 /*
00657  * @implemented
00658  */
00659 BOOL
00660 WINAPI
00661 SetThreadPriority(IN HANDLE hThread,
00662                   IN int nPriority)
00663 {
00664     LONG Prio = nPriority;
00665     NTSTATUS Status;
00666 
00667     /* Check if values forcing saturation should be used */
00668     if (Prio == THREAD_PRIORITY_TIME_CRITICAL)
00669     {
00670         /* This is 16 */
00671         Prio = (HIGH_PRIORITY + 1) / 2;
00672     }
00673     else if (Prio == THREAD_PRIORITY_IDLE)
00674     {
00675         /* This is -16 */
00676         Prio = -((HIGH_PRIORITY + 1) / 2);
00677     }
00678 
00679     /* Set the Base Priority */
00680     Status = NtSetInformationThread(hThread,
00681                                     ThreadBasePriority,
00682                                     &Prio,
00683                                     sizeof(LONG));
00684     if (!NT_SUCCESS(Status))
00685     {
00686         /* Failure */
00687         BaseSetLastNTError(Status);
00688         return FALSE;
00689     }
00690 
00691     /* Return */
00692     return TRUE;
00693 }
00694 
00695 /*
00696  * @implemented
00697  */
00698 int
00699 WINAPI
00700 GetThreadPriority(IN HANDLE hThread)
00701 {
00702     THREAD_BASIC_INFORMATION ThreadBasic;
00703     NTSTATUS Status;
00704 
00705     /* Query the Base Priority Increment */
00706     Status = NtQueryInformationThread(hThread,
00707                                       ThreadBasicInformation,
00708                                       &ThreadBasic,
00709                                       sizeof(THREAD_BASIC_INFORMATION),
00710                                       NULL);
00711     if (!NT_SUCCESS(Status))
00712     {
00713         /* Failure */
00714         BaseSetLastNTError(Status);
00715         return THREAD_PRIORITY_ERROR_RETURN;
00716     }
00717 
00718     /* Do some conversions for saturation values */
00719     if (ThreadBasic.BasePriority == ((HIGH_PRIORITY + 1) / 2))
00720     {
00721         /* Win32 calls this "time critical" */
00722         ThreadBasic.BasePriority = THREAD_PRIORITY_TIME_CRITICAL;
00723     }
00724     else if (ThreadBasic.BasePriority == -((HIGH_PRIORITY + 1) / 2))
00725     {
00726         /* Win32 calls this "idle" */
00727         ThreadBasic.BasePriority = THREAD_PRIORITY_IDLE;
00728     }
00729 
00730     /* Return the final result */
00731     return ThreadBasic.BasePriority;
00732 }
00733 
00734 /*
00735  * @implemented
00736  */
00737 BOOL
00738 WINAPI
00739 GetThreadPriorityBoost(IN HANDLE hThread,
00740                        OUT PBOOL pDisablePriorityBoost)
00741 {
00742     ULONG PriorityBoost;
00743     NTSTATUS Status;
00744 
00745     Status = NtQueryInformationThread(hThread,
00746                                       ThreadPriorityBoost,
00747                                       &PriorityBoost,
00748                                       sizeof(ULONG),
00749                                       NULL);
00750     if (!NT_SUCCESS(Status))
00751     {
00752         BaseSetLastNTError(Status);
00753         return FALSE;
00754     }
00755 
00756     *pDisablePriorityBoost = PriorityBoost;
00757     return TRUE;
00758 }
00759 
00760 /*
00761  * @implemented
00762  */
00763 BOOL
00764 NTAPI
00765 SetThreadPriorityBoost(IN HANDLE hThread,
00766                        IN BOOL bDisablePriorityBoost)
00767 {
00768     ULONG PriorityBoost;
00769     NTSTATUS Status;
00770 
00771     PriorityBoost = bDisablePriorityBoost != FALSE;
00772 
00773     Status = NtSetInformationThread(hThread,
00774                                     ThreadPriorityBoost,
00775                                     &PriorityBoost,
00776                                     sizeof(ULONG));
00777     if (!NT_SUCCESS(Status))
00778     {
00779         BaseSetLastNTError(Status);
00780         return FALSE;
00781     }
00782 
00783     return TRUE;
00784 }
00785 
00786 /*
00787  * @implemented
00788  */
00789 BOOL
00790 WINAPI
00791 GetThreadSelectorEntry(IN HANDLE hThread,
00792                        IN DWORD dwSelector,
00793                        OUT LPLDT_ENTRY lpSelectorEntry)
00794 {
00795 #ifdef _M_IX86
00796     DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
00797     NTSTATUS Status;
00798 
00799     /* Set the selector and do the query */
00800     DescriptionTableEntry.Selector = dwSelector;
00801     Status = NtQueryInformationThread(hThread,
00802                                       ThreadDescriptorTableEntry,
00803                                       &DescriptionTableEntry,
00804                                       sizeof(DESCRIPTOR_TABLE_ENTRY),
00805                                       NULL);
00806     if (!NT_SUCCESS(Status))
00807     {
00808         /* Fail */
00809         BaseSetLastNTError(Status);
00810         return FALSE;
00811     }
00812 
00813     /* Success, return the selector */
00814     *lpSelectorEntry = DescriptionTableEntry.Descriptor;
00815     return TRUE;
00816 #else
00817     DPRINT1("Calling GetThreadSelectorEntry!\n");
00818     return FALSE;
00819 #endif
00820 }
00821 
00822 /*
00823  * @implemented
00824  */
00825 DWORD
00826 WINAPI
00827 SetThreadIdealProcessor(IN HANDLE hThread,
00828                         IN DWORD dwIdealProcessor)
00829 {
00830     NTSTATUS Status;
00831 
00832     Status = NtSetInformationThread(hThread,
00833                                     ThreadIdealProcessor,
00834                                     &dwIdealProcessor,
00835                                     sizeof(ULONG));
00836     if (!NT_SUCCESS(Status))
00837     {
00838         BaseSetLastNTError(Status);
00839         return -1;
00840     }
00841 
00842     return (DWORD)Status;
00843 }
00844 
00845 /*
00846  * @implemented
00847  */
00848 DWORD
00849 WINAPI
00850 GetProcessIdOfThread(IN HANDLE Thread)
00851 {
00852     THREAD_BASIC_INFORMATION ThreadBasic;
00853     NTSTATUS Status;
00854 
00855     Status = NtQueryInformationThread(Thread,
00856                                       ThreadBasicInformation,
00857                                       &ThreadBasic,
00858                                       sizeof(THREAD_BASIC_INFORMATION),
00859                                       NULL);
00860     if (!NT_SUCCESS(Status))
00861     {
00862         BaseSetLastNTError(Status);
00863         return 0;
00864     }
00865 
00866     return HandleToUlong(ThreadBasic.ClientId.UniqueProcess);
00867 }
00868 
00869 /*
00870  * @implemented
00871  */
00872 DWORD
00873 WINAPI
00874 GetThreadId(IN HANDLE Thread)
00875 {
00876     THREAD_BASIC_INFORMATION ThreadBasic;
00877     NTSTATUS Status;
00878 
00879     Status = NtQueryInformationThread(Thread,
00880                                       ThreadBasicInformation,
00881                                       &ThreadBasic,
00882                                       sizeof(THREAD_BASIC_INFORMATION),
00883                                       NULL);
00884     if (!NT_SUCCESS(Status))
00885     {
00886         BaseSetLastNTError(Status);
00887         return 0;
00888     }
00889 
00890     return HandleToUlong(ThreadBasic.ClientId.UniqueThread);
00891 }
00892 
00893 /*
00894  * @unimplemented
00895  */
00896 LANGID
00897 WINAPI
00898 SetThreadUILanguage(IN LANGID LangId)
00899 {
00900     UNIMPLEMENTED;
00901     return NtCurrentTeb()->CurrentLocale;
00902 }
00903 
00904 /*
00905  * @implemented
00906  */
00907 DWORD
00908 WINAPI
00909 QueueUserAPC(IN PAPCFUNC pfnAPC,
00910              IN HANDLE hThread,
00911              IN ULONG_PTR dwData)
00912 {
00913     NTSTATUS Status;
00914     ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
00915 
00916     /* Zero the activation context and query information on it */
00917     RtlZeroMemory(&ActCtxInfo, sizeof(ActCtxInfo));
00918     // WARNING!!! THIS IS USING THE WIN32 FLAG BECAUSE REACTOS CONTINUES TO BE A POS!!! ///
00919     Status = RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX,
00920                                                   NULL,
00921                                                   0,
00922                                                   ActivationContextBasicInformation,
00923                                                   &ActCtxInfo,
00924                                                   sizeof(ActCtxInfo),
00925                                                   NULL);
00926     if (!NT_SUCCESS(Status))
00927     {
00928         /* Fail due to SxS */
00929         DbgPrint("SXS: %s failing because RtlQueryInformationActivationContext()"
00930                  "returned status %08lx\n", __FUNCTION__, Status);
00931         BaseSetLastNTError(Status);
00932         return FALSE;
00933     }
00934 
00935     /* Queue the APC */
00936     Status = NtQueueApcThread(hThread,
00937                               (PKNORMAL_ROUTINE)BaseDispatchApc,
00938                               pfnAPC,
00939                               (PVOID)dwData,
00940                               (ActCtxInfo.dwFlags & 1) ?
00941                               INVALID_ACTIVATION_CONTEXT : ActCtxInfo.hActCtx);
00942     if (!NT_SUCCESS(Status))
00943     {
00944         BaseSetLastNTError(Status);
00945         return FALSE;
00946     }
00947 
00948     /* All good */
00949     return TRUE;
00950 }
00951 
00952 /*
00953  * @implemented
00954  */
00955 BOOL
00956 WINAPI
00957 SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
00958 {
00959     UNIMPLEMENTED;
00960     return FALSE;
00961 }
00962 
00963 /*
00964  * @implemented
00965  */
00966 BOOL
00967 WINAPI
00968 GetThreadIOPendingFlag(IN HANDLE hThread,
00969                        OUT PBOOL lpIOIsPending)
00970 {
00971     ULONG IoPending;
00972     NTSTATUS Status;
00973 
00974     /* Query the flag */
00975     Status = NtQueryInformationThread(hThread,
00976                                       ThreadIsIoPending,
00977                                       &IoPending,
00978                                       sizeof(IoPending),
00979                                       NULL);
00980     if (NT_SUCCESS(Status))
00981     {
00982         /* Return the flag */
00983         *lpIOIsPending = IoPending ? TRUE : FALSE;
00984         return TRUE;
00985     }
00986 
00987     /* Fail */
00988     BaseSetLastNTError(Status);
00989     return FALSE;
00990 }
00991 
00992 /*
00993  * @implemented
00994  */
00995 BOOL
00996 WINAPI
00997 QueueUserWorkItem(IN LPTHREAD_START_ROUTINE Function,
00998                   IN PVOID Context,
00999                   IN ULONG Flags)
01000 {
01001     NTSTATUS Status;
01002 
01003     /* NOTE: Rtl needs to safely call the function using a trampoline */
01004     Status = RtlQueueWorkItem((WORKERCALLBACKFUNC)Function, Context, Flags);
01005     if (!NT_SUCCESS(Status))
01006     {
01007         /* Failed */
01008         BaseSetLastNTError(Status);
01009         return FALSE;
01010     }
01011 
01012     /* All good */
01013     return TRUE;
01014 }
01015 
01016 /*
01017  * @implemented
01018  */
01019 DWORD
01020 WINAPI
01021 TlsAlloc(VOID)
01022 {
01023     ULONG Index;
01024     PTEB Teb;
01025     PPEB Peb;
01026 
01027     /* Get the PEB and TEB, lock the PEB */
01028     Teb = NtCurrentTeb();
01029     Peb = Teb->ProcessEnvironmentBlock;
01030     RtlAcquirePebLock();
01031 
01032     /* Try to get regular TEB slot */
01033     Index = RtlFindClearBitsAndSet(Peb->TlsBitmap, 1, 0);
01034     if (Index != 0xFFFFFFFF)
01035     {
01036         /* Clear the value. */
01037         Teb->TlsSlots[Index] = 0;
01038         RtlReleasePebLock();
01039         return Index;
01040     }
01041 
01042     /* If it fails, try to find expansion TEB slot. */
01043     Index = RtlFindClearBitsAndSet(Peb->TlsExpansionBitmap, 1, 0);
01044     if (Index != 0xFFFFFFFF)
01045     {
01046         /* Is there no expansion slot yet? */
01047         if (!Teb->TlsExpansionSlots)
01048         {
01049             /* Allocate an array */
01050             Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
01051                                                      HEAP_ZERO_MEMORY,
01052                                                      TLS_EXPANSION_SLOTS *
01053                                                      sizeof(PVOID));
01054         }
01055 
01056         /* Did we get an array? */
01057         if (!Teb->TlsExpansionSlots)
01058         {
01059             /* Fail */
01060             RtlClearBits(Peb->TlsExpansionBitmap, Index, 1);
01061             Index = 0xFFFFFFFF;
01062             BaseSetLastNTError(STATUS_NO_MEMORY);
01063         }
01064         else
01065         {
01066             /* Clear the value. */
01067             Teb->TlsExpansionSlots[Index] = 0;
01068             Index += TLS_MINIMUM_AVAILABLE;
01069         }
01070     }
01071     else
01072     {
01073         /* Fail */
01074         BaseSetLastNTError(STATUS_NO_MEMORY);
01075     }
01076 
01077     /* Release the lock and return */
01078     RtlReleasePebLock();
01079     return Index;
01080 }
01081 
01082 /*
01083  * @implemented
01084  */
01085 BOOL
01086 WINAPI
01087 TlsFree(IN DWORD Index)
01088 {
01089     BOOL BitSet;
01090     PPEB Peb;
01091     ULONG TlsIndex;
01092     PVOID TlsBitmap;
01093     NTSTATUS Status;
01094 
01095     /* Acquire the PEB lock and grab the PEB */
01096     Peb = NtCurrentPeb();
01097     RtlAcquirePebLock();
01098 
01099     /* Check if the index is too high */
01100     if (Index >= TLS_MINIMUM_AVAILABLE)
01101     {
01102         /* Check if it can fit in the expansion slots */
01103         TlsIndex = Index - TLS_MINIMUM_AVAILABLE;
01104         if (TlsIndex >= TLS_EXPANSION_SLOTS)
01105         {
01106             /* It's invalid */
01107             BaseSetLastNTError(STATUS_INVALID_PARAMETER);
01108             RtlReleasePebLock();
01109             return FALSE;
01110         }
01111         else
01112         {
01113             /* Use the expansion bitmap */
01114             TlsBitmap = Peb->TlsExpansionBitmap;
01115             Index = TlsIndex;
01116         }
01117     }
01118     else
01119     {
01120         /* Use the normal bitmap */
01121         TlsBitmap = Peb->TlsBitmap;
01122     }
01123 
01124     /* Check if the index was set */
01125     BitSet = RtlAreBitsSet(TlsBitmap, Index, 1);
01126     if (BitSet)
01127     {
01128         /* Tell the kernel to free the TLS cells */
01129         Status = NtSetInformationThread(NtCurrentThread(),
01130                                         ThreadZeroTlsCell,
01131                                         &Index,
01132                                         sizeof(DWORD));
01133         if (!NT_SUCCESS(Status))
01134         {
01135             BaseSetLastNTError(STATUS_INVALID_PARAMETER);
01136             RtlReleasePebLock();
01137             return FALSE;
01138         }
01139 
01140         /* Clear the bit */
01141         RtlClearBits(TlsBitmap, Index, 1);
01142     }
01143     else
01144     {
01145         /* Fail */
01146         BaseSetLastNTError(STATUS_INVALID_PARAMETER);
01147         RtlReleasePebLock();
01148         return FALSE;
01149     }
01150 
01151     /* Done! */
01152     RtlReleasePebLock();
01153     return TRUE;
01154 }
01155 
01156 /*
01157  * @implemented
01158  */
01159 LPVOID
01160 WINAPI
01161 TlsGetValue(IN DWORD Index)
01162 {
01163     PTEB Teb;
01164 
01165     /* Get the TEB and clear the last error */
01166     Teb = NtCurrentTeb();
01167     Teb->LastErrorValue = 0;
01168 
01169     /* Check for simple TLS index */
01170     if (Index < TLS_MINIMUM_AVAILABLE)
01171     {
01172         /* Return it */
01173         return Teb->TlsSlots[Index];
01174     }
01175 
01176     /* Check for valid index */
01177     if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
01178     {
01179         /* Fail */
01180         BaseSetLastNTError(STATUS_INVALID_PARAMETER);
01181         return NULL;
01182     }
01183 
01184     /* The expansion slots are allocated on demand, so check for it. */
01185     Teb->LastErrorValue = 0;
01186     if (!Teb->TlsExpansionSlots) return NULL;
01187 
01188     /* Return the value from the expansion slots */
01189     return Teb->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE];
01190 }
01191 
01192 /*
01193  * @implemented
01194  */
01195 BOOL
01196 WINAPI
01197 TlsSetValue(IN DWORD Index,
01198             IN LPVOID Value)
01199 {
01200     DWORD TlsIndex;
01201     PTEB Teb = NtCurrentTeb();
01202 
01203     /* Check for simple TLS index */
01204     if (Index < TLS_MINIMUM_AVAILABLE)
01205     {
01206         /* Return it */
01207         Teb->TlsSlots[Index] = Value;
01208         return TRUE;
01209     }
01210 
01211     /* Check if this is an expansion slot */
01212     TlsIndex = Index - TLS_MINIMUM_AVAILABLE;
01213     if (TlsIndex >= TLS_EXPANSION_SLOTS)
01214     {
01215         /* Fail */
01216         BaseSetLastNTError(STATUS_INVALID_PARAMETER);
01217         return FALSE;
01218     }
01219 
01220     /* Do we not have expansion slots? */
01221     if (!Teb->TlsExpansionSlots)
01222     {
01223         /* Get the PEB lock to see if we still need them */
01224         RtlAcquirePebLock();
01225         if (!Teb->TlsExpansionSlots)
01226         {
01227             /* Allocate them */
01228             Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
01229                                                      HEAP_ZERO_MEMORY,
01230                                                      TLS_EXPANSION_SLOTS *
01231                                                      sizeof(PVOID));
01232             if (!Teb->TlsExpansionSlots)
01233             {
01234                 /* Fail */
01235                 RtlReleasePebLock();
01236                 BaseSetLastNTError(STATUS_NO_MEMORY);
01237                 return FALSE;
01238             }
01239         }
01240 
01241         /* Release the lock */
01242         RtlReleasePebLock();
01243     }
01244 
01245     /* Write the value */
01246     Teb->TlsExpansionSlots[TlsIndex] = Value;
01247 
01248     /* Success */
01249     return TRUE;
01250 }
01251 
01252 /* EOF */

Generated on Thu May 24 2012 04:24:47 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.