Anatomy of the source code--Deep Windows handle essence

Source: Internet
Author: User

Resources:

1. http://www.codeforge.cn/read/146318/WinDef.h__html

Windef.h header File

2. http://www.codeforge.cn/read/146318/WinNT.h__html

WinNT.h header File

3. https://msdn.microsoft.com/en-us/library/windows/desktop/aa383681%28v=vs.85%29.aspx

Content about strict on Microsoft's website

4.http://wenku.baidu.com/link?url=j0ublizijhgmxthacfwba4ipxrdqyyfg84a9mpmwusn4xhalr94kvadaer6glfcmvd_ Aqortlyfec84-tquwo27dzibxkjndaqxe8ich0eu

Use of "#" and "# #" in C-language macros

5. http://www.cnblogs.com/kerwinshaw/archive/2009/02/02/1382428.html

Usage and differentiation of typedef and # define

6. http://blog.csdn.net/geekcome/article/details/6249151

A profound analysis of the meaning of void and void pointers

Write in front:

This article is an extension to the next previous article, "Graphical description-what exactly is a Windows handle". In the same way, this article is still for beginners. Make programming language easy, let beginners learn you more comfortable, in the communication with the vast number of readers with Mian, is under the consistent purpose and pursuit. Therefore, in the interpretation of the source code, the following will be as detailed as possible, specific to the sentence, for the handle is not particularly relevant to the content, will also be explained. As in the previous article, we still refer to Windows, bitmaps, brushes, etc. collectively as objects.

There is one more thing to be told, and there are some questions about the details of the Windows handle, which will be further explained at the end of the article.

First look at the definition of handle (handle) in WinNT.h:

typedef void *pvoid;

#ifdef STRICT

typedef void *handle;

#define DECLARE_HANDLE (name) struct name# #__ {

int unused;

};

typedef struct name# #__ *name

#else

typedef PVOID HANDLE;

#define DECLARE_HANDLE (name) typedef HANDLE Name

#endif

The above code typedef void *pvoid; from the 178th line in WinNT.h (reference 2), the rest of the code comes from line No. 285 to No. 293 in WinNT.h, with readability in mind, with a slight tweak to the code format.

Before analyzing the source code, again, that is the question of the difference between TypeDef and # define. typedef is used to define an alias for an identifier and a keyword, and # define is a macro definition, simply put, is a string substitution. If you have a reader who is not quite clear, you can refer to resources 5. In the following narrative, we translate both into "definitions". Because under the impression that this can bring about the convenience of the narrative, and if you understand the typedef and the difference between # define, this does not cause misunderstanding of understanding.

Let's start by stepping through the code.

First, typedef void *pvoid, where PVOID is defined as void* type, later, PVOID A, B, equivalent to void *a,*b; (note not void *a,b;). Here's a brief void*, simply stated, void * is the "untyped pointer" and can point to any data type, see Resources 6 for details.

The following section is generally the IF--ELSE structure. Let's look at the If section first.

#ifdef STRICT

If strict is defined, the following code is executed. About strict, in the back we will do a detailed explanation, here we temporarily skip it, first look at the conditions when the code.

#define DECLARE_HANDLE (name) struct name# #__ {

int unused;

};

Here is a macro definition with parameters, name is a parameter, # #为粘贴符号, means to connect the contents of the left and right sides. For a macro definition with parameters and # #, readers can refer to reference 4.

In this case, the structural body

struct name# #__

{

int unused;

};

Defined as

Declare_handle (name).

Next

typedef struct name# #__ *name

Define a pointer name, pointing to the structure above the name# #__.

Below we take the window handle HWND as an example, further explanation.

There is code on line 196th of the windef.h header file (see Resources 1)

Declare_handle (HWND);

We will expand the macro, that is

struct HWND__

{

int unused;

};

Similarly, according to typedef struct name# #__ *name

There are typedef struct HWND__ *hwnd.

That is, the handle HWND is a pointer to the struct struct hwnd__.

Other handles are defined similar to HWND and are not mentioned here, so readers can refer to the code from 195 lines in resources 1.

Note that here we overlook the detail that is the int unused in the struct. In this regard, we will first of all ignore, in the following "Unresolved" section, under the question to be explained.

With the experience of the front, it's easy to analyze the else part of the code, let's see it together.

typedef PVOID HANDLE;

Since the front has a typedef void *pvoid, so here handle is defined as the void* type.

Then

#define DECLARE_HANDLE (name) typedef HANDLE Name

This will

typedef HANDLE Name

Defined as

Declare_handle (name).

Also take the HWND as an example, in which case,

Declare_handle (HWND);

Macro expands to

typedef HANDLE HWND,

That is, the HWND is void* type at this time.

Well, after that, let's focus on strict. For more information, see Resources 3.

The strict is defined in line 13th to 17th of the windef.h header file, which is the following source code:

