Modules, Processes, Threads

xiaoxiao2021-03-06  31

Windows 95 System Programming SECRETS

(Windows 95 system program design big mystery)

Original: Matt Pietrek

Note: Simon Wan

Module, Trip, Performing (Modules, Processes, Threads)

Win32 Module (Modules)

A Win32 module represents a program code, data, and resources of the EXE or DLL loaded by the Win32 loader. Therefore, one module in the memory corresponds to a file in the disk. EXE or DLL itself is not a module. It is the loader reads them into memory and generates modules.

The application uses hModules to represent the loaded module. Win32 does not have a so-called section, so some other methods are required to refer to the loaded module. Microsoft's approach is to let a hmodule becomes the starting linear address when the Win32 loader image PE file. For example, the large part of the exe program is loaded at address 0x400000 (4MB), so their hmodule is 0x400000. Yes, this means that multiple EXEs are executed simultaneously, they have the same HMODULE. This is not a problem, because Windows 95 and NT have maintained a separation address space for each trip.

Win32 requires every trip to have its own module serial. If the module doesn't have implicitly link DLLS, or it is loaded with LoadLibrary DLLS, there is no way to see those DLL modules in memory - even if other strokes are loaded. This is quite different in Win16. Each of Win16's loaded module can be seen by all other strokes, whether there is any reference to the DLL.

Although, "Every Win32 itinerary has its own module serial" This matter has a good impact on security protection and strong solid, it is not very much from "using the program code and resources to save space". Great. After all, if you perform three WinHelp, WinHelp's code should not be loaded three times, right?

Kernel32 must face a laborious choice. From the application vision, each itinerary has its own module serial is good; but from the perspective of Kernel32, a single module serial relatively easily reach the program code and resource sharing. As long as there is a new itinerary to start execution, or a new DLL is loaded, Kernel32 can quickly check the unique all-life module serial, see if the EXE or DLL has been loaded? If so, Kernel32 simply changes its count value. If not, kernel32 needs to generate new modules for it in memory.

KERNEL32 uses two data structures to maintain a whole domain module serial, and make it look like a series of serials in every trip. The first is the data structure IMTE (INTERNAL MODULE TABLE Entry), and the second data structure is modRef.

IMTES (INTERNAL MODULE TABLE ENTRIES)

As shown in Figure 3-1, the all-domain KERNEL32 module serial is actually only the array composed of the IMTES pointer. In the pseudo code listed later, I will point to the pointer of this array with PModuleTableArray. The memory used by this array is configured from the Kernel32 HEAP, which is a block obtained by the general HeapAlloc. The kernel32 utilizes HeapRealloC dynamic expansion or reduced array size using HeapRealloc. When Kernel32 produces a new imte, it will search for blank elements in PModuletableArray; find one, put the Imte metrics. The array index value of this element will have a heavy performance when we search for ModRefs. The first element of PModuletableArray (index is 0) is used to represent the Kernel32.dll module. Let me quickly describe the focus. Each non-zero element in the PModuletableArray represents one loaded EXE or DLL in the system. Each such element is an Imte metric (I am in piMTE)

IMTE structure

The module32.h in the original code in Win32WLK is defined. Every Imte has

The following fields:

l 00h DWORD UN1

This field is used to place some of the flag value.

L 04H PIMAGE_NT_HEADERS PNTHDR

This pointer points to an Image_NT_Headers structure. However, it is just a copy of the content of this structure. The space used in this copy is configured from the Kernel32 HEAP, so it is visible to all the itinerary. The main image_nt_headers structure is located near the base address of the module (possibly below 2GB), can only give the "load this module". Through the copy of the copy, KERNEL32 can easily put any information of any loaded module to all the itinesis, no need to call Ring

0

code

Switch MEMORYCONTEXT.

l 08h DWORD UN2

The meaning of this field is unclear. Its value seems to always -1.

l 0ch pstr pszfilename

Contains an indicator to point to the full file name for EXE or DLL for this module. You can call getModuleFileName to get this full file, and you can use GetModuleHandle to convert the file to your handle. The block placed a full file name is configured from the Kernel32 HEAP.

l 10h pstr pszmodname

Contains a pointer, pointing to the module name. Win32's module name is an EXE or DLL name. For example, the module name of C: /Windows/calc.exe is Calc.exe. PszModName is in fact refers to the PSZFileName, which is mentioned earlier. In the previous example, it will point to "Calc.exe" after the second '/'.

l 14h Word CBFileName

This value indicates the number of characters of the string referred to PSZFileName. GetModuleHandle can use this field to quickly determine if the string is consistent.

l 16h Word CBModName

This value represents the number of characters of the string referred to PszModName. GetModuleHandle can use this field to quickly determine if the string is consistent.

l 18h DWORD UN3

The meaning of this field is unclear.

l 1ch dword csections

The number of Sections (.text, .idata, etc.) contained in this module. This value can also be obtained from the NumberOfSections field in the Image_File_Headers structure (Chapter 8). l 20h DWORD UN5

The meaning of this field is unclear. Its value is always 0, but in COMCTL32.DLL, it contains an indicator to point to a area in Kernel32 HEAP.

l 24h DWord Baseaddress / Module Handle

This field contains the base address of the module. This field can also be interpreted as the module's HMODULE and HINSTANCE in this field. The base address of EXE is almost always 0x40000. The base address of System DLLS is above 2GB, which is a shared memory area. Chapter 8 has more narratives for the base site.

l 28h word hmodule16

This field contains a Selector whose linear address points to a Win16 NE Module Database (which format is detailed in Chapter 7). For Win32 programs, Ne Module Database contains important information, including where you can find resources. This is necessary because the program code bit of the resource is located in KRNL386.EXE and User.exe of Win16. Please note that HModule16 is not configured with Win16's GlobalLococco, so this selector is not like Win16's all-life memory handle, because of this factor and some other factors, Win16 Toolhelp can't see the NE module of the Win32 module .

l 2ah Word Cusage

This field contains a module's reference count. If there are three Calc.exe being executed, this one of Calc.exe's moduleDatabase is 3.

l 2ch DWORD UN7

The meaning of this field is unclear. Usually it contains a legitimate indicator, pointing to a Kernel32 HEAP area.

l 30h pstr pszfilename2

This PSTR (and three fields) is a little mysterious. They seem to "handle this structure 0ch to 16h

Offset position "is the same functions. This field points to a different copy of the exe or DLL full file name. The strings referred to by PSZFileName and PSZFileName2 seem to always have.

l 34h word cbfilename2

This field contains the length of PSZFileName2. It is always the same as the CBFileName field.

l 36h dword pszmodname2

This field points to the module name among PSZFileName2. It is always the same as pszmodname.

l 3ah word cbmodname2

This field contains the length of pszmodname2. It is always the same as the CBModName field.

MODREF structure

A stroke has its own module serial, which does not know anything that other modules loaded by other itzes. Connect the module on each itinerary and the entire domain module table is the Modref structure. Each stroke (except for strange kernel32) is actually a Modref serial, one of which modRef is for the itinerary itself (also constitutes a module), and other modRefs is for each Win32 DLLS for the stroke. ModRefs memory comes from Kernel32 HEAP, which is on 2GB - can share area. Therefore, even if Modrefs makes "every stroke have a module serial" concept, Modref serial actually no one can see. Win32WLK can visit each trip module prove to prove this. Modrefs serial heads are placed among Process Database (discuss later). Each Modrefs structure contains an index and points to the PModuletableArray form. Figure 3-2 shows the relationship between modRefs and IMTES.

