📄 hooks.cpp
字号:
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#pragma hdrstop
#include "Hooks.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma data_seg(".SharedData")
HWND hVeneto = NULL;
UINT UpdateRectMessage = 0;
UINT CopyRectMessage = 0;
UINT MouseMoveMessage = 0;
HHOOK hCallWndHook = NULL; // Handle to the CallWnd hook
HHOOK hGetMsgHook = NULL; // Handle to the GetMsg hook
HHOOK hDialogMsgHook = NULL; // Handle to the DialogMsg hook
HHOOK hLLKeyboardHook = NULL; // Handle to LowLevel kbd hook
HHOOK hLLMouseHook = NULL; // Handle to LowLevel mouse hook
#pragma data_seg( )
const char sPrefSegment[] = "Application_Prefs\\";
char *sModulePrefs = NULL; // Name of the module that created us
BOOL prf_use_GetUpdateRect = FALSE; // Use the GetUpdateRect paint mode
BOOL prf_use_Timer = FALSE; // Use Timer events to trigger updates
BOOL prf_use_KeyPress = FALSE; // Use keyboard events
BOOL prf_use_LButtonUp = TRUE; // Use left mouse button up events
BOOL prf_use_MButtonUp = FALSE; // Use middle mouse button up events
BOOL prf_use_RButtonUp = FALSE; // Use right mouse button up events
BOOL prf_use_Deferral = FALSE; // Use deferred updates
HKEY hModuleKey = NULL; // Key used to save settings
HINSTANCE hInstance = NULL; // This instance of the DLL
BOOL HookMaster = FALSE; // Is this instance veneto itself?
BOOL appHookedOK = FALSE; // Did InitInstance succeed?
BOOL HookHandle(UINT msg, HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK CallWndProc (int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK DialogMessageProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelMouseFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
BOOL ExitInstance();
BOOL InitInstance();
// Messages
const UINT CN_DEFERRED_UPDATE = RegisterWindowMessage("CNHooks.Deferred.UpdateMessage");
// Atoms
const char *CN_WINDOWPOS_ATOMNAME = "CNHooks.CopyRect.WindowPos";
const char *CN_POPUPSELN_ATOMNAME = "CNHooks.PopUpMenu.Selected";
ATOM CN_WINDOWPOS_ATOM = NULL;
ATOM CN_POPUPSELN_ATOM = NULL;
DllExport BOOL SetHook(HWND hWnd, UINT UpdateMsg, UINT CopyMsg, UINT MouseMsg)
{
// Don't add the hook if the window ID is NULL
if (hWnd == NULL)
return FALSE;
// Don't add a hook if there is already one added
if (hVeneto != NULL)
return FALSE;
// Add the CallWnd hook
hCallWndHook = SetWindowsHookEx(WH_CALLWNDPROC, // Hook in before msg reaches app
(HOOKPROC) CallWndProc, // Hook procedure
hInstance, // This DLL instance
0L // Hook in to all apps
// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC
);
// Add the GetMessage hook
hGetMsgHook = SetWindowsHookEx( WH_GETMESSAGE, // Hook in before msg reaches app
(HOOKPROC) GetMessageProc,// Hook procedure
hInstance, // This DLL instance
0L // Hook in to all apps
// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC
);
// Add the GetMessage hook
hDialogMsgHook = SetWindowsHookEx(
WH_SYSMSGFILTER, // Hook in dialogs, menus and scrollbars
(HOOKPROC) DialogMessageProc, // Hook procedure
hInstance, // This DLL instance
0L // Hook in to all apps
);
// Check that it worked
if ((hCallWndHook != NULL) && (hGetMsgHook != NULL) && (hDialogMsgHook != NULL))
{
hVeneto = hWnd; // Save the WinRFB window handle
UpdateRectMessage = UpdateMsg; // Save the message ID to use for rectangle updates
CopyRectMessage = CopyMsg; // Save the message ID to use for copyrect
MouseMoveMessage = MouseMsg; // Save the message ID to send when mouse moves
HookMaster = TRUE; // Set the HookMaster flag for this instance
return TRUE;
}
else
{
// Stop the keyboard hook
SetKeyboardFilterHook(FALSE);
SetMouseFilterHook(FALSE);
// Kill the main hooks
if (hCallWndHook != NULL)
UnhookWindowsHookEx(hCallWndHook);
if (hGetMsgHook != NULL)
UnhookWindowsHookEx(hGetMsgHook);
if (hDialogMsgHook != NULL)
UnhookWindowsHookEx(hDialogMsgHook);
hCallWndHook = NULL;
hGetMsgHook = NULL;
hDialogMsgHook = NULL;
}
// The hook failed, so return an error code
return FALSE;
}
BOOL CALLBACK
KillPropsProc(HWND hwnd, LPARAM lParam)
{
// Remove our custom property...
RemoveProp(hwnd, (LPCTSTR) MAKEWORD(CN_WINDOWPOS_ATOM, 0));
RemoveProp(hwnd, (LPCTSTR) MAKEWORD(CN_POPUPSELN_ATOM, 0));
return TRUE;
}
// Remove the hook from the system
DllExport BOOL UnSetHook(HWND hWnd)
{
BOOL unHooked = TRUE;
// Remove the extra property value from all local windows
EnumWindows((WNDENUMPROC) &KillPropsProc, NULL);
// Stop the keyboard & mouse hooks
unHooked = unHooked && SetKeyboardFilterHook(FALSE);
unHooked = unHooked && SetMouseFilterHook(FALSE);
// Is the window handle valid?
if (hWnd == NULL)
MessageBox(NULL, "Window pointer is null", "Message", MB_OK);
// Is the correct application calling UnSetHook?
if (hWnd != hVeneto)
return FALSE;
// Unhook the procs
if (hCallWndHook != NULL)
{
unHooked = unHooked && UnhookWindowsHookEx(hCallWndHook);
hCallWndHook = NULL;
}
if (hGetMsgHook != NULL)
{
unHooked = unHooked && UnhookWindowsHookEx(hGetMsgHook);
hGetMsgHook = NULL;
}
if (hDialogMsgHook != NULL)
{
unHooked = unHooked && UnhookWindowsHookEx(hDialogMsgHook);
hDialogMsgHook = NULL;
}
// If we managed to unhook then reset
if (unHooked)
{
hVeneto = NULL;
HookMaster = FALSE;
}
return unHooked;
}
// Routine to start and stop local keyboard message filtering
DllExport BOOL SetKeyboardFilterHook(BOOL activate)
{
if (activate)
{
#ifdef WH_KEYBOARD_LL
if (hLLKeyboardHook == NULL)
{
// Start up the hook...
hLLKeyboardHook = SetWindowsHookEx(
WH_KEYBOARD_LL, // Hook in before msg reaches app
(HOOKPROC) LowLevelKeyboardFilterProc,// Hook procedure
hInstance, // This DLL instance
0L // Hook in to all apps
);
if (hLLKeyboardHook == NULL)
return FALSE;
}
return TRUE;
#else
#pragma message("warning:Low-Level Keyboard hook code omitted.")
return FALSE;
#endif
} else {
if (hLLKeyboardHook != NULL)
{
// Stop the hook...
if (!UnhookWindowsHookEx(hLLKeyboardHook))
return FALSE;
hLLKeyboardHook = NULL;
}
return TRUE;
}
}
// Routine to start and stop local mouse message filtering
DllExport BOOL SetMouseFilterHook(BOOL activate)
{
if (activate)
{
#ifdef WH_MOUSE_LL
if (hLLMouseHook == NULL)
{
// Start up the hook...
hLLMouseHook = SetWindowsHookEx(
WH_MOUSE_LL, // Hook in before msg reaches app
(HOOKPROC) LowLevelMouseFilterProc,// Hook procedure
hInstance, // This DLL instance
0L // Hook in to all apps
);
if (hLLMouseHook == NULL)
return FALSE;
}
return TRUE;
#else
#pragma message("warning:Low-Level Mouse hook code omitted.")
return FALSE;
#endif
} else {
if (hLLMouseHook != NULL)
{
// Stop the hook...
if (!UnhookWindowsHookEx(hLLMouseHook))
return FALSE;
hLLMouseHook = NULL;
}
return TRUE;
}
}
// Routine to get the window's client rectangle, in screen coordinates
inline BOOL GetAbsoluteClientRect(HWND hwnd, RECT *rect)
{
POINT topleft;
topleft.x = 0;
topleft.y = 0;
// Get the client rectangle size
if (!GetClientRect(hwnd, rect))
return FALSE;
// Get the client rectangle position
if (!ClientToScreen(hwnd, &topleft))
return FALSE;
// Now adjust the window rectangle
rect->left += topleft.x;
rect->top += topleft.y;
rect->right += topleft.x;
rect->bottom += topleft.y;
return TRUE;
}
// Routine to send a CopyRect message to WinVNC
inline void SendCopyWindowRect(HWND hWnd)
{
WPARAM vwParam;
// All we send back is the handle of the window to be moved
vwParam = (LPARAM) hWnd;
// Send the update to Veneto
PostMessage(
hVeneto,
CopyRectMessage,
vwParam,
0
);
}
// Routine to send an UpdateRect message to Veneto
inline void SendUpdateRect(SHORT x, SHORT y, SHORT x2, SHORT y2)
{
WPARAM vwParam;
LPARAM vlParam;
vwParam = MAKELONG(x, y);
vlParam = MAKELONG(x2, y2);
// Send the update to Veneto
PostMessage(
hVeneto,
UpdateRectMessage,
vwParam,
vlParam
);
}
// Send a window's position to Veneto
inline void SendWindowRect(HWND hWnd)
{
RECT wrect;
// Get the rectangle position
if (GetWindowRect(hWnd, &wrect) && IsWindowVisible(hWnd))
{
// Send the position
SendUpdateRect(
(SHORT) wrect.left,
(SHORT) wrect.top,
(SHORT) wrect.right,
(SHORT) wrect.bottom
);
}
}
// Send a deferred message into this Window's message queue, so that
// we'll intercept it again only after the message that triggered it has been
// handled
inline void SendDeferredUpdateRect(HWND hWnd, SHORT x, SHORT y, SHORT x2, SHORT y2)
{
WPARAM vwParam;
LPARAM vlParam;
vwParam = MAKELONG(x, y);
vlParam = MAKELONG(x2, y2);
if (prf_use_Deferral)
{
// Send the update back to the window
PostMessage(
hWnd,
CN_DEFERRED_UPDATE,
vwParam,
vlParam
);
}
else
{
// Send the update to WinRFB
PostMessage(
hVeneto,
UpdateRectMessage,
vwParam,
vlParam
);
}
}
inline void SendDeferredWindowRect(HWND hWnd)
{
RECT wrect;
// Get the rectangle position
if (::GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))
{
// Send the position
SendDeferredUpdateRect(
hWnd,
(SHORT) wrect.left,
(SHORT) wrect.top,
(SHORT) wrect.right,
(SHORT) wrect.bottom
);
}
}
inline void SendDeferredBorderRect(HWND hWnd)
{
RECT wrect;
RECT crect;
// Get the rectangle position
if (GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))
{
// Get the client rectangle position
if (GetAbsoluteClientRect(hWnd, &crect))
{
// Send the four border rectangles
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) crect.top);
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) crect.left, (SHORT) wrect.bottom);
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) crect.bottom, (SHORT) wrect.right, (SHORT) wrect.bottom);
SendDeferredUpdateRect(hWnd, (SHORT) crect.right, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) wrect.bottom);
}
}
}
// Generic hook-handler
inline BOOL HookHandle(UINT MessageId, HWND hWnd, WPARAM wParam, LPARAM lParam)
{
////////////////////////////////////////////////////////////////
// *** HANDLE DEFERRED UPDATES ***
// Is this a deferred-update message?
if (MessageId == CN_DEFERRED_UPDATE)
{
// NOTE : NEVER use the SendDeferred- routines to send updates
// from here, or you'll get an infinite loop....!
// NB : The format of DEFERRED_UPDATE matches that of UpdateRectMessage,
// so just send the exact same message data to WinRFB:
PostMessage(
hVeneto,
UpdateRectMessage,
wParam,
lParam
);
return FALSE;
}
// *** Could use WM_COPYDATA to send data to WinVNC
/*
if (GetClassLong(hWnd, GCW_ATOM) == 32768)
{
_RPT4(_CRT_WARN, "DBG : popup menu message (hwnd=%d, msg=%d, l=%d, w=%d)\n",
hWnd, MessageId, lParam, wParam);
}
*/
////////////////////////////////////////////////////////////////
// *** UPDATE-TRIGGERING MESSAGES ***
// Do something dependent upon message type
switch (MessageId)
{
////////////////////////////////////////////////////////////////
// Messages indicating only a border repaint.
case WM_NCPAINT:
case WM_NCACTIVATE:
SendDeferredBorderRect(hWnd);
break;
////////////////////////////////////////////////////////////////
// Messages indicating a client area repaint
case WM_CHAR:
case WM_KEYUP: // Handle key-presses
if (prf_use_KeyPress)
SendDeferredWindowRect(hWnd);
break;
case WM_LBUTTONUP: // Handle LMB clicks
if (prf_use_LButtonUp)
SendDeferredWindowRect(hWnd);
break;
case WM_MBUTTONUP: // Handle MMB clicks
if (prf_use_MButtonUp)
SendDeferredWindowRect(hWnd);
break;
case WM_RBUTTONUP: // Handle RMB clicks
if (prf_use_RButtonUp)
SendDeferredWindowRect(hWnd);
break;
case WM_TIMER:
if (prf_use_Timer)
SendDeferredWindowRect(hWnd);
break;
case WM_HSCROLL:
case WM_VSCROLL:
if (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL))
SendDeferredWindowRect(hWnd);
break;
case 485: // HACK to handle popup menus
{
// Get the old popup menu selection value
HANDLE prop = GetProp(hWnd, (LPCTSTR) MAKELONG(CN_POPUPSELN_ATOM, 0));
if (prop != (HANDLE) wParam)
{
// It did, so update the menu & the selection value
SendDeferredWindowRect(hWnd);
SetProp(hWnd,
(LPCTSTR) MAKELONG(CN_POPUPSELN_ATOM, 0),
(HANDLE) wParam);
}
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -