supplement:
The process of Handle is saved in its own Process Handle Table, the system can find the corresponding process database through HProcess, then where the thread of the process has a handle? As mentioned earlier, two locations in the PDB are related to this: A number of threads used to save the process, and the other saved the threadlist's head. Personally, HTREAD should be in Process Handle Table, because you can use CloseHandle to Hthread, and threads are also K32 objects.
Thread Database
Thread Database is a K32 object (K32Obj_thread), which is allocated from the Kernel32 shared data area. In the threaddb.h file of the sample code in this chapter, the format is as follows:
00h dword Type
This location is 6, indicating the k32obj_thread object (as else in Windows 2000 or Later, unknown)
04H dword creference
This location contains a reference count
08h process_database pprocess
This is a pointer, pointing to the process to which the thread belongs.
0ch dword someevent
A pointer pointing to the K32obj_event object. EVENT objects are usually handed over to WaitForsingleObject. This EVENT object is the event you want to call the waitforsingleObject function.
10h DWORD PVEXCEPT
This is a pointer, pointing to the structured abnormal string head (structured exception handling will be discussed later). Note that this location also identifies the beginning of the Tib (Thread Information Block) nest structure in Task Database. TIB will be discussed later.
supplement:
It seems that this book is still effective in Windows 2000 (SP4). After the end of this chapter, I will transplant the routines in this chapter in Windows 2000. It is estimated that it may not be fully transplanted because I don't have a full version of kernel32.lib under Windows 2000. I hope that after completing the book of the "undocument Windows 2000 Secret", I can make up these content. 2004-12-26
14h DWORD TOPOFSTACK
This location stores the highest address of the thread stack. In general, the stack size remaining to the thread is 1MB.
Supplement: The default stack size of the thread in Windows 2000 is also 1MB.
18h dword stacklow
This location stores the lowest bit tag of the thread stack (in Page). You can know how much stack is currently using Topofstack to subtract StackLow.
1Ch Word W16TDB
It is stored here for the Selector of Win 16 Task Database.
1e Word StackSelector16
Before Win32 Code is moved (Thunk Down), you must switch to a 16-bit stack before you first. This member is stored is the 16-bit stack of Selector.
20h dword selmanlist
A pointer, pointing to the SELMANLIST of the thread. The meaning of "selman" is "Selector Manager". Selman in Kernel32 seems to be responsible for managing Selectors, threads can be configured as a given purpose. 24h DWORD Userpointer
The precise significance of this location is not clear. However, in the file of the TIB structure, this location can be used to the application. Don't forget, the TIB structure is nest in Thread Database.
28H PTIB PTIB
This location points to Tib (Thread Information Block). The TIB of Windows 95 is located in Thread Database, so this pointer actually points to another location of Thread Database: PVEXCEPT position (offset address 10h).
Thread Information Block (TIB)
In THREAD DATABASE, some members are extremely useful for executing programs. In fact, they are useful, so that the Win32 architecture allows them to be taken immediately without the need to pass through Database. These members are placed in a structure called Thread Information Block (TIB). Thread Database 10H-3CH members are placed in Tib.
How do applications get TIB? If you have seen the assembly code for Win32 programs, you will find that the frequency of use of FS registers is very high (Whether Windows 2000 or Later is so unknown. 2004-12-27). Wait, Win32 is not a mobile festival? Obviously the answer is YES, but the Win32 underdess (including Windows NT) uses the FS register to point to the Tib.Win32 of the currently executable thread is not the first operating system, OS / 2 2.0 is already so. Just like you feel, yes, when Windows 95 switches the thread, the scheduler must change the value of the FS register, allowing it to include a Selector, pointing to the new TIB.
The main purpose of the FS register and TIB is to increase the number of structured exception handling chains. The header of the processing chain is stored at the 0 offset of the TIB, so when you see the assembly code, you will know that it is doing some action related to structured abnormalities.
The other two members of TIB are also used very widely, which are PvQueue and PVTLSARRAY (28h and 2ch members). The PVQueue member stores the Handle of the message queue of the current thread, which is often used by the user.exe window system. Because in Windows 95, the focus window (Focus Windows) is not only one throughout the system. PvtlsArray points to the TLS array in Thread Database. The compiler vendor uses the .tis section of the executable, provides transparent "Per-Thread Global Variable".
Although the layout of the TIB structure can be calculated from Thread Database, I have to give a little summary here. There is a C language description of TIB in Tib.h in this chapter. Microsoft's first document on this is NTDDK.H provided by Windows NT 3.5 DDK.
The TIB content of Windows 95 is as follows:
00h dword pVEXCEPT
04H dword Topofstack
08h DWORD StackLow0Ch Word W16TDB
0EH Word Stackselector16
10h dword selmanlist
14h DWORD USERPOINTER
18H PTIB PTIB
1Ch Word Tibflags
1EH Word Win16Mutexcount
20h DWord Debugcontext
24h pdword pcurrentpriority
28h dword messagequeue
2Ch DWORD PTLSARRAY
If you want to know the meaning of each member, add its offset value for 10 h, then look at the structure content of the last section, you can know. Please note that only some members are common for other Win32 platforms.
supplement:
In the Windows NT / 2000 system, thread information block is defined as NT_TIB structure, in NTDDK.H of Windows NT / 2000 DDK, you can find C language definitions of this structure. Its layout is as follows:
//
// NT_TIB - Thread Information Block - Portable Part.
//
// this is The Subsystem Portable Part of The Thread Information Block.
// IT APPEARS As The First Part of The Teb for All Threads Which Have
// a User mode component.
//
// from Windows 2000 DDK 1999-9-11
// begin_winnt
Typedef struct _nt_tib {
Struct _exception_registration_record * ExceptionList; // SEH chain entrance
Pvoid stackbase; // stack base
Pvoid stacklimit; // stack size
PVOID SUBSYSTEMTIB;
Union {
PVOID FIBERDATA;
Ulong Version;
}
Pvoid ArbitraryUserPointer;
Struct _nt_tib * self; // This NT_TIB structure itself linear address
} Nt_tib;
TYPEDEF NT_TIB * PNT_TIB;
It can be seen that the TIB structure in Windows 2000 is very different from Windows 95, mainly to remove many things related to DOS and Win16, add some new content such as fiber. But one thing is the same, that is: TIB is always stored at the 0 offset of the data segment specified by the FS segment selector, so fs: [0] is the starting position of the TIB structure (also the entrance address of the SEH chain) ). This feature is valid for Windows 9x and Windows NT / 2000 systems.
Since different threads in a process can have different context. So, in different threads, the FS segment selector can use different values, which makes each thread to set its own TIB, which is very helpful for structural exceptions, and later we will introduce in depth.
Thread Priority (thread priority)
Windows 95 VMM core thread schedule is not really careful, it is only threaded priority, regardless of which process is belonging to. In other words, the process does not really have priority. Of course, for the terminal user of the thread dispatching service (that is, the application), the process has priority is a relatively useful abstraction. At any time, you have the highest priority thread, and it is nothing to do again, it will be one of the upcoming execution. In order to ensure that the system is smooth and avoiding many problems, thread priority can be dynamically changed by the system. For example, when a thread is performing an I / O action, its priority can be temporarily improved. Detailed discussion of this topic, it will take a lot of chapters.
Windows 95's VMM Thread Dispatch Manager supports priority in 32. These 32 priorities are divided into four levels, becoming priority classes, each level is related to a set of priority. In one level, priority can be increased or decreased up and down 2. But there is also a special case such as Thread_Priority_level, which allows priority to completely jump out of its specifications. Unless there is special specified, the priority level given when the operating system generates a process is Normal_Priority_Class.
Four preset priority levels and ranges are:
priority
Defaults
Variation range
IDLE_PRIORITY_CLASS
4
2-6
NORMAL_PRIORITY_CLASS
9 or 7 (the front desk is 9, the background is 7)
6-10
HIGH_PRIORITY_CLASS
13
11-15
RealTime_Priority_Class
twenty four
16-31
Thread priority is 1 is a special case. All three levels of idle_priority_class, normal_priority_class, or high_priority_class can set priority to 1.
Note that 32 priorities of Windows 95 are not the definition of WinBase.h. For example, Normal_Priority_Class is defined in WinBase.H as 0x20. KERNEL32.DLL maps these values to the appropriate Windows 95 thread scheduling priority.
GetthreadPriority
GetThreadPriority is a simple function. Give a Thread Handle (which can be any thread in the process), this function converts the handle to a pointer, pointing to Thread Database. If the conversion has no problem, the function returns the Deltapriority member (198h member) in Thread Database. All code is wrapped in an EntersysLvel and a LeavesysLevel to avoid inappropriate thread switching.
Setthreadpriority
The main body of SetThreadPriority is cut into four parts. First, convert the Thread Database to a Thread Database pointer. Then, check the advanced priority (one of the parameters) to see if it is within a reasonable range. Then, the incoming priority is then converted to the priority of the Windows 95 thread scheduler with the internal function CalculateNewPriority.
Finally, SETTHREADPRIORITY calls vwin32.vxd to notify Ring0 layers in a new priority. KERNEL32 calls the Ring0 layer code through the vxdcall function. The RING3 layer code is to use the vxdcall function to call the Win32 VXD service. In this example, Vwin32.vxd provides a RING3 called service function (Service) to set priority. Win32 VXD Service is a new feature of Windows 95. supplement:
NOTE: There are also similar mechanisms in Windows 2000. In Windows 2000, WDM replaces VXD to implement RING0 layers. Since the RING3 layer code can perform the RING0 layer code through VxD, then in Windows 2000, the RING0 level should be executed via WDM. The KV2005 released in 2004 used a driver-level anti-virus engine, which may use this mechanism. Due to the anti-virus engine RING0.
SetPriorityClass
Call this function can change the priority level of the thread. It first converts HProcess into a process_database pointer and then determines the current priority level of the process based on this pointer. If you are the same as the original grade, no longer do anything.
If the level and the original level, SetPriorityClass writes the new level of the default value to the BausPriority member of Process Database. However, first wait, there is still, I have said that the priority of the so-called process is just a concept, because the VMM thread scheduler only cares about the thread, not a process. In order to set up the bridge between the two fields, setPriorityClass finds each thread owned by the process, then calls VMM32.vxd to set new priorities for each thread.
However, it is necessary to pay attention. The priority of the thread can be slightly different from the standard value of its priority level. This difference is placed in the Deltapriority member of Thread Database. SetPriorityClass must obtain a priority amount of each thread - when it calculates new priority. CalculateNewPriority is responsible for this calculation.
GetPriorityClass
This function returns its priority level for a certain process. After converting HProcess into a Process_Database pointer, it removes its priority from the Process Database structure. The value of the priority should be between 1-31, that is not the same as the xxx_priority_class defined in WinBase.h. Therefore, GetPriorityClass must convert the priority level of the VMM thread scheduler to the corresponding xxx_priority_class definition.
supplement:
The value corresponding to the XXXX_Priority_Class defined in WINBASE.H is not actual priority, and the system calculates the actual priority of threads based on these xxx_priority_class, which is: 1-31, in Windows 2000.