The module32.h in the original code in Win32WLK is defined in the modRef structure. Each modref has the following fields:

l 00h pmodref pnextmodref

This pointer points to the next Modref structure in the serial. Serial finally ends with NULL. As long as you get the MODREFS serial head from the process database of the itinerary, then you can track each module used by the itinerary one by one. There is such a demonstration in Win32WLK.

l 10h Word MTEINDEX

A value based on 0-based value represents an index of the PModuletableArray array.

l 18h pvoid ppdb

This is a PPRocess_Database, that is, a metrics pointing to the Process_Database structure, which provides data that is coupled from the Modref back to "The Trip" of this ModRef. I will explore Process_Database later.

Since Windows 95 must appear to be a module serial in every stroke, and the module-related API correspondence such as getModuleHandle is not able to act on the PModuletableArray, they can only serve in their own Modref Action, and then refer to the element item of the whole field module table by the obtained index. For example, getProcAddress is only able to find an module that exhibits the Current Modref serial. Even if this module has been loaded by other strokes, getProcaddress is not able to find it - it is loaded in the current stroke.

Kernel32 item

The K32 object is a key system data structure, placed in the Kernel32 HEAP. There are a variety of K32 objects, all start with the same head. Deciding whether it is a method of k32 object is to ask questions: How can Handles represent this object? For example, an application can have File Handles or Event Handles, so File and Event are K32 objects. I have never seen any application code has MODREF or IMTE Handles, so they are not K32 objects.

Each K32 object begins with a common top head. This header has the following fields:

l 00h dword

Object type. This value determines how to explain the subsequent structural members.

l 04h DWORD This is the number of references, representing the number of times the object is used. For example, when you call getFileinformationByHandle, the number of applications that is asked will be accumulated 1; and before the form of the function, the number of participation will be reduced.

Now, you may be eager to know which K32 object types are known. Here is a list:

K32OBJ_SEMAPHORE (0x1)

K32OBJ_EVENT (0x2)

K32OBJ_MUTEX (0x3)

K32OBJ_CRITICAL_SECTION (0x4)

K32OBJ_PROCESS (0x5)

K32OBJ_THREAD (0x6)

K32OBJ_FILE (0x7)

K32OBJ_Change (0x8; see FindfirstchanGenotification)

K32obj_console (0x9)

K32OBJ_SCREEN_BUFFER (0xA)

K32OBJ_MEM_MAPPED_FILE (0xB; see CREATEFILEMAPPING)

K32OBJ_SERIAL (0xc)

K32OBJ_DEVICE_IOCTL (0xD; see Deviceiocontrol)

K32OBJ_PIPE (0xE)

K32OBJ_MAILSLOT (0xF)

K32OBJ_TOOLHELP_SNAPSHOT (X10; see CreateToolhelp32Snapshot)

K32OBJ_SOCKET (0x11)

The remaining part of this chapter, our main focus is placed on the stroke object and execution oscillate (IDS 5 and 6). A ProcessDatabase is actually a K32_Process object, and a Thread Database is actually a k32_thread object. Just like you are "What is Process Handle? What is the Process ID?" The section is about to see, a process handle table is actually a pointer array, each pointer points to a wide variety of K32 objects.

Windows 95 Itinerary (Processes)

The trip is actually a collection of ownership of a large number of objects. That is, the itinerary has an object. The itinerary can have memory (more accurately said to have MEMORY Context), you can have file handle, you can have a case where you can have a series of DLL modules (which is loaded in the address space of this stroke).

Note that the itinerary does not mean that "execution facts" (executed is). It is not an exe file. Before being loaded, an EXE file is just a program. Only after being loaded, Windows 95 produces a stroke. Once Windows 95 produces a stroke, it also generates a MEMORY Context, which is performed in it. In addition, Windows 95 also produces the first execution to perform the itinerary. If necessary, the itinerary can be generated again. The system also generates a File Handle Table, and the stroke can hold some files on it. Finally, it is also the most important, Windows 95 produces a Process Database to show this trip.

Process Database is a K32 object that contains a lot of information related to the itinerary. We will observe its fields in detail later in the "Windows95 Process Database (PDB)" section. The memory used by Process Database comes from Kernel32 HEAP, so all Process Database can be seen by other strokes. Process Database contains a series of performed, a series of loaded modules, preset Process Heap Handle, pointing to Process Handle Table, and metrics pointing to Memory Context. There are more more things.

What is Process Handle? What is the Process ID?

Process Handle is basically the same as File Handle. It is a value that is not paled, you can't say it is an indicator of anything. The internal system is in fact the Handle of the K32 object as the index of the Process Handle Table. From this array, it is a K32 object pointer. However, since the application does not need to process the Handle Table directly, Process Handle is useless.

Remember, because every application has its own handle table, so different strokes have the same Process Handle in their respective address spaces. For example, every stroke has a process handle for it, and its value is always 1. That is, Process Handle is not a material that can be discriminated. Another example is: If the program opens another Process Handle for this trip, then there are two Handles, corresponding to the same stroke.

A Process Handle is like a File Handle. Don't be meaningless outside the itinerary. As for a process ID, it is a value that does not conflict between the various strokes. It is an indicator, pointing to the Process Database structure, even though Microsoft adds a bit. Win32wlk demonstrates magical conversion formula, converts the Process ID into a useful indicator.

Windows 95 Process Database (PDB)

Each Process Database of Windows 95 is a memory that is configured from the Kernel32 HEAP. KERNEL32 usually replaces and long "Process Database" with a PDB abbreviation. Each PDB is a K32 object that is "the first word group 5 (k32obj_process)". There is a PDB C language definition of the Win32WLK program, and we look at each field:

l 00h dword Type

This value must be 5 (K32Obj_Process)

l 04h dword creference

Reference count. That is, this PDB is used.

l 08h dword un1

The true meaning of this field is unknown. It seems to always 0.

l 0ch dword someevent

This is a pointer to the K32OBJ_EVENT object. EVENT objects are used in WaitForsingleObject.

l 10h DWord TerminationsTatus

When you call getExitCodeProcess, this value is transmitted. The so-called exit code is the return value of Main or WinMain. It can also be specified by EXITPROCESS or TERMINATEPROCESS. This field is 0x103 (STILL_ACTIVE) when a stroke is still executed. l 14h DWORD UN2

The true meaning of this field is unknown. It seems to always 0.

l 18h dword defaultheap

DEFAULT Process HEAP address. GetProcessHeap is back to this value.

l 1ch dword memoryContext

An indicator, pointing to the Memory Context of the itinerary. The so-called Memory Context, which includes Page DirectoryMApping to provide a private area in the 4GB address space. Chapter 5 has more descriptions for Memory Context.

l 20h DWORD FLAGS

The significance of this flag is as follows:

FDEBUGSINGLE 0x00000001 If set, it means that the stroke is being deserted

FcreateProcessEvent 0x00000002 is set up in the extension stroke (after starting)

FEXITPROCESSEVENT 0X00000004 can be set up in the debugging stroke (at the end)

FWIN16PROCESS 0x00000008 represents a 16-bit program

FDoSPROCESS 0x00000010 represents a DOS program

FconsoleProcess 0x00000020 represents a console (text mode) Win32 program

