ReactOS  0.4.13-dev-479-gec9c8fd
thread.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * FILE: dll/win32/kernel32/client/thread.c
5  * PURPOSE: Thread functions
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  * Ariadne (ariadne@xs4all.nl)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <k32.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #define SXS_SUPPORT_FIXME
18 
20 
22 WINAPI
23 BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
25 
26 /* FUNCTIONS ******************************************************************/
27 
28 __declspec(noreturn)
29 VOID
30 WINAPI
31 BaseThreadStartup(IN LPTHREAD_START_ROUTINE lpStartAddress,
33 {
34  /* Attempt to call the Thread Start Address */
35  _SEH2_TRY
36  {
37  /* Legacy check which is still used today for Win32 threads */
38  if (NtCurrentTeb()->NtTib.Version == (30 << 8)) // OS/2 V3.0 ("Cruiser")
39  {
40  /* This registers the termination port with CSRSS */
42  }
43 
44  /* Get the exit code from the Thread Start */
45  ExitThread((lpStartAddress)((PVOID)lpParameter));
46  }
48  {
49  /* Get the Exit code from the SEH Handler */
51  {
52  /* Kill the whole process, usually */
54  }
55  else
56  {
57  /* If running inside CSRSS, kill just this thread */
59  }
60  }
61  _SEH2_END;
62 }
63 
64 VOID
65 NTAPI
67  IN PVOID Data,
68  IN PACTIVATION_CONTEXT ActivationContext)
69 {
70  RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame;
71 
72  /* Setup the activation context */
73  ActivationFrame.Size = sizeof(ActivationFrame);
75 
76  /* Check if caller wanted one */
77  if (ActivationContext == INVALID_ACTIVATION_CONTEXT)
78  {
79  /* Do the APC directly */
81  return;
82  }
83 
84  /* Then activate it */
85  RtlActivateActivationContextUnsafeFast(&ActivationFrame, ActivationContext);
86 
87  /* Call the routine under SEH */
88  _SEH2_TRY
89  {
91  }
93  {
94 
95  }
96  _SEH2_END;
97 
98  /* Now de-activate and release the activation context */
100  RtlReleaseActivationContext(ActivationContext);
101 }
102 
103 /* PUBLIC FUNCTIONS ***********************************************************/
104 
105 /*
106  * @implemented
107  */
108 HANDLE
109 WINAPI
112  IN DWORD dwStackSize,
113  IN LPTHREAD_START_ROUTINE lpStartAddress,
115  IN DWORD dwCreationFlags,
116  OUT LPDWORD lpThreadId)
117 {
118  /* Act as if we're going to create a remote thread in ourselves */
120  lpThreadAttributes,
121  dwStackSize,
122  lpStartAddress,
123  lpParameter,
124  dwCreationFlags,
125  lpThreadId);
126 }
127 
128 /*
129  * @implemented
130  */
131 HANDLE
132 WINAPI
134  IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
135  IN DWORD dwStackSize,
136  IN LPTHREAD_START_ROUTINE lpStartAddress,
138  IN DWORD dwCreationFlags,
139  OUT LPDWORD lpThreadId)
140 {
142  INITIAL_TEB InitialTeb;
145  OBJECT_ATTRIBUTES LocalObjectAttributes;
147  HANDLE hThread;
148  ULONG Dummy;
149  PTEB Teb;
150  THREAD_BASIC_INFORMATION ThreadBasicInfo;
151  PACTIVATION_CONTEXT_STACK ActivationContextStack = NULL;
152  ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
155  SIZE_T ReturnSize;
156  DPRINT("CreateRemoteThread: hProcess: %p dwStackSize: %lu lpStartAddress"
157  ": %p lpParameter: %p, dwCreationFlags: %lx\n", hProcess,
158  dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
159 
160  /* Clear the Context */
161  RtlZeroMemory(&Context, sizeof(CONTEXT));
162 
163  /* Write PID */
165 
166  /* Create the Stack */
168  dwStackSize,
169  dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
170  dwStackSize : 0,
171  &InitialTeb);
172  if (!NT_SUCCESS(Status))
173  {
175  return NULL;
176  }
177 
178  /* Create Initial Context */
180  lpParameter,
181  lpStartAddress,
182  InitialTeb.StackBase,
183  1);
184 
185  /* initialize the attributes for the thread object */
186  ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
187  lpThreadAttributes,
188  NULL);
189 
190  /* Create the Kernel Thread Object */
194  hProcess,
195  &ClientId,
196  &Context,
197  &InitialTeb,
198  TRUE);
199  if (!NT_SUCCESS(Status))
200  {
201  /* Fail the kernel create */
202  BaseFreeThreadStack(hProcess, &InitialTeb);
204  return NULL;
205  }
206 
207  /* Are we in the same process? */
208  if (hProcess == NtCurrentProcess())
209  {
210  /* Get the TEB */
213  &ThreadBasicInfo,
214  sizeof(ThreadBasicInfo),
215  &ReturnLength);
216  if (!NT_SUCCESS(Status))
217  {
218  /* Fail */
219  ERROR_DBGBREAK("SXS: %s - Failing thread create because "
220  "NtQueryInformationThread() failed with status %08lx\n",
222  return NULL;
223  }
224 
225  /* Allocate the Activation Context Stack */
226  Status = RtlAllocateActivationContextStack(&ActivationContextStack);
227  if (!NT_SUCCESS(Status))
228  {
229  /* Fail */
230  ERROR_DBGBREAK("SXS: %s - Failing thread create because "
231  "RtlAllocateActivationContextStack() failed with status %08lx\n",
233  return NULL;
234  }
235 
236  /* Save it */
237  Teb = ThreadBasicInfo.TebBaseAddress;
238  Teb->ActivationContextStackPointer = ActivationContextStack;
239 
240  /* Query the Context */
242  NULL,
243  0,
244  ActivationContextBasicInformation,
245  &ActCtxInfo,
246  sizeof(ActCtxInfo),
247  &ReturnSize);
248  if (!NT_SUCCESS(Status))
249  {
250  /* Fail */
251  ERROR_DBGBREAK("SXS: %s - Failing thread create because "
252  "RtlQueryInformationActivationContext() failed with status %08lx\n",
254 
255  /* Free the activation context stack */
256  // RtlFreeThreadActivationContextStack();
258 
259  return NULL;
260  }
261 
262  /* Does it need to be activated? */
263  if ((ActCtxInfo.hActCtx) && !(ActCtxInfo.dwFlags & 1))
264  {
265  /* Activate it */
267  Teb,
268  ActCtxInfo.hActCtx,
269  &Cookie);
270  if (!NT_SUCCESS(Status))
271  {
272  /* Fail */
273  ERROR_DBGBREAK("SXS: %s - Failing thread create because "
274  "RtlActivateActivationContextEx() failed with status %08lx\n",
276 
277  /* Free the activation context stack */
278  // RtlFreeThreadActivationContextStack();
280 
281  return NULL;
282  }
283  }
284  }
285 
286  /* Notify CSR */
288  {
291  }
292  else
293  {
294  if (hProcess != NtCurrentProcess())
295  {
297 
298  /* Get the direct CSRSRV export */
301  "CsrCreateRemoteThread");
303  {
304  /* Call it instead of going through LPC */
307  }
308  }
309  }
310 
311  /* Success */
312  if (lpThreadId) *lpThreadId = HandleToUlong(ClientId.UniqueThread);
313 
314  /* Resume it if asked */
315  if (!(dwCreationFlags & CREATE_SUSPENDED)) NtResumeThread(hThread, &Dummy);
316 
317  /* Return handle to thread */
318  return hThread;
319 }
320 
321 /*
322  * @implemented
323  */
324 VOID
325 WINAPI
326 ExitThread(IN DWORD uExitCode)
327 {
330  PRTL_CRITICAL_SECTION LoaderLock;
331 
332  /* Make sure loader lock isn't held */
333  LoaderLock = NtCurrentPeb()->LoaderLock;
334  if (LoaderLock) ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread);
335 
336  /*
337  * Terminate process if this is the last thread
338  * of the current process
339  */
342  &LastThread,
343  sizeof(LastThread),
344  NULL);
345  if ((NT_SUCCESS(Status)) && (LastThread)) ExitProcess(uExitCode);
346 
347  /* Notify DLLs and TLS Callbacks of termination */
349 
350  /* Tell the Kernel to free the Stack */
351  NtCurrentTeb()->FreeStackOnTermination = TRUE;
352  NtTerminateThread(NULL, uExitCode);
353 
354  /* We should never reach this place */
355  ERROR_FATAL("It should not happen\n");
356  while (TRUE); /* 'noreturn' function */
357 }
358 
359 /*
360  * @implemented
361  */
362 HANDLE
363 WINAPI
364 OpenThread(IN DWORD dwDesiredAccess,
367 {
369  HANDLE ThreadHandle;
372 
375 
377  NULL,
378  (bInheritHandle ? OBJ_INHERIT : 0),
379  NULL,
380  NULL);
381 
382  Status = NtOpenThread(&ThreadHandle,
383  dwDesiredAccess,
385  &ClientId);
386  if (!NT_SUCCESS(Status))
387  {
389  return NULL;
390  }
391 
392  return ThreadHandle;
393 }
394 
395 /*
396  * @implemented
397  */
398 PTEB
400 {
401  return NtCurrentTeb();
402 }
403 
404 /*
405  * @implemented
406  */
407 BOOL
408 WINAPI
410 {
412 }
413 
414 
415 /*
416  * @implemented
417  */
418 DWORD
419 WINAPI
421 {
423 }
424 
425 /*
426  * @implemented
427  */
428 BOOL
429 NTAPI
431  OUT LPFILETIME lpCreationTime,
432  OUT LPFILETIME lpExitTime,
433  OUT LPFILETIME lpKernelTime,
434  OUT LPFILETIME lpUserTime)
435 {
436  KERNEL_USER_TIMES KernelUserTimes;
438 
440  ThreadTimes,
441  &KernelUserTimes,
442  sizeof(KERNEL_USER_TIMES),
443  NULL);
444  if (!NT_SUCCESS(Status))
445  {
447  return FALSE;
448  }
449 
450  *lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
451  *lpExitTime = *(LPFILETIME)&KernelUserTimes.ExitTime;
452  *lpKernelTime = *(LPFILETIME)&KernelUserTimes.KernelTime;
453  *lpUserTime = *(LPFILETIME)&KernelUserTimes.UserTime;
454  return TRUE;
455 }
456 
457 /*
458  * @implemented
459  */
460 BOOL
461 WINAPI
463  OUT LPCONTEXT lpContext)
464 {
466 
467  Status = NtGetContextThread(hThread, lpContext);
468  if (!NT_SUCCESS(Status))
469  {
471  return FALSE;
472  }
473 
474  return TRUE;
475 }
476 
477 /*
478  * @implemented
479  */
480 BOOL
481 WINAPI
483  IN CONST CONTEXT *lpContext)
484 {
486 
487  Status = NtSetContextThread(hThread, (PCONTEXT)lpContext);
488  if (!NT_SUCCESS(Status))
489  {
491  return FALSE;
492  }
493 
494  return TRUE;
495 }
496 
497 /*
498  * @implemented
499  */
500 BOOL
501 WINAPI
503  OUT LPDWORD lpExitCode)
504 {
505  THREAD_BASIC_INFORMATION ThreadBasic;
507 
510  &ThreadBasic,
511  sizeof(THREAD_BASIC_INFORMATION),
512  NULL);
513  if (!NT_SUCCESS(Status))
514  {
516  return FALSE;
517  }
518 
519  *lpExitCode = ThreadBasic.ExitStatus;
520  return TRUE;
521 }
522 
523 /*
524  * @implemented
525  */
526 DWORD
527 WINAPI
529 {
530  ULONG PreviousResumeCount;
532 
533  Status = NtResumeThread(hThread, &PreviousResumeCount);
534  if (!NT_SUCCESS(Status))
535  {
537  return -1;
538  }
539 
540  return PreviousResumeCount;
541 }
542 
543 /*
544  * @implemented
545  */
546 BOOL
547 WINAPI
549  IN DWORD dwExitCode)
550 {
552 #if DBG
553  PRTL_CRITICAL_SECTION LoaderLock;
555 #endif /* DBG */
556 
557  /* Check for invalid thread handle */
558  if (!hThread)
559  {
560  /* Fail if one was passed */
562  return FALSE;
563  }
564 
565 #if DBG
566  /* Get the loader lock */
567  LoaderLock = NtCurrentPeb()->LoaderLock;
568  if (LoaderLock)
569  {
570  /* Get our TID */
573  &ThreadInfo,
574  sizeof(ThreadInfo),
575  NULL);
576  if (NT_SUCCESS(Status))
577  {
578  /* If terminating the current thread, we must not hold the loader lock */
579  if (NtCurrentTeb()->ClientId.UniqueThread == ThreadInfo.ClientId.UniqueThread)
581  }
582  }
583 #endif /* DBG */
584 
585  /* Now terminate the thread */
586  Status = NtTerminateThread(hThread, dwExitCode);
587  if (!NT_SUCCESS(Status))
588  {
589  /* Fail */
591  return FALSE;
592  }
593 
594  /* All done */
595  return TRUE;
596 }
597 
598 /*
599  * @implemented
600  */
601 DWORD
602 WINAPI
604 {
605  ULONG PreviousSuspendCount;
607 
608  Status = NtSuspendThread(hThread, &PreviousSuspendCount);
609  if (!NT_SUCCESS(Status))
610  {
612  return -1;
613  }
614 
615  return PreviousSuspendCount;
616 }
617 
618 /*
619  * @implemented
620  */
621 DWORD_PTR
622 WINAPI
624  IN DWORD_PTR dwThreadAffinityMask)
625 {
626  THREAD_BASIC_INFORMATION ThreadBasic;
627  KAFFINITY AffinityMask;
629 
630  AffinityMask = (KAFFINITY)dwThreadAffinityMask;
631 
634  &ThreadBasic,
635  sizeof(THREAD_BASIC_INFORMATION),
636  NULL);
637  if (!NT_SUCCESS(Status))
638  {
640  return 0;
641  }
642 
645  &AffinityMask,
646  sizeof(KAFFINITY));
647  if (!NT_SUCCESS(Status))
648  {
650  ThreadBasic.AffinityMask = 0;
651  }
652 
653  return ThreadBasic.AffinityMask;
654 }
655 
656 /*
657  * @implemented
658  */
659 BOOL
660 WINAPI
662  IN int nPriority)
663 {
664  LONG Prio = nPriority;
666 
667  /* Check if values forcing saturation should be used */
668  if (Prio == THREAD_PRIORITY_TIME_CRITICAL)
669  {
670  /* This is 16 */
671  Prio = (HIGH_PRIORITY + 1) / 2;
672  }
673  else if (Prio == THREAD_PRIORITY_IDLE)
674  {
675  /* This is -16 */
676  Prio = -((HIGH_PRIORITY + 1) / 2);
677  }
678 
679  /* Set the Base Priority */
682  &Prio,
683  sizeof(LONG));
684  if (!NT_SUCCESS(Status))
685  {
686  /* Failure */
688  return FALSE;
689  }
690 
691  /* Return */
692  return TRUE;
693 }
694 
695 /*
696  * @implemented
697  */
698 int
699 WINAPI
701 {
702  THREAD_BASIC_INFORMATION ThreadBasic;
704 
705  /* Query the Base Priority Increment */
708  &ThreadBasic,
709  sizeof(THREAD_BASIC_INFORMATION),
710  NULL);
711  if (!NT_SUCCESS(Status))
712  {
713  /* Failure */
716  }
717 
718  /* Do some conversions for saturation values */
719  if (ThreadBasic.BasePriority == ((HIGH_PRIORITY + 1) / 2))
720  {
721  /* Win32 calls this "time critical" */
723  }
724  else if (ThreadBasic.BasePriority == -((HIGH_PRIORITY + 1) / 2))
725  {
726  /* Win32 calls this "idle" */
727  ThreadBasic.BasePriority = THREAD_PRIORITY_IDLE;
728  }
729 
730  /* Return the final result */
731  return ThreadBasic.BasePriority;
732 }
733 
734 /*
735  * @implemented
736  */
737 BOOL
738 WINAPI
740  OUT PBOOL pDisablePriorityBoost)
741 {
744 
747  &PriorityBoost,
748  sizeof(ULONG),
749  NULL);
750  if (!NT_SUCCESS(Status))
751  {
753  return FALSE;
754  }
755 
756  *pDisablePriorityBoost = PriorityBoost;
757  return TRUE;
758 }
759 
760 /*
761  * @implemented
762  */
763 BOOL
764 NTAPI
766  IN BOOL bDisablePriorityBoost)
767 {
770 
771  PriorityBoost = bDisablePriorityBoost != FALSE;
772 
775  &PriorityBoost,
776  sizeof(ULONG));
777  if (!NT_SUCCESS(Status))
778  {
780  return FALSE;
781  }
782 
783  return TRUE;
784 }
785 
786 /*
787  * @implemented
788  */
789 BOOL
790 WINAPI
792  IN DWORD dwSelector,
793  OUT LPLDT_ENTRY lpSelectorEntry)
794 {
795 #ifdef _M_IX86
796  DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
798 
799  /* Set the selector and do the query */
800  DescriptionTableEntry.Selector = dwSelector;
803  &DescriptionTableEntry,
804  sizeof(DESCRIPTOR_TABLE_ENTRY),
805  NULL);
806  if (!NT_SUCCESS(Status))
807  {
808  /* Fail */
810  return FALSE;
811  }
812 
813  /* Success, return the selector */
814  *lpSelectorEntry = DescriptionTableEntry.Descriptor;
815  return TRUE;
816 #else
817  DPRINT1("Calling GetThreadSelectorEntry!\n");
818  return FALSE;
819 #endif
820 }
821 
822 /*
823  * @implemented
824  */
825 DWORD
826 WINAPI
828  IN DWORD dwIdealProcessor)
829 {
831 
834  &dwIdealProcessor,
835  sizeof(ULONG));
836  if (!NT_SUCCESS(Status))
837  {
839  return -1;
840  }
841 
842  return (DWORD)Status;
843 }
844 
845 /*
846  * @implemented
847  */
848 DWORD
849 WINAPI
851 {
852  THREAD_BASIC_INFORMATION ThreadBasic;
854 
857  &ThreadBasic,
858  sizeof(THREAD_BASIC_INFORMATION),
859  NULL);
860  if (!NT_SUCCESS(Status))
861  {
863  return 0;
864  }
865 
866  return HandleToUlong(ThreadBasic.ClientId.UniqueProcess);
867 }
868 
869 /*
870  * @implemented
871  */
872 DWORD
873 WINAPI
875 {
876  THREAD_BASIC_INFORMATION ThreadBasic;
878 
881  &ThreadBasic,
882  sizeof(THREAD_BASIC_INFORMATION),
883  NULL);
884  if (!NT_SUCCESS(Status))
885  {
887  return 0;
888  }
889 
890  return HandleToUlong(ThreadBasic.ClientId.UniqueThread);
891 }
892 
893 /*
894  * @unimplemented
895  */
896 LANGID
897 WINAPI
899 {
901  return (LANGID)NtCurrentTeb()->CurrentLocale;
902 }
903 
904 /*
905  * @implemented
906  */
907 DWORD
908 WINAPI
910  IN HANDLE hThread,
912 {
914  ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
915 
916  /* Zero the activation context and query information on it */
917  RtlZeroMemory(&ActCtxInfo, sizeof(ActCtxInfo));
919  NULL,
920  0,
921  ActivationContextBasicInformation,
922  &ActCtxInfo,
923  sizeof(ActCtxInfo),
924  NULL);
925  if (!NT_SUCCESS(Status))
926  {
927  /* Fail due to SxS */
928  DbgPrint("SXS: %s failing because RtlQueryInformationActivationContext()"
929  "returned status %08lx\n", __FUNCTION__, Status);
931  return FALSE;
932  }
933 
934  /* Queue the APC */
937  pfnAPC,
938  (PVOID)dwData,
939  (ActCtxInfo.dwFlags & 1) ?
940  INVALID_ACTIVATION_CONTEXT : ActCtxInfo.hActCtx);
941  if (!NT_SUCCESS(Status))
942  {
944  return FALSE;
945  }
946 
947  /* All good */
948  return TRUE;
949 }
950 
951 /*
952  * @unimplemented
953  */
954 BOOL
955 WINAPI
957 {
958  PTEB Teb = NtCurrentTeb();
959  ULONG GuaranteedStackBytes;
961 
962  if (!StackSizeInBytes)
963  {
965  return FALSE;
966  }
967 
968  AllocationSize = *StackSizeInBytes;
969 
970  /* Retrieve the current stack size */
971  GuaranteedStackBytes = Teb->GuaranteedStackBytes;
972 
973  /* Return the size of the previous stack */
974  *StackSizeInBytes = GuaranteedStackBytes;
975 
976  /*
977  * If the new stack size is either zero or is less than the current size,
978  * the previous stack size is returned and we return success.
979  */
980  if ((AllocationSize == 0) || (AllocationSize < GuaranteedStackBytes))
981  {
982  return TRUE;
983  }
984 
985  // FIXME: Unimplemented!
987 
988  // Temporary HACK for supporting applications!
989  return TRUE; // FALSE;
990 }
991 
992 /*
993  * @implemented
994  */
995 BOOL
996 WINAPI
998  OUT PBOOL lpIOIsPending)
999 {
1000  ULONG IoPending;
1001  NTSTATUS Status;
1002 
1003  /* Query the flag */
1006  &IoPending,
1007  sizeof(IoPending),
1008  NULL);
1009  if (NT_SUCCESS(Status))
1010  {
1011  /* Return the flag */
1012  *lpIOIsPending = IoPending ? TRUE : FALSE;
1013  return TRUE;
1014  }
1015 
1016  /* Fail */
1018  return FALSE;
1019 }
1020 
1021 /*
1022  * @implemented
1023  */
1024 BOOL
1025 WINAPI
1027  IN PVOID Context,
1028  IN ULONG Flags)
1029 {
1030  NTSTATUS Status;
1031 
1032  /* NOTE: Rtl needs to safely call the function using a trampoline */
1034  if (!NT_SUCCESS(Status))
1035  {
1036  /* Failed */
1038  return FALSE;
1039  }
1040 
1041  /* All good */
1042  return TRUE;
1043 }
1044 
1045 /*
1046  * @implemented
1047  */
1048 DWORD
1049 WINAPI
1051 {
1052  ULONG Index;
1053  PTEB Teb;
1054  PPEB Peb;
1055 
1056  /* Get the PEB and TEB, lock the PEB */
1057  Teb = NtCurrentTeb();
1060 
1061  /* Try to get regular TEB slot */
1063  if (Index != 0xFFFFFFFF)
1064  {
1065  /* Clear the value. */
1066  Teb->TlsSlots[Index] = 0;
1068  return Index;
1069  }
1070 
1071  /* If it fails, try to find expansion TEB slot. */
1073  if (Index != 0xFFFFFFFF)
1074  {
1075  /* Is there no expansion slot yet? */
1076  if (!Teb->TlsExpansionSlots)
1077  {
1078  /* Allocate an array */
1079  Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
1082  sizeof(PVOID));
1083  }
1084 
1085  /* Did we get an array? */
1086  if (!Teb->TlsExpansionSlots)
1087  {
1088  /* Fail */
1090  Index = 0xFFFFFFFF;
1092  }
1093  else
1094  {
1095  /* Clear the value. */
1096  Teb->TlsExpansionSlots[Index] = 0;
1098  }
1099  }
1100  else
1101  {
1102  /* Fail */
1104  }
1105 
1106  /* Release the lock and return */
1108  return Index;
1109 }
1110 
1111 /*
1112  * @implemented
1113  */
1114 BOOL
1115 WINAPI
1117 {
1118  BOOL BitSet;
1119  PPEB Peb;
1120  ULONG TlsIndex;
1121  PVOID TlsBitmap;
1122  NTSTATUS Status;
1123 
1124  /* Acquire the PEB lock and grab the PEB */
1125  Peb = NtCurrentPeb();
1127 
1128  /* Check if the index is too high */
1130  {
1131  /* Check if it can fit in the expansion slots */
1134  {
1135  /* It's invalid */
1138  return FALSE;
1139  }
1140  else
1141  {
1142  /* Use the expansion bitmap */
1143  TlsBitmap = Peb->TlsExpansionBitmap;
1144  Index = TlsIndex;
1145  }
1146  }
1147  else
1148  {
1149  /* Use the normal bitmap */
1150  TlsBitmap = Peb->TlsBitmap;
1151  }
1152 
1153  /* Check if the index was set */
1154  BitSet = RtlAreBitsSet(TlsBitmap, Index, 1);
1155  if (BitSet)
1156  {
1157  /* Tell the kernel to free the TLS cells */
1160  &Index,
1161  sizeof(DWORD));
1162  if (!NT_SUCCESS(Status))
1163  {
1166  return FALSE;
1167  }
1168 
1169  /* Clear the bit */
1170  RtlClearBits(TlsBitmap, Index, 1);
1171  }
1172  else
1173  {
1174  /* Fail */
1177  return FALSE;
1178  }
1179 
1180  /* Done! */
1182  return TRUE;
1183 }
1184 
1185 /*
1186  * @implemented
1187  */
1188 LPVOID
1189 WINAPI
1191 {
1192  PTEB Teb;
1193 
1194  /* Get the TEB and clear the last error */
1195  Teb = NtCurrentTeb();
1196  Teb->LastErrorValue = 0;
1197 
1198  /* Check for simple TLS index */
1200  {
1201  /* Return it */
1202  return Teb->TlsSlots[Index];
1203  }
1204 
1205  /* Check for valid index */
1207  {
1208  /* Fail */
1210  return NULL;
1211  }
1212 
1213  /* The expansion slots are allocated on demand, so check for it. */
1214  Teb->LastErrorValue = 0;
1215  if (!Teb->TlsExpansionSlots) return NULL;
1216 
1217  /* Return the value from the expansion slots */
1219 }
1220 
1221 /*
1222  * @implemented
1223  */
1224 BOOL
1225 WINAPI
1227  IN LPVOID Value)
1228 {
1229  DWORD TlsIndex;
1230  PTEB Teb = NtCurrentTeb();
1231 
1232  /* Check for simple TLS index */
1234  {
1235  /* Return it */
1236  Teb->TlsSlots[Index] = Value;
1237  return TRUE;
1238  }
1239 
1240  /* Check if this is an expansion slot */
1243  {
1244  /* Fail */
1246  return FALSE;
1247  }
1248 
1249  /* Do we not have expansion slots? */
1250  if (!Teb->TlsExpansionSlots)
1251  {
1252  /* Get the PEB lock to see if we still need them */
1254  if (!Teb->TlsExpansionSlots)
1255  {
1256  /* Allocate them */
1257  Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
1260  sizeof(PVOID));
1261  if (!Teb->TlsExpansionSlots)
1262  {
1263  /* Fail */
1266  return FALSE;
1267  }
1268  }
1269 
1270  /* Release the lock */
1272  }
1273 
1274  /* Write the value */
1276 
1277  /* Success */
1278  return TRUE;
1279 }
1280 
1281 /* EOF */
PRTL_BITMAP TlsExpansionBitmap
Definition: winternl.h:346
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
LANGID WINAPI SetThreadUILanguage(IN LANGID LangId)
Definition: thread.c:898
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define UNIMPLEMENTED_ONCE
Definition: debug.h:138
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define IN
Definition: typedefs.h:38
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define ULongToHandle(h)
Definition: basetsd.h:81
VOID WINAPI BaseInitializeContext(IN PCONTEXT Context, IN PVOID Parameter, IN PVOID StartAddress, IN PVOID StackAddress, IN ULONG ContextType)
Definition: utils.c:503
BOOL NTAPI GetThreadTimes(IN HANDLE hThread, OUT LPFILETIME lpCreationTime, OUT LPFILETIME lpExitTime, OUT LPFILETIME lpKernelTime, OUT LPFILETIME lpUserTime)
Definition: thread.c:430
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
BOOL WINAPI SwitchToThread(VOID)
Definition: thread.c:409
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:707
#define TRUE
Definition: types.h:120
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:482
NTSTATUS NTAPI NtOpenThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL)
Definition: thread.c:1013
PPEB Peb
Definition: dllmain.c:27
PPEB ProcessEnvironmentBlock
Definition: ntddk_ex.h:337
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:548
KAFFINITY AffinityMask
Definition: compat.h:579
#define DbgPrint
Definition: loader.c:25
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1226
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE)
Definition: actctx.c:5267
struct _FILETIME * LPFILETIME
Definition: time.c:29
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_YIELD_PERFORMED
Definition: ntstatus.h:150
#define TLS_EXPANSION_SLOTS
Definition: pstypes.h:294
#define THREAD_PRIORITY_ERROR_RETURN
Definition: winbase.h:279
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
LONG NTSTATUS
Definition: precomp.h:26
LARGE_INTEGER UserTime
Definition: winternl.h:1063
#define HandleToUlong(h)
Definition: basetsd.h:79
#define NtCurrentThread()
NTSYSAPI NTSTATUS NTAPI RtlQueueWorkItem(_In_ WORKERCALLBACKFUNC Function, _In_opt_ PVOID Context, _In_ ULONG Flags)
__declspec(noreturn)
Definition: thread.c:28
static HANDLE ULONG_PTR dwData
Definition: file.c:35
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1517
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
DWORD WINAPI GetThreadId(IN HANDLE Thread)
Definition: thread.c:874
struct _ThreadInfo ThreadInfo
WORD LANGID
Definition: typedefs.h:79
BOOL WINAPI GetThreadIOPendingFlag(IN HANDLE hThread, OUT PBOOL lpIOIsPending)
Definition: thread.c:997
NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL)
Definition: state.c:352
HANDLE UniqueProcess
Definition: compat.h:474
#define RTL_ACTIVATE_ACTIVATION_CONTEXT_EX_FLAG_RELEASE_ON_STACK_DEALLOCATION
Definition: rtltypes.h:106
NTSTATUS NTAPI NtQueueApcThread(IN HANDLE ThreadHandle, IN PKNORMAL_ROUTINE ApcRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: state.c:500
KPRIORITY BasePriority
Definition: compat.h:581
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
LARGE_INTEGER ExitTime
Definition: winternl.h:1061
#define ERROR_FATAL(...)
Definition: debug.h:238
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:502
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:462
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
DWORD WINAPI QueueUserAPC(IN PAPCFUNC pfnAPC, IN HANDLE hThread, IN ULONG_PTR dwData)
Definition: thread.c:909
#define CREATE_SUSPENDED
Definition: winbase.h:178
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:684
static BOOL bInheritHandle
Definition: pipe.c:82
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
BOOL NTAPI SetThreadPriorityBoost(IN HANDLE hThread, IN BOOL bDisablePriorityBoost)
Definition: thread.c:765
LONG WINAPI UnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
Definition: except.c:262
_In_ CCHAR PriorityBoost
Definition: iofuncs.h:763
#define ERROR_DBGBREAK(...)
Definition: debug.h:221
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:111
smooth NULL
Definition: ftsmooth.c:416
DWORD_PTR WINAPI SetThreadAffinityMask(IN HANDLE hThread, IN DWORD_PTR dwThreadAffinityMask)
Definition: thread.c:623
PVOID StackBase
Definition: pstypes.h:678
void DPRINT(...)
Definition: polytest.cpp:61
BOOL WINAPI GetThreadPriorityBoost(IN HANDLE hThread, OUT PBOOL pDisablePriorityBoost)
Definition: thread.c:739
#define RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
Definition: rtltypes.h:101
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:326
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2014
BOOL * PBOOL
Definition: windef.h:161
#define HIGH_PRIORITY
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:420
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
Definition: thread.c:661
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:240
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
BOOLEAN BaseRunningInServerProcess
Definition: dllmain.c:20
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1116
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI BaseDispatchApc(IN PAPCFUNC ApcRoutine, IN PVOID Data, IN PACTIVATION_CONTEXT ActivationContext)
Definition: thread.c:66
NTSTATUS NTAPI NtYieldExecution(VOID)
Definition: thrdschd.c:744
LARGE_INTEGER CreateTime
Definition: winternl.h:1060
#define OBJ_INHERIT
Definition: winternl.h:225
#define STACK_SIZE_PARAM_IS_A_RESERVATION
Definition: winbase.h:558
_In_opt_ PVOID _Out_ PLARGE_INTEGER Cookie
Definition: cmfuncs.h:13
#define WINAPI
Definition: msvc.h:8
BOOL WINAPI SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
Definition: thread.c:956
static const UCHAR Index[8]
Definition: usbohci.c:18
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
Definition: actctx.c:5934
#define SetLastError(x)
Definition: compat.h:409
DWORD WINAPI SetThreadIdealProcessor(IN HANDLE hThread, IN DWORD dwIdealProcessor)
Definition: thread.c:827
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:719
HANDLE UniqueThread
Definition: compat.h:475
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOL WINAPI QueueUserWorkItem(IN LPTHREAD_START_ROUTINE Function, IN PVOID Context, IN ULONG Flags)
Definition: thread.c:1026
#define THREAD_PRIORITY_TIME_CRITICAL
Definition: winbase.h:278
NTSTATUS NTAPI CsrCreateRemoteThread(IN HANDLE hThread, IN PCLIENT_ID ClientId)
Definition: thredsup.c:568
DWORD dwThreadId
Definition: fdebug.c:31
#define THREAD_PRIORITY_IDLE
Definition: winbase.h:275
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:603
NTSTATUS WINAPI BaseCreateStack(HANDLE hProcess, SIZE_T StackCommit, SIZE_T StackReserve, PINITIAL_TEB InitialTeb)
Definition: utils.c:353
LPVOID lpParameter
Definition: kernel32.h:234
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:364
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:819
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1050
PTEB GetTeb(VOID)
Definition: thread.c:399
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define TlsIndex
Definition: ws2_32p.h:277
POBJECT_ATTRIBUTES WINAPI BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL, IN PUNICODE_STRING ObjectName)
Definition: utils.c:304
static NTSTATUS(WINAPI *pNtQueryInformationThread)(HANDLE
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI CsrNewThread(VOID)
Definition: api.c:27
PETHREAD LastThread
Definition: pinsup.c:109
Definition: compat.h:428
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:310
ULONG_PTR SIZE_T
Definition: typedefs.h:78
Definition: compat.h:484
NTSTATUS WINAPI BasepNotifyCsrOfThread(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId)
Definition: proc.c:484
_SEH2_END
Definition: create.c:4424
NTSYSAPI BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP, ULONG, ULONG)
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
DWORD WINAPI GetProcessIdOfThread(IN HANDLE Thread)
Definition: thread.c:850
#define NtCurrentPeb()
Definition: FLS.c:20
ULONG_PTR KAFFINITY
Definition: compat.h:75
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:791
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
Definition: debug.c:371
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI NtCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended)
Definition: thread.c:941
NTSYSAPI NTSTATUS WINAPI RtlQueryInformationActivationContext(ULONG, HANDLE, PVOID, ULONG, PVOID, SIZE_T, SIZE_T *)
Definition: actctx.c:5438
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
HANDLE hThread
Definition: wizard.c:27
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
#define RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
Definition: rtltypes.h:116
#define DPRINT1
Definition: precomp.h:8
NTSTATUS(NTAPI * PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId)
Definition: thread.c:19
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1190
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, IN PVOID Context)
Definition: actctx.c:5857
VOID(NTAPI * WORKERCALLBACKFUNC)(_In_ PVOID Context)
Definition: rtltypes.h:509
NTSTATUS NTAPI RtlActivateActivationContextEx(ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie)
Definition: actctx.c:5291
#define OUT
Definition: typedefs.h:39
NTSTATUS NTAPI RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
Definition: actctx.c:5829
uint32_t * LPDWORD
Definition: typedefs.h:57
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:528
ULONG LastErrorValue
Definition: compat.h:492
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define GetProcAddress(x, y)
Definition: compat.h:410
PVOID TlsSlots[64]
Definition: compat.h:528
PVOID * TlsExpansionSlots
Definition: compat.h:543
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
PVOID ActivationContextStackPointer
Definition: compat.h:503
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:632
NTSTATUS NTAPI LdrShutdownThread(VOID)
Definition: ldrinit.c:1078
PVOID TlsBitmap
Definition: ntddk_ex.h:259
#define __FUNCTION__
Definition: types.h:112
LARGE_INTEGER KernelTime
Definition: winternl.h:1062
int WINAPI GetThreadPriority(IN HANDLE hThread)
Definition: thread.c:700
#define CONST
Definition: pedump.c:81
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:334
#define TLS_MINIMUM_AVAILABLE
Definition: ntddk_ex.h:236
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:133
VOID WINAPI BaseFreeThreadStack(IN HANDLE hProcess, IN PINITIAL_TEB InitialTeb)
Definition: utils.c:486
VOID NTAPI RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
Definition: actctx.c:5363