Cross Process Subclassing
This article will explain how to subcalss a window which is not running in the same process as your application.In the demo example, i will subclass the notepad application window,add menus to it and react when those menu's are clicked.
AI
AI 요약: This codebase represents a historical implementation of the logic described in the metadata. Our preservation engine analyzes the structure to provide context for modern developers.
소스 코드
<p align="center"><b><font size="5">Cross Process Subclassing</font></b></p> <p align="center"> </p> <p align="left"><b>In this article I will explain how to subclass the Notepad application window using hooks & subclassing techniques. This technique can be used to build custom dll-based engines for any application. In this example I will subclass the notepad application create custom menus and react when the menu is clicked. You can download a demo application which will do this </b></p> <p align="left"><b>Before I start describing about cross process subclassing ,I presume you already know what the terms hooking and window subclassing mean. Also I presume you have some experience working with hooks and subcalssing in particular and the windows SDK in general. I will just briefly go over these 2 techniques and explain how you could combine both these techniques to achieve cross-process subclassing.</b></p> <p align="left"><b>Windows Hooking</b></p> <p align="left"><b>This is what MSDN has to say about hooks</b></p> <p>"In the Microsoft® Windows® operating system, a hook is a mechanism by which a function can intercept events (messages, mouse actions, keystrokes) before they reach an application. The function can act on events and, in some cases, modify or discard them. Functions that receive events are called <i>filter functions</i> and are classified according to the type of event they intercept."</p> <p> </p> <p><b>You can install different types of hooks like a keyboard hook, a message hook or a mouse hook depending upon your requirements .Hooks can be categorized in 2 ways, </b></p> <p><b>1.Global Hooks 2.Thread Specific Hooks</b></p> <p><b>Global hooks are, as the name suggests Global in nature .A global hook is installed in each and every thread that is running in the system. Global hooks when not properly used tend to be bulky and also slows down the system in many cases.</b></p> <p><b>Thread Specific Hooks are installed in only one process. This hook can be installed in either the same thread as the calling function (to be explained later) or in a thread running in a different process.</b></p> <p><b>Hooks are installed using the SetWindowsHookEx Api and un-installed using the UnhookWindowsHookEx Api.</b></p> <p align="left"> </p> <h2><font size="4">Window Subclassing</font></h2> <p><b>Subclassing allows you to change the behavior of an existing window, typically a control, by inserting a message map to intercept the window's messages. Subclassing is process specific, you cannot subclass a window which is not running in the same process as your application. </b> </p> <p><b>Although the Windows OS does not allow us to subclass a window which is not in the same process as our application, we can work around this by using hooks and getting into the process space of the window that we want to subclass.</b></p> <p> </p> <p><b>Now let's get to building our application.</b></p> <p><b>Our application will consist of 2 modules, the hooking dll which would install/un-install the hook and also subclass the notepad application and an exe which would load the hooking dll.</b></p> <p> </p> <p><b><font size="4">The Hooking Dll</font></b></p> <p><b>The hooking dll will be used to install/uninstall windows hook and also subclass the notepad application window. Before getting into the code for installing/uninstalling and subcalssing let's look at the following piece of code</b></p> <p><font color="#FF0000"><b>#pragma data_seg("Shared")<br> HWND hTarget=NULL;<br> HWND hApp = NULL;<br> int num=0 ;// Number of the subclassed window handle ,for use in the dll<br> bool done=FALSE;<br> HINSTANCE hInstance=NULL;<br> #pragma data_seg()</b></font></p> <p> </p> <p><b>The #pragma data_seg compiler directive asks the compiler to create a data segment which can be shared by all instances of the dll.The reason we need this is because the dll we will be loading using our exe application will be in one process and the dll which would eventually hook the notepad application will be in notepad application's process.So we need a common data segment which can be shared by different instances of the dll .</b></p> <p><b>The code for installing the windows hook looks something like this.</b></p> <p><font color="#FF0000"><b>int WINAPI SetHandle(HWND HandleofTarget ,HWND HandleofApp)<br> {<br> <br> hTarget=HandleofTarget;<br> hApp=HandleofApp;<br> hWinHook=SetWindowsHookEx(WH_CBT,(HOOKPROC)CBTProc,hInstance,GetWindowThreadProcessId(hTarget,NULL));<br> if(hWinHook==NULL)<br> return 0;<br> else<br> return 1;<br> <br> }//End this function</b></font></p> <p> </p> <p><b>We would be installing a CBT hook. A CBT (Computer Based Training) hook is used when we want to be notifed when a window is created/destroyed/activated/minimized etc. The hook callback procedure looks something like this</b></p> <p><b>//The CBT hook Proc(Computer Based Training Hook)<br> <font color="#FF0000">LRESULT CALLBACK CBTProc(int nCode,WPARAM wParam,LPARAM lParam)<br> {<br> <br> <br> if (nCode==HCBT_ACTIVATE) //Called when the application window is activated<br> {<br> if((HWND)(wParam)==hTarget) //check if the window activated is Our Target App<br> { <br> <br> int count;<br> for (count=0;count<num;count++)<br> {<br> if (blnsubclassed[count]==FALSE)<br> { <br> if(((int)hndll[count])>1)<br> {<br> OldWndHndl[count]=SetWindowLong(hndll[count],GWL_WNDPROC,(long)WindowProc); //Subclass !!!!<br> }<br> <br> blnsubclassed[count]=TRUE; // Set state as subclassed<br> }<br> }<br> <br> } <br> }<br> if (nCode==HCBT_DESTROYWND) //Called when the application window is destroyed<br> {<br> if((HWND)wParam==hTarget)<br> SendNotifyMessage(hApp,WM_APP +1024,(WPARAM)wParam,(LPARAM)lParam);// Send the message to the vb app<br> }<br> return CallNextHookEx(NULL, nCode, wParam, lParam);<br> }</font>//End of the hook procedure</b></p> <p><b>We subclass the notepad application as soon as it is activated the first time. The SetWindowLong Api is used to subclass the notepad application.The subclassed winodw procedure looks like this</b></p> <p><b>//Window Procedures of the subclassed windows<br> <font color="#FF0000">LRESULT CALLBACK WindowProc(<br> HWND hwnd,<br> UINT uMsg,<br> WPARAM wParam,<br> LPARAM lParam<br> )<br> { <br> long val;<br> int count;<br> for(count=0;count<num;count++)<br> {<br> if(hndll[count]==hwnd)<br> {<br> val=count; // this gets us the exact position of this window procedure in the array<br> }<br> }<br> long result;<br> if(uMsg==273) //Message Implying Menu Clicks<br> if(HIWORD(wParam)==0)<br> result=SendNotifyMessage(hApp,WM_APP +1024,(WPARAM)(LOWORD(wParam)),(LPARAM)uMsg);// </font>Send the message to //the hooking exe <font color="#FF0000"><br> <br> return CallWindowProc((WNDPROC)OldWndHndl[val],hwnd,uMsg,wParam,lParam);<br> }</font>//End Procedure<br> <br> Whenever a user clicks on a menu in notepad our hooking exe is notified and depending on which menu was clicked our application reacts to the click.</b></p> <p> </p> <p><b><font size="4">The Hooking Exe</font><br> The hooking exe will create the menus and load the hooking dll. The code for doing this is as follows</b></p> <p><font color="#FF0000"><b>hHookedWindow=FindWindow(NULL,"Untitled - Notepad");<br> if(hHookedWindow==NULL)<br> {<br> MessageBox(0,"Could Not find a running instance of Notepad.\r\nPlease Start Notepad and try again","Error",0);<br> break;<br> }<br> HMENU hAppMenu;<br> hAppMenu=GetMenu(hHookedWindow);<br> HMENU hAppendMenu;<br> hAppendMenu=CreateMenu();<br> AppendMenu(hAppMenu,MF_STRING + MF_POPUP,(unsigned int)hAppendMenu,"HTML");<br> AppendMenu(hAppendMenu,MF_STRING,125,"Make HTML");<br> AppendMenu(hAppendMenu,MF_STRING,126,"Add Line Break");<br> HWND hMenuWnd;<br> hLib = LoadLibrary("grimbo.dll");<br> hMenuWnd = GetWindow(hHookedWindow, 5);<br> DWORD hThread;<br> hThread=GetWindowThreadProcessId(hHookedWindow,NULL);<br> SetHandle = (sthndl)GetProcAddress(hLib, "SetHandle");<br> UnSubClass = (unsub)GetProcAddress(hLib, "UnSubclass");<br> SetHandle(hHookedWindow,hwnd);<br> FillHandleArray = (filhndl)GetProcAddress(hLib, "FillHandleArray");<br> FillHandleArray(hHookedWindow,1);<br> FillHandleArray(hMenuWnd,1);</b></p> <p><b> </b></p> </font> <p><b>Thus by using hooks we can subclass a window running in any process. Cross Process Subclassing should be used very carefully , unsafe hooking/subclassing generally results in crashing the application which was subcalssed/hooked.In order to test the demo, compile the dll first and then place the dll in ur windows/system32 directory and then compile the exe.</b></p> <p> </p> <p><b> </b></p>
원본 댓글 (3)
Wayback Machine에서 복구됨