FFileapisareoem 0x00000040 Please see the setFileaPistooem description in the API file

FNukeProcess 0x00000080

FServiceProcess 0x00000100, for example, Msgsrv32.exe

FLOGINSCRIPTHACK 0x00000800 may be a Novell network check-in stroke

FSENDDLNOTIFICATIONS 0X00200000

FDebugeventpending 0x00400000, for example, stopped in the extension

FNEARLYTERMINATING 0x00800000

FFAULTED 0X08000000

Fterminating 0x10000000

Fterminated 0x20000000

FinitError 0x40000000

fsignaled 0x80000000

l 24h DWORD PPSP

This value is the linear address of this trip DOS PSP. Both the Win16 and Win32 programs are set. This linear address is always below 1MB (the highest address you can see). Please refer to the 28h field.

l 28h Word Pspselector

This is a Selector, pointing to this trip DOS PSP. Win16 and Win32 programs have DOS PSP. Please refer to the 24h field.

l 2ah Word MTEINDEX

Here, there is an index value of a pop-domain module table (PModuletableArray). Imtensity taken out via this index value is the IMTE corresponding to this stroke. Imte and PModuletableArray have been discussed previously in this chapter.

l 2ch Word Cthreads

This field records the number of executions owned by this stroke.

l 2Eh Word CNottermthreads

This field records that belong to the strokes and have not yet ended. It should be the same as the previous field. l 30h Word Un3

The true meaning of this field is unknown. It seems to always 0.

L 32h word cring0threads

This field records the number of RING0 execution by VMM32.vxd. For general procedures, its value should be the same as the CTHREADS field value. However, in Kernel32.dll, this value is more than the CTHREADS field value.

l 34h Handle Heaphandle

This field is a Heap Handle, which contains a table (or possibly other things) belonging to this stroke. Here is the Shared Heap Handle of the kernel32.

l 38h htask w16tdb

This is a Selector, pointing to Win16 Task Database (TDB). All Win16 and Win32 programs have TDB Selector and maintain a legitimate TDB.

l 3ch DWord Memmapfiles

An indicator pointing to the first node in the "Serial" composed of the memory image file used in this stroke. Each memory image file appears as a node in the serial. The format of the node is:

The base address of the DWORD memory image file

DWORD points to the next node; or 0.

l 40h Penvironment_Database PEDB

An indicator pointing to Environment Database. Environment Database contains current subdirectory, environment variables, stroke commands, standard Handles, and other projects. I will describe its detailed format in the "EnvironmentDatabase" section.

l 44h phaldle_table phandletable

This is an indicator pointing to Process Handle Table. All Handles is here, including File Handles, Event Handles, Process Handles, etc. Wait. The peer items in the DOS / Win16 environment are DOS's System File Table (SFT). For SFT, please refer to the undocumented dos, second edition of Schulman et al. However, after all, it is different. SFT is suitable for the entire system, Win32 Process Handle Table only applies to a stroke

l 48h struct _process_database * parentpdb

This is an indicator, pointing to the process_database of the parent itinerary. The parent trip is the File Manager of Windows 95. Msgsrv32 is also the parent's parent stroke of Explorer and Initial "Service" Processes.

l 4ch pmodref modReflist

This field points to the start of the stroke module. This is the Modrefs serial in told earlier.

l 50h DWORD thREADLIST

An indicator pointing to the serial integration of the execution in this stroke. I don't know this truth in this serial.

l 54h DWORD Debuggeecb

This is a Context that is deactivated. When a stroke is deactivated, this field points to one area of ​​2GB or more, which contains a pointer, pointing to the PROCESS DATABASE that is removed.

l 58h DWORD LOCALHEAPFREEHEAD This indicator points to the free blocks of "this stroke preset HEAP" start. Chapter 5 has a detailed description of its format.

l 5ch dword initialRing0ID

This field meaning is unknown. It seems to always be 0.

l 60h critical_section CRST

This field is a critical_section, which is used to synchronize all of the execution in the same journey synchronously. You will see this Critical Section in many pseudo codes later.

l 78h dword un4 [3]

The true meaning of these three DWORD is unknown. It seems to always 0.

l 84h DWORD PCONSOLE

If this itinerary uses console (that is, it is a text mode program), this field points to a console object (K32Obj_console) for output.

l 88h dword tlsinusebits1

These 32 bits indicate the lowest 32 TLS (Thread Local Storage) index. If a bit is set, it means that the corresponding TLS index is used. Each TLS index is constantly accumulating its value, for example:

TLS INDEX: 0 = 0x00000001

TLS INDEX: 1 = 0x00000002

TLS INDEX: 2 = 0x00000004

There will be a section to discuss TLS.

l 8ch dword tlsinusebits2

This DWORD represents the state of the 32nd to 63 indexes in TLS. Please refer to the previous field.

l 90h DWord ProcessDword

The meaning of this field is unclear. There is an unappromantry to take out its value.

l 94h struct _process_database * processgroup

This field is not 0, or you don't point to a "stroke group" as the first itinerary. The so-called "stroke group" is a group of strokes that are mutually mutual. This group is destroyed, all of which are also destroyed. Note that every stroke considers yourself in your own "stroke group", and this field points to PDB of your trip. If the itinerary is in the wrong state, it belongs to the extension "stroke group".

l 98h DWORD PEXEMODREF

This field points to the modRef of Exe (which is described above, is a data item in the module serial). In general, the modRef of Exe is a header in the module serial, so this field is usually consistent with the field 4ch, unless the stroke is loaded into other DLLs via loadLibrary or LoadModule.

l 9ch dword topExcfilter

This DWORD is released in the "TOP Exception Filter". If the itinerary does not have any exception handling routines, then use this one. This value is set up via the SetunHandledExceptionFilter function.

l A0h DWORD Basepriority

This DWORD is stored in the trip priority. Windows 95 supports 32 priorities, divided into four levels (listed on the right is its preset priority):

Idle 4

Normal 8

HIGH 13

Realtime 18

In each group, priority can also be slightly adjusted or lowered. There is also a detailed description of this later.

l A4H DWORD HeapownList This field points to the serial integration formed by "HEAPS" of the stroke. Each trip is only one HEAP in the preset, which can be obtained via getProcessHeap. However, it is also possible to call HeapCreate to generate another HEAP. These HEAPs are placed in serial. Chapter 5 has more narratives for this topic.

l a8h dword HeapHandleblockList

The movable block system in Heap is managed by Moveable Handle Table. Each HEAP corresponds to a table. Many tables form a serial. This field points to the serial head. Chapter 5 has more narratives for moveable handletable.

l ACH DWORD PSOMEHEAPPTR

The true meaning of this field is not very clear. Usually it is 0, if it is not 0, it is an indicator, pointing to the modhole table of this itinerary. HEAP. Please see the A8H field.

l B0H DWORD PCONSOLEPROVIDER

This field is not 0, or it is an indicator to point to the main control table object (K32Obj_console) of Kernel32. It seems to always be 0 for Win32 console programs, but for Winoldap it is not 0. WinoldAP is used to manage DOS programs in Windows.

l B4H Word Environselector

This is a selector, pointing to the ridge area. This Selector's base address (base field) and the value of the Environment Database's Pszenvironment field are the same B6H Word ErrorMode contains the value set by SetErrorMode. The SETERRORMODE of Kernel32 will move down the same name of the KRNL386, so this field reacts the Win16 error mode code. They may be:

