Desktop控制第二部分 - Hook Desktop

本來今天平安夜,我是要來寫點東西的,結果發現上回的文章(Desktop控制第一部分)沒有人注意,
也沒有人有留言, 故信心大減.

但我還是把: Desktop背景圖設置整理一下.

另外再講一下: Hook Desktop 後的方便, 以及Hook Desktop 的實現原理.


1. Desktop背景圖設置
由於上一篇文章沒有講的很細緻, 這回補充說明一下.

下面的代碼是基於VC6 MFC的. 額外使用類: CDVReg 設置註冊表健值, 這個大家可以自己實現. 這裏不再提供.

 

BOOL SetBackImage(LPCTSTR lpszImage)
{
 
if!lpszImage || 0 == lstrlen( lpszImage ) )
  
return TRUE;

      CString strSubKey 
= "";
  

 
// 下面代碼找到當前用戶的KEY值, 如: S-1-5-21-329068152-1788223648-839522115-500
 HKEY keyUsers = NULL;
 
forint i = 0; i < 24; i ++ )
 {
  DWORD dwRet 
= RegEnumKey( HKEY_USERS, 
   i,
   strSubKey.GetBuffer( 
256 ),
   
256 );
  strSubKey.ReleaseBuffer();

  
if( ERROR_SUCCESS == dwRet )
  {
   CString strCheck 
= strSubKey + "/Software/Microsoft/Internet Explorer/Desktop/General";
   
   HKEY hKeySub 
= NULL;
   
if( ERROR_SUCCESS == RegOpenKey( HKEY_USERS, strCheck, &hKeySub ) )
   {
    RegCloseKey( hKeySub );
    
break;
   }
  }
  
else
  {
   strSubKey 
= "";
   
break;
  }

  strSubKey 
= "";
 }


 
if( strSubKey.IsEmpty() )
  
return FALSE;

 CString strWallPaper 
= lpszImage;
 CString WallpaperStyle 
= "2";  // 風格


 
// 1. 
 CString strPath = "Control Panel/Desktop";
 CString strField 
= "Wallpaper";
 CString strWallpaperStyle 
= "WallpaperStyle";

 
// a.
 BOOL bSet = CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
 
// b.
 strField = "BackupWallpaper";
 bSet 
= CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
 
// c.
 CDVReg::RegString( REG_SET_CURRENT, strPath, strWallpaperStyle, &WallpaperStyle );




 
// 2. 
 strPath = "Software/Microsoft/Internet Explorer/Desktop/General";
 
// a. 
 strField = "Wallpaper";
 CDVReg::RegString( REG_SET_CURRENT, strPath, strField, 
&strWallPaper );
 
// b.
 strField = "BackupWallpaper";
 CDVReg::RegString( REG_SET_CURRENT, strPath, strField, 
&strWallPaper );
 
// c. 
 CDVReg::RegString( REG_SET_CURRENT, strPath, strWallpaperStyle, &WallpaperStyle );



 
// 4. 
 strPath = strSubKey + "/Control Panel/Desktop";
 
// a.
 strField = "Wallpaper";
 CDVReg::RegString( REG_SET_USERS, strPath, strField, 
&strWallPaper );
 
// b.
 strField = "BackupWallpaper";
 CDVReg::RegString( REG_SET_USERS, strPath, strField, 
&strWallPaper );
 
// c.
 CDVReg::RegString( REG_SET_USERS, strPath, strWallpaperStyle, &WallpaperStyle );
 


 
// 5. 
 strPath = strSubKey + "/Software/Microsoft/Internet Explorer/Desktop/General";
 
// a.
 strField = "Wallpaper";
 CDVReg::RegString( REG_SET_USERS, strPath, strField, 
&strWallPaper );
 
// b.
 strField = "BackupWallpaper";
 CDVReg::RegString( REG_SET_USERS, strPath, strField, 
&strWallPaper );
 
// c
 CDVReg::RegString( REG_SET_USERS, strPath, strWallpaperStyle, &WallpaperStyle );



 BOOL b 
= SystemParametersInfo( 0x0014
  NULL, 
  (PVOID)lpszImage, 
  SPIF_UPDATEINIFILE 
| SPIF_SENDCHANGE );
 ASSERT( b );

 
// SPIF_UPDATEINIFILE, SPIF_SENDCHANGE 兩個參數不再說明.
 
// 請參考網上其他人的說明以及MSDN.

 
return TRUE;
}



 

2. HOOK Desktop

A. 爲什麼要Hook desktop

