Subclass of Security in Win32 (translation)

Source: Internet
Author: User
Tags ole

The topic of sub-class is somewhat old, but it is still a powerful technology to develop windows, in the core of MFC, even. NET kernel is inseparable from it, I hope this serial can be helpful to the fans of Windows development.


Original title: Safe subclassing in Win32
Kyle Marsh
MSDN Technology Group

Click here to view the original

Summary

This article describes the subclass of the WIN32 environment, describes how it works and the rules that must be followed to implement a secure subclass. This paper covers real-class and global subclasses. The super-class is introduced as an optional alternative to the global sub-class.
From Win16 to Win32, there is no particularly significant change in subclasses, but in Win32, an application adheres to several new subclass rules. One of the most important (and most obvious) of these is that an application cannot subclass a window or class belonging to another process, and this rule cannot be broken unless a workspace is available for use by the application.

Sub-class definition

Sub-class is a technique that allows an application to intercept messages destined for another window. An application implements the default behavior of adding, monitoring, or modifying that window by intercepting messages belonging to another window. Subclasses are an effective way to change or extend the behavior of an existing window without being re-developed. One convenient way to get the functionality of predefined control window classes (Button controls, edit controls, list controls, drop-down list controls, static controls, and scroll bar controls) and to modify some of their behavior is to subclass them. For example, for a multi-line edit box in a dialog box, the dialog box closes when the user presses the ENTER key. By subclasses of the edit control, an application can have an edit control that inserts a carriage return and a newline into the text without closing the dialog box, and the application does not specifically develop an edit control for this particular need.

Sub-Class Basics

The first step in creating a window is to populate a WNDCLASS structure and call the registerclass function to register a window class. One of the members of the WNDCLASS structure is the window procedure address of this window class, when a window is established, the 32-bit version of the Microsoft Windows operating system takes out the window procedure address in the WNDCLASS structure, and copy it into a new window information structure. When a message is sent to this window, Windows invokes the Window's window procedure through this address in the window information structure. In order to subclass a window, you need to replace the original window procedure address with a new window procedure address, so that the new window procedure can receive all messages sent to the original window procedure.
When an application subclasses a window, it can take three kinds of actions on the message: (1) Pass the message to the original window procedure, (2) modify the message and then pass it to the original window procedure; (3) No more messages are passed down.
When an application subclasses a window, it can decide under what circumstances to react to the received message, and the application can process the message before passing the message to the original window procedure or (and).

Sub-class type

There are two types of seed classes, which are real examples and global subclasses .

Real example class is a sub-class of a separate window information structure, after the real example of the class, only the message belonging to a particular window instance will be sent to the new window process.
A global subclass is a window procedure address in a WNDCLASS structure that replaces a window class, all of which are created after this window class with the replaced window procedure address. Global subclasses are only valid for Windows created after the subclass is in effect, and before subclasses, if there are any windows created with this class of global subclasses, the existing Windows will not be overridden. If the application wants to make the subclasses effective for these already existing windows, the application must subclass each instance of the window class that already exists.

There are two rules applied to instance subclasses and global subclasses under Win32.

Subclasses are only allowed to be used within a process, and one application cannot subclass a window or window class belonging to another process.

The cause of this rule is simple: TheWin32 process has a separate process address space. In a particular process, a window process has an address, and in a different process, the address value does not point to the window process, the result is that in one process, using the address obtained from another process to replace the address does not obtain the desired result, so 32-bit Windows does not allow this address substitution to occur. The SetWindowLong and Setclasslong functions prevent this type of subclasses from occurring. You can't subclass a window or window class that belongs to another process, and that's all you can do.

However, there are ways that you can use a class-like function for each process. As long as you can get a function in the address space of a process, you will be able to subclass everything in that process. There are several ways to do this, and one of the easiest (and most unreasonable) ways to do this is to add a dynamic link library name to the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Nt\currentversion\windows\appinit_dlls

This key causes windows to attach your DLL to every process in the system. Your DLL needs some method that can be woken up when the event it is about to subclass occurs, usually a WH_CBT hook can be implemented. This DLL can monitor the Hcbt_createwnd event and then subclass the window it wants to subclass. The example program Ctl3d uses the WH_CBT hook to implement its subclass, although it does not use registry keys to subclass each process, and the application that wants to get the Ctl3d function can link him to the process.

