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 ****************************************************************/
25 #include <internal/debug.h>
27 /* TYPES *******************************************************************/
29 /* GLOBALS ******************************************************************/
31 extern LIST_ENTRY PsProcessListHead
;
33 POBJECT_TYPE EXPORTED PsThreadType
= NULL
;
35 LONG PiNrThreadsAwaitingReaping
= 0;
38 * PURPOSE: List of threads associated with each priority level
40 static LIST_ENTRY PriorityListHead
[MAXIMUM_PRIORITY
];
41 static ULONG PriorityListMask
= 0;
42 static BOOLEAN DoneInitYet
= FALSE
;
43 static KEVENT PiReaperThreadEvent
;
44 static BOOLEAN PiReaperThreadShouldTerminate
= FALSE
;
46 static GENERIC_MAPPING PiThreadMapping
= {STANDARD_RIGHTS_READ
| THREAD_GET_CONTEXT
| THREAD_QUERY_INFORMATION
,
47 STANDARD_RIGHTS_WRITE
| THREAD_TERMINATE
| THREAD_SUSPEND_RESUME
| THREAD_ALERT
|
48 THREAD_SET_INFORMATION
| THREAD_SET_CONTEXT
,
49 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
52 /* FUNCTIONS ***************************************************************/
57 PKTHREAD STDCALL
KeGetCurrentThread(VOID
)
62 Ke386SaveFlags(Flags
);
63 Ke386DisableInterrupts();
64 Thread
= KeGetCurrentKPCR()->PrcbData
.CurrentThread
;
65 Ke386RestoreFlags(Flags
);
68 return(KeGetCurrentKPCR()->PrcbData
.CurrentThread
);
75 HANDLE STDCALL
PsGetCurrentThreadId(VOID
)
77 return(PsGetCurrentThread()->Cid
.UniqueThread
);
85 PsGetThreadFreezeCount(
89 return Thread
->Tcb
.FreezeCount
;
97 PsGetThreadHardErrorsAreDisabled(
101 return Thread
->HardErrorsAreDisabled
;
113 return Thread
->Cid
.UniqueThread
;
125 return Thread
->ThreadsProcess
;
133 PsGetThreadProcessId(
137 return Thread
->Cid
.UniqueProcess
;
145 PsGetThreadSessionId(
149 return (HANDLE
)Thread
->ThreadsProcess
->SessionId
;
161 return Thread
->Tcb
.Teb
;
169 PsGetThreadWin32Thread(
173 return Thread
->Tcb
.Win32Thread
;
181 PsGetCurrentThreadPreviousMode (
185 return (KPROCESSOR_MODE
)PsGetCurrentThread()->Tcb
.PreviousMode
;
193 PsGetCurrentThreadStackBase (
197 return PsGetCurrentThread()->Tcb
.StackBase
;
205 PsGetCurrentThreadStackLimit (
209 return (PVOID
)PsGetCurrentThread()->Tcb
.StackLimit
;
216 PsIsThreadTerminating(IN PETHREAD Thread
)
218 return (Thread
->HasTerminated
? TRUE
: FALSE
);
239 PsIsThreadImpersonating(
243 return Thread
->ActiveImpersonationInfo
;
247 KiRequestReschedule(CCHAR Processor
)
251 Pcr
= (PKPCR
)(KPCR_BASE
+ Processor
* PAGE_SIZE
);
252 Pcr
->PrcbData
.QuantumEnd
= TRUE
;
253 KiIpiSendRequest(1 << Processor
, IPI_REQUEST_DPC
);
257 PsInsertIntoThreadList(KPRIORITY Priority
, PETHREAD Thread
)
259 ASSERT(THREAD_STATE_READY
== Thread
->Tcb
.State
);
260 ASSERT(Thread
->Tcb
.Priority
== Priority
);
261 if (Priority
>= MAXIMUM_PRIORITY
|| Priority
< LOW_PRIORITY
)
263 DPRINT1("Invalid thread priority (%d)\n", Priority
);
266 InsertTailList(&PriorityListHead
[Priority
], &Thread
->Tcb
.QueueListEntry
);
267 PriorityListMask
|= (1 << Priority
);
270 static VOID
PsRemoveFromThreadList(PETHREAD Thread
)
272 ASSERT(THREAD_STATE_READY
== Thread
->Tcb
.State
);
273 RemoveEntryList(&Thread
->Tcb
.QueueListEntry
);
274 if (IsListEmpty(&PriorityListHead
[(ULONG
)Thread
->Tcb
.Priority
]))
276 PriorityListMask
&= ~(1 << Thread
->Tcb
.Priority
);
281 VOID
PsDumpThreads(BOOLEAN IncludeSystem
)
283 PLIST_ENTRY AThread
, AProcess
;
288 AProcess
= PsProcessListHead
.Flink
;
289 while(AProcess
!= &PsProcessListHead
)
291 Process
= CONTAINING_RECORD(AProcess
, EPROCESS
, ProcessListEntry
);
292 /* FIXME - skip suspended, ... processes? */
293 if((Process
!= PsInitialSystemProcess
) ||
294 (Process
== PsInitialSystemProcess
&& IncludeSystem
))
296 AThread
= Process
->ThreadListHead
.Flink
;
297 while(AThread
!= &Process
->ThreadListHead
)
299 Thread
= CONTAINING_RECORD(AThread
, ETHREAD
, ThreadListEntry
);
302 DbgPrint("Thread->Tcb.State %d PID.TID %d.%d Name %.8s Stack: \n",
304 Thread
->ThreadsProcess
->UniqueProcessId
,
305 Thread
->Cid
.UniqueThread
,
306 Thread
->ThreadsProcess
->ImageFileName
);
307 if(Thread
->Tcb
.State
== THREAD_STATE_READY
||
308 Thread
->Tcb
.State
== THREAD_STATE_SUSPENDED
||
309 Thread
->Tcb
.State
== THREAD_STATE_BLOCKED
)
312 PULONG Esp
= (PULONG
)Thread
->Tcb
.KernelStack
;
313 PULONG Ebp
= (PULONG
)Esp
[4];
314 DbgPrint("Ebp 0x%.8X\n", Ebp
);
315 while(Ebp
!= 0 && Ebp
>= (PULONG
)Thread
->Tcb
.StackLimit
)
317 DbgPrint("%.8X %.8X%s", Ebp
[0], Ebp
[1], (i
% 8) == 7 ? "\n" : " ");
318 Ebp
= (PULONG
)Ebp
[0];
326 AThread
= AThread
->Flink
;
329 AProcess
= AProcess
->Flink
;
333 static PETHREAD
PsScanThreadList(KPRIORITY Priority
, ULONG Affinity
)
335 PLIST_ENTRY current_entry
;
339 Mask
= (1 << Priority
);
340 if (PriorityListMask
& Mask
)
342 current_entry
= PriorityListHead
[Priority
].Flink
;
343 while (current_entry
!= &PriorityListHead
[Priority
])
345 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
347 if (current
->Tcb
.State
!= THREAD_STATE_READY
)
349 DPRINT1("%d/%d\n", current
->Cid
.UniqueThread
, current
->Tcb
.State
);
351 ASSERT(current
->Tcb
.State
== THREAD_STATE_READY
);
352 DPRINT("current->Tcb.Affinity %x Affinity %x PID %d %d\n",
353 current
->Tcb
.Affinity
, Affinity
, current
->Cid
.UniqueThread
,
355 if (current
->Tcb
.Affinity
& Affinity
)
357 PsRemoveFromThreadList(current
);
360 current_entry
= current_entry
->Flink
;
367 PiWakeupReaperThread(VOID
)
369 KeSetEvent(&PiReaperThreadEvent
, 0, FALSE
);
373 PiReaperThreadMain(PVOID Ignored
)
377 KeWaitForSingleObject(&PiReaperThreadEvent
,
382 if (PiReaperThreadShouldTerminate
)
384 PsTerminateSystemThread(0);
390 VOID
PsDispatchThreadNoLock (ULONG NewThreadStatus
)
392 KPRIORITY CurrentPriority
;
395 PKTHREAD KCurrentThread
= KeGetCurrentThread();
396 PETHREAD CurrentThread
= CONTAINING_RECORD(KCurrentThread
, ETHREAD
, Tcb
);
398 DPRINT("PsDispatchThread() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(),
399 CurrentThread
->Cid
.UniqueThread
, NewThreadStatus
, CurrentThread
->Tcb
.State
);
401 CurrentThread
->Tcb
.State
= (UCHAR
)NewThreadStatus
;
402 switch(NewThreadStatus
)
404 case THREAD_STATE_READY
:
405 PsInsertIntoThreadList(CurrentThread
->Tcb
.Priority
,
408 case THREAD_STATE_TERMINATED_1
:
409 PsQueueThreadReap(CurrentThread
);
413 Affinity
= 1 << KeGetCurrentProcessorNumber();
414 for (CurrentPriority
= HIGH_PRIORITY
;
415 CurrentPriority
>= LOW_PRIORITY
;
418 Candidate
= PsScanThreadList(CurrentPriority
, Affinity
);
419 if (Candidate
== CurrentThread
)
421 Candidate
->Tcb
.State
= THREAD_STATE_RUNNING
;
422 KeReleaseDispatcherDatabaseLockFromDpcLevel();
425 if (Candidate
!= NULL
)
429 DPRINT("Scheduling %x(%d)\n",Candidate
, CurrentPriority
);
431 Candidate
->Tcb
.State
= THREAD_STATE_RUNNING
;
433 OldThread
= CurrentThread
;
434 CurrentThread
= Candidate
;
436 MmUpdatePageDir(PsGetCurrentProcess(),(PVOID
)CurrentThread
->ThreadsProcess
, sizeof(EPROCESS
));
438 KiArchContextSwitch(&CurrentThread
->Tcb
, &OldThread
->Tcb
);
442 CPRINT("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber());
448 PsDispatchThread(ULONG NewThreadStatus
)
452 if (!DoneInitYet
|| KeGetCurrentKPCR()->PrcbData
.IdleThread
== NULL
)
456 oldIrql
= KeAcquireDispatcherDatabaseLock();
457 PsDispatchThreadNoLock(NewThreadStatus
);
458 KeLowerIrql(oldIrql
);
462 PsUnblockThread(PETHREAD Thread
, PNTSTATUS WaitStatus
)
464 if (THREAD_STATE_TERMINATED_1
== Thread
->Tcb
.State
||
465 THREAD_STATE_TERMINATED_2
== Thread
->Tcb
.State
)
467 DPRINT("Can't unblock thread %d because it's terminating\n",
468 Thread
->Cid
.UniqueThread
);
470 else if (THREAD_STATE_READY
== Thread
->Tcb
.State
||
471 THREAD_STATE_RUNNING
== Thread
->Tcb
.State
)
473 DPRINT("Can't unblock thread %d because it's ready or running\n",
474 Thread
->Cid
.UniqueThread
);
478 if (WaitStatus
!= NULL
)
480 Thread
->Tcb
.WaitStatus
= *WaitStatus
;
482 Thread
->Tcb
.State
= THREAD_STATE_READY
;
483 PsInsertIntoThreadList(Thread
->Tcb
.Priority
, Thread
);
488 PsBlockThread(PNTSTATUS Status
, UCHAR Alertable
, ULONG WaitMode
,
489 BOOLEAN DispatcherLock
, KIRQL WaitIrql
, UCHAR WaitReason
)
494 PKWAIT_BLOCK WaitBlock
;
498 oldIrql
= KeAcquireDispatcherDatabaseLock();
501 KThread
= KeGetCurrentThread();
502 Thread
= CONTAINING_RECORD (KThread
, ETHREAD
, Tcb
);
503 if (KThread
->ApcState
.KernelApcPending
)
505 WaitBlock
= (PKWAIT_BLOCK
)Thread
->Tcb
.WaitBlockList
;
508 RemoveEntryList (&WaitBlock
->WaitListEntry
);
509 WaitBlock
= WaitBlock
->NextWaitBlock
;
511 Thread
->Tcb
.WaitBlockList
= NULL
;
512 PsDispatchThreadNoLock (THREAD_STATE_READY
);
515 *Status
= STATUS_KERNEL_APC
;
520 Thread
->Tcb
.Alertable
= Alertable
;
521 Thread
->Tcb
.WaitMode
= (UCHAR
)WaitMode
;
522 Thread
->Tcb
.WaitReason
= WaitReason
;
523 PsDispatchThreadNoLock(THREAD_STATE_BLOCKED
);
527 *Status
= Thread
->Tcb
.WaitStatus
;
530 KeLowerIrql(WaitIrql
);
534 PsFreezeAllThreads(PEPROCESS Process
)
536 * Used by the debugging code to freeze all the process's threads
537 * while the debugger is examining their state.
541 PLIST_ENTRY current_entry
;
544 oldIrql
= KeAcquireDispatcherDatabaseLock();
545 current_entry
= Process
->ThreadListHead
.Flink
;
546 while (current_entry
!= &Process
->ThreadListHead
)
548 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
552 * We have to be careful here, we can't just set the freeze the
553 * thread inside kernel mode since it may be holding a lock.
556 current_entry
= current_entry
->Flink
;
559 KeReleaseDispatcherDatabaseLock(oldIrql
);
563 PsEnumThreadsByProcess(PEPROCESS Process
)
566 PLIST_ENTRY current_entry
;
569 oldIrql
= KeAcquireDispatcherDatabaseLock();
571 current_entry
= Process
->ThreadListHead
.Flink
;
572 while (current_entry
!= &Process
->ThreadListHead
)
575 current_entry
= current_entry
->Flink
;
578 KeReleaseDispatcherDatabaseLock(oldIrql
);
587 PsRemoveCreateThreadNotifyRoutine (
588 IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
592 return STATUS_NOT_IMPLEMENTED
;
600 PsSetLegoNotifyRoutine(
601 PVOID LegoNotifyRoutine
613 PsSetThreadHardErrorsAreDisabled(
615 BOOLEAN HardErrorsAreDisabled
618 Thread
->HardErrorsAreDisabled
= HardErrorsAreDisabled
;
626 PsSetThreadWin32Thread(
631 Thread
->Tcb
.Win32Thread
= Win32Thread
;
635 PsApplicationProcessorInit(VOID
)
640 PsPrepareForApplicationProcessorInit(ULONG Id
)
643 HANDLE IdleThreadHandle
;
644 PKPCR Pcr
= (PKPCR
)((ULONG_PTR
)KPCR_BASE
+ Id
* PAGE_SIZE
);
646 PsInitializeThread(NULL
,
652 IdleThread
->Tcb
.State
= THREAD_STATE_RUNNING
;
653 IdleThread
->Tcb
.FreezeCount
= 0;
654 IdleThread
->Tcb
.Affinity
= 1 << Id
;
655 IdleThread
->Tcb
.UserAffinity
= 1 << Id
;
656 IdleThread
->Tcb
.Priority
= LOW_PRIORITY
;
657 IdleThread
->Tcb
.BasePriority
= LOW_PRIORITY
;
658 Pcr
->PrcbData
.IdleThread
= &IdleThread
->Tcb
;
659 Pcr
->PrcbData
.CurrentThread
= &IdleThread
->Tcb
;
660 NtClose(IdleThreadHandle
);
661 DPRINT("IdleThread for Processor %d has PID %d\n",
662 Id
, IdleThread
->Cid
.UniqueThread
);
666 PsInitThreadManagment(VOID
)
668 * FUNCTION: Initialize thread managment
671 HANDLE PiReaperThreadHandle
;
672 PETHREAD FirstThread
;
674 HANDLE FirstThreadHandle
;
677 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
679 InitializeListHead(&PriorityListHead
[i
]);
682 PsThreadType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
684 PsThreadType
->Tag
= TAG('T', 'H', 'R', 'T');
685 PsThreadType
->TotalObjects
= 0;
686 PsThreadType
->TotalHandles
= 0;
687 PsThreadType
->MaxObjects
= 0;
688 PsThreadType
->MaxHandles
= 0;
689 PsThreadType
->PagedPoolCharge
= 0;
690 PsThreadType
->NonpagedPoolCharge
= sizeof(ETHREAD
);
691 PsThreadType
->Mapping
= &PiThreadMapping
;
692 PsThreadType
->Dump
= NULL
;
693 PsThreadType
->Open
= NULL
;
694 PsThreadType
->Close
= NULL
;
695 PsThreadType
->Delete
= PiDeleteThread
;
696 PsThreadType
->Parse
= NULL
;
697 PsThreadType
->Security
= NULL
;
698 PsThreadType
->QueryName
= NULL
;
699 PsThreadType
->OkayToClose
= NULL
;
700 PsThreadType
->Create
= NULL
;
701 PsThreadType
->DuplicationNotify
= NULL
;
703 RtlRosInitUnicodeStringFromLiteral(&PsThreadType
->TypeName
, L
"Thread");
705 ObpCreateTypeObject(PsThreadType
);
707 PsInitializeThread(NULL
,&FirstThread
,&FirstThreadHandle
,
708 THREAD_ALL_ACCESS
,NULL
, TRUE
);
709 FirstThread
->Tcb
.State
= THREAD_STATE_RUNNING
;
710 FirstThread
->Tcb
.FreezeCount
= 0;
711 FirstThread
->Tcb
.UserAffinity
= (1 << 0); /* Set the affinity of the first thread to the boot processor */
712 FirstThread
->Tcb
.Affinity
= (1 << 0);
713 KeGetCurrentKPCR()->PrcbData
.CurrentThread
= (PVOID
)FirstThread
;
714 NtClose(FirstThreadHandle
);
716 DPRINT("FirstThread %x\n",FirstThread
);
721 * Create the reaper thread
723 PsInitializeThreadReaper();
724 KeInitializeEvent(&PiReaperThreadEvent
, SynchronizationEvent
, FALSE
);
725 Status
= PsCreateSystemThread(&PiReaperThreadHandle
,
732 if (!NT_SUCCESS(Status
))
734 DPRINT1("PS: Failed to create reaper thread.\n");
738 NtClose(PiReaperThreadHandle
);
745 KeSetBasePriorityThread (PKTHREAD Thread
,
748 * Sets thread's base priority relative to the process' base priority
749 * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
757 else if (Increment
> 2)
761 Priority
= ((PETHREAD
)Thread
)->ThreadsProcess
->Pcb
.BasePriority
+ Increment
;
762 if (Priority
< LOW_PRIORITY
)
764 Priority
= LOW_PRIORITY
;
766 else if (Priority
>= MAXIMUM_PRIORITY
)
768 Thread
->BasePriority
= HIGH_PRIORITY
;
770 KeSetPriorityThread(Thread
, Priority
);
779 KeSetPriorityThread (PKTHREAD Thread
, KPRIORITY Priority
)
781 KPRIORITY OldPriority
;
783 PKTHREAD CurrentThread
;
788 if (Priority
< LOW_PRIORITY
|| Priority
>= MAXIMUM_PRIORITY
)
793 oldIrql
= KeAcquireDispatcherDatabaseLock();
795 OldPriority
= Thread
->Priority
;
797 if (OldPriority
!= Priority
)
799 CurrentThread
= KeGetCurrentThread();
800 if (Thread
->State
== THREAD_STATE_READY
)
802 PsRemoveFromThreadList((PETHREAD
)Thread
);
803 Thread
->BasePriority
= Thread
->Priority
= (CHAR
)Priority
;
804 PsInsertIntoThreadList(Priority
, (PETHREAD
)Thread
);
805 if (CurrentThread
->Priority
< Priority
)
807 PsDispatchThreadNoLock(THREAD_STATE_READY
);
808 KeLowerIrql(oldIrql
);
809 return (OldPriority
);
812 else if (Thread
->State
== THREAD_STATE_RUNNING
)
814 Thread
->BasePriority
= Thread
->Priority
= (CHAR
)Priority
;
815 if (Priority
< OldPriority
)
817 /* Check for threads with a higher priority */
818 Mask
= ~((1 << (Priority
+ 1)) - 1);
819 if (PriorityListMask
& Mask
)
821 if (Thread
== CurrentThread
)
823 PsDispatchThreadNoLock(THREAD_STATE_READY
);
824 KeLowerIrql(oldIrql
);
825 return (OldPriority
);
829 for (i
= 0; i
< KeNumberProcessors
; i
++)
831 Pcr
= (PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
);
832 if (Pcr
->PrcbData
.CurrentThread
== Thread
)
834 KeReleaseDispatcherDatabaseLockFromDpcLevel();
835 KiRequestReschedule(i
);
836 KeLowerIrql(oldIrql
);
837 return (OldPriority
);
846 Thread
->BasePriority
= Thread
->Priority
= (CHAR
)Priority
;
849 KeReleaseDispatcherDatabaseLock(oldIrql
);
857 KeSetAffinityThread(PKTHREAD Thread
,
860 * Sets thread's affinity
866 KAFFINITY ProcessorMask
;
868 DPRINT("KeSetAffinityThread(Thread %x, Affinity %x)\n", Thread
, Affinity
);
870 ASSERT(Affinity
& ((1 << KeNumberProcessors
) - 1));
872 oldIrql
= KeAcquireDispatcherDatabaseLock();
874 Thread
->UserAffinity
= Affinity
;
875 if (Thread
->SystemAffinityActive
== FALSE
)
877 Thread
->Affinity
= Affinity
;
878 if (Thread
->State
== THREAD_STATE_RUNNING
)
880 ProcessorMask
= 1 << KeGetCurrentKPCR()->ProcessorNumber
;
881 if (Thread
== KeGetCurrentThread())
883 if (!(Affinity
& ProcessorMask
))
885 PsDispatchThreadNoLock(THREAD_STATE_READY
);
886 KeLowerIrql(oldIrql
);
887 return STATUS_SUCCESS
;
892 for (i
= 0; i
< KeNumberProcessors
; i
++)
894 Pcr
= (PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
);
895 if (Pcr
->PrcbData
.CurrentThread
== Thread
)
897 if (!(Affinity
& ProcessorMask
))
899 KeReleaseDispatcherDatabaseLockFromDpcLevel();
900 KiRequestReschedule(i
);
901 KeLowerIrql(oldIrql
);
902 return STATUS_SUCCESS
;
907 ASSERT (i
< KeNumberProcessors
);
911 KeReleaseDispatcherDatabaseLock(oldIrql
);
912 return STATUS_SUCCESS
;
917 NtAlertResumeThread(IN HANDLE ThreadHandle
,
918 OUT PULONG SuspendCount
)
921 return(STATUS_NOT_IMPLEMENTED
);
927 NtAlertThread (IN HANDLE ThreadHandle
)
931 NTSTATUS ThreadStatus
;
934 Status
= ObReferenceObjectByHandle(ThreadHandle
,
935 THREAD_SUSPEND_RESUME
,
940 if (Status
!= STATUS_SUCCESS
)
945 ThreadStatus
= STATUS_ALERTED
;
946 oldIrql
= KeAcquireDispatcherDatabaseLock();
947 (VOID
)PsUnblockThread(Thread
, &ThreadStatus
);
948 KeReleaseDispatcherDatabaseLock(oldIrql
);
950 ObDereferenceObject(Thread
);
951 return(STATUS_SUCCESS
);
954 /**********************************************************************
960 NtOpenThread(OUT PHANDLE ThreadHandle
,
961 IN ACCESS_MASK DesiredAccess
,
962 IN POBJECT_ATTRIBUTES ObjectAttributes
,
963 IN PCLIENT_ID ClientId
)
965 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
967 if((NULL
!= ThreadHandle
)&&(NULL
!= ObjectAttributes
))
969 PETHREAD EThread
= NULL
;
972 && (ClientId
->UniqueThread
))
974 // It is an error to specify both
975 // ObjectAttributes.ObjectName
977 if((ObjectAttributes
)
978 && (ObjectAttributes
->ObjectName
)
979 && (0 < ObjectAttributes
->ObjectName
->Length
))
981 return(STATUS_INVALID_PARAMETER_MIX
);
984 Status
= PsLookupThreadByThreadId(ClientId
->UniqueThread
,
987 else if((ObjectAttributes
)
988 && (ObjectAttributes
->ObjectName
)
989 && (0 < ObjectAttributes
->ObjectName
->Length
))
991 // Three Ob attributes are forbidden
992 if(!(ObjectAttributes
->Attributes
&
993 (OBJ_PERMANENT
| OBJ_EXCLUSIVE
| OBJ_OPENIF
)))
995 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
996 ObjectAttributes
->Attributes
,
1002 (PVOID
*) & EThread
);
1005 // EThread may be OK...
1006 if(STATUS_SUCCESS
== Status
)
1008 Status
= ObCreateHandle(PsGetCurrentProcess(),
1013 ObDereferenceObject(EThread
);
1020 NtYieldExecution(VOID
)
1022 PsDispatchThread(THREAD_STATE_READY
);
1023 return(STATUS_SUCCESS
);
1031 PsLookupProcessThreadByCid(IN PCLIENT_ID Cid
,
1032 OUT PEPROCESS
*Process OPTIONAL
,
1033 OUT PETHREAD
*Thread
)
1035 PCID_OBJECT CidObject
;
1036 PETHREAD FoundThread
;
1038 CidObject
= PsLockCidHandle((HANDLE
)Cid
->UniqueThread
, PsThreadType
);
1039 if(CidObject
!= NULL
)
1041 FoundThread
= CidObject
->Obj
.Thread
;
1042 ObReferenceObject(FoundThread
);
1046 *Process
= FoundThread
->ThreadsProcess
;
1047 ObReferenceObject(FoundThread
->ThreadsProcess
);
1050 PsUnlockCidObject(CidObject
);
1051 return STATUS_SUCCESS
;
1054 return STATUS_INVALID_PARAMETER
;
1062 PsLookupThreadByThreadId(IN PVOID ThreadId
,
1063 OUT PETHREAD
*Thread
)
1065 PCID_OBJECT CidObject
;
1067 CidObject
= PsLockCidHandle((HANDLE
)ThreadId
, PsThreadType
);
1068 if(CidObject
!= NULL
)
1070 *Thread
= CidObject
->Obj
.Thread
;
1071 ObReferenceObject(*Thread
);
1073 PsUnlockCidObject(CidObject
);
1074 return STATUS_SUCCESS
;
1077 return STATUS_INVALID_PARAMETER
;