1 /* $Id: thread.c,v 1.131 2004/08/09 22:15:01 gvg Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/thread.c
6 * PURPOSE: Thread managment
7 * PROGRAMMER: David Welch (welch@mcmail.com)
10 * 12/10/99: Phillip Susi: Thread priorities, and APC work
16 * All of the routines that manipulate the thread queue synchronize on
21 /* INCLUDES ****************************************************************/
23 #include <ddk/ntddk.h>
24 #include <internal/ke.h>
25 #include <internal/ob.h>
26 #include <internal/ps.h>
27 #include <internal/ob.h>
28 #include <internal/pool.h>
29 #include <ntos/minmax.h>
30 #include <internal/ldr.h>
31 #include <rosrtl/string.h>
34 #include <internal/debug.h>
36 /* TYPES *******************************************************************/
38 /* GLOBALS ******************************************************************/
40 POBJECT_TYPE EXPORTED PsThreadType
= NULL
;
42 KSPIN_LOCK PiThreadListLock
;
45 * PURPOSE: List of threads associated with each priority level
47 LIST_ENTRY PiThreadListHead
;
48 static LIST_ENTRY PriorityListHead
[MAXIMUM_PRIORITY
];
49 static ULONG PriorityListMask
= 0;
50 static BOOLEAN DoneInitYet
= FALSE
;
51 static PETHREAD IdleThreads
[MAXIMUM_PROCESSORS
];
52 ULONG PiNrThreads
= 0;
53 ULONG PiNrReadyThreads
= 0;
54 static HANDLE PiReaperThreadHandle
;
55 static KEVENT PiReaperThreadEvent
;
56 static BOOLEAN PiReaperThreadShouldTerminate
= FALSE
;
57 ULONG PiNrThreadsAwaitingReaping
= 0;
59 static GENERIC_MAPPING PiThreadMapping
= {THREAD_READ
,
64 /* FUNCTIONS ***************************************************************/
69 PKTHREAD STDCALL
KeGetCurrentThread(VOID
)
71 return(((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
);
77 HANDLE STDCALL
PsGetCurrentThreadId(VOID
)
79 return(PsGetCurrentThread()->Cid
.UniqueThread
);
87 PsGetThreadFreezeCount(
91 return Thread
->Tcb
.FreezeCount
;
99 PsGetThreadHardErrorsAreDisabled(
103 return Thread
->HardErrorsAreDisabled
;
115 return Thread
->Cid
.UniqueThread
;
127 return Thread
->ThreadsProcess
;
135 PsGetThreadProcessId(
139 return Thread
->Cid
.UniqueProcess
;
147 PsGetThreadSessionId(
151 return (HANDLE
)Thread
->ThreadsProcess
->SessionId
;
163 return Thread
->Tcb
.Teb
;
171 PsGetThreadWin32Thread(
175 return Thread
->Win32Thread
;
182 PsGetCurrentThreadPreviousMode (
186 return (KPROCESSOR_MODE
)PsGetCurrentThread()->Tcb
.PreviousMode
;
194 PsGetCurrentThreadStackBase (
198 return PsGetCurrentThread()->Tcb
.StackBase
;
206 PsGetCurrentThreadStackLimit (
210 return (PVOID
)PsGetCurrentThread()->Tcb
.StackLimit
;
217 PsIsThreadTerminating(IN PETHREAD Thread
)
219 return(Thread
->DeadThread
);
240 PsIsThreadImpersonating(
249 PsInsertIntoThreadList(KPRIORITY Priority
, PETHREAD Thread
)
251 assert(THREAD_STATE_READY
== Thread
->Tcb
.State
);
252 if (Priority
>= MAXIMUM_PRIORITY
|| Priority
< LOW_PRIORITY
)
254 DPRINT1("Invalid thread priority (%d)\n", Priority
);
257 InsertTailList(&PriorityListHead
[Priority
], &Thread
->Tcb
.QueueListEntry
);
258 PriorityListMask
|= (1 << Priority
);
262 static VOID
PsRemoveFromThreadList(PETHREAD Thread
)
264 assert(THREAD_STATE_READY
== Thread
->Tcb
.State
);
265 RemoveEntryList(&Thread
->Tcb
.QueueListEntry
);
266 if (IsListEmpty(&PriorityListHead
[(ULONG
)Thread
->Tcb
.Priority
]))
268 PriorityListMask
&= ~(1 << Thread
->Tcb
.Priority
);
274 VOID
PsDumpThreads(BOOLEAN IncludeSystem
)
276 PLIST_ENTRY current_entry
;
281 current_entry
= PiThreadListHead
.Flink
;
284 while (current_entry
!= &PiThreadListHead
)
289 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
290 Tcb
.ThreadListEntry
);
294 DbgPrint("Too many threads on list\n");
297 if (IncludeSystem
|| current
->ThreadsProcess
->UniqueProcessId
>= 6)
299 DbgPrint("current->Tcb.State %d PID.TID %d.%d Name %.8s Stack: \n",
301 current
->ThreadsProcess
->UniqueProcessId
,
302 current
->Cid
.UniqueThread
,
303 current
->ThreadsProcess
->ImageFileName
);
304 if (current
->Tcb
.State
== THREAD_STATE_READY
||
305 current
->Tcb
.State
== THREAD_STATE_SUSPENDED
||
306 current
->Tcb
.State
== THREAD_STATE_BLOCKED
)
308 Esp
= (PULONG
)current
->Tcb
.KernelStack
;
309 Ebp
= (PULONG
)Esp
[3];
310 DbgPrint("Ebp 0x%.8X\n", Ebp
);
312 while (Ebp
!= 0 && Ebp
>= (PULONG
)current
->Tcb
.StackLimit
)
314 DbgPrint("%.8X %.8X%s", Ebp
[0], Ebp
[1],
315 (i
% 8) == 7 ? "\n" : " ");
316 Ebp
= (PULONG
)Ebp
[0];
325 current_entry
= current_entry
->Flink
;
329 static PETHREAD
PsScanThreadList (KPRIORITY Priority
, ULONG Affinity
)
331 PLIST_ENTRY current_entry
;
335 Mask
= (1 << Priority
);
336 if (PriorityListMask
& Mask
)
338 current_entry
= PriorityListHead
[Priority
].Flink
;
339 while (current_entry
!= &PriorityListHead
[Priority
])
341 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
343 if (current
->Tcb
.State
!= THREAD_STATE_READY
)
345 DPRINT1("%d/%d\n", current
->Cid
.UniqueThread
, current
->Tcb
.State
);
347 assert(current
->Tcb
.State
== THREAD_STATE_READY
);
348 DPRINT("current->Tcb.UserAffinity %x Affinity %x PID %d %d\n",
349 current
->Tcb
.UserAffinity
, Affinity
, current
->Cid
.UniqueThread
,
351 if (current
->Tcb
.UserAffinity
& Affinity
)
353 PsRemoveFromThreadList(current
);
356 current_entry
= current_entry
->Flink
;
363 PiWakeupReaperThread(VOID
)
365 KeSetEvent(&PiReaperThreadEvent
, 0, FALSE
);
369 PiReaperThreadMain(PVOID Ignored
)
373 KeWaitForSingleObject(&PiReaperThreadEvent
,
378 if (PiReaperThreadShouldTerminate
)
380 PsTerminateSystemThread(0);
386 VOID
PsDispatchThreadNoLock (ULONG NewThreadStatus
)
388 KPRIORITY CurrentPriority
;
391 PKTHREAD KCurrentThread
= ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
;
392 PETHREAD CurrentThread
= CONTAINING_RECORD(KCurrentThread
, ETHREAD
, Tcb
);
394 DPRINT("PsDispatchThread() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(),
395 CurrentThread
->Cid
.UniqueThread
, NewThreadStatus
, CurrentThread
->Tcb
.State
);
397 CurrentThread
->Tcb
.State
= (UCHAR
)NewThreadStatus
;
398 if (CurrentThread
->Tcb
.State
== THREAD_STATE_READY
)
400 PsInsertIntoThreadList(CurrentThread
->Tcb
.Priority
,
403 if (CurrentThread
->Tcb
.State
== THREAD_STATE_TERMINATED_1
)
405 PiNrThreadsAwaitingReaping
++;
408 Affinity
= 1 << KeGetCurrentProcessorNumber();
409 for (CurrentPriority
= HIGH_PRIORITY
;
410 CurrentPriority
>= LOW_PRIORITY
;
413 Candidate
= PsScanThreadList(CurrentPriority
, Affinity
);
414 if (Candidate
== CurrentThread
)
416 Candidate
->Tcb
.State
= THREAD_STATE_RUNNING
;
417 KeReleaseSpinLockFromDpcLevel(&PiThreadListLock
);
420 if (Candidate
!= NULL
)
424 DPRINT("Scheduling %x(%d)\n",Candidate
, CurrentPriority
);
426 Candidate
->Tcb
.State
= THREAD_STATE_RUNNING
;
428 OldThread
= CurrentThread
;
429 CurrentThread
= Candidate
;
432 * This code is moved to the end of KiArchContextSwitch.
433 * It should be execute after the context switch.
435 KeReleaseSpinLockFromDpcLevel(&PiThreadListLock
);
436 if (PiNrThreadsAwaitingReaping
> 0)
438 PiWakeupReaperThread();
441 KiArchContextSwitch(&CurrentThread
->Tcb
, &OldThread
->Tcb
);
445 CPRINT("CRITICAL: No threads are ready\n");
450 PsDispatchThread(ULONG NewThreadStatus
)
459 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
463 ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
->WaitIrql
= oldIrql
;
464 PsDispatchThreadNoLock(NewThreadStatus
);
465 KeLowerIrql(oldIrql
);
469 PsUnblockThread(PETHREAD Thread
, PNTSTATUS WaitStatus
)
473 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
474 if (THREAD_STATE_TERMINATED_1
== Thread
->Tcb
.State
||
475 THREAD_STATE_TERMINATED_2
== Thread
->Tcb
.State
)
477 DPRINT("Can't unblock thread %d because it's terminating\n",
478 Thread
->Cid
.UniqueThread
);
480 else if (THREAD_STATE_READY
== Thread
->Tcb
.State
||
481 THREAD_STATE_RUNNING
== Thread
->Tcb
.State
)
483 DPRINT("Can't unblock thread %d because it's ready or running\n",
484 Thread
->Cid
.UniqueThread
);
488 if (WaitStatus
!= NULL
)
490 Thread
->Tcb
.WaitStatus
= *WaitStatus
;
492 Thread
->Tcb
.State
= THREAD_STATE_READY
;
493 PsInsertIntoThreadList(Thread
->Tcb
.Priority
, Thread
);
495 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
499 PsBlockThread(PNTSTATUS Status
, UCHAR Alertable
, ULONG WaitMode
,
500 BOOLEAN DispatcherLock
, KIRQL WaitIrql
, UCHAR WaitReason
)
505 PKWAIT_BLOCK WaitBlock
;
507 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
509 KThread
= ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
;
510 Thread
= CONTAINING_RECORD (KThread
, ETHREAD
, Tcb
);
511 if (KThread
->ApcState
.KernelApcPending
)
515 KeAcquireDispatcherDatabaseLockAtDpcLevel();
517 WaitBlock
= (PKWAIT_BLOCK
)Thread
->Tcb
.WaitBlockList
;
520 RemoveEntryList (&WaitBlock
->WaitListEntry
);
521 WaitBlock
= WaitBlock
->NextWaitBlock
;
523 Thread
->Tcb
.WaitBlockList
= NULL
;
524 KeReleaseDispatcherDatabaseLockFromDpcLevel();
525 PsDispatchThreadNoLock (THREAD_STATE_READY
);
528 *Status
= STATUS_KERNEL_APC
;
535 KeReleaseDispatcherDatabaseLockFromDpcLevel();
537 Thread
->Tcb
.Alertable
= Alertable
;
538 Thread
->Tcb
.WaitMode
= (UCHAR
)WaitMode
;
539 Thread
->Tcb
.WaitIrql
= WaitIrql
;
540 Thread
->Tcb
.WaitReason
= WaitReason
;
541 PsDispatchThreadNoLock(THREAD_STATE_BLOCKED
);
545 *Status
= Thread
->Tcb
.WaitStatus
;
548 KeLowerIrql(WaitIrql
);
552 PsFreezeAllThreads(PEPROCESS Process
)
554 * Used by the debugging code to freeze all the process's threads
555 * while the debugger is examining their state.
559 PLIST_ENTRY current_entry
;
562 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
564 current_entry
= Process
->ThreadListHead
.Flink
;
565 while (current_entry
!= &Process
->ThreadListHead
)
567 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
568 Tcb
.ProcessThreadListEntry
);
571 * We have to be careful here, we can't just set the freeze the
572 * thread inside kernel mode since it may be holding a lock.
575 current_entry
= current_entry
->Flink
;
578 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
582 PsEnumThreadsByProcess(PEPROCESS Process
)
585 PLIST_ENTRY current_entry
;
588 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
590 current_entry
= Process
->ThreadListHead
.Flink
;
591 while (current_entry
!= &Process
->ThreadListHead
)
594 current_entry
= current_entry
->Flink
;
597 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
606 PsRemoveCreateThreadNotifyRoutine (
607 IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
611 return STATUS_NOT_IMPLEMENTED
;
619 PsSetLegoNotifyRoutine(
620 PVOID LegoNotifyRoutine
632 PsSetThreadHardErrorsAreDisabled(
634 BOOLEAN HardErrorsAreDisabled
637 Thread
->HardErrorsAreDisabled
= HardErrorsAreDisabled
;
645 PsSetThreadWin32Thread(
650 Thread
->Win32Thread
= Win32Thread
;
654 PsApplicationProcessorInit(VOID
)
656 ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
=
657 (PVOID
)IdleThreads
[KeGetCurrentProcessorNumber()];
661 PsPrepareForApplicationProcessorInit(ULONG Id
)
664 HANDLE IdleThreadHandle
;
666 PsInitializeThread(NULL
,
672 IdleThread
->Tcb
.State
= THREAD_STATE_RUNNING
;
673 IdleThread
->Tcb
.FreezeCount
= 0;
674 IdleThread
->Tcb
.UserAffinity
= 1 << Id
;
675 IdleThread
->Tcb
.Priority
= LOW_PRIORITY
;
676 IdleThreads
[Id
] = IdleThread
;
678 NtClose(IdleThreadHandle
);
679 DPRINT("IdleThread for Processor %d has PID %d\n",
680 Id
, IdleThread
->Cid
.UniqueThread
);
684 PsInitThreadManagment(VOID
)
686 * FUNCTION: Initialize thread managment
689 PETHREAD FirstThread
;
691 HANDLE FirstThreadHandle
;
694 KeInitializeSpinLock(&PiThreadListLock
);
695 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
697 InitializeListHead(&PriorityListHead
[i
]);
700 InitializeListHead(&PiThreadListHead
);
702 PsThreadType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
704 PsThreadType
->Tag
= TAG('T', 'H', 'R', 'T');
705 PsThreadType
->TotalObjects
= 0;
706 PsThreadType
->TotalHandles
= 0;
707 PsThreadType
->MaxObjects
= 0;
708 PsThreadType
->MaxHandles
= 0;
709 PsThreadType
->PagedPoolCharge
= 0;
710 PsThreadType
->NonpagedPoolCharge
= sizeof(ETHREAD
);
711 PsThreadType
->Mapping
= &PiThreadMapping
;
712 PsThreadType
->Dump
= NULL
;
713 PsThreadType
->Open
= NULL
;
714 PsThreadType
->Close
= NULL
;
715 PsThreadType
->Delete
= PiDeleteThread
;
716 PsThreadType
->Parse
= NULL
;
717 PsThreadType
->Security
= NULL
;
718 PsThreadType
->QueryName
= NULL
;
719 PsThreadType
->OkayToClose
= NULL
;
720 PsThreadType
->Create
= NULL
;
721 PsThreadType
->DuplicationNotify
= NULL
;
723 RtlRosInitUnicodeStringFromLiteral(&PsThreadType
->TypeName
, L
"Thread");
725 ObpCreateTypeObject(PsThreadType
);
727 PsInitializeThread(NULL
,&FirstThread
,&FirstThreadHandle
,
728 THREAD_ALL_ACCESS
,NULL
, TRUE
);
729 FirstThread
->Tcb
.State
= THREAD_STATE_RUNNING
;
730 FirstThread
->Tcb
.FreezeCount
= 0;
731 ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
= (PVOID
)FirstThread
;
732 NtClose(FirstThreadHandle
);
734 DPRINT("FirstThread %x\n",FirstThread
);
739 * Create the reaper thread
741 KeInitializeEvent(&PiReaperThreadEvent
, SynchronizationEvent
, FALSE
);
742 Status
= PsCreateSystemThread(&PiReaperThreadHandle
,
749 if (!NT_SUCCESS(Status
))
751 DPRINT1("PS: Failed to create reaper thread.\n");
760 KeSetBasePriorityThread (PKTHREAD Thread
,
763 * Sets thread's base priority relative to the process' base priority
764 * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
772 else if (Increment
> 2)
776 Priority
= ((PETHREAD
)Thread
)->ThreadsProcess
->Pcb
.BasePriority
+ Increment
;
777 if (Priority
< LOW_PRIORITY
)
779 Priority
= LOW_PRIORITY
;
781 else if (Priority
>= MAXIMUM_PRIORITY
)
783 Thread
->BasePriority
= HIGH_PRIORITY
;
785 KeSetPriorityThread(Thread
, Priority
);
794 KeSetPriorityThread (PKTHREAD Thread
, KPRIORITY Priority
)
796 KPRIORITY OldPriority
;
798 PKTHREAD CurrentThread
;
801 if (Priority
< LOW_PRIORITY
|| Priority
>= MAXIMUM_PRIORITY
)
806 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
808 OldPriority
= Thread
->Priority
;
809 Thread
->BasePriority
= Thread
->Priority
= (CHAR
)Priority
;
811 if (OldPriority
!= Priority
)
813 if (Thread
->State
== THREAD_STATE_READY
)
815 PsRemoveFromThreadList((PETHREAD
)Thread
);
816 PsInsertIntoThreadList(Priority
, (PETHREAD
)Thread
);
817 CurrentThread
= ((PIKPCR
) KeGetCurrentKPCR())->CurrentThread
;
818 if (CurrentThread
->Priority
< Priority
)
820 PsDispatchThreadNoLock(THREAD_STATE_READY
);
821 KeLowerIrql(oldIrql
);
822 return (OldPriority
);
825 else if (Thread
->State
== THREAD_STATE_RUNNING
)
827 if (Priority
< OldPriority
)
829 /* Check for threads with a higher priority */
830 Mask
= ~((1 << (Priority
+ 1)) - 1);
831 if (PriorityListMask
& Mask
)
833 PsDispatchThreadNoLock(THREAD_STATE_READY
);
834 KeLowerIrql(oldIrql
);
835 return (OldPriority
);
840 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
848 KeSetAffinityThread(PKTHREAD Thread
,
851 * Sets thread's affinity
854 DPRINT1("KeSetAffinityThread() is a stub returning STATUS_SUCCESS");
855 return STATUS_SUCCESS
; // FIXME: Use function below
856 //return ZwSetInformationThread(handle, ThreadAffinityMask,<pointer to affinity mask>,sizeof(KAFFINITY));
861 NtAlertResumeThread(IN HANDLE ThreadHandle
,
862 OUT PULONG SuspendCount
)
865 return(STATUS_NOT_IMPLEMENTED
);
871 NtAlertThread (IN HANDLE ThreadHandle
)
875 NTSTATUS ThreadStatus
;
877 Status
= ObReferenceObjectByHandle(ThreadHandle
,
878 THREAD_SUSPEND_RESUME
,
883 if (Status
!= STATUS_SUCCESS
)
888 ThreadStatus
= STATUS_ALERTED
;
889 (VOID
)PsUnblockThread(Thread
, &ThreadStatus
);
891 ObDereferenceObject(Thread
);
892 return(STATUS_SUCCESS
);
895 /**********************************************************************
901 NtOpenThread(OUT PHANDLE ThreadHandle
,
902 IN ACCESS_MASK DesiredAccess
,
903 IN POBJECT_ATTRIBUTES ObjectAttributes
,
904 IN PCLIENT_ID ClientId
)
906 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
908 if((NULL
!= ThreadHandle
)&&(NULL
!= ObjectAttributes
))
910 PETHREAD EThread
= NULL
;
913 && (ClientId
->UniqueThread
))
915 // It is an error to specify both
916 // ObjectAttributes.ObjectName
918 if((ObjectAttributes
)
919 && (ObjectAttributes
->ObjectName
)
920 && (0 < ObjectAttributes
->ObjectName
->Length
))
922 return(STATUS_INVALID_PARAMETER_MIX
);
925 Status
= PsLookupThreadByThreadId(ClientId
->UniqueThread
,
928 else if((ObjectAttributes
)
929 && (ObjectAttributes
->ObjectName
)
930 && (0 < ObjectAttributes
->ObjectName
->Length
))
932 // Three Ob attributes are forbidden
933 if(!(ObjectAttributes
->Attributes
&
934 (OBJ_PERMANENT
| OBJ_EXCLUSIVE
| OBJ_OPENIF
)))
936 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
937 ObjectAttributes
->Attributes
,
946 // EThread may be OK...
947 if(STATUS_SUCCESS
== Status
)
949 Status
= ObCreateHandle(PsGetCurrentProcess(),
954 ObDereferenceObject(EThread
);
961 NtYieldExecution(VOID
)
963 PsDispatchThread(THREAD_STATE_READY
);
964 return(STATUS_SUCCESS
);
972 PsLookupProcessThreadByCid(IN PCLIENT_ID Cid
,
973 OUT PEPROCESS
*Process OPTIONAL
,
974 OUT PETHREAD
*Thread
)
977 PLIST_ENTRY current_entry
;
980 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
982 current_entry
= PiThreadListHead
.Flink
;
983 while (current_entry
!= &PiThreadListHead
)
985 current
= CONTAINING_RECORD(current_entry
,
987 Tcb
.ThreadListEntry
);
988 if (current
->Cid
.UniqueThread
== Cid
->UniqueThread
&&
989 current
->Cid
.UniqueProcess
== Cid
->UniqueProcess
)
993 *Process
= current
->ThreadsProcess
;
994 ObReferenceObject(current
->ThreadsProcess
);
998 ObReferenceObject(current
);
1000 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
1001 return(STATUS_SUCCESS
);
1004 current_entry
= current_entry
->Flink
;
1007 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
1009 return(STATUS_INVALID_PARAMETER
);
1017 PsLookupThreadByThreadId(IN PVOID ThreadId
,
1018 OUT PETHREAD
*Thread
)
1021 PLIST_ENTRY current_entry
;
1024 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
1026 current_entry
= PiThreadListHead
.Flink
;
1027 while (current_entry
!= &PiThreadListHead
)
1029 current
= CONTAINING_RECORD(current_entry
,
1031 Tcb
.ThreadListEntry
);
1032 if (current
->Cid
.UniqueThread
== (HANDLE
)ThreadId
)
1034 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
1036 ObReferenceObject(current
);
1037 return(STATUS_SUCCESS
);
1040 current_entry
= current_entry
->Flink
;
1043 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
1045 return(STATUS_INVALID_PARAMETER
);
1053 NtOpenThreadTokenEx(
1054 IN HANDLE ThreadHandle
,
1055 IN ACCESS_MASK DesiredAccess
,
1056 IN BOOLEAN OpenAsSelf
,
1057 IN ULONG HandleAttributes
,
1058 OUT PHANDLE TokenHandle
1062 return STATUS_NOT_IMPLEMENTED
;