Another way to attach your sub-class code to each process is to use a system hook. When a system hook is called in the context of another process, the system loads the DLL containing the hook into the process space. the code for the sample Ctl3d uses the system WH_CBT hooks in a way that uses the local WH_CBT hooks in the current thread .

The third handler for the class code is more complex to attach to another process: it uses openprocess, writeprocessmemory, and CreateRemoteThread functions to inject code into other processes. I do not recommend this method, and I do not intend to describe in more detail how to implement this method. If someone insists on using this method, Jeffrey Richter has said he plans to describe the technology in one of his upcoming Win32 q&a columns in Microsoft Systems Journal .

Many Windows 3.1 applications now subclass other processes to extend operations and add some cool features. When windows moves to an object-oriented system, object linking and Embedding technology (OLE) provides a better way to implement these features. In future versions of Windows, it may become more difficult to subclass other processes, and OLE might be easier. I recommend that, whenever possible, you should let your application turn to OLE instead of sub-class other processes.

The subclass operation does not use the original window procedure address directly.

In Win16, an application will use the window procedure address returned from the SetWindowLong or Setclasslong function to call the window procedure directly, after all, the return value is simply a pointer to the function, why not use it? In Win32, this practice is a taboo. The return value of the SetWindowLong or Setclasslong function may not be a pointer to the original window procedure at all. Win32 may return a pointer to a data structure that can be used to invoke the current window procedure. This happens in Windows NT when an application subclasses a Unicode window with a non- Unicode window procedure , or when a non-Unicode window is instantiated with a Unicode window procedure . In both cases, the operating system must perform a conversion between Unicode and ANSI for the message received by the window . If an application invokes a window procedure directly with a pointer to this structure, the application immediately causes an exception. The only way to use the window address returned by the SetWindowLong or Setclasslong function is to call the CallWindowProc function with the return value as a parameter.

Real example of class

setwindowlong function is used to subclass one instance of a window. The application must know the address of the subclass function, which is a function that receives a message from windows and passes the message to the original window procedure. The subclass function must be exported in the application or in the module definition file dll.