#ifndef no_strict

#ifndef STRICT

#define STRICT 1

#endif

#endif/* no_strict */

It's just that the strict is defined as a value of 1, and there's nothing to see. The key is that the compiler (note not the system) "interprets" the strict.

As the name implies, strict is "strict", "Stern" meaning. When the compiler "sees" that strict is defined, a strict type check is made on the handles used in Windows applications. The original text in the Windows website is enabling STRICT redefines certain data types so, the compiler does not permit assignment from one type T O Another without an explicit cast.

That is, if you define strict, you are not allowed to convert data from one type to another unless you explicitly enforce type conversions. In other words, defining strict can suppress implicit type conversions.

So, how does this happen, and what is the use of it? Take the window handle HWND and the hook handle hhook as an example. The HWND and hhook are defined on lines 196th and 197 of the windef.h header file:

Declare_handle (HWND);

Declare_handle (Hhook);

From the previous analysis, we know that if strict is defined, then the #ifdef strict code is executed naturally, so that the HWND is the hwnd__* pointer, and Hhook is the hhook__* type pointer, the two types are different. If the strict is not defined, then the #else code will be executed, and it can be found that this code directly defines all the handles as handle, which is pvoid, the void* type. In this case, the above HWND and Hhook are all void* types, the same type. So what's the difference between the two cases? Let us illustrate.

Now a function requires a parameter of type Hhook, and we pass it an hwnd type parameter. In the absence of define strict, this would be legal, since Hhook and HWND are void* types. And if we define Strict,hhook and HWND as two different types of pointers, the arguments passed in the above will become illegal and will be incorrectly compiled, which avoids the programmer knowing that the code is in error until the program has run-time errors.

By the way, now VC, vs both define the strict, that is, the strict type check by default.

At this point, I believe you have understood the role of strict and why not directly with the int unused and to use the structure to encapsulate it.

Finally, let's word to summarize the nature of the Windows handle:

Windows a handle is essentially a pointer to a struct (in the case of define strict).

The so-called "pointer pointer" is not correct, it is only a logical understanding.

Not yet resolved:

Now, let's go back to the question about int unused that we ignored earlier.

If a reader has read the previous article, "illustrated-what exactly is a Windows handle", then believe that someone will be like the original idea, that the unused here is what we call area A. The handle points to a struct, and the unique data unused in the struct holds the address of the object (although unused is not a pointer type, but int and pointer are 4 bytes, the address of the object is stored in the unused, and the object is found in some way by unused in the future. This is also achievable), which coincides with our previous diagram. But a little pondering, we find that this explanation in some places is still somewhat justified. There are at least 2 reasons:

① first is the name problem, I believe that a little careful reader will find this problem. Through the source code to see, each name is aptly reflect its due meaning, as a matter of view, the structure of the int variable stored a useful address, it should not be called unused.

② if unused is equivalent to zone A, in the case of define strict, the handle points to zone A, and in the absence of define strict, there is no struct defined and the handle is defined as the void* type, so where is the zone A in this case? And how does the handle point to it?

Therefore, the synthesis of the previous analysis, under the view that unused is not region a. On the int unused, the next conjecture is:

When a process is created, the system stores the address of each object in one place in memory, while the system assigns a handle to each object, stores it in another place in memory, and points each handle to the address of the corresponding object (that is, zone a). As for how to point, it is likely that:

For cases where the strict is not define, direct pointing is possible because the handle is the void* type. In the case of define strict, a forced type conversion or similar means can be used to point to a 32-bit address to a handle that originally pointed to the struct. Notice that the original handle points to a struct, and there is only one int in the struct, and from the memory point of view, the handle points to a 4-byte memory, and later, the handle points to a 32-bit address, which also points to a 4-byte memory. And if we remove the intunused and keep only an empty structure, we know that the empty structure is 1 bytes (readers who have doubts about this, can write an empty structure, measured with the sizeof () function), when the handle points to 1 bytes of memory, And now to point it at 4 bytes of memory (32-bit address), it is likely that it will not "convert". However, if the handle points to 4 bytes of memory before and after the conversion, it is likely that it will be able to convert. So, the role of int unused is to make the handle point to a 4-byte memory so that the future handle points to the object's address and "translates" smoothly. From the beginning to the end, unused has never been explicitly used, so named unused. Obviously, the unused here means "unused" rather than "useless".

At this point, all the details about the Windows handle are covered.

Write in the back:

1. Under the knowledge of shallow, limited capacity, the explanation of the process will inevitably have errors in the place, here we urge you must criticize correct, in the next first thanked.

2. Regrettably, in the end, there were still some doubts that had not been resolved. Here in the request passed by the great God, but also sincerely hope that the vast number of readers, let us think together and progress together.

Anatomy of the source code--Deep Windows handle essence

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.