Advertisement
6_2008-2009 System Services/ Functions #202058

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.

ซอร์สโค้ด
original-source
<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