This chapter will show you every detail of the GDI handle and the important data structure behind these GDI handles. You may not be interested in the details of the GDI data structure, however, understanding the internal design of GDI/DirectDraw will make you a knowledgeable programmer.
For GDI, common objects include device context, logical paint brush, logical paint brush, logical color palette, and device-related bitmap. Therefore, all device context objects are instances of the device context class, And all logical color palette instances are instances of the logical color palette class. Objects in WIN32API can be considered implemented using abstract base classes without data members. The data representation of objects is completely hidden from user programs. Information Hiding provided by WIN32API greatly improves program portability.
# Pointer and handle
To create an object in the object-oriented language, you need to allocate a memory to save the object member variables. If its class has a virtual function, it needs to assign an Extra pointer and assign it to the pointer pointing to all the virtual functions of the class to implement the routine table. In a language like C ++, pointers to objects are very important. It is passed to all non-static member functions of the class to access the data members of the object and call the correct virtual function. Such a pointer is called the this pointer in C ++.
For WIN32API, although data blocks are allocated to each object, Microsoft does not want to return pointers to user applications. Because the pointer gives the exact location of the object storage, the pointer generally allows read and write operations on the internal representation of the object, and these internal representations may be exactly what the operating system wants to hide. Pointers also make it difficult to cross-process address space consensus objects.
To further hide information for programmers, Win32 object creation routines generally return object handles rather than returning pointers. The handle is defined as a unique identifier of the object value or indirect reference of the object.
The ing between object pointers and handles can be visualized by the encode and decode functions.
# Table-based ing
The most common mechanism for ing between object pointers and handles is table-based ing. In WIN32API, kernel objects are implemented using the process table. Kernel objects include mutex, semaphores, events, registration keys, ports, files, symbolic links, object directories, memory ing files, threads, processes, Windows workstations, desktops, and timers. To accommodate a large number of kernel objects, each process has its own kernel object table.
# Decode the GDI object handle
When a GDI object is created, the handle of the object is obtained. The type of the handle may be Hpen, hbrush, hfont, or HDC, depending on the type of the created GDI object. However, the most common type of GDI object is hgdiobj, and hgdiobj is defined as a null pointer. The actual compilation Type Definition of Hpen varies with the Compilation Time macro strict. In the strict version, warnings are given for incorrect mix of GDI object handles, or for incorrect mix of non-GDI handles, such as hwnd and hmenu, it is acceptable to pass Hpen to the function that accepts hgdiobj, but if the type is not performed, it is not allowed to pass hgdiobj to the function that accepts hbrush.
These clear definitions of different GDI handles mimic the class hierarchies of different classes of the GDI object, but do not use the real class hierarchies. A GDI object only supports one handle of an object. Therefore, you cannot copy a handle to create another handle for the same object. The handle of the GDI object is generally private to the process. That is, only the process that creates the GDI object can use it. It is invalid to pass the sentence to another process on the West Side.
Generally, a GDI object has multiple creation functions and a eobject destructor that accepts hgdiobj. Resource loading functions such as loadbitmap or LoadImage can create necessary GDI objects.
Next, the author uses the program handles to describe the internal principle of hgdiobj. The ing of the object table uses a non-document public function gdiquerytable, but unfortunately, in win7, note: gdiquerytable (unpartitioned ented gdi32.dll Win32 API) and peb-> getsharedgdihandletable don't work on win7. (http://www.chromium.org/developers/how-tos/leak-gdi-object-in-windows), unable to use the gdiquerytable function. (But it is strange that the use of this function is restored on Win8. Speechless.
The example in the author's book (this example also needs to be modified to run correctly on win7). Regardless of the Call Sequence of getstockobject, the handle it returns always a constant. The possible explanation is that the system initializes the heap object and is created and reused by all processes. In addition, we note that although the GDI handle is defined as a pointer in the windef. h file, it is not actually a pointer. The book discusses the maximum number of processes created by GDI and system GDI. I don't think you need to pay attention to them at this stage.
The low 4-bit hexadecimal number of hgdiobj is the index value. The 3rd and 4-bit hexadecimal numbers are the encoding and heap object mark of the GDI object type. The basic structure of the 32-bit hgdiobj handle value is as follows:
8-bit unknown + 1-bit stack OBJECT tag + 7-bit object type + 4-bit unused + 12-bit index.
The document lists the values of the GDI handle type in general cases (3, 4 hexadecimal digits ):
Gdi_objtypeb_dc = 0x01;
Gdi_objtypeb_region = 0x04;
Gdi_objtypeb_bitmap = 0x05;
Gdi_objtypeb_palette = 0x08;
Gdi_objtypeb_font = 0x0a;
Gdi_objtypeb_brush = 0x10;
Gdi_objtypeb_enhmetafile = 0x21;
Gdi_objtypeb_pen = 0x30;
Gdi_objtypeb_extpen = 0x50;
# Locate the GDI handle table
This part is more interesting. You can learn a lot from the analysis. If you are not familiar with memory processing, hurry up and learn about the memory chapter in Windows core programming.
However, since gdiquerytable cannot be correctly called to return the address of the handle table, I cannot verify whether the address I found is actually the address of the handle table, you can try it in another Windows development environment. I cannot verify the structure of the data above the address because I cannot determine the address. List the structure of each table item guessed by the author:
Typedef struct
{
Void * pkernel;
Unsigned short _ nprocess; // NT/200 switch order for _ nprocess, _ ncount
Unsigned short _ ncount;
Unsigned short nupper;
Unsigned short ntype;
Void * puser;
} Gditablecell;
# User mode data structure of the GDI object
User Mode painter data: solid color painter optimized;
User Mode area data: Square area optimization;
User Mode font data: width table;
Device context data in user mode: stores configuration information;
# Access the address space in kernel mode
The kernel-mode driver is a special DLL that complies with a set of rules. If you cannot call WIN32API in the kernel-mode driver, the entry point of WIN32API is in the user-mode address space. The kernel-mode driver is loaded into the kernel address space.
WindowsNT/2000 kernel I/O device drivers generally only have entry point DriverEntry. When the driver is loaded, DriverEntry is called.
Ntstatus DriverEntry (in pdriver_object driver, in punicode_string registrypath)
DriverEntry routines and _ dllmainstartcrtstartup assume the same role-user mode DLL entry point, but unlike user mode DLL, kernel mode drivers generally do not export functions...
To deeply understand the kernel mode address space, we need to compile and execute the peris example in this chapter. However, this requires a lot of knowledge, including some compilation, WIN32API, startservice, opening device files, and completing ports. Fortunately, I have learned from my previous Reading Notes. Although some of them are not very profound, I have been able to improve my impression for the second time. I will go back and review them to consolidate my knowledge. I already have some problems debugging in win7.
In general, this chapter is boring, but it is very basic and has an important inspiration for the deep understanding behind it. I plan to spend more time in this boring chapter to understand some of the ins and outs.