SEM_FAILCRIRALRORS

SEM_NOALIGHMENTFAULTEXCEPT

SEM_NOGPFAULTERRORBOX

SEM_NOOPENFILEERRORBOX

B8H dword pevtleadfinished

This field points to the Event Object (K32Obj_event) of Kernel32. This event is excited when the itinerary is loaded.

l BCH Word UtState

The meaning of this field is not clear.

ENVIRONMENT DATABASE

The 40H field of Process Database is an indicator, pointing to an important data structure, with information related to the stroke. Inside the KERNEL32, this indicator is PEDB, I explained it to "Pointer to EnvironmentDatabase". Just like Process_Database, I describe the structural layout of Environment_Database in ProCDB.H. Now let's take a look at these fields:

l 00h pstr pszenvironment

This field points to the environmental area of ​​the stroke. The so-called environmental zone is a standard DOS environment (String = Value; string = value). The itinerary environmental area is a memory that is located in each trip private data space, usually on the address of the module loaded.

l 04h DWORD UN1

This field is meaningless. It is usually always 0. l 08h PSTR PSZCMDLINE

This field contains the command column parameters in the CreateProcess function. In most cases this command is a complete EXE file name. Sometimes it will point to an empty string (/ 0).

l 0ch pstr pszcurrdirectory

This field points to the current disk directory.

l 10h lpstartupinfoa pstartupinfo

This is a pointer, pointing to the StartupInfoA structure (defined in WinBase.h). The StartupInfoA structure is one of the parameters of CreateProcess, which can be used to specify the size, title, standard File Handles ..., etc. of the window. This field refers to a copy of this structure.

l 14h Handle Hstdin

This is a File Handle that is used to use it as a standard file input device. This value is -1 if it is not used (for example, a GUI program).

l 18h Handle Hstdout

This is a File Handle that is used to use it as a standard file output device. This value is -1 if it is not used (for example, a GUI program).

l 1ch handle hstderr

This is a File Handle that is used as a standard error output device. This value is -1 if it is not used (for example, a GUI program).

l 20h DWORD UN2

This field is meaningless. It is usually always 1.

l 24h dword inheritconsole

From the name, it can be speculated that this field indicates whether the stroke is inherited from the Console program. Please refer to the create_new_console flag of the createProcess. In my observation, this field is always 0.

l 28h DWord BreakType

This field is most likely to indicate how Console Event is handled. In the program I have implemented, it is usually 0, but it will be 0xa.

l 2ch DWord Breaksem

This is usually 0, but if the process calls setConsolectrlHandle, this field will point to a kernel32semaphore object (k32obj_semaphore).

l 30h DWord Breakevent

This is usually 0, but if the process calls setConsolectrlHandle, this field will point to a kernel32event Object (k32obj_event).

l 34h dword breakthreadid

Usually this is 0, but if the process calls setConsolectrlHandle, this field points to an execution object (K32Obj_thread), and the execution is now installing the execution of this processing routine itself.

l 38h dword breakhandlers

This is usually 0, but if the process calls setConsolectrlHandle, this field will point to a data structure configured from the Kernel32Shared HEAP, put a series of installed main controllers Console ControlHandler.

Process Handle Tables

The 44h offset of Process_Database is an indicator, pointing to the Handle Table of the itinerary. I will use the word representative from Handle Table. In addition to File Handles, Windows 95 also produces Handles of other system objects, like it, execution, Event, Mutex, etc. The content of Handle is in theory that it is opaque, that is, Handle itself has no way to tell you what it is representative. If it is 5, you judge that this is a File Handle or a Mutex Handle. However, once you know the Handle Tables of the Windows 95 itinerary, you can easily generate a Handle value with the data you refer to.

The Handle Table construct of the Windows 95 itinerary is very simple. The first DWORD is placed in the maximum capacity of this table (number of items). This value is initially 0x30 (48). However, this does not mean that there can be only 48 open handles. When the itinerary needs more Handles, Kernel32 reconfigure a memory so that the table has a growth space. Add 0x10 Handles each time. There seems to have no significant upper limit.

After the first DWORD, it is an array composed of many structures. Each structure consists of two DWORD:

DWORD FLAGS

DWORD PK32OBJECT

The second field is an indicator, pointing to 17 possible K32 objects. As for the first field, it is the Access Control Flags of this object. The meaning of these flags is dependent on the object. For a k32obj_process object, these flags will be process_xxx (defined in Winnt.h), like Process_Termnate, Process_VM_READ, and more.

By here, maybe you can feel what is Handle. If you guess your handle is an index, point to Handle Table, you are right! Once you think, you can easily put a Handle value to be compared to the Kernel32 object. A useless handle, two DWORDs must be filled with 0. When the program configures a new Handle, Kernel32 uses the index value of the first blank term in the handle Table as a handle.

Thread (execution 绪)

The itinerary is mainly to express the ownership of File Handles, address space, and so on, which is primarily expressed the implementation facts of the code from the module.

From the abstraction level, performed is a convenient way to perform some part code - when other partial codes are waiting for some external events. After further assigning the work of the itinerary to the execution, you can almost eliminate actions like "pooling loop". Pooling loop Wastes a lot of CPU time. At any time, execution is in three states.

l The first is "Running State). At this time, the CPU buffer content is the cache value of the cache. Other performers are in a done state when an execution is in an execution state.

l The second case is called "Ready to Run State). There is no reason for the execution in this state that it will not be executed - time morning and evening. It is finally possible to control the CPU.

l The third case is called the "Blocked State). If you are blocked, it means that it is waiting for something. The scheduler is not configured before that. It is called Synchronization Objects. Synchronous control objects of Windows 95 have four kinds of critical sections, events, semaphores, mutexes. Initially, each trip started at an execution. If you need, the itinerary can generate more execution.

Like the itinerary, execution is performed with a memory that is configured from the kernel32 shared memory. This memory holds all the necessary information, so that kernel32 is used to maintain an execution. Although I said "All necessary information", in fact this memory has some pointers pointing to other information, but you know what I mean. This book is present in this book called Thread Database, or TDB. Just like ProcessDatabase, Thread Database is a kernel32 item, its first DWORD value is 6, indicating that this is a K32obj_thread object.

If you are a senior programmer, you can rewrite DDK or use WDEB386 or Softice / W, you may have encountered another data structure related to the execution, named THCB (Thread Control Block). THCB is a rendering that is executed in RING0. In Windows 95, it is performed to present RING0 and RING3 two data structures. Ring

0

code

If the VMM VXD is handled via THCB. Ring

3

code

If kernel32 is processed via Thread Database. This chapter describes Ring3 execution behaviors and mechanisms and does not intend to cover the end of Ring0.

The execution kettle itself has something. The first thing is the buffer group (Register Set). As soon as I said earlier, the execution is not being implemented, or if it is not executed (this is not nonsense). When the intent is executed, its buffer group content is placed in the CPU buffer, that is, the EIP value of the execution is the cache EIP value. It is not in the execution state, and its buffer must be stored in memory. Therefore, each of the performed wits have a pointer to a memory buffer, where the buffer content is stored. Another thing that has a relationship with each execution is a trip. All of the actuations in the itinerary share everything in the itinerary, for example, the itinerary has Memory Context and a private address space, so all execution below is executed in the same address space. The itinerary has a handle table, used to refer to files, console, memory mapped files, events, and more, all of the itinerary also share the same Handles. If Handle 3 represents a memory image file, any of the strokes can be used to refer to this memory image file with Handle 3.

