KTHREAD和ETHREAD
2023-10-26
84
0
Windows系统中,每一个线程在内核中都有一个ETHREAD结构体与之对应,其ETHREAD结构体的第一个成员就是KTHREAD结构体。
ETHREAD结构体的定义为:
1: kd> dt _ETHREAD
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x5e0 CreateTime : _LARGE_INTEGER
+0x5e8 ExitTime : _LARGE_INTEGER
+0x5e8 KeyedWaitChain : _LIST_ENTRY
+0x5f8 ChargeOnlySession : Ptr64 Void
+0x600 PostBlockList : _LIST_ENTRY
+0x600 ForwardLinkShadow : Ptr64 Void
+0x608 StartAddress : Ptr64 Void
+0x610 TerminationPort : Ptr64 _TERMINATION_PORT
+0x610 ReaperLink : Ptr64 _ETHREAD
+0x610 KeyedWaitValue : Ptr64 Void
+0x618 ActiveTimerListLock : Uint8B
+0x620 ActiveTimerListHead : _LIST_ENTRY
+0x630 Cid : _CLIENT_ID
+0x640 KeyedWaitSemaphore : _KSEMAPHORE
+0x640 AlpcWaitSemaphore : _KSEMAPHORE
+0x660 ClientSecurity : _PS_CLIENT_SECURITY_CONTEXT
+0x668 IrpList : _LIST_ENTRY
+0x678 TopLevelIrp : Uint8B
+0x680 DeviceToVerify : Ptr64 _DEVICE_OBJECT
+0x688 Win32StartAddress : Ptr64 Void
+0x690 LegacyPowerObject : Ptr64 Void
+0x698 ThreadListEntry : _LIST_ENTRY
+0x6a8 RundownProtect : _EX_RUNDOWN_REF
+0x6b0 ThreadLock : _EX_PUSH_LOCK
+0x6b8 ReadClusterSize : Uint4B
+0x6bc MmLockOrdering : Int4B
+0x6c0 CrossThreadFlags : Uint4B
+0x6c0 Terminated : Pos 0, 1 Bit
+0x6c0 ThreadInserted : Pos 1, 1 Bit
+0x6c0 HideFromDebugger : Pos 2, 1 Bit
+0x6c0 ActiveImpersonationInfo : Pos 3, 1 Bit
+0x6c0 HardErrorsAreDisabled : Pos 4, 1 Bit
+0x6c0 BreakOnTermination : Pos 5, 1 Bit
+0x6c0 SkipCreationMsg : Pos 6, 1 Bit
+0x6c0 SkipTerminationMsg : Pos 7, 1 Bit
+0x6c0 CopyTokenOnOpen : Pos 8, 1 Bit
+0x6c0 ThreadIoPriority : Pos 9, 3 Bits
+0x6c0 ThreadPagePriority : Pos 12, 3 Bits
+0x6c0 RundownFail : Pos 15, 1 Bit
+0x6c0 UmsForceQueueTermination : Pos 16, 1 Bit
+0x6c0 IndirectCpuSets : Pos 17, 1 Bit
+0x6c0 DisableDynamicCodeOptOut : Pos 18, 1 Bit
+0x6c0 ExplicitCaseSensitivity : Pos 19, 1 Bit
+0x6c0 ReservedCrossThreadFlags : Pos 20, 12 Bits
+0x6c4 SameThreadPassiveFlags : Uint4B
+0x6c4 ActiveExWorker : Pos 0, 1 Bit
+0x6c4 MemoryMaker : Pos 1, 1 Bit
+0x6c4 StoreLockThread : Pos 2, 2 Bits
+0x6c4 ClonedThread : Pos 4, 1 Bit
+0x6c4 KeyedEventInUse : Pos 5, 1 Bit
+0x6c4 SelfTerminate : Pos 6, 1 Bit
+0x6c4 RespectIoPriority : Pos 7, 1 Bit
+0x6c4 ActivePageLists : Pos 8, 1 Bit
+0x6c4 ReservedSameThreadPassiveFlags : Pos 9, 23 Bits
+0x6c8 SameThreadApcFlags : Uint4B
+0x6c8 OwnsProcessAddressSpaceExclusive : Pos 0, 1 Bit
+0x6c8 OwnsProcessAddressSpaceShared : Pos 1, 1 Bit
+0x6c8 HardFaultBehavior : Pos 2, 1 Bit
+0x6c8 StartAddressInvalid : Pos 3, 1 Bit
+0x6c8 EtwCalloutActive : Pos 4, 1 Bit
+0x6c8 SuppressSymbolLoad : Pos 5, 1 Bit
+0x6c8 Prefetching : Pos 6, 1 Bit
+0x6c8 OwnsVadExclusive : Pos 7, 1 Bit
+0x6c9 SystemPagePriorityActive : Pos 0, 1 Bit
+0x6c9 SystemPagePriority : Pos 1, 3 Bits
+0x6cc CacheManagerActive : UChar
+0x6cd DisablePageFaultClustering : UChar
+0x6ce ActiveFaultCount : UChar
+0x6cf LockOrderState : UChar
+0x6d0 AlpcMessageId : Uint8B
+0x6d8 AlpcMessage : Ptr64 Void
+0x6d8 AlpcReceiveAttributeSet : Uint4B
+0x6e0 AlpcWaitListEntry : _LIST_ENTRY
+0x6f0 ExitStatus : Int4B
+0x6f4 CacheManagerCount : Uint4B
+0x6f8 IoBoostCount : Uint4B
+0x6fc IoQoSBoostCount : Uint4B
+0x700 IoQoSThrottleCount : Uint4B
+0x708 BoostList : _LIST_ENTRY
+0x718 DeboostList : _LIST_ENTRY
+0x728 BoostListLock : Uint8B
+0x730 IrpListLock : Uint8B
+0x738 ReservedForSynchTracking : Ptr64 Void
+0x740 CmCallbackListHead : _SINGLE_LIST_ENTRY
+0x748 ActivityId : Ptr64 _GUID
+0x750 SeLearningModeListHead : _SINGLE_LIST_ENTRY
+0x758 VerifierContext : Ptr64 Void
+0x760 KernelStackReference : Uint4B
+0x768 AdjustedClientToken : Ptr64 Void
+0x770 WorkOnBehalfThread : Ptr64 Void
+0x778 PropertySet : _PS_PROPERTY_SET
+0x790 PicoContext : Ptr64 Void
+0x798 UserFsBase : Uint8B
+0x7a0 UserGsBase : Uint8B
+0x7a8 EnergyValues : Ptr64 _THREAD_ENERGY_VALUES
+0x7b0 CmDbgInfo : Ptr64 Void
+0x7b8 SelectedCpuSets : Uint8B
+0x7b8 SelectedCpuSetsIndirect : Ptr64 Uint8B
+0x7c0 Silo : Ptr64 _EJOB
+0x7c8 ThreadName : Ptr64 _UNICODE_STRING
+0x7d0 SetContextState : Ptr64 _CONTEXT
+0x7d8 ReadyTime : Uint4B
其中ETHREAD结构体的第一个成员为KTHREAD
1: kd> dt _ETHREAD
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
...
KTHREA结构体的内容为:
1: kd> dt _KTHREAD
nt!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
+0x018 SListFaultAddress : Ptr64 Void
+0x020 QuantumTarget : Uint8B
+0x028 InitialStack : Ptr64 Void
+0x030 StackLimit : Ptr64 Void
+0x038 StackBase : Ptr64 Void
+0x040 ThreadLock : Uint8B
+0x048 CycleTime : Uint8B
+0x050 CurrentRunTime : Uint4B
+0x054 ExpectedRunTime : Uint4B
+0x058 KernelStack : Ptr64 Void
+0x060 StateSaveArea : Ptr64 _XSAVE_FORMAT
+0x068 SchedulingGroup : Ptr64 _KSCHEDULING_GROUP
+0x070 WaitRegister : _KWAIT_STATUS_REGISTER
+0x071 Running : UChar
+0x072 Alerted : [2] UChar
+0x074 AutoBoostActive : Pos 0, 1 Bit
+0x074 ReadyTransition : Pos 1, 1 Bit
+0x074 WaitNext : Pos 2, 1 Bit
+0x074 SystemAffinityActive : Pos 3, 1 Bit
+0x074 Alertable : Pos 4, 1 Bit
+0x074 UserStackWalkActive : Pos 5, 1 Bit
+0x074 ApcInterruptRequest : Pos 6, 1 Bit
+0x074 QuantumEndMigrate : Pos 7, 1 Bit
+0x074 UmsDirectedSwitchEnable : Pos 8, 1 Bit
+0x074 TimerActive : Pos 9, 1 Bit
+0x074 SystemThread : Pos 10, 1 Bit
+0x074 ProcessDetachActive : Pos 11, 1 Bit
+0x074 CalloutActive : Pos 12, 1 Bit
+0x074 ScbReadyQueue : Pos 13, 1 Bit
+0x074 ApcQueueable : Pos 14, 1 Bit
+0x074 ReservedStackInUse : Pos 15, 1 Bit
+0x074 UmsPerformingSyscall : Pos 16, 1 Bit
+0x074 TimerSuspended : Pos 17, 1 Bit
+0x074 SuspendedWaitMode : Pos 18, 1 Bit
+0x074 SuspendSchedulerApcWait : Pos 19, 1 Bit
+0x074 Reserved : Pos 20, 12 Bits
+0x074 MiscFlags : Int4B
+0x078 AutoAlignment : Pos 0, 1 Bit
+0x078 DisableBoost : Pos 1, 1 Bit
+0x078 ThreadFlagsSpare0 : Pos 2, 1 Bit
+0x078 AlertedByThreadId : Pos 3, 1 Bit
+0x078 QuantumDonation : Pos 4, 1 Bit
+0x078 EnableStackSwap : Pos 5, 1 Bit
+0x078 GuiThread : Pos 6, 1 Bit
+0x078 DisableQuantum : Pos 7, 1 Bit
+0x078 ChargeOnlySchedulingGroup : Pos 8, 1 Bit
+0x078 DeferPreemption : Pos 9, 1 Bit
+0x078 QueueDeferPreemption : Pos 10, 1 Bit
+0x078 ForceDeferSchedule : Pos 11, 1 Bit
+0x078 SharedReadyQueueAffinity : Pos 12, 1 Bit
+0x078 FreezeCount : Pos 13, 1 Bit
+0x078 TerminationApcRequest : Pos 14, 1 Bit
+0x078 AutoBoostEntriesExhausted : Pos 15, 1 Bit
+0x078 KernelStackResident : Pos 16, 1 Bit
+0x078 CommitFailTerminateRequest : Pos 17, 1 Bit
+0x078 ProcessStackCountDecremented : Pos 18, 1 Bit
+0x078 RestrictedGuiThread : Pos 19, 1 Bit
+0x078 ThreadFlagsSpare : Pos 20, 4 Bits
+0x078 EtwStackTraceApcInserted : Pos 24, 8 Bits
+0x078 ThreadFlags : Int4B
+0x07c Tag : UChar
+0x07d SystemHeteroCpuPolicy : UChar
+0x07e UserHeteroCpuPolicy : Pos 0, 7 Bits
+0x07e ExplicitSystemHeteroCpuPolicy : Pos 7, 1 Bit
+0x07f Spare0 : UChar
+0x080 SystemCallNumber : Uint4B
+0x084 Spare10 : Uint4B
+0x088 FirstArgument : Ptr64 Void
+0x090 TrapFrame : Ptr64 _KTRAP_FRAME
+0x098 ApcState : _KAPC_STATE
+0x098 ApcStateFill : [43] UChar
+0x0c3 Priority : Char
+0x0c4 UserIdealProcessor : Uint4B
+0x0c8 WaitStatus : Int8B
+0x0d0 WaitBlockList : Ptr64 _KWAIT_BLOCK
+0x0d8 WaitListEntry : _LIST_ENTRY
+0x0d8 SwapListEntry : _SINGLE_LIST_ENTRY
+0x0e8 Queue : Ptr64 _DISPATCHER_HEADER
+0x0f0 Teb : Ptr64 Void
+0x0f8 RelativeTimerBias : Uint8B
+0x100 Timer : _KTIMER
+0x140 WaitBlock : [4] _KWAIT_BLOCK
+0x140 WaitBlockFill4 : [20] UChar
+0x154 ContextSwitches : Uint4B
+0x140 WaitBlockFill5 : [68] UChar
+0x184 State : UChar
+0x185 Spare13 : Char
+0x186 WaitIrql : UChar
+0x187 WaitMode : Char
+0x140 WaitBlockFill6 : [116] UChar
+0x1b4 WaitTime : Uint4B
+0x140 WaitBlockFill7 : [164] UChar
+0x1e4 KernelApcDisable : Int2B
+0x1e6 SpecialApcDisable : Int2B
+0x1e4 CombinedApcDisable : Uint4B
+0x140 WaitBlockFill8 : [40] UChar
+0x168 ThreadCounters : Ptr64 _KTHREAD_COUNTERS
+0x140 WaitBlockFill9 : [88] UChar
+0x198 XStateSave : Ptr64 _XSTATE_SAVE
+0x140 WaitBlockFill10 : [136] UChar
+0x1c8 Win32Thread : Ptr64 Void
+0x140 WaitBlockFill11 : [176] UChar
+0x1f0 Ucb : Ptr64 _UMS_CONTROL_BLOCK
+0x1f8 Uch : Ptr64 _KUMS_CONTEXT_HEADER
+0x200 Spare21 : Ptr64 Void
+0x208 QueueListEntry : _LIST_ENTRY
+0x218 NextProcessor : Uint4B
+0x218 NextProcessorNumber : Pos 0, 31 Bits
+0x218 SharedReadyQueue : Pos 31, 1 Bit
+0x21c QueuePriority : Int4B
+0x220 Process : Ptr64 _KPROCESS
+0x228 UserAffinity : _GROUP_AFFINITY
+0x228 UserAffinityFill : [10] UChar
+0x232 PreviousMode : Char
+0x233 BasePriority : Char
+0x234 PriorityDecrement : Char
+0x234 ForegroundBoost : Pos 0, 4 Bits
+0x234 UnusualBoost : Pos 4, 4 Bits
+0x235 Preempted : UChar
+0x236 AdjustReason : UChar
+0x237 AdjustIncrement : Char
+0x238 AffinityVersion : Uint8B
+0x240 Affinity : _GROUP_AFFINITY
+0x240 AffinityFill : [10] UChar
+0x24a ApcStateIndex : UChar
+0x24b WaitBlockCount : UChar
+0x24c IdealProcessor : Uint4B
+0x250 NpxState : Uint8B
+0x258 SavedApcState : _KAPC_STATE
+0x258 SavedApcStateFill : [43] UChar
+0x283 WaitReason : UChar
+0x284 SuspendCount : Char
+0x285 Saturation : Char
+0x286 SListFaultCount : Uint2B
+0x288 SchedulerApc : _KAPC
+0x288 SchedulerApcFill0 : [1] UChar
+0x289 ResourceIndex : UChar
+0x288 SchedulerApcFill1 : [3] UChar
+0x28b QuantumReset : UChar
+0x288 SchedulerApcFill2 : [4] UChar
+0x28c KernelTime : Uint4B
+0x288 SchedulerApcFill3 : [64] UChar
+0x2c8 WaitPrcb : Ptr64 _KPRCB
+0x288 SchedulerApcFill4 : [72] UChar
+0x2d0 LegoData : Ptr64 Void
+0x288 SchedulerApcFill5 : [83] UChar
+0x2db CallbackNestingLevel : UChar
+0x2dc UserTime : Uint4B
+0x2e0 SuspendEvent : _KEVENT
+0x2f8 ThreadListEntry : _LIST_ENTRY
+0x308 MutantListHead : _LIST_ENTRY
+0x318 AbEntrySummary : UChar
+0x319 AbWaitEntryCount : UChar
+0x31a Spare20 : Uint2B
+0x31c SecureThreadCookie : Uint4B
+0x320 LockEntries : [6] _KLOCK_ENTRY
+0x560 PropagateBoostsEntry : _SINGLE_LIST_ENTRY
+0x568 IoSelfBoostsEntry : _SINGLE_LIST_ENTRY
+0x570 PriorityFloorCounts : [16] UChar
+0x580 PriorityFloorSummary : Uint4B
+0x584 AbCompletedIoBoostCount : Int4B
+0x588 AbCompletedIoQoSBoostCount : Int4B
+0x58c KeReferenceCount : Int2B
+0x58e AbOrphanedEntrySummary : UChar
+0x58f AbOwnedEntryCount : UChar
+0x590 ForegroundLossTime : Uint4B
+0x598 GlobalForegroundListEntry : _LIST_ENTRY
+0x598 ForegroundDpcStackListEntry : _SINGLE_LIST_ENTRY
+0x5a0 InGlobalForegroundList : Uint8B
+0x5a8 ReadOperationCount : Int8B
+0x5b0 WriteOperationCount : Int8B
+0x5b8 OtherOperationCount : Int8B
+0x5c0 ReadTransferCount : Int8B
+0x5c8 WriteTransferCount : Int8B
+0x5d0 OtherTransferCount : Int8B
+0x5d8 QueuedScb : Ptr64 _KSCB
在KTHREAD结构体
+0x1c8 Win32Thread : Ptr64 Void
处有一指针为Win32Thread,只有图形界面的线程该指针才有内容。如果不是图形界面的线程,该指针成员为NULL.
一个线程刚创建的进候都是普通线程,当线程第一次调用Win32k.sys中的函数时,会调用一个函数PsConvertToGuiThread。该函数的主要内容为:
1.扩充内核栈
2.创建一个包含消息队列的结构体存放在KTHREAD的Win32Thread上。该结构体为THREADINFO.
3.线程的ServiceTable指向KeServiceDescriptorTableShadow
4.将需要的内存数据映射到本进程空间
THREADINFO结构体在员MessageQueue就是消息队列。
#ifdef __cplusplus
typedef struct _THREADINFO : _W32THREAD
{
#else
typedef struct _THREADINFO
{
W32THREAD;
#endif
PTL ptl;
PPROCESSINFO ppi;
struct _USER_MESSAGE_QUEUE* MessageQueue;
struct tagKL* KeyboardLayout;
struct _CLIENTTHREADINFO * pcti;
struct _DESKTOP* rpdesk;
struct _DESKTOPINFO * pDeskInfo;
struct _CLIENTINFO * pClientInfo;
FLONG TIF_flags;
PUNICODE_STRING pstrAppName;
struct _USER_SENT_MESSAGE *pusmSent;
struct _USER_SENT_MESSAGE *pusmCurrent;
/* Queue of messages sent to the queue. */
LIST_ENTRY SentMessagesListHead; // psmsReceiveList
/* Last message time and ID */
LONG timeLast;
ULONG_PTR idLast;
/* True if a WM_QUIT message is pending. */
BOOLEAN QuitPosted;
/* The quit exit code. */
INT exitCode;
HDESK hdesk;
UINT cPaintsReady; /* Count of paints pending. */
UINT cTimersReady; /* Count of timers pending. */
struct tagMENUSTATE* pMenuState;
DWORD dwExpWinVer;
DWORD dwCompatFlags;
DWORD dwCompatFlags2;
struct _USER_MESSAGE_QUEUE* pqAttach;
PTHREADINFO ptiSibling;
ULONG fsHooks;
struct tagHOOK * sphkCurrent;
LPARAM lParamHkCurrent;
WPARAM wParamHkCurrent;
struct tagSBTRACK* pSBTrack;
/* Set if there are new messages specified by WakeMask in any of the queues. */
HANDLE hEventQueueClient;
/* Handle for the above event (in the context of the process owning the queue). */
PKEVENT pEventQueueServer;
LIST_ENTRY PtiLink;
INT iCursorLevel;
/* Last message cursor position */
POINT ptLast;
/* Input context-related */
struct _WND* spwndDefaultIme;
struct tagIMC* spDefaultImc;
HKL hklPrev;
INT cEnterCount;
/* Queue of messages posted to the queue. */
LIST_ENTRY PostedMessagesListHead; // mlPost
WORD fsChangeBitsRemoved;
WCHAR wchInjected;
UINT cWindows;
UINT cVisWindows;
#ifndef __cplusplus
LIST_ENTRY aphkStart[NB_HOOKS];
CLIENTTHREADINFO cti; // Used only when no Desktop or pcti NULL.
/* ReactOS */
/* Thread Queue state tracking */
// Send list QS_SENDMESSAGE
// Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
// Hard list QS_MOUSE|QS_KEY only
// Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
LIST_ENTRY WindowListHead;
LIST_ENTRY W32CallbackListHead;
SINGLE_LIST_ENTRY ReferencesList;
ULONG cExclusiveLocks;
#if DBG
USHORT acExclusiveLockCount[GDIObjTypeTotal + 1];
#endif
#endif // __cplusplus
} THREADINFO;
REACTOS中该函数PsConvertToGuiThread定义为:
NTSTATUS NTAPI PsConvertToGuiThread ( VOID )
{
ULONG_PTR NewStack;
PVOID OldStack;
PETHREAD Thread = PsGetCurrentThread();
PEPROCESS Process = PsGetCurrentProcess();
NTSTATUS Status;
PAGED_CODE();
/* Validate the previous mode */
if (KeGetPreviousMode() == KernelMode) return STATUS_INVALID_PARAMETER;
/* If no win32k, crashes later */
ASSERT(PspW32ProcessCallout != NULL);
/* Make sure win32k is here */
if (!PspW32ProcessCallout) return STATUS_ACCESS_DENIED;
/* Make sure it's not already win32 */
if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
{
/* We're already a win32 thread */
return STATUS_ALREADY_WIN32;
}
/* Check if we don't already have a kernel-mode stack */
if (!Thread->Tcb.LargeStack)
{
/* We don't create one */
NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE, 0);
if (!NewStack)
{
/* Panic in user-mode */
NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
return STATUS_NO_MEMORY;
}
/* We're about to switch stacks. Enter a guarded region */
KeEnterGuardedRegion();
/* Switch stacks */
OldStack = KeSwitchKernelStack((PVOID)NewStack,
(PVOID)(NewStack - KERNEL_STACK_SIZE));
/* Leave the guarded region */
KeLeaveGuardedRegion();
/* Delete the old stack */
MmDeleteKernelStack(OldStack, FALSE);
}
/* Always do the process callout! */
Status = PspW32ProcessCallout(Process, TRUE);
if (!NT_SUCCESS(Status)) return Status;
/* Set the new service table */
Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
ASSERT(Thread->Tcb.Win32Thread == 0);
/* Tell Win32k about our thread */
Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize);
if (!NT_SUCCESS(Status))
{
/* Revert our table */
Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
}
/* Return status */
return Status;
}