summaryrefslogtreecommitdiffstats
path: root/win/wm_hooks
diff options
context:
space:
mode:
authorConstantin Kaplinsky <const@tightvnc.com>2006-05-25 05:12:25 +0000
committerConstantin Kaplinsky <const@tightvnc.com>2006-05-25 05:12:25 +0000
commit729598cb00d791bbdfe23ebe0023d3a1c3962f83 (patch)
treeffe1b87705a0541998b8d7c44ea75dc4702dc515 /win/wm_hooks
parentb30ae7facbdf8273f34f5d67d3d2e9c81db75576 (diff)
downloadtigervnc-729598cb00d791bbdfe23ebe0023d3a1c3962f83.tar.gz
tigervnc-729598cb00d791bbdfe23ebe0023d3a1c3962f83.zip
Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@591 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'win/wm_hooks')
-rw-r--r--win/wm_hooks/resource.h15
-rw-r--r--win/wm_hooks/wm_hooks.cxx465
-rw-r--r--win/wm_hooks/wm_hooks.def5
-rw-r--r--win/wm_hooks/wm_hooks.dsp149
-rw-r--r--win/wm_hooks/wm_hooks.h102
-rw-r--r--win/wm_hooks/wm_hooks.rc109
6 files changed, 845 insertions, 0 deletions
diff --git a/win/wm_hooks/resource.h b/win/wm_hooks/resource.h
new file mode 100644
index 00000000..0d8f646f
--- /dev/null
+++ b/win/wm_hooks/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by wm_hooks.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/win/wm_hooks/wm_hooks.cxx b/win/wm_hooks/wm_hooks.cxx
new file mode 100644
index 00000000..fd01159c
--- /dev/null
+++ b/win/wm_hooks/wm_hooks.cxx
@@ -0,0 +1,465 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- wm_hooks.cxx
+//
+// Window Message Hooks Dynamic Link library
+
+#include <tchar.h>
+
+#include <wm_hooks/wm_hooks.h>
+
+UINT WM_HK_PingThread = RegisterWindowMessage(_T("RFB.WM_Hooks.PingThread"));
+
+UINT WM_HK_WindowChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.WindowChanged"));
+UINT WM_Hooks_WindowChanged() {
+ return WM_HK_WindowChanged;
+}
+
+UINT WM_HK_WindowClientAreaChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.WindowClientAreaChanged"));
+UINT WM_Hooks_WindowClientAreaChanged() {
+ return WM_HK_WindowClientAreaChanged;
+}
+
+UINT WM_HK_WindowBorderChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.WindowBorderChanged"));
+UINT WM_Hooks_WindowBorderChanged() {
+ return WM_HK_WindowBorderChanged;
+}
+
+UINT WM_HK_RectangleChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.RectangleChanged"));
+UINT WM_Hooks_RectangleChanged() {
+ return WM_HK_RectangleChanged;
+}
+
+UINT WM_HK_CursorChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.CursorChanged"));
+UINT WM_Hooks_CursorChanged() {
+ return WM_HK_CursorChanged;
+}
+
+#ifdef _DEBUG
+UINT WM_HK_Diagnostic = RegisterWindowMessage(_T("RFB.WM_Hooks.Diagnostic"));
+UINT WM_Hooks_Diagnostic() {
+ return WM_HK_Diagnostic;
+}
+#endif
+
+ATOM ATOM_Popup_Selection = GlobalAddAtom(_T("RFB.WM_Hooks.PopupSelectionAtom"));
+
+//
+// -=- DLL entry point
+//
+
+HINSTANCE dll_instance = 0;
+
+BOOL WINAPI DllMain(HANDLE instance, ULONG reason, LPVOID reserved) {
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ dll_instance = (HINSTANCE)instance;
+ return TRUE;
+ case DLL_PROCESS_DETACH:
+ return TRUE;
+ case DLL_THREAD_DETACH:
+ WM_Hooks_Remove(GetCurrentThreadId());
+ return TRUE;
+ default:
+ return TRUE;
+ };
+}
+
+//
+// -=- Display update hooks
+//
+
+#pragma data_seg(".WM_Hooks_Shared")
+DWORD hook_owner = 0;
+DWORD hook_target = 0;
+HHOOK hook_CallWndProc = 0;
+HHOOK hook_CallWndProcRet = 0;
+HHOOK hook_GetMessage = 0;
+HHOOK hook_DialogMessage = 0;
+BOOL enable_cursor_shape = FALSE;
+HCURSOR cursor = 0;
+#ifdef _DEBUG
+UINT diagnostic_min=1;
+UINT diagnostic_max=0;
+#endif
+#pragma data_seg()
+
+#ifdef _DEBUG
+DLLEXPORT void WM_Hooks_SetDiagnosticRange(UINT min, UINT max) {
+ diagnostic_min = min; diagnostic_max=max;
+}
+#endif
+
+bool NotifyHookOwner(UINT event, WPARAM wParam, LPARAM lParam) {
+ if (hook_owner) {
+ return PostThreadMessage(hook_owner, event, wParam, lParam)!=0;
+ /*
+ if (last_event)
+ return PostThreadMessage(hook_owner, last_event, last_wParam, last_lParam);
+ last_event = event;
+ last_wParam = wParam;
+ last_lParam = lParam;
+ return true;
+ */
+ }
+ return false;
+}
+
+bool NotifyWindow(HWND hwnd, UINT msg) {
+ return NotifyHookOwner(WM_HK_WindowChanged, msg, (LPARAM)hwnd);
+}
+bool NotifyWindowBorder(HWND hwnd, UINT msg) {
+ return NotifyHookOwner(WM_HK_WindowBorderChanged, msg, (LPARAM)hwnd);
+}
+bool NotifyWindowClientArea(HWND hwnd, UINT msg) {
+ return NotifyHookOwner(WM_HK_WindowClientAreaChanged, msg, (LPARAM)hwnd);
+}
+bool NotifyRectangle(RECT* rect) {
+ WPARAM w = MAKELONG((SHORT)rect->left, (SHORT)rect->top);
+ LPARAM l = MAKELONG((SHORT)rect->right, (SHORT)rect->bottom);
+ return NotifyHookOwner(WM_HK_RectangleChanged, w, l);
+}
+bool NotifyCursor(HCURSOR cursor) {
+ return NotifyHookOwner(WM_HK_CursorChanged, 0, (LPARAM)cursor);
+}
+
+void ProcessWindowMessage(UINT msg, HWND wnd, WPARAM wParam, LPARAM lParam) {
+#ifdef _DEBUG
+ if ((msg >= diagnostic_min) && (msg <= diagnostic_max))
+ PostThreadMessage(hook_owner, WM_HK_Diagnostic, msg, (LPARAM)wnd);
+#endif
+ if (!IsWindowVisible(wnd)) return;
+ switch (msg) {
+
+ // -=- Border update events
+ case WM_NCPAINT:
+ case WM_NCACTIVATE:
+ NotifyWindowBorder(wnd, msg);
+ break;
+
+ // -=- Client area update events
+ case BM_SETCHECK:
+ case BM_SETSTATE:
+ case EM_SETSEL:
+ case WM_CHAR:
+ case WM_ENABLE:
+ case WM_KEYUP:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_PALETTECHANGED:
+ case WM_RBUTTONUP:
+ case WM_SYSCOLORCHANGE:
+ case WM_SETTEXT:
+ case WM_SETFOCUS:
+ //case WM_TIMER:
+ NotifyWindowClientArea(wnd, msg);
+ break;
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ if (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL))
+ NotifyWindow(wnd, msg);
+ break;
+
+ case WM_WINDOWPOSCHANGING:
+ case WM_DESTROY:
+ {
+ RECT wrect;
+ if (GetWindowRect(wnd, &wrect)) {
+ NotifyRectangle(&wrect);
+ }
+ }
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ NotifyWindow(wnd, msg);
+ break;
+
+ case WM_PAINT:
+ // *** could improve this
+ NotifyWindowClientArea(wnd, msg);
+ break;
+
+ // Handle pop-up menus appearing
+ case 482:
+ NotifyWindow(wnd, 482);
+ break;
+
+ // Handle pop-up menus having items selected
+ case 485:
+ {
+ HANDLE prop = GetProp(wnd, (LPCTSTR) MAKELONG(ATOM_Popup_Selection, 0));
+ if (prop != (HANDLE) wParam) {
+ NotifyWindow(wnd, 485);
+ SetProp(wnd,
+ (LPCTSTR) MAKELONG(ATOM_Popup_Selection, 0),
+ (HANDLE) wParam);
+ }
+ }
+ break;
+
+ case WM_NCMOUSEMOVE:
+ case WM_MOUSEMOVE:
+ if (enable_cursor_shape) {
+ HCURSOR new_cursor = GetCursor();
+ if (new_cursor != cursor) {
+ cursor = new_cursor;
+ NotifyCursor(cursor);
+ }
+ }
+ break;
+
+ /* ***
+ if (prf_use_GetUpdateRect)
+ {
+ HRGN region;
+ region = CreateRectRgn(0, 0, 0, 0);
+
+ // Get the affected region
+ if (GetUpdateRgn(hWnd, region, FALSE) != ERROR)
+ {
+ int buffsize;
+ UINT x;
+ RGNDATA *buff;
+ POINT TopLeft;
+
+ // Get the top-left point of the client area
+ TopLeft.x = 0;
+ TopLeft.y = 0;
+ if (!ClientToScreen(hWnd, &TopLeft))
+ break;
+
+ // Get the size of buffer required
+ buffsize = GetRegionData(region, 0, 0);
+ if (buffsize != 0)
+ {
+ buff = (RGNDATA *) new BYTE [buffsize];
+ if (buff == NULL)
+ break;
+
+ // Now get the region data
+ if(GetRegionData(region, buffsize, buff))
+ {
+ for (x=0; x<(buff->rdh.nCount); x++)
+ {
+ // Obtain the rectangles from the list
+ RECT *urect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + (x * sizeof(RECT)));
+ SendDeferredUpdateRect(
+ hWnd,
+ (SHORT) (TopLeft.x + urect->left),
+ (SHORT) (TopLeft.y + urect->top),
+ (SHORT) (TopLeft.x + urect->right),
+ (SHORT) (TopLeft.y + urect->bottom)
+ );
+ }
+ }
+
+ delete [] buff;
+ }
+ }
+
+ // Now free the region
+ if (region != NULL)
+ DeleteObject(region);
+ }
+ */
+ };
+}
+
+LRESULT CALLBACK HookCallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode == HC_ACTION) {
+ CWPSTRUCT* info = (CWPSTRUCT*) lParam;
+ ProcessWindowMessage(info->message, info->hwnd, info->wParam, info->lParam);
+ }
+ return CallNextHookEx(hook_CallWndProc, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK HookCallWndProcRet(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode == HC_ACTION) {
+ CWPRETSTRUCT* info = (CWPRETSTRUCT*) lParam;
+ ProcessWindowMessage(info->message, info->hwnd, info->wParam, info->lParam);
+ }
+ return CallNextHookEx(hook_CallWndProcRet, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK HookGetMessage(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode == HC_ACTION) {
+ if (wParam & PM_REMOVE) {
+ MSG* msg = (MSG*) lParam;
+ ProcessWindowMessage(msg->message, msg->hwnd, msg->wParam, msg->lParam);
+ }
+ }
+ return CallNextHookEx(hook_GetMessage, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK HookDialogMessage(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode == HC_ACTION) {
+ MSG* msg = (MSG*) lParam;
+ ProcessWindowMessage(msg->message, msg->hwnd, msg->wParam, msg->lParam);
+ }
+ return CallNextHookEx(hook_DialogMessage, nCode, wParam, lParam);
+}
+
+// - WM_Hooks_Install
+
+BOOL WM_Hooks_Install(DWORD owner, DWORD thread) {
+ // - Are there already hooks set?
+ if (hook_owner) {
+ if (!PostThreadMessage(hook_owner, WM_HK_PingThread, 0, 0)) {
+ WM_Hooks_Remove(hook_owner);
+ } else {
+ return FALSE;
+ }
+ }
+
+ // - Initialise the hooks
+ hook_owner = owner;
+ hook_target = thread;
+
+ hook_CallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, HookCallWndProc, dll_instance, thread);
+ hook_CallWndProcRet = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallWndProcRet, dll_instance, thread);
+ hook_GetMessage = SetWindowsHookEx(WH_GETMESSAGE, HookGetMessage, dll_instance, thread);
+ hook_DialogMessage = SetWindowsHookEx(WH_SYSMSGFILTER, HookDialogMessage, dll_instance, thread);
+
+ if (!hook_CallWndProc /*|| !hook_CallWndProcRet*/ || !hook_GetMessage || !hook_DialogMessage) {
+ WM_Hooks_Remove(owner);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// - WM_Hooks_Remove
+
+BOOL WM_Hooks_Remove(DWORD owner) {
+ if (owner != hook_owner) return FALSE;
+ if (hook_CallWndProc) {
+ UnhookWindowsHookEx(hook_CallWndProc);
+ hook_CallWndProc = 0;
+ }
+ if (hook_CallWndProcRet) {
+ UnhookWindowsHookEx(hook_CallWndProcRet);
+ hook_CallWndProcRet = 0;
+ }
+ if (hook_GetMessage) {
+ UnhookWindowsHookEx(hook_GetMessage);
+ hook_GetMessage = 0;
+ }
+ if (hook_DialogMessage) {
+ UnhookWindowsHookEx(hook_DialogMessage);
+ hook_DialogMessage = 0;
+ }
+ hook_owner = 0;
+ hook_target = 0;
+ return TRUE;
+}
+
+//
+// -=- User input hooks
+//
+
+#pragma data_seg(".WM_Hooks_Shared")
+HHOOK hook_keyboard = 0;
+HHOOK hook_pointer = 0;
+bool enable_real_ptr = true;
+bool enable_synth_ptr = true;
+bool enable_real_kbd = true;
+bool enable_synth_kbd = true;
+#pragma data_seg()
+
+#ifdef WH_KEYBOARD_LL
+LRESULT CALLBACK HookKeyboardHook(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode >= 0) {
+ KBDLLHOOKSTRUCT* info = (KBDLLHOOKSTRUCT*) lParam;
+ bool real_event = (info->flags & LLKHF_INJECTED) == 0;
+ if ((real_event && !enable_real_kbd) ||
+ (!real_event && !enable_synth_kbd)) {
+ return 1;
+ }
+ }
+ return CallNextHookEx(hook_keyboard, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK HookPointerHook(int nCode, WPARAM wParam, LPARAM lParam) {
+ if (nCode >= 0) {
+ MSLLHOOKSTRUCT* info = (MSLLHOOKSTRUCT*) lParam;
+ bool real_event = (info->flags & LLMHF_INJECTED) == 0;
+ if ((real_event && !enable_real_ptr) ||
+ (!real_event && !enable_synth_ptr)) {
+ return 1;
+ }
+ }
+ return CallNextHookEx(hook_keyboard, nCode, wParam, lParam);
+}
+
+bool RefreshInputHooks() {
+ bool success = true;
+ bool set_ptr_hook = !enable_real_ptr || !enable_synth_ptr;
+ bool set_kbd_hook = !enable_real_kbd || !enable_synth_kbd;
+ if (hook_keyboard && !set_kbd_hook) {
+ UnhookWindowsHookEx(hook_keyboard);
+ hook_keyboard = 0;
+ }
+ if (hook_pointer && !set_ptr_hook) {
+ UnhookWindowsHookEx(hook_pointer);
+ hook_pointer = 0;
+ }
+ if (!hook_keyboard && set_kbd_hook) {
+ hook_keyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboardHook, dll_instance, 0);
+ if (!hook_keyboard) success = false;
+ }
+ if (!hook_pointer && set_ptr_hook) {
+ hook_pointer = SetWindowsHookEx(WH_MOUSE_LL, HookPointerHook, dll_instance, 0);
+ if (!hook_pointer) success = false;
+ }
+ return success;
+}
+#else
+#pragma message(" NOTE: low-level mouse and keyboard hooks not supported")
+#endif
+
+// - WM_Hooks_EnableRealInputs
+
+BOOL WM_Hooks_EnableRealInputs(BOOL pointer, BOOL keyboard) {
+#ifdef WH_KEYBOARD_LL
+ enable_real_ptr = pointer!=0;
+ enable_real_kbd = keyboard!=0;
+ return RefreshInputHooks();
+#else
+ return FALSE;
+#endif
+}
+
+// - WM_Hooks_EnableSynthInputs
+
+BOOL WM_Hooks_EnableSynthInputs(BOOL pointer, BOOL keyboard) {
+#ifdef WH_KEYBOARD_LL
+ enable_synth_ptr = pointer!=0;
+ enable_synth_kbd = keyboard!=0;
+ return RefreshInputHooks();
+#else
+ return FALSE;
+#endif
+}
+
+// - WM_Hooks_EnableCursorShape
+
+BOOL WM_Hooks_EnableCursorShape(BOOL enable) {
+ enable_cursor_shape = enable;
+ return TRUE;
+}
diff --git a/win/wm_hooks/wm_hooks.def b/win/wm_hooks/wm_hooks.def
new file mode 100644
index 00000000..b9198ab9
--- /dev/null
+++ b/win/wm_hooks/wm_hooks.def
@@ -0,0 +1,5 @@
+LIBRARY "wm_hooks"
+DESCRIPTION 'Window Message Hooks Dynamic Link Library'
+
+SECTIONS
+ .WM_Hooks_Shared read write shared
diff --git a/win/wm_hooks/wm_hooks.dsp b/win/wm_hooks/wm_hooks.dsp
new file mode 100644
index 00000000..65e4b866
--- /dev/null
+++ b/win/wm_hooks/wm_hooks.dsp
@@ -0,0 +1,149 @@
+# Microsoft Developer Studio Project File - Name="wm_hooks" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=wm_hooks - Win32 Debug Unicode
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wm_hooks.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wm_hooks.mak" CFG="wm_hooks - Win32 Debug Unicode"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wm_hooks - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "wm_hooks - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "wm_hooks - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wm_hooks - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../Release"
+# PROP Intermediate_Dir "..\Release\wm_hooks"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /FI"../../common/rdr/msvcwarning.h" /D "NDEBUG" /D "_MBCS" /D "_WINDOWS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /D "WIN32" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "wm_hooks - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Debug"
+# PROP Intermediate_Dir "..\Debug\wm_hooks"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"../../common/rdr/msvcwarning.h" /D "_DEBUG" /D "_MBCS" /D "_WINDOWS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /D "WIN32" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /profile
+
+!ELSEIF "$(CFG)" == "wm_hooks - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "wm_hooks___Win32_Debug_Unicode"
+# PROP BASE Intermediate_Dir "wm_hooks___Win32_Debug_Unicode"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug_Unicode"
+# PROP Intermediate_Dir "..\Debug_Unicode\wm_hooks"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"../../common/rdr/msvcwarning.h" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_WINDOWS" /D "_USRDLL" /D "WM_HOOKS_EXPORTS" /D "WIN32" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wm_hooks - Win32 Release"
+# Name "wm_hooks - Win32 Debug"
+# Name "wm_hooks - Win32 Debug Unicode"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\wm_hooks.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\wm_hooks.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\wm_hooks.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\wm_hooks.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/win/wm_hooks/wm_hooks.h b/win/wm_hooks/wm_hooks.h
new file mode 100644
index 00000000..f65412ea
--- /dev/null
+++ b/win/wm_hooks/wm_hooks.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- wm_hooks.h
+//
+// Window Message Hooks Dynamic Link library
+//
+// This interface is used by the WMHooks class in rfb_win32 to hook the
+// windows on the desktop and receive notifications of changes in their
+// state.
+
+#ifndef __WM_HOOKS_H__
+#define __WM_HOOKS_H__
+
+#include <windows.h>
+
+#define DLLEXPORT __declspec(dllexport)
+
+extern "C"
+{
+ //
+ // -=- Display hook message types
+ //
+
+ DLLEXPORT UINT WM_Hooks_WindowChanged();
+ DLLEXPORT UINT WM_Hooks_WindowBorderChanged();
+ DLLEXPORT UINT WM_Hooks_WindowClientAreaChanged();
+ DLLEXPORT UINT WM_Hooks_RectangleChanged();
+ DLLEXPORT UINT WM_Hooks_CursorChanged();
+
+ //
+ // -=- Display update hooks
+ //
+
+ // - WM_Hooks_Install
+ // Add the current thread to the list of threads that will receive
+ // notifications of changes to the display.
+ // If thread is NULL then the entire display will be hooked.
+ // If thread is !NULL and then the specified
+ // thread will be hooked.
+ // Each thread may only register one hook at a time.
+ // The call will fail (return FALSE) if the thread already has hooks
+ // set, or if the hooks cannot be set, or some other error occurs.
+
+ DLLEXPORT BOOL WM_Hooks_Install(DWORD owner, DWORD thread);
+
+ // - WM_Hooks_Remove
+ // Removes any hook set by the current thread.
+ // The return indicates whether anything went wrong removing the hooks,
+ // that might cause problems later.
+
+ DLLEXPORT BOOL WM_Hooks_Remove(DWORD owner);
+
+ //
+ // -=- User input hooks
+ //
+
+ // - WM_Hooks_EnableRealInputs
+ // If TRUE is passed, then "real" input is enabled, otherwise it is disabled.
+
+ DLLEXPORT BOOL WM_Hooks_EnableRealInputs(BOOL pointer, BOOL keyboard);
+
+ // - WM_Hooks_EnableSynthInputs
+ // If TRUE is passed, then synthetic inputs are enabled, otherwise disabled.
+
+ DLLEXPORT BOOL WM_Hooks_EnableSynthInputs(BOOL pointer, BOOL keyboard);
+
+ //
+ // -=- Cursor shape hooking
+ //
+
+ // - WM_Hooks_EnableCursorShape
+ // If TRUE is passed, then hooks will produce notifications when cursor shape
+ // changes.
+
+ DLLEXPORT BOOL WM_Hooks_EnableCursorShape(BOOL enable);
+
+#ifdef _DEBUG
+ // - WM_Hooks_SetDiagnosticRange
+ // Select a range of messages that will be reported while hooks are active
+ DLLEXPORT void WM_Hooks_SetDiagnosticRange(UINT min, UINT max);
+ DLLEXPORT UINT WM_Hooks_Diagnostic();
+#endif
+
+}
+
+#endif // __WM_HOOKS_H__
diff --git a/win/wm_hooks/wm_hooks.rc b/win/wm_hooks/wm_hooks.rc
new file mode 100644
index 00000000..3f171d26
--- /dev/null
+++ b/win/wm_hooks/wm_hooks.rc
@@ -0,0 +1,109 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 4,1,0,0
+ PRODUCTVERSION 4,1,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "080904b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "Constantin Kaplinsky\0"
+ VALUE "FileDescription", "TightVNC Server Hooking DLL for Win32\0"
+ VALUE "FileVersion", "4.1\0"
+ VALUE "InternalName", "\0"
+ VALUE "LegalCopyright", "Copyright (C) 1998-2005 [many holders]\0"
+ VALUE "LegalTrademarks", "TightVNC\0"
+ VALUE "OriginalFilename", "wm_hooks.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "TightVNC Server\0"
+ VALUE "ProductVersion", "4.1\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x809, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+