MORE INFORMATION
For a 16-bit application, sub-classing methods are the same as they were in
Windows version 3.1. However, Windows 95 performs some behind-the-scenes
magic to make it possible for a 16-bit window to subclass a 32-bit window.
Usually, a subclass consists of saving one window procedure and
substituting another in its place. However, this could present a problem
when a 16-bit application tries to call a 32-bit window procedure. Windows
95 works around this potential problem by providing 32-bit windows with a
16-bit window procedure. All 32-bit windows will have the same selector for
their wndProcs that references code in KRNL386.EXE where the 16-bit
wndProcs for all 32-bit windows are stored. Eventually, each of these
16-bit wndProcs will jump to the real 32-bit window procedure.
Sub-classing windows belonging to another process, either 16-bit or 32-bit,
from a 32-bit process or application works as it does in Windows NT. The
difficulty is that each 32-bit process has its own private address space.
Hence, a window procedure's address in one process is not valid in another.
To get a window procedure from one process into another, you need to inject
the subclass procedure code into the other process's address space. There
are a number of ways to do this.
Method 1: Windows 95 and Windows NT
You can use the registry, hooks, or remote threads and the
WriteProcessMemory() API to inject code into another process's address
space.
Method 2: Windows NT Only
If you use the registry, the code that needs to be injected should reside
in a DLL. By either running REGEDIT.EXE or using the registry APIs, add the
\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\AppInit_DLLs key to the
registry if it does not exist. Set its value to a string containing the
DLL's pathname. This key may contain more than one DLL pathname separated
by single spaces. This has the effect, once the machine is restarted, of
loading the library with DLL_PROCESS_ATTACH into every process at its
creation time. While this method is very easy, it also has several
disadvantages. For example, the computer must be restarted before it takes
effect, and the DLL will last the lifetime of the process.
Method 3: Windows 95 and Windows NT
You can also use hooks to inject code into another process's address space.
When a window hooks another thread belonging to a different process, the
system maps the DLL containing the hook procedure into the address space of
the hooked thread. Windows will map the entire DLL, not just the hook
procedure.
Because of this mapping, the target process will get a fresh copy of all
the DLL[ASCII 146]s variables. Any changes to variables that are created by one
process will not be available to another. One way to share DLL data among
processes is to create a shared section:
#pragma data_seg(".MyData")
HWND hMyWin = NULL
HHOOK ghMyHookProc = MyProcedureName
...other data
#pragma data_seg()
These items should be initialized when the share is created. Please review
the documentation on Win95[ASCII 146]s memory management to make sure that your data
is sharable.
Be aware that shared sections are a violation of Level B security on WinNT
systems, so be careful about what kind of data gets placed in these
sections.
To subclass a window in another process, install a
WH_GETMESSAGE hook or another such hook on the thread that owns the window
to be sub-classed. In the DLL that contains the hook procedure, include the
subclass window procedure. In the hook procedure, call SetWindowLong() to
enact the subclass. It is important to leave the hook in place until the
subclass is no longer needed, so the DLL remains in the target window's
address space. When the subclass is removed, the hook would be unhooked,
thus un-mapping the DLL.
A third way to inject a DLL into another address space involves the use of
remote threads and the WriteProcessMemory() API. It is more flexible and
significantly more complicated than the previously mentioned methods, and
is described in the following reference.