There are many other things to do. Each to perform a exclusive stack, a exclusive message queue, a exclusive Thread Local Storage (TLS), and a exclusive structured exception handling string chain. In addition, execution is in the execution process, it may ask, release the ownership of the synchronous control object. After I have seen Thread Database, I will explain all these things.

What is Thread Handle? What is Thread ID? This chapter I have said the difference between the Process Handle and Process IDs earlier. My instructions can be easily set to Thread

Handle and Thread IDs - Just change the "trip" to "Optics". If you are not sure, please

Head to see "What is Process Handle? What is the section of Process ID?".

Thread Database

Thread Database is a K32 object (K32Obj_thread), which is configured from the Kernel32 shared data area. Like Process Database, Thread Database is not directly a serial form. Win32wlk's threaddb.h file has the C language definition of Thread Database, the format is as follows:

l 00h dword Type

This column is 6, indicating the K32obj_thread object.

l 04h dword creference

This column contains the number of applications.

l 08h pprocess_database pprocess

This is an indicator that points to the itinerary to which the execution is.

l 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 given when you call WaitForsingleObject.

l 10h dword pVEXCEPT

This is a pointer, pointing to the structured string head (structured exception handling will be discussed later). Note that this field is also marked with the beginning of the Tib (Thread Information Block nest structure in Task Database. TIB will also be discussed later.

l 14h DWORD TOPOFSTACK

This field is placed is the highest address of the execution stack. Generally, the stack size reserved to the execution is 1MB.

l 18h dword stacklow

This field is placed is a low water level mark (in page) of the execution pile. You can know how much stack is currently used by Topofstack to subtract StackLow.

l 1ch Word W16TDB

It is stored here as the Selector of Win16 Task Database. Chapter 7 tells you that every Win32 itinerary has a Win16 Task Database and a Win32 Process Database.

l 1e Word StackSelector16

Win

32

code

Before the Thunk Down is 16 digits, you must switch to a 16-bit stack. This field is stored as the 16-bit stack of Selector.

l 20h dword selmanlist

An indicator, pointing to SELMANLIST. "Selman" means "Selector Manager". Selman in Kernel32 seems to be responsible for managing Selectors, and execution is configured as a variety of purposes.

l 24h DWORD Userpointer

The precise significance of this field is unclear. However, in the file file of the TIB structure, this field can be used for the application. Don't forget, the TIB structure is nest in Thread Database. l 28h ptib PTIB

This field points to Tib (Thread Information Block). The TIB bit of Windows 95 is in Thread Database, so this indicator actually points to another field of Thread Database: PVEXCEPT field (offset location 10h).

l 2ch Word Tibflags

This field contains some flag values ​​to use it for TIB. They are:

TIBF_WIN32 (0x0001) This execution is from Win32 program

TIBF_TRAP (0x0002) a certain exception handling (Exception Handling)

l 2Eh Word Win16Mutexcount

This field and Win16Mutex (also known as Win16Lock) are a bit related. Usually this field is in -1 in Win32, and is 0 in Win16.

l 30h DWord DebugContext

If the itinerary of the acting intent is being removed, this field will point to a debug context structure. The format of this structure is unknown, but it seems to have some buffer values. If the itinerary is not in the wrong state, this field is 0.

l 34h pdword pcurrentpriority

This field points to a DWORD, inherent priority. This DWORD is located on 0xC0000000, which is truly the power range of VXD.

l 38h dword messagequeue

The low word of this field is placed a Win16 Global Heap Handle to use as a message queue that is executed. The message queue is a place where the window message of the storage system will be stored in Chapter 4. This field is closely related to the 1CH field of W16TDB.

l 3ch dword ptlsArray

This pointer points to the TLS array of performed auxiliary. The items in the array are used in the TLSSetValue functions. TLS will be described later in this chapter. The memory used by the TLS array is behind THREAD DATABASE.

l 40h pprocess_database pprocess2

This field container indicator pointing to the trip to this execution. It seems to always repeat the 08H field.

l 44h dword flags

This park contains a wide variety of flags. Here is some of the flags I know:

FcreateThreadEvent 0x00000001 execution is in the wrong

FcancelexceptionAbort 0x00000002

FontempStack 0x00000004

FgrowableStack 0x00000008

FDELAYSINGLESTEP 0X00000010

Fopenexeasimmovablefile 0x00000020

FcreateSuspended 0x00000040 is specified when CreateProcess is called

CREATE_SUSPENDED

Fstackoverflow 0x00000080

FnestedCleanapcs 0x00000100 APC = Asynchronous Procedure Call

FWASOEMNOWANSI 0x00000200 ANSI / OEM file function

Foktosetthreadoem 0x00000400 ANSI / OEM file features l 48h dword terminationStatus

This field will be later returned by getExitcodetteread. The exit code of the execution can be specified via EXITTHREAD or TERMINATTHREAD. If the read is yet, this field will be 0x103 (STILL_ACTIVE).

l 4ch Word TibSelector

This field is important, with a Selector, represents the Tib (Thread Information Block) of the current execution. The TIB contains an important information, such as the "Head of the ExceptionHandler Chain) of this unusual. When Windows 95 handover, the FS buffer is changed, and this value is stored. In this way, it is possible to get these important data via the FS buffer.

l 4EH Word EmulatorSelector

This field may be a Selector that represents a memory space, where the 80387 emulator status is stored (it may be a FSAVE-style structure). If the machine uses the Math Coprocessor, this column will be 0.

l 50h dword chandles

The meaning of this field is unclear, and it seems to always 0.

l 54h dword waitnodeelist

If the read is waiting for an (above) Event to be excited, this field will point to a serial consisting of the Event node in the VXD area. Each node contains an indicator, pointing to an EVENT object; another indicator, pointing to the performed inhase that is waiting for Event.

l 58h dword un4

The meaning of this field is unclear. Usually it is not 0 is 2.

l 5ch DWord Ring0Thread

This field contains an indicator, pointing to the Ring0 THCB (Thread Control Block) of the executed.

l 60h PTDBX PTDBX

This field contains a pointer and points to the TDBX structure. TDBX is the rendering in Vwin32.vxd, and Chapter 6 has a more detailed description of this structure.

l 64h DWORD StackBase

Perform a win32, this value represents the minimum possible address of the execution stack. With this value to reduce the stack maximum address (14h field of this structure) You can calculate how much address space is left to the stack. This column is 0 for Win16.

l 68h dword terminationStack

Based on its name, this field should contain the ESP value initially used in the execution intent. This field is the same as the Topofstack (14H field) for Win32 execution. For Win16 execution, this field contains an address, which is under Shared Kernel32 HEAP.

l 6ch DWord EmulatorData

I speculate this field is the 32-bit linear address of 80387 emulator data. If this is true, then this field is associated with the EmulatorSelector field (4EH field).

l 70h dword getLastErrorcode

This field contains the return value of getLastError. This value can be set via SetLastError. l 74h dword debuggercb

If the intent is a removal case (that is, it calls WaitFordebugEvent), this field contains a metrics, pointing to the data used by the deactivated error, including the modal Database, ThreadDatabase, and the divided The thread database of the wrong person.

l 78h dword debuggerthread

This field contains a Non-Null value if the insert is unpredictable. It is really unknown because it is too low, not a legal indicator.

l 7ch PCONText ThreadContext

This pointer points to Intel's context structure (defined in Winnt.h). This structure is put in a buffer value in which a unforgettable is not in the execution state. The structure content can be read from the GetThreadContext function and the setthreadContext function.

l 80h dword except16list

This field is meaningless. It seems to be a bit related to the abnormality processing from the name. My observation shows that it is always 0.

l 84h DWORD THUNKCONNECT

The meaning is unclear. It seems to be a bit related to Thunking action from the name. My observation shows that it is always 0.

l 88h dword negstackbase

If you add this field to the StackBase field (64H field), you always get FFEF9000. Do not ask me why.

l 8ch DWord Currentss

This field contains a 16-bit stack Selector, which is related to the 32-bit code down (Thunk Down) to the 16-bit element code. This field seems to be very close to the StackSelector16 field (1EH field), I don't know the difference between the two.

l 90h DWord SSTABLE

This pointer points to a piece of memory, and the information contained in the "32-bit code down (Thunk Down) is related.

l 94h dword thunks16

This field is also an information related to the movement of the Thunk Down. In some cases, it matches the StackSelector16 field (1EH field), and in other cases, it is the same as the currentss field (8CH field).

l 98h dword tlsarray [64]

This is an array of 64 DWORDs. Each DWORD is the "TLSGetValue letter" The value returned according to the known TLS ID ". For example, the first DWORD is a return value of TLSGetValue (0), and the second DWORD is the return value of TLSGetValue (1), and so on. TLS will be described later.

L 198h DWORD DELTAPRIORIRIRITY

This field contains the difference between "priority" this execution 」" and its "priority level". It may be:

Thread_Priority_lowest -2

Thread_priority_below_normal -1

Thread_Priority_NORMAL 0

Thread_priority_above_normal 1 (Translation: The original book is 2, it is wrong) Thread_Priority_Highest 2 (Translation: The original book is 1, it is wrong)

l 19ch DWORD UN5 [7]

The meaning of this field is unclear. It seems to always 0.

l 1b8h dword pcreatedata16

If this field is not 0, it is pointing to a structure. This structure has two 32-bit pointers:

00h pprocessinfo a PPRocess_information

04H Pstartupinfo a PStartupinfo

However, according to my observation, this field is always 0.

l 1bch DWord Apisuspendcount

Whenever SuspendThread once, this field is accumulated 1; whenever calling ResumeThread once, this field is reduced by 1.

l

1C

0h dword un6

The meaning of this field is unclear.

l

1C

4h dword wowchain

This field is related to the support of WOW (Windows On Windows) based on the support of WOW (Windows On Windows). WOW is a method of performing 16-bit programs in its protection address space, which prevents them from destroying 32-bit programs. According to my observation, this field is always 0.

l

1C

8h Word WSSBIG

From its name, this field contains a 32-bit Selector of a smooth mode (FLAT MODAL) as a stack seating area. However, according to my observation, this field is always 0.

l 1cah word un7

The meaning of this field is unclear. It may just be used to fill the space to make the subsequent fields to DWORD as the boundary.

l 1cch dword LP16SwitchRec

The meaning of this field is unclear. From its name, it may be related to Win16 Thunking action.

l 1D0H DWORD UN8 [6]

These five fields seem to always 0.

l 1e8h dword psomecritsect1

This field points to a k32obj_critical_section object. This object is different in every trip, I am not very clear. This field seems to always be the same as psomecritsect2.

l 1ec DWord PWIN16MUTEX

This indicator points to Win16Mutex in KRNL386.EXE.

l

Allf

0h dword PWIN32MUTEX

This indicator points to Win32Mutex in kernel32.dll.

l

Allf

4H dword psomecritsect2

This field points to a k32obj_critical_section object. This object is different in every stroke. This field seems to always be the same as psomecritsect1.

l

Allf

8h DWORD UN9

The meaning of this field is unclear. It seems to always 0.

l 1fch dword ripstring

From its name, this field should be a string pointer that will be used in FataPpexit RIP. However, in most cases this field is 0; if not 0, according to my observation, it does not point to a string.

l 200h dword lasttlssetvalueeip [64]

This array composed of 64 DWORDs is parallel to the TLS array (the 98h offset of Thread Database). Each item in the array is related to a TLS index value, containing the EIP value. The EIP value is removed from the stack (set by TLSSetValue). Finally, I have to add a little: not only one way to get the Thread Database indicator. In addition to the previous I mentioned

Outside the game, every Win16 Task Database also contains an indicator to the corresponding Thread Database. Task

The Database's 54H field has a linear address that represents the first thread Database.

Thread Information Block (TIB)

In Thread Database, some fields are extremely useful for executions. In fact, they are useful, so that the Win32 architecture allows them to be taken immediately without going through Thread Database. These fields are placed in a structure called Thread Information Block (TIB). Thread Database 10H ~ 3CH fields are all put in Tib.

How do applications take TIB? If you have seen the Win32 program assembly language, you will find that the FS buffer has frequent usage. Wait, WIN32 is not a moving section? Although the answer is YES, the Win32 underlayer (including Windows NT, Windows 95, Win32S) dedicates the FS buffer to point to the TIB currently executed. Win32 is not the first operating system, OS / 2 2.0 is old. Just like what you feel, yes, when Windows 95 handovers, the scheduler must change the FS buffer value, let it contain a Selector, point to the new TIB.

The main purpose of the FS buffer and TIB is to increase the number of structural exceptions to structured Exception HandlingChain. The string-chain head is placed at the 0 offset of TIB, so when you see the assembly language code using fs: [0], you know that it is doing some action related to structured exception handling. The other two fields of TIB are also widely used, which are PvQueue and PVTLSARRAY (28h and 2CH fields). The PvQueue field is put into the Handle of the currently performed message queue, which is often used by the User.exe window system. Because in Windows 95, "Focus Window" is not only one throughout the system. PvtlsArray points to the TLS array in Thread Database. The compiler manufacturer uses it and the executable .tls Section, providing transparent "Per-Thread Global Variable".

Although the layout of the TIB structure can be made from Thread Database, I have to give a little summary here. Win32wlk's Tib.h file has a TIB C language structure definition.

The TIB content of Windows 95 is as follows:

00h dword pVEXCEPT

04H dword Topofstack

08h DWORD StackLow

0ch Word W16TDB

0EH Word Stackselector16

10h dword selmanlist

14h DWORD Userpointer18h 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 field, add the offset value of 10 h, then look at the structure content of the last section, you know. Note that only some fields are common to other Win32 platforms.

Thread priority (execution 绪 priority)

Windows 95's VMM core scheduling system does not really care about it, it is only careled by the priority, regardless of which it is to be performed. In other words, the itinerary does not really have priority. Of course, for the end user (which is the application) for the execution oscillatable, "priority" is a relatively useful abstraction. At any time, you have the highest priority to perform, and it is nothing to wait, will be one of the upcoming. To ensure that the system is smooth and avoiding many problems, execution priority can be dynamically changed by the system. For example, when an actuator is performing an I / O action, its priority can be temporarily improved. More detailed discussing this topic, it will take a lot of chapters. Therefore, I will put the discussion of the execution 绪 priority in another book (or in the future magazine article).

Windows 95's VMM schedule supports 32 priority. These 32 priorities are distinguished from four levels, called priority classes, each of which 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 is generated in a stroke is Normal_Priority_Class. The preset priority of the four priority levels and the range of up and down swings are:

IDLE_PRIORITY_CLASS 4 2 ~ 6

NORMAL_PRIORITY_CLASS 9 or 7 (the foreground is 9, the background is 7) 6 ~ 10

High_Priority_Class 13 11 ~ 15

RealTime_Priority_Class 24 16 ~ 31

Performing 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 these 32 priorities in the Windows 95 schedule, which are not defined in WinBase.h. For example, Normal_Priority_Class is defined in WinBase.H as 0x20. Kernel32.dll maps these values ​​to the appropriate Windows 95 schedule priority.

Structured exception handling

Structured exception handling, short-handed SEH) is a topic that has been promoted and often misunderstood in modern operating systems such as OS / 2, Windows NT, Windows 95. Most of the books and articles that talk about it will put it on the compiler level. The compiler uses some reserved words such as __TRY, __EXCEPT, CATCH, THROW, etc., and packages the zero-chained operating system foundation interface. When an exception occurs, the CPU will immediately turn the control to RING0 exception handle, the latter address is placed in the Interrupt Descriptor Table. Ring0 handling a function can determine how it is good. If this is a system know how to deal with the abnormal situation, Ring

