ReactOS 0.4.15-dev-7788-g1ad9096
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
21/* FUNCTIONS ******************************************************************/
22
27{
28 BASE_API_MESSAGE ApiMessage;
29 PBASE_CREATE_THREAD CreateThreadRequest = &ApiMessage.Data.CreateThreadRequest;
30
31 DPRINT("BasepNotifyCsrOfThread: Thread: %p, Handle %p\n",
32 ClientId->UniqueThread, ThreadHandle);
33
34 /* Fill out the request */
35 CreateThreadRequest->ClientId = *ClientId;
36 CreateThreadRequest->ThreadHandle = ThreadHandle;
37
38 /* Call CSR */
40 NULL,
42 sizeof(*CreateThreadRequest));
43 if (!NT_SUCCESS(ApiMessage.Status))
44 {
45 DPRINT1("Failed to tell CSRSS about new thread: %lx\n", ApiMessage.Status);
46 return ApiMessage.Status;
47 }
48
49 /* Return Success */
50 return STATUS_SUCCESS;
51}
52
54VOID
57 _In_ LPTHREAD_START_ROUTINE lpStartAddress,
58 _In_ LPVOID lpParameter)
59{
60 /* Attempt to call the Thread Start Address */
62 {
63 /* Legacy check which is still used today for Win32 threads */
64 if (NtCurrentTeb()->NtTib.Version == (30 << 8)) // OS/2 V3.0 ("Cruiser")
65 {
66 /* This registers the termination port with CSRSS */
68 }
69
70 /* Get the exit code from the Thread Start */
71 ExitThread(lpStartAddress(lpParameter));
72 }
74 {
75 /* Get the Exit code from the SEH Handler */
77 {
78 /* Kill the whole process, usually */
80 }
81 else
82 {
83 /* If running inside CSRSS, kill just this thread */
85 }
86 }
88}
89
90VOID
94 IN PACTIVATION_CONTEXT ActivationContext)
95{
96 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame;
97
98 /* Setup the activation context */
99 ActivationFrame.Size = sizeof(ActivationFrame);
101
102 /* Check if caller wanted one */
103 if (ActivationContext == INVALID_ACTIVATION_CONTEXT)
104 {
105 /* Do the APC directly */
107 return;
108 }
109
110 /* Then activate it */
111 RtlActivateActivationContextUnsafeFast(&ActivationFrame, ActivationContext);
112
113 /* Call the routine under SEH */
115 {
117 }
119 {
120
121 }
122 _SEH2_END;
123
124 /* Now de-activate and release the activation context */
126 RtlReleaseActivationContext(ActivationContext);
127}
128
129/* PUBLIC FUNCTIONS ***********************************************************/
130
131/*
132 * @implemented
133 */
134HANDLE
135WINAPI
138 IN DWORD dwStackSize,
139 IN LPTHREAD_START_ROUTINE lpStartAddress,
140 IN LPVOID lpParameter,
141 IN DWORD dwCreationFlags,
142 OUT LPDWORD lpThreadId)
143{
144 /* Act as if we're going to create a remote thread in ourselves */
146 lpThreadAttributes,
147 dwStackSize,
148 lpStartAddress,
149 lpParameter,
150 dwCreationFlags,
151 lpThreadId);
152}
153
154/*
155 * @implemented
156 */
157HANDLE
158WINAPI
160 IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
161 IN DWORD dwStackSize,
162 IN LPTHREAD_START_ROUTINE lpStartAddress,
163 IN LPVOID lpParameter,
164 IN DWORD dwCreationFlags,
165 OUT LPDWORD lpThreadId)
166{
168 INITIAL_TEB InitialTeb;
171 OBJECT_ATTRIBUTES LocalObjectAttributes;
174 ULONG Dummy;
175 PTEB Teb;
176 THREAD_BASIC_INFORMATION ThreadBasicInfo;
177 PACTIVATION_CONTEXT_STACK ActivationContextStack = NULL;
178 ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
181 SIZE_T ReturnSize;
182
183 DPRINT("CreateRemoteThread: hProcess: %p dwStackSize: %lu lpStartAddress"
184 ": %p lpParameter: %p, dwCreationFlags: %lx\n", hProcess,
185 dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
186
187 /* Clear the Context */
188 RtlZeroMemory(&Context, sizeof(Context));
189
190 /* Write PID */
192
193 /* Create the Stack */
195 (dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION) ?
196 0 : dwStackSize,
197 (dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION) ?
198 dwStackSize : 0,
199 &InitialTeb);
200 if (!NT_SUCCESS(Status))
201 {
203 return NULL;
204 }
205
206 /* Create the Initial Context */
208 lpParameter,
209 lpStartAddress,
210 InitialTeb.StackBase,
211 1);
212
213 /* Initialize the attributes for the thread object */
214 ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
215 lpThreadAttributes,
216 NULL);
217
218 /* Create the Kernel Thread Object */
222 hProcess,
223 &ClientId,
224 &Context,
225 &InitialTeb,
226 TRUE);
227 if (!NT_SUCCESS(Status))
228 {
229 /* Fail the kernel create */
230 BaseFreeThreadStack(hProcess, &InitialTeb);
232 return NULL;
233 }
234
235 /* Are we in the same process? */
236 if (hProcess == NtCurrentProcess())
237 {
238 /* Get the TEB */
241 &ThreadBasicInfo,
242 sizeof(ThreadBasicInfo),
243 &ReturnLength);
244 if (!NT_SUCCESS(Status))
245 {
246 /* Fail */
247 DPRINT1("SXS: %s - Failing thread create because "
248 "NtQueryInformationThread() failed with status %08lx\n",
250 goto Quit;
251 }
252
253 /* Allocate the Activation Context Stack */
254 Status = RtlAllocateActivationContextStack(&ActivationContextStack);
255 if (!NT_SUCCESS(Status))
256 {
257 /* Fail */
258 DPRINT1("SXS: %s - Failing thread create because "
259 "RtlAllocateActivationContextStack() failed with status %08lx\n",
261 goto Quit;
262 }
263
264 /* Save it */
265 Teb = ThreadBasicInfo.TebBaseAddress;
266 Teb->ActivationContextStackPointer = ActivationContextStack;
267
268 /* Query the Context */
270 NULL,
271 0,
272 ActivationContextBasicInformation,
273 &ActCtxInfo,
274 sizeof(ActCtxInfo),
275 &ReturnSize);
276 if (!NT_SUCCESS(Status))
277 {
278 /* Fail */
279 DPRINT1("SXS: %s - Failing thread create because "
280 "RtlQueryInformationActivationContext() failed with status %08lx\n",
282 goto Quit;
283 }
284
285 /* Does it need to be activated? */
286 if ((ActCtxInfo.hActCtx) && !(ActCtxInfo.dwFlags & 1))
287 {
288 /* Activate it */
290 Teb,
291 ActCtxInfo.hActCtx,
292 &Cookie);
293 if (!NT_SUCCESS(Status))
294 {
295 /* Fail */
296 DPRINT1("SXS: %s - Failing thread create because "
297 "RtlActivateActivationContextEx() failed with status %08lx\n",
299 goto Quit;
300 }
301 }
302
303 /* Sync the service tag with the parent thread's one */
304 Teb->SubProcessTag = NtCurrentTeb()->SubProcessTag;
305 }
306
307 /* Notify CSR */
309 {
311 }
312 else
313 {
314 if (hProcess != NtCurrentProcess())
315 {
317
318 /* Get the direct CSRSRV export */
321 "CsrCreateRemoteThread");
323 {
324 /* Call it instead of going through LPC */
326 }
327 }
328 }
329
330Quit:
331 if (!NT_SUCCESS(Status))
332 {
333 /* Failed to create the thread */
334
335 /* Free the activation context stack */
336 if (ActivationContextStack)
337 RtlFreeActivationContextStack(ActivationContextStack);
338
340 // FIXME: Wait for the thread to terminate?
341 BaseFreeThreadStack(hProcess, &InitialTeb);
343
345 return NULL;
346 }
347
348 /* Success */
349 if (lpThreadId)
350 *lpThreadId = HandleToUlong(ClientId.UniqueThread);
351
352 /* Resume the thread if asked */
353 if (!(dwCreationFlags & CREATE_SUSPENDED))
354 NtResumeThread(hThread, &Dummy);
355
356 /* Return handle to thread */
357 return hThread;
358}
359
360/*
361 * @implemented
362 */
363VOID
364WINAPI
366{
369 PRTL_CRITICAL_SECTION LoaderLock;
370
371 /* Make sure loader lock isn't held */
372 LoaderLock = NtCurrentPeb()->LoaderLock;
373 if (LoaderLock) ASSERT(NtCurrentTeb()->ClientId.UniqueThread != LoaderLock->OwningThread);
374
375 /*
376 * Terminate process if this is the last thread
377 * of the current process
378 */
381 &LastThread,
382 sizeof(LastThread),
383 NULL);
384 if ((NT_SUCCESS(Status)) && (LastThread)) ExitProcess(uExitCode);
385
386 /* Notify DLLs and TLS Callbacks of termination */
388
389 /* Tell the Kernel to free the Stack */
390 NtCurrentTeb()->FreeStackOnTermination = TRUE;
391 NtTerminateThread(NULL, uExitCode);
392
393 /* We should never reach this place */
394 ERROR_FATAL("It should not happen\n");
395 while (TRUE); /* 'noreturn' function */
396}
397
398/*
399 * @implemented
400 */
401HANDLE
402WINAPI
403OpenThread(IN DWORD dwDesiredAccess,
406{
408 HANDLE ThreadHandle;
411
414
416 NULL,
418 NULL,
419 NULL);
420
421 Status = NtOpenThread(&ThreadHandle,
422 dwDesiredAccess,
424 &ClientId);
425 if (!NT_SUCCESS(Status))
426 {
428 return NULL;
429 }
430
431 return ThreadHandle;
432}
433
434/*
435 * @implemented
436 */
437PTEB
439{
440 return NtCurrentTeb();
441}
442
443/*
444 * @implemented
445 */
446BOOL
447WINAPI
449{
451}
452
453
454/*
455 * @implemented
456 */
457DWORD
458WINAPI
460{
462}
463
464/*
465 * @implemented
466 */
467BOOL
468NTAPI
470 OUT LPFILETIME lpCreationTime,
471 OUT LPFILETIME lpExitTime,
472 OUT LPFILETIME lpKernelTime,
473 OUT LPFILETIME lpUserTime)
474{
475 KERNEL_USER_TIMES KernelUserTimes;
477
480 &KernelUserTimes,
481 sizeof(KERNEL_USER_TIMES),
482 NULL);
483 if (!NT_SUCCESS(Status))
484 {
486 return FALSE;
487 }
488
489 *lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
490 *lpExitTime = *(LPFILETIME)&KernelUserTimes.ExitTime;
491 *lpKernelTime = *(LPFILETIME)&KernelUserTimes.KernelTime;
492 *lpUserTime = *(LPFILETIME)&KernelUserTimes.UserTime;
493 return TRUE;
494}
495
496/*
497 * @implemented
498 */
499BOOL
500WINAPI
502 OUT LPCONTEXT lpContext)
503{
505
506 Status = NtGetContextThread(hThread, lpContext);
507 if (!NT_SUCCESS(Status))
508 {
510 return FALSE;
511 }
512
513 return TRUE;
514}
515
516/*
517 * @implemented
518 */
519BOOL
520WINAPI
522 IN CONST CONTEXT *lpContext)
523{
525
527 if (!NT_SUCCESS(Status))
528 {
530 return FALSE;
531 }
532
533 return TRUE;
534}
535
536/*
537 * @implemented
538 */
539BOOL
540WINAPI
542 OUT LPDWORD lpExitCode)
543{
544 THREAD_BASIC_INFORMATION ThreadBasic;
546
549 &ThreadBasic,
551 NULL);
552 if (!NT_SUCCESS(Status))
553 {
555 return FALSE;
556 }
557
558 *lpExitCode = ThreadBasic.ExitStatus;
559 return TRUE;
560}
561
562/*
563 * @implemented
564 */
565DWORD
566WINAPI
568{
569 ULONG PreviousResumeCount;
571
572 Status = NtResumeThread(hThread, &PreviousResumeCount);
573 if (!NT_SUCCESS(Status))
574 {
576 return -1;
577 }
578
579 return PreviousResumeCount;
580}
581
582/*
583 * @implemented
584 */
585BOOL
586WINAPI
588 IN DWORD dwExitCode)
589{
591#if DBG
592 PRTL_CRITICAL_SECTION LoaderLock;
594#endif /* DBG */
595
596 /* Check for invalid thread handle */
597 if (!hThread)
598 {
599 /* Fail if one was passed */
601 return FALSE;
602 }
603
604#if DBG
605 /* Get the loader lock */
606 LoaderLock = NtCurrentPeb()->LoaderLock;
607 if (LoaderLock)
608 {
609 /* Get our TID */
612 &ThreadInfo,
613 sizeof(ThreadInfo),
614 NULL);
615 if (NT_SUCCESS(Status))
616 {
617 /* If terminating the current thread, we must not hold the loader lock */
618 if (NtCurrentTeb()->ClientId.UniqueThread == ThreadInfo.ClientId.UniqueThread)
620 }
621 }
622#endif /* DBG */
623
624 /* Now terminate the thread */
625 Status = NtTerminateThread(hThread, dwExitCode);
626 if (!NT_SUCCESS(Status))
627 {
628 /* Fail */
630 return FALSE;
631 }
632
633 /* All done */
634 return TRUE;
635}
636
637/*
638 * @implemented
639 */
640DWORD
641WINAPI
643{
644 ULONG PreviousSuspendCount;
646
647 Status = NtSuspendThread(hThread, &PreviousSuspendCount);
648 if (!NT_SUCCESS(Status))
649 {
651 return -1;
652 }
653
654 return PreviousSuspendCount;
655}
656
657/*
658 * @implemented
659 */
661WINAPI
663 IN DWORD_PTR dwThreadAffinityMask)
664{
665 THREAD_BASIC_INFORMATION ThreadBasic;
666 KAFFINITY AffinityMask;
668
669 AffinityMask = (KAFFINITY)dwThreadAffinityMask;
670
673 &ThreadBasic,
675 NULL);
676 if (!NT_SUCCESS(Status))
677 {
679 return 0;
680 }
681
684 &AffinityMask,
685 sizeof(KAFFINITY));
686 if (!NT_SUCCESS(Status))
687 {
689 ThreadBasic.AffinityMask = 0;
690 }
691
692 return ThreadBasic.AffinityMask;
693}
694
695/*
696 * @implemented
697 */
698BOOL
699WINAPI
701 IN int nPriority)
702{
703 LONG Prio = nPriority;
705
706 /* Check if values forcing saturation should be used */
708 {
709 /* This is 16 */
710 Prio = (HIGH_PRIORITY + 1) / 2;
711 }
712 else if (Prio == THREAD_PRIORITY_IDLE)
713 {
714 /* This is -16 */
715 Prio = -((HIGH_PRIORITY + 1) / 2);
716 }
717
718 /* Set the Base Priority */
721 &Prio,
722 sizeof(LONG));
723 if (!NT_SUCCESS(Status))
724 {
725 /* Failure */
727 return FALSE;
728 }
729
730 /* Return */
731 return TRUE;
732}
733
734/*
735 * @implemented
736 */
737int
738WINAPI
740{
741 THREAD_BASIC_INFORMATION ThreadBasic;
743
744 /* Query the Base Priority Increment */
747 &ThreadBasic,
749 NULL);
750 if (!NT_SUCCESS(Status))
751 {
752 /* Failure */
755 }
756
757 /* Do some conversions for saturation values */
758 if (ThreadBasic.BasePriority == ((HIGH_PRIORITY + 1) / 2))
759 {
760 /* Win32 calls this "time critical" */
762 }
763 else if (ThreadBasic.BasePriority == -((HIGH_PRIORITY + 1) / 2))
764 {
765 /* Win32 calls this "idle" */
767 }
768
769 /* Return the final result */
770 return ThreadBasic.BasePriority;
771}
772
773/*
774 * @implemented
775 */
776BOOL
777WINAPI
779 OUT PBOOL pDisablePriorityBoost)
780{
783
787 sizeof(ULONG),
788 NULL);
789 if (!NT_SUCCESS(Status))
790 {
792 return FALSE;
793 }
794
795 *pDisablePriorityBoost = PriorityBoost;
796 return TRUE;
797}
798
799/*
800 * @implemented
801 */
802BOOL
803NTAPI
805 IN BOOL bDisablePriorityBoost)
806{
809
810 PriorityBoost = bDisablePriorityBoost != FALSE;
811
815 sizeof(ULONG));
816 if (!NT_SUCCESS(Status))
817 {
819 return FALSE;
820 }
821
822 return TRUE;
823}
824
825/*
826 * @implemented
827 */
828BOOL
829WINAPI
831 IN DWORD dwSelector,
832 OUT LPLDT_ENTRY lpSelectorEntry)
833{
834#ifdef _M_IX86
835 DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
837
838 /* Set the selector and do the query */
839 DescriptionTableEntry.Selector = dwSelector;
842 &DescriptionTableEntry,
843 sizeof(DESCRIPTOR_TABLE_ENTRY),
844 NULL);
845 if (!NT_SUCCESS(Status))
846 {
847 /* Fail */
849 return FALSE;
850 }
851
852 /* Success, return the selector */
853 *lpSelectorEntry = DescriptionTableEntry.Descriptor;
854 return TRUE;
855#else
856 DPRINT1("Calling GetThreadSelectorEntry!\n");
857 return FALSE;
858#endif
859}
860
861/*
862 * @implemented
863 */
864DWORD
865WINAPI
867 IN DWORD dwIdealProcessor)
868{
870
873 &dwIdealProcessor,
874 sizeof(ULONG));
875 if (!NT_SUCCESS(Status))
876 {
878 return -1;
879 }
880
881 return (DWORD)Status;
882}
883
884/*
885 * @implemented
886 */
887DWORD
888WINAPI
890{
891 THREAD_BASIC_INFORMATION ThreadBasic;
893
896 &ThreadBasic,
898 NULL);
899 if (!NT_SUCCESS(Status))
900 {
902 return 0;
903 }
904
905 return HandleToUlong(ThreadBasic.ClientId.UniqueProcess);
906}
907
908/*
909 * @implemented
910 */
911DWORD
912WINAPI
914{
915 THREAD_BASIC_INFORMATION ThreadBasic;
917
920 &ThreadBasic,
922 NULL);
923 if (!NT_SUCCESS(Status))
924 {
926 return 0;
927 }
928
929 return HandleToUlong(ThreadBasic.ClientId.UniqueThread);
930}
931
932/*
933 * @unimplemented
934 */
935LANGID
936WINAPI
938{
939#if (NTDDI_VERSION < NTDDI_LONGHORN)
940 /* We only support LangId == 0, for selecting a language
941 * identifier that best supports the NT Console. */
942 if (LangId != 0)
943 {
945 return 0;
946 }
947#endif
948
950
951 return LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale);
952}
953
954/*
955 * @implemented
956 */
957DWORD
958WINAPI
962{
964 ACTIVATION_CONTEXT_BASIC_INFORMATION ActCtxInfo;
965
966 /* Zero the activation context and query information on it */
967 RtlZeroMemory(&ActCtxInfo, sizeof(ActCtxInfo));
969 NULL,
970 0,
971 ActivationContextBasicInformation,
972 &ActCtxInfo,
973 sizeof(ActCtxInfo),
974 NULL);
975 if (!NT_SUCCESS(Status))
976 {
977 /* Fail due to SxS */
978 DbgPrint("SXS: %s failing because RtlQueryInformationActivationContext()"
979 "returned status %08lx\n", __FUNCTION__, Status);
981 return FALSE;
982 }
983
984 /* Queue the APC */
987 pfnAPC,
988 (PVOID)dwData,
989 (ActCtxInfo.dwFlags & 1) ?
990 INVALID_ACTIVATION_CONTEXT : ActCtxInfo.hActCtx);
991 if (!NT_SUCCESS(Status))
992 {
994 return FALSE;
995 }
996
997 /* All good */
998 return TRUE;
999}
1000
1001/*
1002 * @unimplemented
1003 */
1004BOOL
1005WINAPI
1007{
1008 PTEB Teb = NtCurrentTeb();
1009 ULONG GuaranteedStackBytes;
1011
1012 if (!StackSizeInBytes)
1013 {
1015 return FALSE;
1016 }
1017
1018 AllocationSize = *StackSizeInBytes;
1019
1020 /* Retrieve the current stack size */
1021 GuaranteedStackBytes = Teb->GuaranteedStackBytes;
1022
1023 /* Return the size of the previous stack */
1024 *StackSizeInBytes = GuaranteedStackBytes;
1025
1026 /*
1027 * If the new stack size is either zero or is less than the current size,
1028 * the previous stack size is returned and we return success.
1029 */
1030 if ((AllocationSize == 0) || (AllocationSize < GuaranteedStackBytes))
1031 {
1032 return TRUE;
1033 }
1034
1035 // FIXME: Unimplemented!
1037
1038 // Temporary HACK for supporting applications!
1039 return TRUE; // FALSE;
1040}
1041
1042/*
1043 * @implemented
1044 */
1045BOOL
1046WINAPI
1048 OUT PBOOL lpIOIsPending)
1049{
1050 ULONG IoPending;
1052
1053 /* Query the flag */
1056 &IoPending,
1057 sizeof(IoPending),
1058 NULL);
1059 if (NT_SUCCESS(Status))
1060 {
1061 /* Return the flag */
1062 *lpIOIsPending = IoPending ? TRUE : FALSE;
1063 return TRUE;
1064 }
1065
1066 /* Fail */
1068 return FALSE;
1069}
1070
1071/*
1072 * @implemented
1073 */
1074BOOL
1075WINAPI
1078 IN ULONG Flags)
1079{
1081
1082 /* NOTE: Rtl needs to safely call the function using a trampoline */
1084 if (!NT_SUCCESS(Status))
1085 {
1086 /* Failed */
1088 return FALSE;
1089 }
1090
1091 /* All good */
1092 return TRUE;
1093}
1094
1095/*
1096 * @implemented
1097 */
1098DWORD
1099WINAPI
1101{
1102 ULONG Index;
1103 PTEB Teb;
1104 PPEB Peb;
1105
1106 /* Get the PEB and TEB, lock the PEB */
1107 Teb = NtCurrentTeb();
1110
1111 /* Try to get regular TEB slot */
1113 if (Index != 0xFFFFFFFF)
1114 {
1115 /* Clear the value. */
1116 Teb->TlsSlots[Index] = 0;
1118 return Index;
1119 }
1120
1121 /* If it fails, try to find expansion TEB slot. */
1123 if (Index != 0xFFFFFFFF)
1124 {
1125 /* Is there no expansion slot yet? */
1126 if (!Teb->TlsExpansionSlots)
1127 {
1128 /* Allocate an array */
1129 Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
1132 sizeof(PVOID));
1133 }
1134
1135 /* Did we get an array? */
1136 if (!Teb->TlsExpansionSlots)
1137 {
1138 /* Fail */
1140 Index = 0xFFFFFFFF;
1142 }
1143 else
1144 {
1145 /* Clear the value. */
1146 Teb->TlsExpansionSlots[Index] = 0;
1148 }
1149 }
1150 else
1151 {
1152 /* Fail */
1154 }
1155
1156 /* Release the lock and return */
1158 return Index;
1159}
1160
1161/*
1162 * @implemented
1163 */
1164BOOL
1165WINAPI
1167{
1168 BOOL BitSet;
1169 PPEB Peb;
1171 PVOID TlsBitmap;
1173
1174 /* Acquire the PEB lock and grab the PEB */
1175 Peb = NtCurrentPeb();
1177
1178 /* Check if the index is too high */
1180 {
1181 /* Check if it can fit in the expansion slots */
1184 {
1185 /* It's invalid */
1188 return FALSE;
1189 }
1190 else
1191 {
1192 /* Use the expansion bitmap */
1193 TlsBitmap = Peb->TlsExpansionBitmap;
1194 Index = TlsIndex;
1195 }
1196 }
1197 else
1198 {
1199 /* Use the normal bitmap */
1200 TlsBitmap = Peb->TlsBitmap;
1201 }
1202
1203 /* Check if the index was set */
1204 BitSet = RtlAreBitsSet(TlsBitmap, Index, 1);
1205 if (BitSet)
1206 {
1207 /* Tell the kernel to free the TLS cells */
1210 &Index,
1211 sizeof(DWORD));
1212 if (!NT_SUCCESS(Status))
1213 {
1216 return FALSE;
1217 }
1218
1219 /* Clear the bit */
1220 RtlClearBits(TlsBitmap, Index, 1);
1221 }
1222 else
1223 {
1224 /* Fail */
1227 return FALSE;
1228 }
1229
1230 /* Done! */
1232 return TRUE;
1233}
1234
1235/*
1236 * @implemented
1237 */
1238LPVOID
1239WINAPI
1241{
1242 PTEB Teb;
1243
1244 /* Get the TEB and clear the last error */
1245 Teb = NtCurrentTeb();
1246 Teb->LastErrorValue = 0;
1247
1248 /* Check for simple TLS index */
1250 {
1251 /* Return it */
1252 return Teb->TlsSlots[Index];
1253 }
1254
1255 /* Check for valid index */
1257 {
1258 /* Fail */
1260 return NULL;
1261 }
1262
1263 /* The expansion slots are allocated on demand, so check for it. */
1264 Teb->LastErrorValue = 0;
1265 if (!Teb->TlsExpansionSlots) return NULL;
1266
1267 /* Return the value from the expansion slots */
1269}
1270
1271/*
1272 * @implemented
1273 */
1274BOOL
1275WINAPI
1277 IN LPVOID Value)
1278{
1280 PTEB Teb = NtCurrentTeb();
1281
1282 /* Check for simple TLS index */
1284 {
1285 /* Return it */
1286 Teb->TlsSlots[Index] = Value;
1287 return TRUE;
1288 }
1289
1290 /* Check if this is an expansion slot */
1293 {
1294 /* Fail */
1296 return FALSE;
1297 }
1298
1299 /* Do we not have expansion slots? */
1300 if (!Teb->TlsExpansionSlots)
1301 {
1302 /* Get the PEB lock to see if we still need them */
1304 if (!Teb->TlsExpansionSlots)
1305 {
1306 /* Allocate them */
1307 Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(),
1310 sizeof(PVOID));
1311 if (!Teb->TlsExpansionSlots)
1312 {
1313 /* Fail */
1316 return FALSE;
1317 }
1318 }
1319
1320 /* Release the lock */
1322 }
1323
1324 /* Write the value */
1326
1327 /* Success */
1328 return TRUE;
1329}
1330
1331/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:243
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
@ BasepCreateThread
Definition: basemsg.h:22
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ULongToHandle(h)
Definition: basetsd.h:81
#define UNIMPLEMENTED
Definition: debug.h:115
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
NTSTATUS NTAPI CsrCreateRemoteThread(IN HANDLE hThread, IN PCLIENT_ID ClientId)
Definition: thredsup.c:569
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NTSTATUS
Definition: precomp.h:21
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
@ ThreadDescriptorTableEntry
Definition: compat.h:941
@ ThreadAmILastThread
Definition: compat.h:947
@ ThreadTimes
Definition: compat.h:936
@ ThreadIdealProcessor
Definition: compat.h:948
@ ThreadAffinityMask
Definition: compat.h:939
@ ThreadBasePriority
Definition: compat.h:938
@ ThreadBasicInformation
Definition: compat.h:935
@ ThreadPriorityBoost
Definition: compat.h:949
@ ThreadIsIoPending
Definition: compat.h:951
@ ThreadZeroTlsCell
Definition: compat.h:945
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
PPEB Peb
Definition: dllmain.c:27
BOOLEAN BaseRunningInServerProcess
Definition: dllmain.c:20
LONG WINAPI UnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
Definition: except.c:269
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
DWORD WINAPI QueueUserAPC(IN PAPCFUNC pfnAPC, IN HANDLE hThread, IN ULONG_PTR dwData)
Definition: thread.c:959
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1240
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
Definition: thread.c:700
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:159
VOID NTAPI BaseDispatchApc(IN PAPCFUNC ApcRoutine, IN PVOID Data, IN PACTIVATION_CONTEXT ActivationContext)
Definition: thread.c:92
DWORD_PTR WINAPI SetThreadAffinityMask(IN HANDLE hThread, IN DWORD_PTR dwThreadAffinityMask)
Definition: thread.c:662
DECLSPEC_NORETURN VOID WINAPI BaseThreadStartup(_In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_ LPVOID lpParameter)
Definition: thread.c:56
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:521
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1100
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
BOOL NTAPI GetThreadTimes(IN HANDLE hThread, OUT LPFILETIME lpCreationTime, OUT LPFILETIME lpExitTime, OUT LPFILETIME lpKernelTime, OUT LPFILETIME lpUserTime)
Definition: thread.c:469
LANGID WINAPI SetThreadUILanguage(IN LANGID LangId)
Definition: thread.c:937
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
BOOL WINAPI QueueUserWorkItem(IN LPTHREAD_START_ROUTINE Function, IN PVOID Context, IN ULONG Flags)
Definition: thread.c:1076
DWORD WINAPI GetProcessIdOfThread(IN HANDLE Thread)
Definition: thread.c:889
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1276
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:830
DWORD WINAPI SetThreadIdealProcessor(IN HANDLE hThread, IN DWORD dwIdealProcessor)
Definition: thread.c:866
PTEB GetTeb(VOID)
Definition: thread.c:438
NTSTATUS(NTAPI * PCSR_CREATE_REMOTE_THREAD)(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId)
Definition: thread.c:19
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:137
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
NTSTATUS WINAPI BasepNotifyCsrOfThread(IN HANDLE ThreadHandle, IN PCLIENT_ID ClientId)
Definition: thread.c:25
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1166
BOOL WINAPI SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
Definition: thread.c:1006
DWORD WINAPI GetThreadId(IN HANDLE Thread)
Definition: thread.c:913
BOOL WINAPI GetThreadPriorityBoost(IN HANDLE hThread, OUT PBOOL pDisablePriorityBoost)
Definition: thread.c:778
BOOL NTAPI SetThreadPriorityBoost(IN HANDLE hThread, IN BOOL bDisablePriorityBoost)
Definition: thread.c:804
int WINAPI GetThreadPriority(IN HANDLE hThread)
Definition: thread.c:739
BOOL WINAPI GetThreadIOPendingFlag(IN HANDLE hThread, OUT PBOOL lpIOIsPending)
Definition: thread.c:1047
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
NTSTATUS WINAPI BaseCreateStack(_In_ HANDLE hProcess, _In_opt_ SIZE_T StackCommit, _In_opt_ SIZE_T StackReserve, _Out_ PINITIAL_TEB InitialTeb)
Definition: utils.c:354
VOID WINAPI BaseInitializeContext(IN PCONTEXT Context, IN PVOID Parameter, IN PVOID StartAddress, IN PVOID StackAddress, IN ULONG ContextType)
Definition: utils.c:513
POBJECT_ATTRIBUTES WINAPI BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL, IN PUNICODE_STRING ObjectName)
Definition: utils.c:304
VOID WINAPI BaseFreeThreadStack(_In_ HANDLE hProcess, _In_ PINITIAL_TEB InitialTeb)
Definition: utils.c:495
#define __FUNCTION__
Definition: types.h:116
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
DWORD dwThreadId
Definition: fdebug.c:31
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:25
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define TLS_EXPANSION_SLOTS
Definition: pstypes.h:310
#define OBJ_INHERIT
Definition: winternl.h:225
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:82
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:72
NTSYSAPI NTSTATUS WINAPI NtYieldExecution(void)
Definition: thrdschd.c:744
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE)
Definition: actctx.c:5344
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI LdrShutdownThread(void)
Definition: ldrinit.c:1082
NTSYSAPI NTSTATUS WINAPI RtlQueryInformationActivationContext(ULONG, HANDLE, PVOID, ULONG, PVOID, SIZE_T, SIZE_T *)
Definition: actctx.c:5515
NTSYSAPI BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP, ULONG, ULONG)
#define HIGH_PRIORITY
#define NtCurrentTeb
USHORT LANGID
Definition: mui.h:9
struct _FILETIME * LPFILETIME
Definition: time.c:29
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
struct _ThreadInfo ThreadInfo
#define ASSERT(a)
Definition: mode.c:44
static HANDLE ULONG_PTR dwData
Definition: file.c:35
static BOOL bInheritHandle
Definition: pipe.c:82
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _In_
Definition: ms_sal.h:308
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:726
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:744
NTSYSAPI NTSTATUS NTAPI RtlQueueWorkItem(_In_ WORKERCALLBACKFUNC Function, _In_opt_ PVOID Context, _In_ ULONG Flags)
#define RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
Definition: rtltypes.h:101
#define RTL_ACTIVATE_ACTIVATION_CONTEXT_EX_FLAG_RELEASE_ON_STACK_DEALLOCATION
Definition: rtltypes.h:106
#define RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
Definition: rtltypes.h:116
VOID(NTAPI * WORKERCALLBACKFUNC)(_In_ PVOID Context)
Definition: rtltypes.h:513
HANDLE hThread
Definition: wizard.c:28
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1279
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI NTSTATUS NTAPI NtCreateThread(OUT PHANDLE phThread, IN ACCESS_MASK AccessMask, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE hProcess, OUT PCLIENT_ID pClientId, IN PCONTEXT pContext, OUT PSTACKINFO pStackInfo, IN BOOLEAN bSuspended)
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
Definition: debug.c:387
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:350
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2018
NTSTATUS NTAPI NtQueueApcThread(IN HANDLE ThreadHandle, IN PKNORMAL_ROUTINE ApcRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: state.c:600
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL)
Definition: state.c:352
NTSTATUS NTAPI NtOpenThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL)
Definition: thread.c:1013
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_NO_YIELD_PERFORMED
Definition: ntstatus.h:150
#define CONST
Definition: pedump.c:81
long LONG
Definition: pedump.c:60
PETHREAD LastThread
Definition: pinsup.c:109
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define ERROR_FATAL(...)
Definition: debug.h:238
NTSTATUS NTAPI CsrNewThread(VOID)
Definition: api.c:26
NTSTATUS NTAPI CsrClientCallServer(_Inout_ PCSR_API_MESSAGE ApiMessage, _Inout_opt_ PCSR_CAPTURE_BUFFER CaptureBuffer, _In_ CSR_API_NUMBER ApiNumber, _In_ ULONG DataLength)
Definition: connect.c:366
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, IN PVOID Context)
Definition: actctx.c:5934
NTSTATUS NTAPI RtlActivateActivationContextEx(ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie)
Definition: actctx.c:5368
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
Definition: actctx.c:6011
NTSTATUS NTAPI RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
Definition: actctx.c:5906
VOID NTAPI RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
Definition: actctx.c:5440
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
#define TLS_MINIMUM_AVAILABLE
Definition: ntddk_ex.h:236
NTSTATUS Status
Definition: basemsg.h:279
BASE_CREATE_THREAD CreateThreadRequest
Definition: basemsg.h:284
union _BASE_API_MESSAGE::@3533 Data
HANDLE ThreadHandle
Definition: basemsg.h:104
CLIENT_ID ClientId
Definition: basemsg.h:105
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
PVOID StackBase
Definition: pstypes.h:694
LARGE_INTEGER UserTime
Definition: winternl.h:1063
LARGE_INTEGER CreateTime
Definition: winternl.h:1060
LARGE_INTEGER KernelTime
Definition: winternl.h:1062
LARGE_INTEGER ExitTime
Definition: winternl.h:1061
Definition: compat.h:777
PVOID TlsBitmap
Definition: ntddk_ex.h:259
PRTL_BITMAP TlsExpansionBitmap
Definition: winternl.h:346
Definition: compat.h:836
PVOID ActivationContextStackPointer
Definition: compat.h:854
PVOID * TlsExpansionSlots
Definition: compat.h:894
ULONG GuaranteedStackBytes
Definition: winternl.h:279
PVOID TlsSlots[64]
Definition: compat.h:879
PPEB ProcessEnvironmentBlock
Definition: ntddk_ex.h:337
ULONG LastErrorValue
Definition: compat.h:843
KPRIORITY BasePriority
Definition: compat.h:932
KAFFINITY AffinityMask
Definition: compat.h:930
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define UNIMPLEMENTED_ONCE
Definition: typedefs.h:30
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFREQUEST _In_ NTSTATUS _In_ CCHAR PriorityBoost
Definition: wdfrequest.h:1016
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
BOOL WINAPI SwitchToThread(void)
Definition: thread.c:448
#define STACK_SIZE_PARAM_IS_A_RESERVATION
Definition: winbase.h:577
#define CREATE_SUSPENDED
Definition: winbase.h:178
#define THREAD_PRIORITY_TIME_CRITICAL
Definition: winbase.h:281
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:729
#define THREAD_PRIORITY_ERROR_RETURN
Definition: winbase.h:282
#define THREAD_PRIORITY_IDLE
Definition: winbase.h:278
BOOL * PBOOL
Definition: windef.h:161
#define WINAPI
Definition: msvc.h:6
#define TlsIndex
Definition: ws2_32p.h:277
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PVOID _Out_ PLARGE_INTEGER Cookie
Definition: cmfuncs.h:14
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151
#define NtCurrentThread()