when the application sub-class window is used, the handle of the window that will be quilt-like, gwl_wndproc flag (in windows. H defines setwindowlong. function setwindowlong returns a dword A value of type , which is the window's original window procedure address, which the application should save to be used to pass intercepted messages to the original window procedure, and to remove subclasses from the window in the future. The application uses the address of the original window procedure and the hwnd windows messages.   Message ,   wParam and lparam parameters Call function callwindowproc Passes a message to the original window procedure. Typically, the application simply passes the data it receives from windows to the function callwindowproc .

The application also needs the original window procedure address to remove the subclasses for the window. By calling the function SetWindowLong again to remove subclasses for the window, the application passes the original window procedure address, theGWL_WNDPROC flag, and the handle of the window that has been quilt-typed to the function.

The following code demonstrates a subclass of an edit box control and the removal of subclasses for it:

LONG far PASCAL subclassfunc (HWND hwnd,uint message,wparam wparam,long lParam);

Farproc Lpfnoldwndproc;
HWND Heditwnd;

//
Create an edit control and subclass it.
The details of this particular edit control is not important.
//

Heditwnd = CreateWindow ("edit", "Edit Test",
Ws_child | ws_visible | Ws_border,
0, 0, 50, 50,
Hwndmain,null,hinst,null);

//
Now subclass the window is just Created.
//

Lpfnoldwndproc = (farproc) SetWindowLong (Heditwnd,gwl_wndproc, (DWORD) subclassfunc);

.
.
.

//
Remove the subclass for the edit control.
//

SetWindowLong (Heditwnd, GWL_WNDPROC, (DWORD) lpfnoldwndproc);

//
Here is a sample subclass function.
//

LONG far PASCAL Subclassfunc (HWND hwnd,
UINT Message,wparam Wparam,long LParam)
{
//
When the inside a dialog box with the focus is in an edit control, the
Default ENTER key action is not occur.
//
if (Message = = Wm_getdlgcode)
return Dlgc_wantallkeys;

Return CallWindowProc (Lpfnoldwndproc, HWnd, Message, Wparam,lparam);
}

Potential flaws

As long as you pay attention to the following safeguard rules, real-case classes are usually safe.

When you subclass a window, you must know who is responsible for the behavior of the window, for example,Windows is responsible for the behavior of all the controls it provides, and the application is responsible for all the windows it defines. Subclasses can work on any window in the same process, but when an application subclasses a window that is not owned by itself, the application must ensure that the subclass function does not break the original behavior of that window. Since the application does not control that window, it should not rely on any window information that is likely to be changed by the owner of the window in the future. A subclass function should not use them unless you know exactly what the window attaches to the bytes or the meaning of the window class additional bytes and how the original window procedure uses them. Step back, even if the application knows everything about the window attached bytes or the window class additional bytes, do not use them unless the application is responsible for the window. If an application uses a window-attached byte of a window that is owned by another component, the subclass process is likely to fail when that component decides to update the window and change the structure of the additional bytes. It is for this reason thatMicrosoft recommends that you do not subclass the control class because Windows is responsible for the controls it provides, and that the next version of Windows may change the appearance of those controls. If your application must subclass a Windows-provided control, the code is likely to need to be updated after the new version of Windows is released.

Since the instantiation of a real example occurs after a window is created, the application sub-class window cannot add any additional bytes to the window, and the application may need to save all the data required for the instance of the Quilt-typed window in the Window's property list.

setprop function to attach a property to a window. The application calls the setprop function as a parameter using the window's handle, a string that identifies the property, and a handle to the property data. The handle of the data is usually called from localalloc or   globalalloc The function obtains. When an application wants to use this data from a window's property list, the getprop function can be called using the window's handle and the string that identifies the property, which returns the setprop function. When the application no longer needs this data or when the window is about to be destroyed, the application must call removeprop using the window handle and the string that identifies the property. function to remove these property data from the property list, the function returns a handle to the data, and the application uses the handle to call the function localfree or function Span lang= "en-us" >globalfree. about function setprop For more information on Getprop and removeprop , see platform sdk documentation.

When an application subclasses a window that has been quilt-like, all subclasses are removed in the reverse order when they are set.

Global sub-class

Global subclasses are similar to instance subclasses. An application can globally subclass a window class by calling the function Setclasslong , as in the case of a real instance, where the application also needs the address of the subclass function, and the subclass function must be exported in the application or in the DLL's module definition file.

To globally subclass a window class, an application must have a window instance of that class. To get a window instance of this class, most applications take a method that belongs to the window class that will be globally subclasses, and when the application wants to remove the subclass, there must also be a window handle that belongs to the window class to which the application is subclasses, so It's a good idea to create and save a window specifically for this purpose. If an application needs to create a window instance of the window class that it wants to subclass, this window instance should usually be invisible. After you have a window handle of the correct type, the application can use the window handle, thegcl_wndproc flag (in WINDOWS. H is defined) and the address of the new subclass function is called as a parameter to the function Setclasslong, which returns a DWORD value that is the original window procedure address of the window class. The use of the original window procedure address in the global subclass is the same as in the real example class, and the window message is passed to the original window procedure by calling the function CallWindowProc as in the real example class. The application can remove subclasses from the window class by calling the Setclasslong function again, by passing parameters that are the window instance handle of the original window procedure address, thegcl_wndproc flag, and the Quilt-class window class. An application that globally subclasses a control must remove the subclasses at the end of the application.

The following code demonstrates a global subclass of an edit box control and the removal of subclasses for it:

LONG far PASCAL subclassfunc (HWND hwnd,uint,message,word wparam,long lParam);
Farproc Lpfnoldclasswndproc;
HWND Heditwnd;

//
Create an edit control and subclass it.
Notice the edit control is not visible.
Other details of this particular edit control is not important.
//
Heditwnd = CreateWindow ("edit", "Edit Test",
Ws_child,
0, 0, 50, 50,
Hwndmain,
Null
HInst,
NULL);

Lpfnoldclasswndproc = (farproc) setclasslong (Heditwnd, Gcl_wndproc, (DWORD) subclassfunc);
.
.
.
//
To remove the subclass:
//
Setclasslong (Heditwnd, GWL_WNDPROC, (DWORD) lpfnoldclasswndproc);
DestroyWindow (Heditwnd);

Potential flaws

Global subclasses have the same limitations as real-world examples, and applications should not attempt to use them unless you know explicitly how the original window procedure uses the additional bytes of the window class and window instances. If the data must be associated with a window, you can use the Window property list as described in the real example class.

In Win32 , global subclasses do not take effect on window classes in any other process or window instances created from those classes, which is a significant change for the WIN16 environment. In the system,Windows separately saves the window class information for each WIN32 process, and you can see the details of windows in this area by referring to the Technical article window Classes in Win32 on MSDN. The current global subclass cannot be applied to other processes, which is a useful technique for developers. In Win16, global subclasses take effect on every window instance of a quilt-typed window class: Not just the application that performs the subclass operation, but also the entire system, which is disappointing. Often this is an effect that the application does not want to achieve, so the application has to use a more inconvenient and bad way to change the behavior of the window instance created from the System window class. Now, in Win32, it is very easy to use global subclasses.

Hyper-Class

A subclass of a window class that causes a message that is originally part of a window procedure to be sent to a subclass function, which then passes the message to the original window procedure, and the superclass (also called the Window class clone) creates a new window class. This new window class uses the window procedure of an already existing window class to add to itself the same functionality as the existing window class, which is based on other window classes-also known as the base class. A base class is often a Windows-predefined control class, but it can also be any other window class.

Note do not superclass the ScrollBar control class, because Windows uses the class name to provide standard behavior for the scrollbar.

Hyper-class has its own window process-the hyper-class process, which can play the same role as the sub-class function. The hyper-class process can implement three actions on a message: (1) Pass the message directly to the original window procedure. (2) modify the message before passing it to the original window procedure. (3) Do not pass the message down. Hyper-class can manipulate messages before, after, or both, before passing the message to the original window procedure.

Unlike a subclass function, a hyper-class process can also receive create messages from windows (such as wm_nccreate, wm_create, etc.), and the superclass can handle these messages, but it must pass these messages to the original base class window procedure. Such a base class window procedure can be initialized

The application calls the function getclassinfo to make a superclass based on a base class. function getclassinfo using wndclass The structure values are populated with a new wndclass structure. The superclass-class application then puts the new wndclass structure hinstance The value of the field is set to the application's own instance handle and must also be lpszclassname The value of the field is set to the new name that it wants to give the superclass. If the base class has a menu, the application of the superclass class must provide a new menu that must have the same menu identifier as the base class's menu. If the superclass is intended to handle wm_command messages and no longer passes the message to the window procedure of the base class, then the identity of the menu may not be the same as the base class. function getclassinfo does not return wndclass structure in the domain   lpszmenuname lpszClassName ,  and   hinstance .

The last one that must be set in the WNDCLASS structure of the superclass is the domain Lpfnwndproc, and the function GetClassInfo populates it with the address of the original window procedure. The application must save this address so that it can pass the message to the window procedure of the base class using the function CallWindowProc . The application wants to set the address value in the WNDCLASS structure to the address of its hyper-class process. This address is not a process instance address, because the function registerclass to get the process instance address. Applications can modify the values of other domains in the WNDCLASS structure to meet the needs of the application.

The application can add bytes to the window class and append bytes to the window instance, because it registers a new window class. When the application does this, it must obey two rules: (1) The original class additional bytes and window instance additional bytes cannot be overridden by the quilt, which is the same as in the case of real-class and global subclasses. (2) If an application adds additional bytes to a window class or window instance because it needs to, it must remain referenced relative to the number of additional bytes used by the base class when referencing these additional bytes. Also, because the base class of a version may use a different number of additional bytes than the next, the starting offset of the superclass's own additional bytes differs depending on the base class version.

When the WNDCLASS structure is populated, the application should call the function registerclass to register the new window class, and now you can create and use a window instance that belongs to the new window class.

Applications typically use hyper-Win16 in the context of an environment, because global subclasses are frustrating in Win16 environments. Now , under Win32, global subclasses are no longer disappointing, so super-class is no longer attractive. But when your application wants to change the behavior of some windows that are just part of all the windows created by a system window class, you can still see that using superclass is useful, instead, it is a global subclass of functionality to work with all windows created from a system window class.

Summarize

Sub-class is a powerful technology, and in the use of Win32 there is no particularly significant changes, the only major change is that you can no longer belong to another process window or window class, although there are ways to bypass this limitation, if you really need this ability, I still recommend porting your application to OLE, which is better than still relying on subclasses.

Well, at this point the entire article has been translated (finally to finish before the holiday), in the Win32 of safe sub-class (1) , provided the text of the English text link, because I time, the level is limited, So welcome everyone to correct the mistakes and omissions in the text, thank you!

Original link: http://www.cnblogs.com/tonybain/archive/2006/01/19/320366.html

Subclass of Security in Win32 (translation)

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.