0

code

Do the necessary measures, then let the instruction continue. These abnormalities are basically RING

3

code

And System DLLS is invisible, and we don't care about them here. What we have cared here is that if the system does not know how to deal with this abnormal situation, what should I do? The typical response to the old homework system is to cut off the stroke caused by abnormal conditions. This is why you will see a bug that triggered a UAE dialog box (in Windows 3.0) or a GPF dialog (in Windows 3.1) and vigorous screen.

Although the philosophy of "Ending any procedures that causes unpredictable errors" is impeccable, it has no inclusiveness after all. A preferred method is to notify the application (or other applications) to make them decide what to do. If you use Win16 Toolhelp's InterruptRegister, you will see the implementation of this strategy. The application can register a callback in the system via it to handle interrupt and abnormal conditions (but each stroke can only have a handset). When the expected interrupt or exception occurs, ToolHelp will call the registered Callback function and determine how this exception is dealt according to its return value. Winspector or Dr. Watson This type of program uses this way, records the machine status in the abnormal situation. Then, they tell ToolHelp to hand over the abnormal situation to the next handset. Suppose there is no one Toolhelp callback letter that will trigger an exception, and the system-preset exception handle will be evoked, cut off the culprit.

Although Toolhelp's Callback institution is a big step forward (more than a lot of control, it is still not good. 32-bit PC operating systems such as OS / 2 and NT into a more flexible processing method. The new method is what we said structured (SEH). The SEH performance is much better than the previous method in processing multi-execution and use C Catch / Throw mechanism. For C abnormal conditions, the application itself can trigger an exception in one and CPU abnormal conditions. Assuming that the C New Operament fails, it will throw out an abnormal situation that represents insufficient memory. The SEH mechanism of the 32-bit operating system has sufficient elasticity, with the same code, and handles the abnormality of the language and the hardware exception. Before proceeding, I would like to emphasize that SEH I have to talk is the actual situation in which they are at the operating system. The following narrative may be completely different from the training you are in the C / C course. In a system with SEH, each performed in its own private serial, including the installation exception handle. When an exception occurs, the operating system visits the serial, and calls the appropriate functions. Such actions have continued until a letter transfer code, indicating that it is to handle this exception. This is the first phase: find the prostitute. If these functions can handle this exception, the system will come out and cut off the trip of the trouble. We don't care about this plot because the operating system cuts off the trip is very simple. When you get a word for processing anomalies, the second phase is to re-visiting serials again. Unapprounded French RTLunwind made this kind of power, it was called by the "Decision Processing Plus". When RTLunwind triggers a function in serial, the system will give them a flag. This flag tells the form that the stack that is executed is currently being "unwound". The stack "unwinding" is a way to "restore the program status to the state of the abnormality." Do not only resume execution in the __except block, the system also gives each "installed, but not to process this anomalies", one chance to clean yourself. After giving this opportunity, important things such as the "Deconstruction of the C object in the call stack" can be done in a discipline. There are enough theories, what is the structure and interface of Windows 95? When I introduced Tibies, I have said that fs: [0] always points to the serial head of the current unusual tolerance, and the string of the exception handle is a series of ExceptionRegistrationRecord serials. This long name comes from the BSExcept.h file of OS / 2 2.0. For some reason, Microsoft seems to hide the information of the average SEH in the operating system level. The ExceptionRegistrationRecord structure looks like this:

DWORD prev_structure // a Pointer to the Previously Installed

// ExceptionRegistrationRecord

DWORD exceptionhandler // address of the exception handler function.

Serial final is ended in -1 (prev_structure). Under normal circumstances, the program will use the space from the stack to create ExceptionRegistrationRecord. In the C / C program, each ExceptionRegistrationRecord corresponds to a __try / __ except block. When the program enters the __Try block, the compiler generates a new ExceptionRegistrationRecord in the stack and put it on the serial stand. After leaving the __except block, the compiler sets fs: [0] points to the next ExceptionRegistrationRecord in the serial. Figure 3-3 shows these skewers. Remember, the above-mentioned 8-byte structure is only the minimum demand for the operating system. Nothing can prevent the compiler from producing greater structures in the stack and put the ExceptionRegistrationRecord looks at the structure. The compiler can provide sufficient information from other fields obtained in the above structure to make a single exception handler for all __TRY blocks. Microsoft and Borland's compilers use ExceptionRegistrationRecord's expansion structure.

Speaking of abnormal handle functions, what is it looks like? Once again, Microsoft seems to hide certain information, but at least the Win32 header file provides a function of a function. In an excpt.h file, you can see this prototype:

EXCEPTION_DISPSITION __CDECL _EXCEPT_HANDLER

Struct_exception_record * ExceptionRecord,

Void * EstablisherFrame,

Struct_Context * ContexTrecord,

Void * DispatcherContext

);

It seems that it seems to be too complicated. The pass value exception_disposition is actually just an enum, telling the system how this one is used to handle exceptions:

Typedef enum _EXCEPTION_DISPSITION {

ExceptionContinueexecution,

ExceptionContinueSearch,

ExceptionnestedException,

ExceptionCollidedunwind

} EXCEPTION_DISPSITION;

The last two items will be encountered. As for the first ExceptionContinueexecution, it is telling the system that the exception handler has handled the exception situation and intends to let the implementation continue. ExceptionContinueSearch is telling the system that the exception handling routine does not intend to process this exception, the system should continue to visit ExceptionRegistrationRecord serials until a handler is back to ExceptionContinueExecution. Write the _EXCEPT_HANDLER card prototype, it seems to be more acceptable:

INT _EXCEPT_HANDLER

PEXCEPTION_RECORD EXCEPTIONRECORD,

Pvoid ​​Establisherframe,

PCONText ContextRecord,

PVOID DispatcherContext);

