Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/vncdll/winvnc/VNCHooks/VNCHooks.cpp
Views: 11783
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.1//2// This file is part of the VNC system.3//4// The VNC system is free software; you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation; either version 2 of the License, or7// (at your option) any later version.8//9// This program is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.13//14// You should have received a copy of the GNU General Public License15// along with this program; if not, write to the Free Software16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,17// USA.18//19// TightVNC distribution homepage on the Web: http://www.tightvnc.com/20//21// If the source code for the VNC system is not available from the place22// whence you received this file, check http://www.uk.research.att.com/vnc or contact23// the authors on [email protected] for information on obtaining it.2425// VNCHooks.cpp : Defines the implementation of the DLL.26//2728#include "VNCHooks.h"2930#include <stdlib.h>31#include <stdio.h>32#include <crtdbg.h>3334/////////////////////////////////////////////////////////////////////////////35// Storage for the global data in the DLL36// Note: For Borland C++ compilers, this data segment is defined in a37// separate file, SharedData.cpp.3839#ifdef _MSC_VER4041// MSVC is bugged - if a default value is missed off from one of the following42// variables then that variable is process-specific for some reason!4344#pragma data_seg(".SharedData")45HWND hVeneto = NULL;46HWND hKeyboardPriorityWindow = NULL;47HWND hMousePriorityWindow = NULL;48UINT UpdateRectMessage = 0;49UINT CopyRectMessage = 0;50UINT MouseMoveMessage = 0;51UINT LocalMouseMessage = 0;52UINT LocalKeyboardMessage = 0;53HHOOK hCallWndHook = NULL; // Handle to the CallWnd hook54HHOOK hGetMsgHook = NULL; // Handle to the GetMsg hook55HHOOK hDialogMsgHook = NULL; // Handle to the DialogMsg hook56HHOOK hLLKeyboardHook = NULL; // Handle to LowLevel kbd hook57HHOOK hLLMouseHook = NULL; // Handle to LowLevel mouse hook58HHOOK hLLKeyboardPrHook = NULL; // Handle to LowLevel kbd hook for local event priority59HHOOK hLLMousePrHook = NULL; // Handle to LowLevel mouse hook for local event priority60HHOOK hKeyboardHook = NULL; // Handle to kbd hook61HHOOK hMouseHook = NULL; // Handle to mouse hook6263#pragma data_seg( )6465#else6667#include "SharedData.h"6869#endif // _MSC_VER7071/////////////////////////////////////////////////////////////////////////////72// Per-instance DLL variables7374const char sPrefSegment[] = "Application_Prefs\\";75char *sModulePrefs = NULL; // Name of the module that created us76BOOL prf_use_GetUpdateRect = FALSE; // Use the GetUpdateRect paint mode77BOOL prf_use_Timer = FALSE; // Use Timer events to trigger updates78BOOL prf_use_KeyPress = FALSE; // Use keyboard events79BOOL prf_use_LButtonUp = TRUE; // Use left mouse button up events80BOOL prf_use_MButtonUp = FALSE; // Use middle mouse button up events81BOOL prf_use_RButtonUp = FALSE; // Use right mouse button up events82BOOL prf_use_Deferral = FALSE; // Use deferred updates8384HKEY hModuleKey = NULL; // Key used to save settings85HINSTANCE hInstance = NULL; // This instance of the DLL86BOOL HookMaster = FALSE; // Is this instance veneto itself?8788BOOL appHookedOK = FALSE; // Did InitInstance succeed?8990/////////////////////////////////////////////////////////////////////////////91// Registered messages & atoms to be used by VNCHooks.DLL9293// Messages94const UINT VNC_DEFERRED_UPDATE = RegisterWindowMessage("VNCHooks.Deferred.UpdateMessage");9596// Atoms97const char *VNC_WINDOWPOS_ATOMNAME = "VNCHooks.CopyRect.WindowPos";98const char *VNC_POPUPSELN_ATOMNAME = "VNCHooks.PopUpMenu.Selected";99ATOM VNC_WINDOWPOS_ATOM = NULL;100ATOM VNC_POPUPSELN_ATOM = NULL;101102/////////////////////////////////////////////////////////////////////////////103// The DLL functions104105// Forward definition of hook procedures106107BOOL HookHandle(UINT msg, HWND hWnd, WPARAM wParam, LPARAM lParam);108LRESULT CALLBACK CallWndProc (int nCode, WPARAM wParam, LPARAM lParam);109LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);110LRESULT CALLBACK DialogMessageProc(int nCode, WPARAM wParam, LPARAM lParam);111LRESULT CALLBACK LowLevelKeyboardFilterProc(int nCode, WPARAM wParam, LPARAM lParam);112LRESULT CALLBACK LowLevelMouseFilterProc(int nCode, WPARAM wParam, LPARAM lParam);113LRESULT CALLBACK LowLevelKeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam);114LRESULT CALLBACK LowLevelMousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam);115LRESULT CALLBACK KeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam);116LRESULT CALLBACK MousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam);117118// Forward definition of setup and shutdown procedures119BOOL InitInstance();120BOOL ExitInstance();121122// The DLL's main procedure123BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)124{125// Find out why we're being called126switch (ul_reason_for_call)127{128129case DLL_PROCESS_ATTACH:130#ifdef _MSC_VER131_RPT0(_CRT_WARN, "vncHooks : Hook DLL loaded\n");132#endif133134// Save the instance handle135hInstance = (HINSTANCE)hInst;136137// Call the initialisation function138appHookedOK = InitInstance();139140// ALWAYS return TRUE to avoid breaking unhookable applications!!!141return TRUE;142143case DLL_PROCESS_DETACH:144#ifdef _MSC_VER145_RPT0(_CRT_WARN, "vncHooks : Hook DLL unloaded\n");146#endif147148// Call the exit function149// If the app failed to hook OK, ExitInstance will still operate OK (hopefully...)150ExitInstance();151152return TRUE;153154default:155return TRUE;156}157}158159// Add the new hook160161DllExport BOOL SetHook(HWND hWnd, UINT UpdateMsg, UINT CopyMsg, UINT MouseMsg)162{163164// Don't add the hook if the window ID is NULL165if (hWnd == NULL)166return FALSE;167168// Don't add a hook if there is already one added169if (hVeneto != NULL)170return FALSE;171172// Add the CallWnd hook173hCallWndHook = SetWindowsHookEx(174WH_CALLWNDPROC, // Hook in before msg reaches app175(HOOKPROC) CallWndProc, // Hook procedure176hInstance, // This DLL instance1770L // Hook in to all apps178// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC179);180181// Add the GetMessage hook182hGetMsgHook = SetWindowsHookEx(183WH_GETMESSAGE, // Hook in before msg reaches app184(HOOKPROC) GetMessageProc, // Hook procedure185hInstance, // This DLL instance1860L // Hook in to all apps187// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC188);189190// Add the GetMessage hook191hDialogMsgHook = SetWindowsHookEx(192WH_SYSMSGFILTER, // Hook in dialogs, menus and scrollbars193(HOOKPROC) DialogMessageProc, // Hook procedure194hInstance, // This DLL instance1950L // Hook in to all apps196);197198// Check that it worked199if ((hCallWndHook != NULL) && (hGetMsgHook != NULL) && (hDialogMsgHook != NULL))200{201hVeneto = hWnd; // Save the WinRFB window handle202UpdateRectMessage = UpdateMsg; // Save the message ID to use for rectangle updates203CopyRectMessage = CopyMsg; // Save the message ID to use for copyrect204MouseMoveMessage = MouseMsg; // Save the message ID to send when mouse moves205HookMaster = TRUE; // Set the HookMaster flag for this instance206207#ifdef _MSC_VER208_RPT1(_CRT_WARN, "Window : %d\n", hWnd);209#endif210211return TRUE;212}213else214{215// Stop the keyboard hook216SetKeyboardFilterHook(FALSE);217SetMouseFilterHook(FALSE);218219// Kill the main hooks220if (hCallWndHook != NULL)221UnhookWindowsHookEx(hCallWndHook);222if (hGetMsgHook != NULL)223UnhookWindowsHookEx(hGetMsgHook);224if (hDialogMsgHook != NULL)225UnhookWindowsHookEx(hDialogMsgHook);226hCallWndHook = NULL;227hGetMsgHook = NULL;228hDialogMsgHook = NULL;229}230231// The hook failed, so return an error code232return FALSE;233234}235236// EnumWindows procedure to remove the extra property we added237238BOOL CALLBACK239KillPropsProc(HWND hwnd, LPARAM lParam)240{241// Remove our custom property...242RemoveProp(hwnd, (LPCTSTR) MAKEWORD(VNC_WINDOWPOS_ATOM, 0));243RemoveProp(hwnd, (LPCTSTR) MAKEWORD(VNC_POPUPSELN_ATOM, 0));244return TRUE;245}246247// Remove the hook from the system248249DllExport BOOL UnSetHook(HWND hWnd)250{251252BOOL unHooked = TRUE;253254// Remove the extra property value from all local windows255EnumWindows((WNDENUMPROC) &KillPropsProc, NULL);256257// Stop the keyboard & mouse hooks258unHooked = unHooked && SetKeyboardFilterHook(FALSE);259unHooked = unHooked && SetMouseFilterHook(FALSE);260261// Is the window handle valid?262if (hWnd == NULL)263MessageBox(NULL, "Window pointer is null", "Message", MB_OK);264265// Is the correct application calling UnSetHook?266if (hWnd != hVeneto)267return FALSE;268269// Unhook the procs270if (hCallWndHook != NULL)271{272unHooked = unHooked && UnhookWindowsHookEx(hCallWndHook);273hCallWndHook = NULL;274}275276if (hGetMsgHook != NULL)277{278unHooked = unHooked && UnhookWindowsHookEx(hGetMsgHook);279hGetMsgHook = NULL;280}281282if (hDialogMsgHook != NULL)283{284unHooked = unHooked && UnhookWindowsHookEx(hDialogMsgHook);285hDialogMsgHook = NULL;286}287288// If we managed to unhook then reset289if (unHooked)290{291hVeneto = NULL;292HookMaster = FALSE;293}294295return unHooked;296297}298299// Routine to start and stop local keyboard message filtering300DllExport BOOL SetKeyboardFilterHook(BOOL activate)301{302if (activate)303{304#ifdef WH_KEYBOARD_LL305if (hLLKeyboardHook == NULL)306{307// Start up the hook...308hLLKeyboardHook = SetWindowsHookEx(309WH_KEYBOARD_LL, // Hook in before msg reaches app310(HOOKPROC) LowLevelKeyboardFilterProc, // Hook procedure311hInstance, // This DLL instance3120L // Hook in to all apps313);314if (hLLKeyboardHook == NULL)315return FALSE;316}317return TRUE;318#else319#pragma message("warning:Low-Level Keyboard hook code omitted.")320return FALSE;321#endif322} else {323if (hLLKeyboardHook != NULL)324{325// Stop the hook...326if (!UnhookWindowsHookEx(hLLKeyboardHook))327return FALSE;328hLLKeyboardHook = NULL;329}330return TRUE;331}332}333334DllExport BOOL SetKeyboardPriorityLLHook(HWND hwnd, BOOL activate, UINT LocalKbdMsg)335{336LocalKeyboardMessage = LocalKbdMsg;337if (activate)338{339#ifdef WH_KEYBOARD_LL340if (hLLKeyboardPrHook == NULL)341{342// save the window handle343hKeyboardPriorityWindow = hwnd;344345// Start up the hook...346hLLKeyboardPrHook = SetWindowsHookEx(347WH_KEYBOARD_LL, // Hook in before msg reaches app348(HOOKPROC) LowLevelKeyboardPriorityProc, // Hook procedure349hInstance, // This DLL instance3500L // Hook in to all apps351);352if (hLLKeyboardPrHook == NULL)353return FALSE;354}355return TRUE;356#else357#pragma message("warning:Low-Level Keyboard hook code omitted.")358return FALSE;359#endif360} else {361if (hLLKeyboardPrHook != NULL)362{363// Stop the hook...364if (!UnhookWindowsHookEx(hLLKeyboardPrHook))365return FALSE;366367// reset the hook and window handle368hKeyboardPriorityWindow = NULL;369hLLKeyboardPrHook = NULL;370}371return TRUE;372}373}374375// Routine to start and stop local mouse message filtering376DllExport BOOL SetMouseFilterHook(BOOL activate)377{378if (activate)379{380#ifdef WH_MOUSE_LL381if (hLLMouseHook == NULL)382{383// Start up the hook...384hLLMouseHook = SetWindowsHookEx(385WH_MOUSE_LL, // Hook in before msg reaches app386(HOOKPROC) LowLevelMouseFilterProc, // Hook procedure387hInstance, // This DLL instance3880L // Hook in to all apps389);390if (hLLMouseHook == NULL)391return FALSE;392}393return TRUE;394#else395#pragma message("warning:Low-Level Mouse hook code omitted.")396return FALSE;397#endif398} else {399if (hLLMouseHook != NULL)400{401// Stop the hook...402if (!UnhookWindowsHookEx(hLLMouseHook))403return FALSE;404hLLMouseHook = NULL;405}406return TRUE;407}408}409410DllExport BOOL SetMousePriorityLLHook(HWND hwnd, BOOL activate, UINT LocalMouseMsg)411{412LocalMouseMessage = LocalMouseMsg;413if (activate)414{415#ifdef WH_MOUSE_LL416if (hLLMousePrHook == NULL)417{418// save the window handle419hMousePriorityWindow = hwnd;420421// Start up the hook...422hLLMousePrHook = SetWindowsHookEx(423WH_MOUSE_LL, // Hook in before msg reaches app424(HOOKPROC) LowLevelMousePriorityProc, // Hook procedure425hInstance, // This DLL instance4260L // Hook in to all apps427);428if (hLLMousePrHook == NULL)429return FALSE;430}431return TRUE;432#else433#pragma message("warning:Low-Level Mouse hook code omitted.")434return FALSE;435#endif436} else {437if (hLLMousePrHook != NULL)438{439// Stop the hook...440if (!UnhookWindowsHookEx(hLLMousePrHook))441return FALSE;442443// reset the hook and window handle444hMousePriorityWindow = NULL;445hLLMousePrHook = NULL;446}447return TRUE;448}449}450451452// Routine to start and stop local keyboard message filtering453DllExport BOOL SetKeyboardPriorityHook(HWND hwnd, BOOL activate, UINT LocalKbdMsg)454{455LocalKeyboardMessage = LocalKbdMsg;456if (activate)457{458if (hKeyboardHook == NULL)459{460// save the window handle461hKeyboardPriorityWindow = hwnd;462463// Start up the hook...464hKeyboardHook = SetWindowsHookEx(465WH_KEYBOARD, // Hook in before msg reaches app466(HOOKPROC) KeyboardPriorityProc,// Hook procedure467hInstance, // This DLL instance4680L // Hook in to all apps469);470if (hKeyboardHook == NULL)471return FALSE;472}473return TRUE;474} else {475if (hKeyboardHook != NULL)476{477// Stop the hook...478if (!UnhookWindowsHookEx(hKeyboardHook))479return FALSE;480481// reset the hook and window handle482hKeyboardPriorityWindow = NULL;483hKeyboardHook = NULL;484}485return TRUE;486}487}488489490// Routine to start and stop local mouse message filtering491DllExport BOOL SetMousePriorityHook(HWND hwnd, BOOL activate, UINT LocalMouseMsg)492{493LocalMouseMessage = LocalMouseMsg;494if (activate)495{496if (hMouseHook == NULL)497{498// save the window handle499hMousePriorityWindow = hwnd;500501// Start up the hook...502hMouseHook = SetWindowsHookEx(503WH_MOUSE, // Hook in before msg reaches app504(HOOKPROC) MousePriorityProc, // Hook procedure505hInstance, // This DLL instance5060L // Hook in to all apps507);508if (hMouseHook == NULL)509return FALSE;510}511return TRUE;512} else {513if (hMouseHook != NULL)514{515// Stop the hook...516if (!UnhookWindowsHookEx(hMouseHook))517return FALSE;518519// reset the hook and window handle520hMousePriorityWindow = NULL;521hMouseHook = NULL;522}523return TRUE;524}525}526527528529// Routine to get the window's client rectangle, in screen coordinates530inline BOOL GetAbsoluteClientRect(HWND hwnd, RECT *rect)531{532POINT topleft;533topleft.x = 0;534topleft.y = 0;535536// Get the client rectangle size537if (!GetClientRect(hwnd, rect))538return FALSE;539540// Get the client rectangle position541if (!ClientToScreen(hwnd, &topleft))542return FALSE;543544// Now adjust the window rectangle545rect->left += topleft.x;546rect->top += topleft.y;547rect->right += topleft.x;548rect->bottom += topleft.y;549550return TRUE;551}552553// Routine to send a CopyRect message to WinVNC554inline void SendCopyWindowRect(HWND hWnd)555{556WPARAM vwParam;557558// All we send back is the handle of the window to be moved559vwParam = (LPARAM) hWnd;560561// Send the update to Veneto562PostMessage(563hVeneto,564CopyRectMessage,565vwParam,5660567);568}569570// Routine to send an UpdateRect message to Veneto571inline void SendUpdateRect(SHORT x, SHORT y, SHORT x2, SHORT y2)572{573WPARAM vwParam;574LPARAM vlParam;575576vwParam = MAKELONG(x, y);577vlParam = MAKELONG(x2, y2);578579// Send the update to Veneto580PostMessage(581hVeneto,582UpdateRectMessage,583vwParam,584vlParam585);586}587588// Send a window's position to Veneto589590inline void SendWindowRect(HWND hWnd)591{592RECT wrect;593594// Get the rectangle position595if (GetWindowRect(hWnd, &wrect) && IsWindowVisible(hWnd))596{597// Send the position598SendUpdateRect(599(SHORT) wrect.left,600(SHORT) wrect.top,601(SHORT) wrect.right,602(SHORT) wrect.bottom603);604}605}606607// Send a deferred message into this Window's message queue, so that608// we'll intercept it again only after the message that triggered it has been609// handled610611inline void SendDeferredUpdateRect(HWND hWnd, SHORT x, SHORT y, SHORT x2, SHORT y2)612{613WPARAM vwParam;614LPARAM vlParam;615616vwParam = MAKELONG(x, y);617vlParam = MAKELONG(x2, y2);618619if (prf_use_Deferral)620{621// Send the update back to the window622PostMessage(623hWnd,624VNC_DEFERRED_UPDATE,625vwParam,626vlParam627);628}629else630{631// Send the update to WinRFB632PostMessage(633hVeneto,634UpdateRectMessage,635vwParam,636vlParam637);638}639}640641inline void SendDeferredWindowRect(HWND hWnd)642{643RECT wrect;644645// Get the rectangle position646if (::GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))647{648// Send the position649SendDeferredUpdateRect(650hWnd,651(SHORT) wrect.left,652(SHORT) wrect.top,653(SHORT) wrect.right,654(SHORT) wrect.bottom655);656}657}658659inline void SendDeferredBorderRect(HWND hWnd)660{661RECT wrect;662RECT crect;663664// Get the rectangle position665if (GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))666{667// Get the client rectangle position668if (GetAbsoluteClientRect(hWnd, &crect))669{670// Send the four border rectangles671SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) crect.top);672SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) crect.left, (SHORT) wrect.bottom);673SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) crect.bottom, (SHORT) wrect.right, (SHORT) wrect.bottom);674SendDeferredUpdateRect(hWnd, (SHORT) crect.right, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) wrect.bottom);675}676}677}678679// Generic hook-handler680681inline BOOL HookHandle(UINT MessageId, HWND hWnd, WPARAM wParam, LPARAM lParam)682{683////////////////////////////////////////////////////////////////684// *** HANDLE DEFERRED UPDATES ***685686// Is this a deferred-update message?687if (MessageId == VNC_DEFERRED_UPDATE)688{689690// NOTE : NEVER use the SendDeferred- routines to send updates691// from here, or you'll get an infinite loop....!692693// NB : The format of DEFERRED_UPDATE matches that of UpdateRectMessage,694// so just send the exact same message data to WinRFB:695696PostMessage(697hVeneto,698UpdateRectMessage,699wParam,700lParam701);702703return FALSE;704}705706// *** Could use WM_COPYDATA to send data to WinVNC707708/*709if (GetClassLong(hWnd, GCW_ATOM) == 32768)710{711_RPT4(_CRT_WARN, "DBG : popup menu message (hwnd=%d, msg=%d, l=%d, w=%d)\n",712hWnd, MessageId, lParam, wParam);713}714*/715716////////////////////////////////////////////////////////////////717// *** UPDATE-TRIGGERING MESSAGES ***718719// Do something dependent upon message type720switch (MessageId)721{722723////////////////////////////////////////////////////////////////724// Messages indicating only a border repaint.725case WM_NCPAINT:726case WM_NCACTIVATE:727SendDeferredBorderRect(hWnd);728break;729730////////////////////////////////////////////////////////////////731// Messages indicating a client area repaint732case WM_CHAR:733case WM_KEYUP: // Handle key-presses734if (prf_use_KeyPress)735SendDeferredWindowRect(hWnd);736break;737738case WM_LBUTTONUP: // Handle LMB clicks739if (prf_use_LButtonUp)740SendDeferredWindowRect(hWnd);741break;742743case WM_MBUTTONUP: // Handle MMB clicks744if (prf_use_MButtonUp)745SendDeferredWindowRect(hWnd);746break;747748case WM_RBUTTONUP: // Handle RMB clicks749if (prf_use_RButtonUp)750SendDeferredWindowRect(hWnd);751break;752753case WM_TIMER:754if (prf_use_Timer)755SendDeferredWindowRect(hWnd);756break;757758case WM_HSCROLL:759case WM_VSCROLL:760if (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL))761SendDeferredWindowRect(hWnd);762break;763764case 485: // HACK to handle popup menus765{766// Get the old popup menu selection value767HANDLE prop = GetProp(hWnd, (LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0));768if (prop != (HANDLE) wParam)769{770// It did, so update the menu & the selection value771SendDeferredWindowRect(hWnd);772SetProp(hWnd,773(LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0),774(HANDLE) wParam);775}776}777break;778779////////////////////////////////////////////////////////////////780// Messages indicating a full window update781case WM_SYSCOLORCHANGE:782case WM_PALETTECHANGED:783case WM_SETTEXT:784case WM_ENABLE:785case BM_SETCHECK:786case BM_SETSTATE:787case EM_SETSEL:788//case WM_MENUSELECT:789SendDeferredWindowRect(hWnd);790break;791792////////////////////////////////////////////////////////////////793// Messages indicating that an area of the window needs updating794// Uses GetUpdateRect to find out which795case WM_PAINT:796if (prf_use_GetUpdateRect)797{798HRGN region;799region = CreateRectRgn(0, 0, 0, 0);800801// Get the affected region802if (GetUpdateRgn(hWnd, region, FALSE) != ERROR)803{804int buffsize;805UINT x;806RGNDATA *buff;807POINT TopLeft;808809// Get the top-left point of the client area810TopLeft.x = 0;811TopLeft.y = 0;812if (!ClientToScreen(hWnd, &TopLeft))813break;814815// Get the size of buffer required816buffsize = GetRegionData(region, 0, 0);817if (buffsize != 0)818{819buff = (RGNDATA *) new BYTE [buffsize];820if (buff == NULL)821break;822823// Now get the region data824if(GetRegionData(region, buffsize, buff))825{826for (x=0; x<(buff->rdh.nCount); x++)827{828// Obtain the rectangles from the list829RECT *urect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + (x * sizeof(RECT)));830SendDeferredUpdateRect(831hWnd,832(SHORT) (TopLeft.x + urect->left),833(SHORT) (TopLeft.y + urect->top),834(SHORT) (TopLeft.x + urect->right),835(SHORT) (TopLeft.y + urect->bottom)836);837}838}839840delete [] buff;841}842}843844// Now free the region845if (region != NULL)846DeleteObject(region);847}848else849SendDeferredWindowRect(hWnd);850break;851852////////////////////////////////////////////////////////////////853// Messages indicating full repaint of this and a different window854// Send the new position of the window855case WM_WINDOWPOSCHANGING:856if (IsWindowVisible(hWnd))857SendWindowRect(hWnd);858break;859860case WM_WINDOWPOSCHANGED:861if (IsWindowVisible(hWnd))862SendDeferredWindowRect(hWnd);863break;864865////////////////////////////////////////////////////////////////866// WinRFB also wants to know about mouse movement867case WM_NCMOUSEMOVE:868case WM_MOUSEMOVE:869// Inform WinRFB that the mouse has moved and pass it the current cursor handle870PostMessage(871hVeneto,872MouseMoveMessage,873(ULONG) GetCursor(),8740875);876break;877878////////////////////////////////////////////////////////////////879// VNCHOOKS PROPERTIES HANDLING WINDOWS880case WM_DESTROY:881RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_WINDOWPOS_ATOM, 0));882RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_POPUPSELN_ATOM, 0));883break;884885}886887return TRUE;888}889890// Hook procedure for CallWindow hook891892LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)893{894// Do we have to handle this message?895if (nCode == HC_ACTION)896{897// Process the hook if the Veneto window handle is valid898if (hVeneto != NULL)899{900CWPSTRUCT *cwpStruct = (CWPSTRUCT *) lParam;901HookHandle(cwpStruct->message, cwpStruct->hwnd, cwpStruct->wParam, cwpStruct->lParam);902}903}904905// Call the next handler in the chain906return CallNextHookEx (hCallWndHook, nCode, wParam, lParam);907}908909// Hook procedure for GetMessageProc hook910911LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)912{913// Do we have to handle this message?914if (nCode == HC_ACTION)915{916// Process the hook only if the Veneto window is valid917if (hVeneto != NULL)918{919MSG *msg = (MSG *) lParam;920921// Only handle application messages if they're being removed:922if (wParam & PM_REMOVE)923{924// Handle the message925HookHandle(msg->message, msg->hwnd, msg->wParam, msg->lParam);926}927}928}929930// Call the next handler in the chain931return CallNextHookEx (hGetMsgHook, nCode, wParam, lParam);932}933934// Hook procedure for DialogMessageProc hook935936LRESULT CALLBACK DialogMessageProc(int nCode, WPARAM wParam, LPARAM lParam)937{938// Do we have to handle this message?939if (nCode >= 0)940{941// Process the hook only if the Veneto window is valid942if (hVeneto != NULL)943{944MSG *msg = (MSG *) lParam;945946// Handle the message947HookHandle(msg->message, msg->hwnd, msg->wParam, msg->lParam);948}949}950951// Call the next handler in the chain952return CallNextHookEx (hGetMsgHook, nCode, wParam, lParam);953}954955// Hook procedure for LowLevel Keyboard filtering956957#ifdef WH_KEYBOARD_LL958LRESULT CALLBACK LowLevelKeyboardFilterProc(int nCode, WPARAM wParam, LPARAM lParam)959{960// Are we expected to handle this callback?961if (nCode == HC_ACTION)962{963// Is this keyboard event "real" or "injected"964// i.e. hardware or software-produced?965KBDLLHOOKSTRUCT *hookStruct = (KBDLLHOOKSTRUCT*)lParam;966if (!(hookStruct->flags & LLKHF_INJECTED)) {967// Message was not injected - reject it!968return TRUE;969}970}971972// Otherwise, pass on the message973return CallNextHookEx(hLLKeyboardHook, nCode, wParam, lParam);974}975976LRESULT CALLBACK LowLevelKeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam)977{978// Are we expected to handle this callback?979// do we have a target window handle?980if (nCode == HC_ACTION && hKeyboardPriorityWindow != NULL)981{982// Is this keyboard event "real" or "injected"983// i.e. hardware or software-produced?984KBDLLHOOKSTRUCT *hookStruct = (KBDLLHOOKSTRUCT*)lParam;985if (!(hookStruct->flags & LLKHF_INJECTED)) {986// Message was not injected - send RFB_LOCAL_KEYBOARD msg!987// Remote event will be blocked988PostMessage(989hKeyboardPriorityWindow,990LocalKeyboardMessage,9910,9920993);994}995}996997// Otherwise, pass on the message998return CallNextHookEx(hLLKeyboardPrHook, nCode, wParam, lParam);999}10001001#endif10021003// Hook procedure for LowLevel Mouse filtering10041005#ifdef WH_MOUSE_LL1006LRESULT CALLBACK LowLevelMouseFilterProc(int nCode, WPARAM wParam, LPARAM lParam)1007{1008// Are we expected to handle this callback?1009if (nCode == HC_ACTION)1010{1011// Is this mouse event "real" or "injected"1012// i.e. hardware or software-produced?1013MSLLHOOKSTRUCT *hookStruct = (MSLLHOOKSTRUCT*)lParam;1014if (!(hookStruct->flags & LLMHF_INJECTED)) {10151016return TRUE;1017}1018}10191020// Otherwise, pass on the message1021return CallNextHookEx(hLLMouseHook, nCode, wParam, lParam);1022}10231024LRESULT CALLBACK LowLevelMousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam)1025{1026// Are we expected to handle this callback?1027// do we have a target window handle?1028if (nCode == HC_ACTION && hMousePriorityWindow != NULL)1029{1030// Is this mouse event "real" or "injected"1031// i.e. hardware or software-produced?1032MSLLHOOKSTRUCT *hookStruct = (MSLLHOOKSTRUCT*)lParam;1033if (!(hookStruct->flags & LLMHF_INJECTED)) {1034// Message was not injected - send RFB_LOCAL_MOUSE msg!1035// Remote event will be blocked1036PostMessage(1037hMousePriorityWindow,1038LocalMouseMessage,10390,104001041);1042}1043}10441045// Otherwise, pass on the message1046return CallNextHookEx(hLLMousePrHook, nCode, wParam, lParam);1047}10481049#endif10501051LRESULT CALLBACK KeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam)1052{1053// Are we expected to handle this callback?1054// do we have a target window handle?1055if (nCode == HC_ACTION && hKeyboardPriorityWindow != NULL)1056{1057PostMessage(1058hKeyboardPriorityWindow,1059LocalKeyboardMessage,10600,106101062);10631064}10651066return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);1067}106810691070LRESULT CALLBACK MousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam)1071{1072// Are we expected to handle this callback?1073// do we have a target window handle?1074if (nCode == HC_ACTION && hMousePriorityWindow != NULL)1075{1076if ( (wParam == WM_LBUTTONDOWN) || (wParam == WM_RBUTTONDOWN) || (wParam == WM_MBUTTONDOWN) || (wParam == WM_MOUSEMOVE) )1077PostMessage(1078hMousePriorityWindow,1079LocalMouseMessage,10800,108101082);1083}10841085return CallNextHookEx(hMouseHook, nCode, wParam, lParam);1086}108710881089char * NameFromPath(const char *path)1090{1091int x;1092int l = strlen(path);1093char *temp = NULL;10941095// Find the file part of a filename1096for (x=l-1; x>0; x--)1097{1098if (path[x] == '\\')1099{1100temp = strdup(&(path[x+1]));1101break;1102}1103}11041105// If we didn't fine a \ then just return a copy of the original1106if (temp == NULL)1107temp = strdup(path);11081109return temp;1110}11111112/////////////////////////////////////////////////////////////////////////////1113// Initialise / Exit routines.1114// These functions handle the update settings for any apps used with WinVNC.11151116static const TCHAR szSoftware[] = "Software";1117static const TCHAR szCompany[] = "ORL";1118static const TCHAR szProfile[] = "VNCHooks";11191120HKEY GetRegistryKey()1121{1122HKEY hAppKey = NULL;1123HKEY hSoftKey = NULL;1124HKEY hCompanyKey = NULL;1125if (RegOpenKeyEx(HKEY_CURRENT_USER, szSoftware, 0, KEY_WRITE|KEY_READ,1126&hSoftKey) == ERROR_SUCCESS)1127{1128DWORD dw;1129if (RegCreateKeyEx(hSoftKey, szCompany, 0, REG_NONE,1130REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,1131&hCompanyKey, &dw) == ERROR_SUCCESS)1132{1133RegCreateKeyEx(hCompanyKey, szProfile, 0, REG_NONE,1134REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,1135&hAppKey, &dw);1136}1137}1138if (hSoftKey != NULL)1139RegCloseKey(hSoftKey);1140if (hCompanyKey != NULL)1141RegCloseKey(hCompanyKey);11421143return hAppKey;1144}11451146HKEY GetModuleKey(const char *proc_name)1147{1148HKEY hModule = NULL;11491150// Work out the registry key to save this under1151sModulePrefs = (char *) malloc(strlen(sPrefSegment) + strlen(proc_name) + 1);1152if (sModulePrefs == NULL)1153return FALSE;1154sprintf(sModulePrefs, "%s%s", sPrefSegment, proc_name);11551156// Check whether the library's entry exists!1157HKEY hAppKey = GetRegistryKey();1158if (hAppKey == NULL)1159return NULL;11601161// Attempt to open the section for this application1162if (RegOpenKeyEx(hAppKey,1163sModulePrefs,11640, KEY_WRITE|KEY_READ,1165&hModule1166) != ERROR_SUCCESS)1167{1168// Cut off the app directory and just use the name1169char *file_name = NameFromPath(proc_name);11701171if (file_name == NULL)1172{1173RegCloseKey(hAppKey);1174return NULL;1175}11761177// Adjust the moduleprefs name1178sprintf(sModulePrefs, "%s%s", sPrefSegment, file_name);1179free(file_name);11801181// Now get the module key again1182DWORD dw;1183if (RegCreateKeyEx(hAppKey,1184sModulePrefs,11850, REG_NONE, REG_OPTION_NON_VOLATILE,1186KEY_WRITE|KEY_READ,1187NULL,1188&hModule,1189&dw) != ERROR_SUCCESS)1190{1191// Couldn't find/create the key - fail!1192RegCloseKey(hAppKey);1193return NULL;1194}1195}11961197// Close the application registry key1198RegCloseKey(hAppKey);11991200return hModule;1201}12021203int GetProfileInt(LPTSTR key, int def)1204{1205DWORD type;1206DWORD value;1207ULONG size = sizeof(value);12081209if (RegQueryValueEx(1210hModuleKey,1211key,1212NULL,1213&type,1214(unsigned char *)&value,1215&size) == ERROR_SUCCESS)1216{1217// Is the value of the right type?1218if (type != REG_DWORD)1219{1220return def;1221}1222else1223{1224return value;1225}1226}1227else1228{1229return def;1230}1231}12321233void WriteProfileInt(LPTSTR key, int value)1234{1235RegSetValueEx(1236hModuleKey,1237key,12380,1239REG_DWORD,1240(unsigned char *)&value,1241sizeof(value));1242}12431244BOOL InitInstance()1245{1246// Create the global atoms1247VNC_WINDOWPOS_ATOM = GlobalAddAtom(VNC_WINDOWPOS_ATOMNAME);1248if (VNC_WINDOWPOS_ATOM == NULL)1249return FALSE;1250VNC_POPUPSELN_ATOM = GlobalAddAtom(VNC_POPUPSELN_ATOMNAME);1251if (VNC_POPUPSELN_ATOM == NULL)1252return FALSE;12531254// Get the module name1255char proc_name[_MAX_PATH];1256DWORD size;12571258// Attempt to get the program/module name1259if ((size = GetModuleFileName(1260GetModuleHandle(NULL),1261(char *) &proc_name,1262_MAX_PATH1263)) == 0)1264return FALSE;12651266// Get the key for the module1267hModuleKey = GetModuleKey(proc_name);1268if (hModuleKey == NULL)1269return FALSE;12701271// Read in the prefs1272prf_use_GetUpdateRect = GetProfileInt(1273"use_GetUpdateRect",1274TRUE1275);12761277prf_use_Timer = GetProfileInt(1278"use_Timer",1279FALSE1280);1281prf_use_KeyPress = GetProfileInt(1282"use_KeyPress",1283TRUE1284);1285prf_use_LButtonUp = GetProfileInt(1286"use_LButtonUp",1287TRUE1288);1289prf_use_MButtonUp = GetProfileInt(1290"use_MButtonUp",1291TRUE1292);1293prf_use_RButtonUp = GetProfileInt(1294"use_RButtonUp",1295TRUE1296);1297prf_use_Deferral = GetProfileInt(1298"use_Deferral",1299#ifdef HORIZONLIVE1300FALSE // we use full screen polling anyway1301#else1302TRUE1303#endif1304);13051306return TRUE;1307}13081309BOOL ExitInstance()1310{1311// Free the created atoms1312if (VNC_WINDOWPOS_ATOM != NULL)1313{1314GlobalDeleteAtom(VNC_WINDOWPOS_ATOM);1315VNC_WINDOWPOS_ATOM = NULL;1316}1317if (VNC_POPUPSELN_ATOM != NULL)1318{1319GlobalDeleteAtom(VNC_POPUPSELN_ATOM);1320VNC_POPUPSELN_ATOM = NULL;1321}13221323// Write the module settings to disk1324if (sModulePrefs != NULL)1325{1326WriteProfileInt(1327"use_GetUpdateRect",1328prf_use_GetUpdateRect1329);13301331WriteProfileInt(1332"use_Timer",1333prf_use_Timer1334);13351336WriteProfileInt(1337"use_KeyPress",1338prf_use_KeyPress1339);13401341WriteProfileInt(1342"use_LButtonUp",1343prf_use_LButtonUp1344);13451346WriteProfileInt(1347"use_MButtonUp",1348prf_use_MButtonUp1349);13501351WriteProfileInt(1352"use_RButtonUp",1353prf_use_RButtonUp1354);13551356WriteProfileInt(1357"use_Deferral",1358prf_use_Deferral1359);13601361free(sModulePrefs);1362sModulePrefs = NULL;1363}13641365// Close the registry key for this module1366if (hModuleKey != NULL)1367RegCloseKey(hModuleKey);13681369return TRUE;1370}137113721373