因爲有這樣的情況: desktop上設置了背景圖, 背景圖上有個太陽.
而點太陽, 要做一些事, 比如: 彈出一個網頁之類的.

當然上面只是一種情況, 還有其他的情況也都可以使用HOOK Desktop實現.
或者是使用遠程線程叉入實現.

也可以兩種方式都使用.


B. 如何實現Hook Desktop
最好的方法當然是使用explorer 內部的線程實現hook.
這裏我就不再說明這些細節, 因爲Hook 其實是非常容易使用的.
如果不知道, 請查MSDN: SetWindowsHookEx

我的實現代碼:

頭文件:

#ifndef _WNDPROC_HOOKER_H_
#define _WNDPROC_HOOKER_H_
/////////////////////////////////////////////////////////////
#include <windows.h>

typedef HHOOK (WINAPI
* SetWindowsHookExAProc)(int,HOOKPROC,HINSTANCE,DWORD);
typedef LRESULT (WINAPI
* CallNextHookExProc)(HHOOK,int,WPARAM,LPARAM);
typedef BOOL (WINAPI
* UnhookWindowsHookExProc)(HHOOK);
 
class CHooker
{
 CHooker();

public:
 
static void OnMouseUp( PMSG p );
 
static void InitHook(HWND hWnd);
 
static void UnHook();
 
static void OnMouseMove( PMSG p );

}
;

/////////////////////////////////////////////////////////////
#endif

 


實現文件:

CallNextHookExProc g_ptrCallNextHookEx = (CallNextHookExProc)::GetProcAddress( LoadLibrary( "User32.dll" ), "CallNextHookEx" );
HHOOK g_hHookMessage 
= NULL;


static LRESULT WINAPI GetMsgProc( int code, WPARAM wParam, LPARAM lParam )
{
 PMSG p 
= (PMSG)lParam;

    
if( code == HC_ACTION && p && wParam == PM_REMOVE )
    {
  
if( WM_MOUSEMOVE == p->message )
  {
   CHooker::OnMouseMove( p );
  }
  
else if( WM_LBUTTONUP == p->message )
  {
   CHooker::OnMouseUp( p );
  }
 }

NextHook:
 
if( code == HC_ACTION && p && wParam == PM_REMOVE )
 {
  
return TRUE;
 }
 
else
 {
  
// return CallNextHookEx( g_hMessage, code, wParam, lParam );
  return g_ptrCallNextHookEx( NULL, code, wParam, lParam );
 }
}







void CHooker::InitHook(HWND hWnd)
{
 
if!g_hHookMessage )
 {
  DWORD dwThreadID 
= GetWindowThreadProcessId( hWnd, NULL );
  HINSTANCE hModule 
= (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE); 

  SetWindowsHookExAProc ptrSetWindowsHookExA 
= (SetWindowsHookExAProc)::GetProcAddress( LoadLibrary( "User32.dll" ), "SetWindowsHookExA" );
  
if( ptrSetWindowsHookExA &&
   dwThreadID 
&&
   hModule )
  {
   g_hHookMessage 
= ptrSetWindowsHookExA( WH_GETMESSAGE, GetMsgProc, hModule, dwThreadID );
  }  
 }
}

void CHooker::UnHook()
{
 
if!g_hHookMessage )
 {
  UnhookWindowsHookExProc ptrUnhookWindowsHookEx 
= 
   (UnhookWindowsHookExProc)::GetProcAddress( LoadLibrary( 
"User32.dll" ), "UnhookWindowsHookEx" );
  
  
if( ptrUnhookWindowsHookEx )
  {
   ptrUnhookWindowsHookEx( g_hHookMessage );
  }

  g_hHookMessage 
= NULL;
 }
}



至於:
void CHooker::OnMouseUp(PMSG p)
void CHooker::OnMouseMove(PMSG p)

的實現, 就隨心所欲了. 想怎麼樣就怎麼樣.

 

3. 關於遠程線程的叉入
這裏不再說明, 事實網上實例很多.
那麼是否能在遠程線程內部實現一個Web browser 對象呢?

是可以的. 不過稍微複雜一些.

如果你有這方面問題請留言,或者加入下面的VC技術羣提問.


4. 關於Hook explorer 裏面的文件目錄
並顯示圖像.
事實非常容易, 直接使用Hook 就可以. 至於找wnd, 當然是必須要的.

下篇一內容, 有可能我會做個實例並公開給大家.

如果你有這方面問題請留言,或者加入下面的VC技術羣提問.

 


VC技術羣: 30107096

 


 

發佈了60 篇原創文章 · 獲贊 2 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章