We found that an exception handler requires four indicator parameters, pointing to anomalies, and information such as machine status. This letter is transmitted back to an integer and tells the system whether it will handle exceptions. EXCEPTION_RECORD structure contains exception code, and other things. Winnt.h is some instructions for this. The CONTEXT structure contains an abnormally occurred cache, Winnt.h has an explanation. The ESTABLISHERFRAME parameter contains an indicator that points to the setting of the stack-ExceptionRegistrationRecord structure. The DispatcherContext parameter does not seem to be used. I have said earlier, and the handset will be called twice. The first time the system is looking for proper handlers. The second time is for the system to "unwinding", and the process of handling the function is considered to perform any necessary cleaning operations (like the decimal configuration of the call stack, etc.). Where is the difference between this two startup? The ExceptionRecord structure contains an ExceptionFlags flag in the first parameter, if the EH_UNWINDING (0x2) or EH_EXIT_UNWIND (0x4) flag is not set, then the first case; if there are two flags One setup, then the aforementioned second case. Although I am not enough to let you write an abnormal situation in your own operating system level, it is enough to let you know how SEH is working. In order to prove that I didn't blow the air, I wrote a showseh program and put it in the book. Showseh uses the __TRY paragraph to set up an exception handling string chain. After all set up, this program visits SEH serial and prints the content of each node. ShowSeh's output results are shown in Figure 3-4. I want you to pay attention to the point. First, note the "Next REC" field is always incremented, which is the compiler to place the stack area of ​​ExceptionRegistrationRecord. The first four data reflects the __TRY paragraph in Showseh.c. Second, please note that the first four data has a constant ESP value. The last line of the output screen shows the ESP value of each of ShowSeh.c. OFFSET OF __EXCEPT_HANDLER3: 00401468

Next REC Handler

======== ========

0063FD90 00401468

0063FDC0 00401468

0063fdf0 00401468

0063fe30 00401468

0063FF68 00401468

Fffffffff BFFC2D18

IN c (), ESP = 0063fd84

IN b (), ESP = 0063fd78

IN A (), ESP = 0063FDA8

IN main (), ESP = 0063fdd8

The last thing worth noting is that the Handler field of the top five data is the same, and the address is falling in the program area of ​​showseh (not the data area), which shows the code generated by the compiler for each __TRY paragraph. The same exception handler. Just now I said, the first four is the four __try of Showseh.c. As for the 5th, it is installed by the execution periodic library before calling. The location of these processing routines is a function in __except_handler3-Visual C execution period. The last exception handler is a preset system handler, located in kernel32.dll. Thread Local Storage (Space Save Space)

TLS is a good Win32 trait that makes it easier for multi-execution. TLS is a mechanism, via it, the program can have a national variable, but is in the state of "each execution is different." That is, all of the execution in the stroke can have a national variable, but these variables are actually specific to a certain performers. For example, you may have a multi-execute program, each of which is written to different files (and therefore they use different files handle). In this case, it will be very convenient to store the file handle used by each performed intent in TLS. It is necessary to know the Handle used, it can be obtained from TLS. The focus is: Performing a color to obtain the same size of the file handle is the same in any case, and the files from the TLS are different. Very defect, isn't it? There is a convenience of the variables in the whole domain, but it is also affixed.

Of course, you can use serial, let a profile handle with a Thread ID, and each execution is a node. Use this to simulate TLS. When the intended is needed to know which file handle it uses, it can look for a file Handle from the serial. You can of course store the file handle in the zone variable (located in the stack of the case). But it is therefore necessary to transfer this handle between the function and the functions. That pain. TLS can eliminate these issues with a simple Alloc / SET / GET / FREE function. Although TLS is very convenient, it is not unlimited. In Windows NT and Windows 95, there are 64 DWORD Slots for every execution. This means that there is a maximum of 64 "Different Significance for each execution to make a different meaning". In order to keep one slot in each performed, the program should call TLSalloc. Each time you call TLSalloc to pass an index value that can be used by all execution. This index value is often stored in a national variable. When the intent is written to a SLOT, it uses TLSSetValue to confserve a TLS index and a data. Later, when you execute the kettle, it calls TLSGetValue and you will configure a TLS index again. Finally, the program calls TLSFree and gives a TLS index and releases Slot. Of course, if of course, the SLOT will no longer be used by any case, because the TLS index value is common between each execution.

Although TLS can store a single value such as a file handle, a more common use is to place the indicator, pointing to the private information of the executed. There are many cases that multi-execute procedures need to store a bunch of data, and they are related to each execution. Many programmers's practice is to package these variables as a C structure and store the structural pointers in TLS. When a new execution is born, the program configures some memory to this structure and stores the pointer in the TLS that is reserved for execution. Once the thread is completed, the program code releases all configuration blocks. The best demonstration of this program style is the apispy32 of Chapter 10. Apispy32.dll needs to keep a roller, used to pass the functions it intercepted (I am using classical calculator science terminology "stack", in fact I refer to an architecture, and a stack pointer) . Since the intercepted program may have a lot of performed, Apispy32.dll must keep your respective backup addresses for each. If each execution has 64 slots to store the execution to your own data, these spaces play? I have said earlier, and every Thread Database has 64 DWORDs to use TLS. When you set or remove data in a TLS letter, it is true that you really face that 64 dWords. No public file tells us that you can access other TLSs. Let us take a more detailed look at these TLS functions. TLSalloc

Since TLS only provides up to 64 slots to use each perform, there must be some way to track which SLOT has been used. Kernel32 uses two DWORDs (a total of 64 bits) to record which Slot is available, which Slot has been used. These two DWORDs imagine a 64-bit array. If a bit is set, it means that it corresponds to the TLS Slot has been used. This 64-bit TLS Slot array is stored in Process Database (maybe you will guess in Thread Database, no, not this). Remember, when you configure a TLS Slot, this SLOT can be referenced by the index value in any case where the itinerary belongs. 64-bit TLS Slots array placed in Process Database 0x88 and 0x

8C

Two DWORD fields. Although the following TLSalloc functions may look a bit complicated, it doesn't matter. It's just that it is just a bit in the 64-bit array, see if there is 0. If found, change it to 1 and return its array position (index value). Therefore, if the 5th bit is 0, TLSalloc changes it to 1 and passes back 4 (the index value starts from 0).

TLSSetValue

TLSSetValue can put data into previously configured TLS Slot. The two parameters are the TLS Slot index value, respectively, and the data content to be written. The function first checks if the array index is legal (less than 64). The earlier version of Windows 95 also checks if this index is indeed configured, but only the above simple check is made in the beta3 version. If the index value is less than 64, TLSSetValue puts your specified data into an array of 64 DWORDs (located in the current Thread Database) appropriate location. In addition, TLSSetValue updates the second 64 DWORDS array. This array contains the EIP value, and the last time TLSSetValue is called there. Obviously, these EIPs are for sistering. Microsoft does not provide what method allows the application to take this data.

TLSGetValue

This form is almost a mirror of TLSSetValue, the biggest difference is that it takes out data instead of setting data. Like TLSSetValue, this function is also a legal or not, check the TLS index value. If so, TLSGetValue uses this index value to find the corresponding data item of the 64 DWORDS array (located in Thread Database) and turn its content back.

TLSFree

This letter removes all the efforts of TLSalloc and TLSSetValue. TLSFree first verifies that the index value you handed over is indeed configured. If so, it offs the corresponding 64-bit TLS Slots bit. Then, in order to avoid the content that is no longer legitimate, the TLSFree tour is in the trip, put the 0 on the TLS Slot just released. So, if there is a TLS index later being reconfigured, all permeable intensions for this index will guarantee a 0 value, unless they call TLSsetValue.

转载请注明原文地址:https://www.9cbs.com/read-83158.html

New Post(0)