大神帮忙看下这里(已在程序里标出)的UnhookWindowsHookEx有什么作用,我感觉去掉也可以呀?可是一去掉就崩溃,这个dll的作用是跨进程subclass 开始按钮,然后交换鼠标左右键? #include <windows.h>
#include "HookInjEx_DLL.h"
#pragma data_seg (".shared")
int g_bSubclassed = 0;
UINT WM_HOOKEX = 0;
HWND g_hWnd = 0;
HHOOK g_hHook = 0;
#pragma data_seg () #pragma comment(linker,"/SECTION:.shared,RWS") HINSTANCE hDll; // New & old window procedure of the subclassed START button
WNDPROC OldProc = NULL;
LRESULT CALLBACK NewProc( HWND,UINT,WPARAM,LPARAM );
//-------------------------------------------------------------
// DllMain
//
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if( ul_reason_for_call == DLL_PROCESS_ATTACH )
{
hDll = (HINSTANCE) hModule;
::DisableThreadLibraryCalls( hDll ); if( WM_HOOKEX==NULL )
WM_HOOKEX = ::RegisterWindowMessage( "WM_HOOKEX_RK" );
}
return TRUE;
}
#define pCW ((CWPSTRUCT*)lParam) LRESULT HookProc (
int code,
WPARAM wParam,
LPARAM lParam
)
{
if( (pCW->message == WM_HOOKEX) && pCW->lParam )
{
//就是下面这行的UnhookWindowsHookEx有什么作用,我感觉去掉也可以呀?可是一去掉就崩溃,为什么??
::UnhookWindowsHookEx( g_hHook ); if( g_bSubclassed )
goto END; char lib_name[MAX_PATH];
::GetModuleFileName( hDll, lib_name, MAX_PATH );
if( !::LoadLibrary( lib_name ) )
goto END;
OldProc = (WNDPROC)
::SetWindowLong( g_hWnd, GWL_WNDPROC, (long)NewProc );
if( OldProc==NULL )
::FreeLibrary( hDll );
else {
::MessageBeep(MB_OK);
g_bSubclassed = true;
}
}
else if( pCW->message == WM_HOOKEX )
{
::UnhookWindowsHookEx( g_hHook );
if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) )
goto END; ::FreeLibrary( hDll ); ::MessageBeep(MB_OK);
g_bSubclassed = false;
} END:
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
//-------------------------------------------------------------
// NewProc
// Notice: - new window procedure for the START button;
// - it just swaps the left & right muse clicks;
//
LRESULT CALLBACK NewProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch (uMsg)
{
case WM_LBUTTONDOWN: uMsg = WM_RBUTTONDOWN; break;
case WM_LBUTTONUP: uMsg = WM_RBUTTONUP; break; case WM_RBUTTONDOWN: uMsg = WM_LBUTTONDOWN; break;
case WM_RBUTTONUP: uMsg = WM_LBUTTONUP; break; case WM_LBUTTONDBLCLK: uMsg = WM_RBUTTONDBLCLK; break;
case WM_RBUTTONDBLCLK: uMsg = WM_LBUTTONDBLCLK; break;
}
return CallWindowProc( OldProc,hwnd,uMsg,wParam,lParam );
}
//-------------------------------------------------------------
// InjectDll
// Notice:
// - injects "HookInjEx.dll" into "explorer.exe" (via SetWindowsHookEx);
// - subclasses the START button (see HookProc for more details);
//
// Parameters: - hWnd = START button handle
//
// Return value: 1 - success;
// 0 - failure;
//
int InjectDll( HWND hWnd )
{
g_hWnd = hWnd; // Hook "explorer.exe"
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(hWnd,NULL) );
if( g_hHook==NULL )
return 0;
// By the time SendMessage returns,
// the START button has already been subclassed
SendMessage( hWnd,WM_HOOKEX,0,1 ); return g_bSubclassed;
}
//-------------------------------------------------------------
// UnmapDll
// Notice:
// - restores the old window procedure for the START button;
// - unmapps the DLL from the remote process
// (see HookProc for more details);
//
// Return value: 1 - success;
// 0 - failure;
//
int UnmapDll( )
{
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(g_hWnd,NULL) ); if( g_hHook==NULL )
return 0;
SendMessage( g_hWnd,WM_HOOKEX,0,0 ); return (g_bSubclassed == NULL);
}windowscallback
#include "HookInjEx_DLL.h"
#pragma data_seg (".shared")
int g_bSubclassed = 0;
UINT WM_HOOKEX = 0;
HWND g_hWnd = 0;
HHOOK g_hHook = 0;
#pragma data_seg () #pragma comment(linker,"/SECTION:.shared,RWS") HINSTANCE hDll; // New & old window procedure of the subclassed START button
WNDPROC OldProc = NULL;
LRESULT CALLBACK NewProc( HWND,UINT,WPARAM,LPARAM );
//-------------------------------------------------------------
// DllMain
//
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if( ul_reason_for_call == DLL_PROCESS_ATTACH )
{
hDll = (HINSTANCE) hModule;
::DisableThreadLibraryCalls( hDll ); if( WM_HOOKEX==NULL )
WM_HOOKEX = ::RegisterWindowMessage( "WM_HOOKEX_RK" );
}
return TRUE;
}
#define pCW ((CWPSTRUCT*)lParam) LRESULT HookProc (
int code,
WPARAM wParam,
LPARAM lParam
)
{
if( (pCW->message == WM_HOOKEX) && pCW->lParam )
{
//就是下面这行的UnhookWindowsHookEx有什么作用,我感觉去掉也可以呀?可是一去掉就崩溃,为什么??
::UnhookWindowsHookEx( g_hHook ); if( g_bSubclassed )
goto END; char lib_name[MAX_PATH];
::GetModuleFileName( hDll, lib_name, MAX_PATH );
if( !::LoadLibrary( lib_name ) )
goto END;
OldProc = (WNDPROC)
::SetWindowLong( g_hWnd, GWL_WNDPROC, (long)NewProc );
if( OldProc==NULL )
::FreeLibrary( hDll );
else {
::MessageBeep(MB_OK);
g_bSubclassed = true;
}
}
else if( pCW->message == WM_HOOKEX )
{
::UnhookWindowsHookEx( g_hHook );
if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) )
goto END; ::FreeLibrary( hDll ); ::MessageBeep(MB_OK);
g_bSubclassed = false;
} END:
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
//-------------------------------------------------------------
// NewProc
// Notice: - new window procedure for the START button;
// - it just swaps the left & right muse clicks;
//
LRESULT CALLBACK NewProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch (uMsg)
{
case WM_LBUTTONDOWN: uMsg = WM_RBUTTONDOWN; break;
case WM_LBUTTONUP: uMsg = WM_RBUTTONUP; break; case WM_RBUTTONDOWN: uMsg = WM_LBUTTONDOWN; break;
case WM_RBUTTONUP: uMsg = WM_LBUTTONUP; break; case WM_LBUTTONDBLCLK: uMsg = WM_RBUTTONDBLCLK; break;
case WM_RBUTTONDBLCLK: uMsg = WM_LBUTTONDBLCLK; break;
}
return CallWindowProc( OldProc,hwnd,uMsg,wParam,lParam );
}
//-------------------------------------------------------------
// InjectDll
// Notice:
// - injects "HookInjEx.dll" into "explorer.exe" (via SetWindowsHookEx);
// - subclasses the START button (see HookProc for more details);
//
// Parameters: - hWnd = START button handle
//
// Return value: 1 - success;
// 0 - failure;
//
int InjectDll( HWND hWnd )
{
g_hWnd = hWnd; // Hook "explorer.exe"
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(hWnd,NULL) );
if( g_hHook==NULL )
return 0;
// By the time SendMessage returns,
// the START button has already been subclassed
SendMessage( hWnd,WM_HOOKEX,0,1 ); return g_bSubclassed;
}
//-------------------------------------------------------------
// UnmapDll
// Notice:
// - restores the old window procedure for the START button;
// - unmapps the DLL from the remote process
// (see HookProc for more details);
//
// Return value: 1 - success;
// 0 - failure;
//
int UnmapDll( )
{
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(g_hWnd,NULL) ); if( g_hHook==NULL )
return 0;
SendMessage( g_hWnd,WM_HOOKEX,0,0 ); return (g_bSubclassed == NULL);
}windowscallback
解决方案 »
- 比较懂得文件操作和线程的高手们进来看下,谢谢了
- 关于malloc和free的一点疑问
- 请问哪里有电子版的《泛型编程与STL》下载
- Vc连接oracle的问题!
- 有关图像拷贝
- there is error in binding sockets
- Do what?
- 如何在程序里得到资源文件的内容?
- 宏定义的问题,特难
- 救急!!!!!为什么我把BITMAP类型的位图存为.ico图标类型文件,在vc资源resources中import(导入)该ico图标,系统还是将其放入bitmap类型中,而不是icon类型中
- 求大神指教,为何我CEdit设置了焦点后立即失去焦点呢?
- 如何快速的取得MOV的播放时长与分辨率及取得第一帧图像
图1
图2
--------------------------
导致资源管理器崩溃的根源:
注入到Explorer.exe进程中的HookInjEx.dll产生AV异常。导致错误的位置:
位于HookInjEx_DLL.cpp文件的HookProc过程中的“::FreeLibrary( hDll );”代码后,具体的调用栈可以查看上面的图2,正是崩溃时的栈回溯。是什么原因导致上述的AV错误:
祸起钩子。首先需要说明,使用SetWindowsHookEx安装钩子时,后安装的钩子会处子钩子链的最前端。钩子的卸载需要使用UnhookWindowsHookEx。重复安装的钩子不会“覆盖”。分析“案”发过程:
1、启动主程序HookInjEx,当点击“Inject Dll”按钮时,获得资源管理器上的“开始”按钮的句柄(注:在Win7上测试上面的代码时,获取“开始”按钮的句柄使用“hStart = ::FindWindow ("BUTTON",NULL);”代码,否则在Win7上取的句柄为空),然后调用HookInjEx.dll导出的InjectDll过程。在此过程之前还有一个在DllMain过程中需要说明的操作,调用RegisterWindowMessage向系统注册了一个系统范围内惟一的消息。
2、在InjectDll中安装了一个全局的WH_CALLWNDPROC类型的钩子,接着向"BUTTON"这个窗口发送了一个注册的消息,消息的WPARAM=0, LPARAM=1。这个消息的发送,将导致HookProc的调用。
3、在HookProc过程中,因LPARAM=1为1,先使用LoadLibrary( lib_name )加载模块。接着使用SetWindowLong修改窗口的窗口过程。注:在这个过程中因你将"::UnhookWindowsHookEx( g_hHook );"这句注释了,这将导致此钩子过程仍然处于钩子链中。
4、此时在“桌面”的“开始”按钮上测试效果正确。
6、接着退出程序或点击“Unmap Dll”按钮,调用到HookInjEx.dll导出的UnmapDll过程。
7、在UnmapDll过程中,再次调用SetWindowsHookEx安装了同样的一个钩子(注:共两个钩子了,因为之前的钩子并没有被卸载)。接下来使用SendMessage发送了一个WPARAM=0,LPARAM=0的消息。同样导致钩子链上的HookProc被调用。
8、在HookProc的else if 分支处开始执行,首先卸载链上的过程,接着调用SetWindowLong恢复”Button“的窗口过程,然后释放了Dll(并未真的Free,引用计数变为1)。接下来执行“return ::CallNextHookEx(g_hHook, code, wParam, lParam);”对钩子链上的下一个钩子进行调用。
9、然而,这就引发当前钩子过程HookProc被再次调用。同上,首先卸载链上的过程,接着调用SetWindowLong恢复”Button“的窗口过程,然后释放了Dll,此时HookInjEx.dll被正真的从内存卸载,而后从FreeLibraray返回时,eip指针并指向一个不可以为Read的内存区域。这样就更发生了AV错误。
这也是为什么发生错误时,模块的名字变为Unloaded module。注释掉“::UnhookWindowsHookEx( g_hHook ); ”且不报错的方案:
(也是对上面分析的一个证明)
再定义一个HHOOK类型的变量HHOOK g_hOoldHook = 0;用于保存上上一次的安装的钩子句柄。
修改1:int InjectDll( HWND hWnd )
{
g_hWnd = hWnd; // Hook "explorer.exe"
//DC add
if(g_hHook ) g_hOoldHook = g_hHook;
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(hWnd,NULL) );
if( g_hHook==NULL )
return 0; // By the time SendMessage returns,
// the START button has already been subclassed
SendMessage( hWnd,WM_HOOKEX,0,1 ); return g_bSubclassed;
}
修改2int UnmapDll( )
{
// DC add
if( g_hHook ) g_hOoldHook = g_hHook;
g_hHook = SetWindowsHookEx( WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(g_hWnd,NULL) ); if( g_hHook==NULL )
return 0; SendMessage( g_hWnd,WM_HOOKEX,0,0 ); return (g_bSubclassed == NULL);
}
修改3:
LRESULT HookProc (
int code,
WPARAM wParam,
LPARAM lParam
)
{
if( (pCW->message == WM_HOOKEX) && pCW->lParam )
{ //::UnhookWindowsHookEx( g_hHook ); //??为什么把这个地方给注释了,exploer.exe就崩溃了??? if( g_bSubclassed )
goto END; char lib_name[MAX_PATH];
::GetModuleFileName( hDll, lib_name, MAX_PATH ); if( !::LoadLibrary( lib_name ) )
goto END;
OldProc = (WNDPROC)
::SetWindowLong( g_hWnd, GWL_WNDPROC, (long)NewProc );
if( OldProc==NULL )
::FreeLibrary( hDll );
else {
::MessageBeep(MB_OK);
g_bSubclassed = true;
}
}
else if( pCW->message == WM_HOOKEX )
{
::UnhookWindowsHookEx( g_hHook ); // DebugEr-CHEN 添加
if( g_hOoldHook )
::UnhookWindowsHookEx( g_hOoldHook ); if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) )
goto END; ::FreeLibrary( hDll ); ::MessageBeep(MB_OK);
g_bSubclassed = false;
}END:
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
int code,
WPARAM wParam,
LPARAM lParam
)
{
if( (pCW->message == WM_HOOKEX) && pCW->lParam )
{//::UnhookWindowsHookEx( g_hHook ); //??为什么把这个地方给注释了,exploer.exe就崩溃了???if( g_bSubclassed )
goto END; char lib_name[MAX_PATH];
::GetModuleFileName( hDll, lib_name, MAX_PATH );if( !::LoadLibrary( lib_name ) )
goto END;
OldProc = (WNDPROC)
::SetWindowLong( g_hWnd, GWL_WNDPROC, (long)NewProc );
if( OldProc==NULL )
::FreeLibrary( hDll );
else {
::MessageBeep(MB_OK);
g_bSubclassed = true;
}
}
else if( pCW->message == WM_HOOKEX )
{
::UnhookWindowsHookEx( g_hHook );// DebugEr-CHEN 添加
if( g_hOoldHook )
::UnhookWindowsHookEx( g_hOoldHook );if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) )
goto END;::FreeLibrary( hDll ); ::MessageBeep(MB_OK);
g_bSubclassed = false;
}END:
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}