CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/vncdll/winvnc/VNCHooks/VNCHooks.cpp
Views: 11783
1
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
2
//
3
// This file is part of the VNC system.
4
//
5
// The VNC system is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 2 of the License, or
8
// (at your option) any later version.
9
//
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18
// USA.
19
//
20
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
21
//
22
// If the source code for the VNC system is not available from the place
23
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
24
// the authors on [email protected] for information on obtaining it.
25
26
// VNCHooks.cpp : Defines the implementation of the DLL.
27
//
28
29
#include "VNCHooks.h"
30
31
#include <stdlib.h>
32
#include <stdio.h>
33
#include <crtdbg.h>
34
35
/////////////////////////////////////////////////////////////////////////////
36
// Storage for the global data in the DLL
37
// Note: For Borland C++ compilers, this data segment is defined in a
38
// separate file, SharedData.cpp.
39
40
#ifdef _MSC_VER
41
42
// MSVC is bugged - if a default value is missed off from one of the following
43
// variables then that variable is process-specific for some reason!
44
45
#pragma data_seg(".SharedData")
46
HWND hVeneto = NULL;
47
HWND hKeyboardPriorityWindow = NULL;
48
HWND hMousePriorityWindow = NULL;
49
UINT UpdateRectMessage = 0;
50
UINT CopyRectMessage = 0;
51
UINT MouseMoveMessage = 0;
52
UINT LocalMouseMessage = 0;
53
UINT LocalKeyboardMessage = 0;
54
HHOOK hCallWndHook = NULL; // Handle to the CallWnd hook
55
HHOOK hGetMsgHook = NULL; // Handle to the GetMsg hook
56
HHOOK hDialogMsgHook = NULL; // Handle to the DialogMsg hook
57
HHOOK hLLKeyboardHook = NULL; // Handle to LowLevel kbd hook
58
HHOOK hLLMouseHook = NULL; // Handle to LowLevel mouse hook
59
HHOOK hLLKeyboardPrHook = NULL; // Handle to LowLevel kbd hook for local event priority
60
HHOOK hLLMousePrHook = NULL; // Handle to LowLevel mouse hook for local event priority
61
HHOOK hKeyboardHook = NULL; // Handle to kbd hook
62
HHOOK hMouseHook = NULL; // Handle to mouse hook
63
64
#pragma data_seg( )
65
66
#else
67
68
#include "SharedData.h"
69
70
#endif // _MSC_VER
71
72
/////////////////////////////////////////////////////////////////////////////
73
// Per-instance DLL variables
74
75
const char sPrefSegment[] = "Application_Prefs\\";
76
char *sModulePrefs = NULL; // Name of the module that created us
77
BOOL prf_use_GetUpdateRect = FALSE; // Use the GetUpdateRect paint mode
78
BOOL prf_use_Timer = FALSE; // Use Timer events to trigger updates
79
BOOL prf_use_KeyPress = FALSE; // Use keyboard events
80
BOOL prf_use_LButtonUp = TRUE; // Use left mouse button up events
81
BOOL prf_use_MButtonUp = FALSE; // Use middle mouse button up events
82
BOOL prf_use_RButtonUp = FALSE; // Use right mouse button up events
83
BOOL prf_use_Deferral = FALSE; // Use deferred updates
84
85
HKEY hModuleKey = NULL; // Key used to save settings
86
HINSTANCE hInstance = NULL; // This instance of the DLL
87
BOOL HookMaster = FALSE; // Is this instance veneto itself?
88
89
BOOL appHookedOK = FALSE; // Did InitInstance succeed?
90
91
/////////////////////////////////////////////////////////////////////////////
92
// Registered messages & atoms to be used by VNCHooks.DLL
93
94
// Messages
95
const UINT VNC_DEFERRED_UPDATE = RegisterWindowMessage("VNCHooks.Deferred.UpdateMessage");
96
97
// Atoms
98
const char *VNC_WINDOWPOS_ATOMNAME = "VNCHooks.CopyRect.WindowPos";
99
const char *VNC_POPUPSELN_ATOMNAME = "VNCHooks.PopUpMenu.Selected";
100
ATOM VNC_WINDOWPOS_ATOM = NULL;
101
ATOM VNC_POPUPSELN_ATOM = NULL;
102
103
/////////////////////////////////////////////////////////////////////////////
104
// The DLL functions
105
106
// Forward definition of hook procedures
107
108
BOOL HookHandle(UINT msg, HWND hWnd, WPARAM wParam, LPARAM lParam);
109
LRESULT CALLBACK CallWndProc (int nCode, WPARAM wParam, LPARAM lParam);
110
LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);
111
LRESULT CALLBACK DialogMessageProc(int nCode, WPARAM wParam, LPARAM lParam);
112
LRESULT CALLBACK LowLevelKeyboardFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
113
LRESULT CALLBACK LowLevelMouseFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
114
LRESULT CALLBACK LowLevelKeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam);
115
LRESULT CALLBACK LowLevelMousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam);
116
LRESULT CALLBACK KeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam);
117
LRESULT CALLBACK MousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam);
118
119
// Forward definition of setup and shutdown procedures
120
BOOL InitInstance();
121
BOOL ExitInstance();
122
123
// The DLL's main procedure
124
BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
125
{
126
// Find out why we're being called
127
switch (ul_reason_for_call)
128
{
129
130
case DLL_PROCESS_ATTACH:
131
#ifdef _MSC_VER
132
_RPT0(_CRT_WARN, "vncHooks : Hook DLL loaded\n");
133
#endif
134
135
// Save the instance handle
136
hInstance = (HINSTANCE)hInst;
137
138
// Call the initialisation function
139
appHookedOK = InitInstance();
140
141
// ALWAYS return TRUE to avoid breaking unhookable applications!!!
142
return TRUE;
143
144
case DLL_PROCESS_DETACH:
145
#ifdef _MSC_VER
146
_RPT0(_CRT_WARN, "vncHooks : Hook DLL unloaded\n");
147
#endif
148
149
// Call the exit function
150
// If the app failed to hook OK, ExitInstance will still operate OK (hopefully...)
151
ExitInstance();
152
153
return TRUE;
154
155
default:
156
return TRUE;
157
}
158
}
159
160
// Add the new hook
161
162
DllExport BOOL SetHook(HWND hWnd, UINT UpdateMsg, UINT CopyMsg, UINT MouseMsg)
163
{
164
165
// Don't add the hook if the window ID is NULL
166
if (hWnd == NULL)
167
return FALSE;
168
169
// Don't add a hook if there is already one added
170
if (hVeneto != NULL)
171
return FALSE;
172
173
// Add the CallWnd hook
174
hCallWndHook = SetWindowsHookEx(
175
WH_CALLWNDPROC, // Hook in before msg reaches app
176
(HOOKPROC) CallWndProc, // Hook procedure
177
hInstance, // This DLL instance
178
0L // Hook in to all apps
179
// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC
180
);
181
182
// Add the GetMessage hook
183
hGetMsgHook = SetWindowsHookEx(
184
WH_GETMESSAGE, // Hook in before msg reaches app
185
(HOOKPROC) GetMessageProc, // Hook procedure
186
hInstance, // This DLL instance
187
0L // Hook in to all apps
188
// GetCurrentThreadId() // DEBUG : HOOK ONLY WinVNC
189
);
190
191
// Add the GetMessage hook
192
hDialogMsgHook = SetWindowsHookEx(
193
WH_SYSMSGFILTER, // Hook in dialogs, menus and scrollbars
194
(HOOKPROC) DialogMessageProc, // Hook procedure
195
hInstance, // This DLL instance
196
0L // Hook in to all apps
197
);
198
199
// Check that it worked
200
if ((hCallWndHook != NULL) && (hGetMsgHook != NULL) && (hDialogMsgHook != NULL))
201
{
202
hVeneto = hWnd; // Save the WinRFB window handle
203
UpdateRectMessage = UpdateMsg; // Save the message ID to use for rectangle updates
204
CopyRectMessage = CopyMsg; // Save the message ID to use for copyrect
205
MouseMoveMessage = MouseMsg; // Save the message ID to send when mouse moves
206
HookMaster = TRUE; // Set the HookMaster flag for this instance
207
208
#ifdef _MSC_VER
209
_RPT1(_CRT_WARN, "Window : %d\n", hWnd);
210
#endif
211
212
return TRUE;
213
}
214
else
215
{
216
// Stop the keyboard hook
217
SetKeyboardFilterHook(FALSE);
218
SetMouseFilterHook(FALSE);
219
220
// Kill the main hooks
221
if (hCallWndHook != NULL)
222
UnhookWindowsHookEx(hCallWndHook);
223
if (hGetMsgHook != NULL)
224
UnhookWindowsHookEx(hGetMsgHook);
225
if (hDialogMsgHook != NULL)
226
UnhookWindowsHookEx(hDialogMsgHook);
227
hCallWndHook = NULL;
228
hGetMsgHook = NULL;
229
hDialogMsgHook = NULL;
230
}
231
232
// The hook failed, so return an error code
233
return FALSE;
234
235
}
236
237
// EnumWindows procedure to remove the extra property we added
238
239
BOOL CALLBACK
240
KillPropsProc(HWND hwnd, LPARAM lParam)
241
{
242
// Remove our custom property...
243
RemoveProp(hwnd, (LPCTSTR) MAKEWORD(VNC_WINDOWPOS_ATOM, 0));
244
RemoveProp(hwnd, (LPCTSTR) MAKEWORD(VNC_POPUPSELN_ATOM, 0));
245
return TRUE;
246
}
247
248
// Remove the hook from the system
249
250
DllExport BOOL UnSetHook(HWND hWnd)
251
{
252
253
BOOL unHooked = TRUE;
254
255
// Remove the extra property value from all local windows
256
EnumWindows((WNDENUMPROC) &KillPropsProc, NULL);
257
258
// Stop the keyboard & mouse hooks
259
unHooked = unHooked && SetKeyboardFilterHook(FALSE);
260
unHooked = unHooked && SetMouseFilterHook(FALSE);
261
262
// Is the window handle valid?
263
if (hWnd == NULL)
264
MessageBox(NULL, "Window pointer is null", "Message", MB_OK);
265
266
// Is the correct application calling UnSetHook?
267
if (hWnd != hVeneto)
268
return FALSE;
269
270
// Unhook the procs
271
if (hCallWndHook != NULL)
272
{
273
unHooked = unHooked && UnhookWindowsHookEx(hCallWndHook);
274
hCallWndHook = NULL;
275
}
276
277
if (hGetMsgHook != NULL)
278
{
279
unHooked = unHooked && UnhookWindowsHookEx(hGetMsgHook);
280
hGetMsgHook = NULL;
281
}
282
283
if (hDialogMsgHook != NULL)
284
{
285
unHooked = unHooked && UnhookWindowsHookEx(hDialogMsgHook);
286
hDialogMsgHook = NULL;
287
}
288
289
// If we managed to unhook then reset
290
if (unHooked)
291
{
292
hVeneto = NULL;
293
HookMaster = FALSE;
294
}
295
296
return unHooked;
297
298
}
299
300
// Routine to start and stop local keyboard message filtering
301
DllExport BOOL SetKeyboardFilterHook(BOOL activate)
302
{
303
if (activate)
304
{
305
#ifdef WH_KEYBOARD_LL
306
if (hLLKeyboardHook == NULL)
307
{
308
// Start up the hook...
309
hLLKeyboardHook = SetWindowsHookEx(
310
WH_KEYBOARD_LL, // Hook in before msg reaches app
311
(HOOKPROC) LowLevelKeyboardFilterProc, // Hook procedure
312
hInstance, // This DLL instance
313
0L // Hook in to all apps
314
);
315
if (hLLKeyboardHook == NULL)
316
return FALSE;
317
}
318
return TRUE;
319
#else
320
#pragma message("warning:Low-Level Keyboard hook code omitted.")
321
return FALSE;
322
#endif
323
} else {
324
if (hLLKeyboardHook != NULL)
325
{
326
// Stop the hook...
327
if (!UnhookWindowsHookEx(hLLKeyboardHook))
328
return FALSE;
329
hLLKeyboardHook = NULL;
330
}
331
return TRUE;
332
}
333
}
334
335
DllExport BOOL SetKeyboardPriorityLLHook(HWND hwnd, BOOL activate, UINT LocalKbdMsg)
336
{
337
LocalKeyboardMessage = LocalKbdMsg;
338
if (activate)
339
{
340
#ifdef WH_KEYBOARD_LL
341
if (hLLKeyboardPrHook == NULL)
342
{
343
// save the window handle
344
hKeyboardPriorityWindow = hwnd;
345
346
// Start up the hook...
347
hLLKeyboardPrHook = SetWindowsHookEx(
348
WH_KEYBOARD_LL, // Hook in before msg reaches app
349
(HOOKPROC) LowLevelKeyboardPriorityProc, // Hook procedure
350
hInstance, // This DLL instance
351
0L // Hook in to all apps
352
);
353
if (hLLKeyboardPrHook == NULL)
354
return FALSE;
355
}
356
return TRUE;
357
#else
358
#pragma message("warning:Low-Level Keyboard hook code omitted.")
359
return FALSE;
360
#endif
361
} else {
362
if (hLLKeyboardPrHook != NULL)
363
{
364
// Stop the hook...
365
if (!UnhookWindowsHookEx(hLLKeyboardPrHook))
366
return FALSE;
367
368
// reset the hook and window handle
369
hKeyboardPriorityWindow = NULL;
370
hLLKeyboardPrHook = NULL;
371
}
372
return TRUE;
373
}
374
}
375
376
// Routine to start and stop local mouse message filtering
377
DllExport BOOL SetMouseFilterHook(BOOL activate)
378
{
379
if (activate)
380
{
381
#ifdef WH_MOUSE_LL
382
if (hLLMouseHook == NULL)
383
{
384
// Start up the hook...
385
hLLMouseHook = SetWindowsHookEx(
386
WH_MOUSE_LL, // Hook in before msg reaches app
387
(HOOKPROC) LowLevelMouseFilterProc, // Hook procedure
388
hInstance, // This DLL instance
389
0L // Hook in to all apps
390
);
391
if (hLLMouseHook == NULL)
392
return FALSE;
393
}
394
return TRUE;
395
#else
396
#pragma message("warning:Low-Level Mouse hook code omitted.")
397
return FALSE;
398
#endif
399
} else {
400
if (hLLMouseHook != NULL)
401
{
402
// Stop the hook...
403
if (!UnhookWindowsHookEx(hLLMouseHook))
404
return FALSE;
405
hLLMouseHook = NULL;
406
}
407
return TRUE;
408
}
409
}
410
411
DllExport BOOL SetMousePriorityLLHook(HWND hwnd, BOOL activate, UINT LocalMouseMsg)
412
{
413
LocalMouseMessage = LocalMouseMsg;
414
if (activate)
415
{
416
#ifdef WH_MOUSE_LL
417
if (hLLMousePrHook == NULL)
418
{
419
// save the window handle
420
hMousePriorityWindow = hwnd;
421
422
// Start up the hook...
423
hLLMousePrHook = SetWindowsHookEx(
424
WH_MOUSE_LL, // Hook in before msg reaches app
425
(HOOKPROC) LowLevelMousePriorityProc, // Hook procedure
426
hInstance, // This DLL instance
427
0L // Hook in to all apps
428
);
429
if (hLLMousePrHook == NULL)
430
return FALSE;
431
}
432
return TRUE;
433
#else
434
#pragma message("warning:Low-Level Mouse hook code omitted.")
435
return FALSE;
436
#endif
437
} else {
438
if (hLLMousePrHook != NULL)
439
{
440
// Stop the hook...
441
if (!UnhookWindowsHookEx(hLLMousePrHook))
442
return FALSE;
443
444
// reset the hook and window handle
445
hMousePriorityWindow = NULL;
446
hLLMousePrHook = NULL;
447
}
448
return TRUE;
449
}
450
}
451
452
453
// Routine to start and stop local keyboard message filtering
454
DllExport BOOL SetKeyboardPriorityHook(HWND hwnd, BOOL activate, UINT LocalKbdMsg)
455
{
456
LocalKeyboardMessage = LocalKbdMsg;
457
if (activate)
458
{
459
if (hKeyboardHook == NULL)
460
{
461
// save the window handle
462
hKeyboardPriorityWindow = hwnd;
463
464
// Start up the hook...
465
hKeyboardHook = SetWindowsHookEx(
466
WH_KEYBOARD, // Hook in before msg reaches app
467
(HOOKPROC) KeyboardPriorityProc,// Hook procedure
468
hInstance, // This DLL instance
469
0L // Hook in to all apps
470
);
471
if (hKeyboardHook == NULL)
472
return FALSE;
473
}
474
return TRUE;
475
} else {
476
if (hKeyboardHook != NULL)
477
{
478
// Stop the hook...
479
if (!UnhookWindowsHookEx(hKeyboardHook))
480
return FALSE;
481
482
// reset the hook and window handle
483
hKeyboardPriorityWindow = NULL;
484
hKeyboardHook = NULL;
485
}
486
return TRUE;
487
}
488
}
489
490
491
// Routine to start and stop local mouse message filtering
492
DllExport BOOL SetMousePriorityHook(HWND hwnd, BOOL activate, UINT LocalMouseMsg)
493
{
494
LocalMouseMessage = LocalMouseMsg;
495
if (activate)
496
{
497
if (hMouseHook == NULL)
498
{
499
// save the window handle
500
hMousePriorityWindow = hwnd;
501
502
// Start up the hook...
503
hMouseHook = SetWindowsHookEx(
504
WH_MOUSE, // Hook in before msg reaches app
505
(HOOKPROC) MousePriorityProc, // Hook procedure
506
hInstance, // This DLL instance
507
0L // Hook in to all apps
508
);
509
if (hMouseHook == NULL)
510
return FALSE;
511
}
512
return TRUE;
513
} else {
514
if (hMouseHook != NULL)
515
{
516
// Stop the hook...
517
if (!UnhookWindowsHookEx(hMouseHook))
518
return FALSE;
519
520
// reset the hook and window handle
521
hMousePriorityWindow = NULL;
522
hMouseHook = NULL;
523
}
524
return TRUE;
525
}
526
}
527
528
529
530
// Routine to get the window's client rectangle, in screen coordinates
531
inline BOOL GetAbsoluteClientRect(HWND hwnd, RECT *rect)
532
{
533
POINT topleft;
534
topleft.x = 0;
535
topleft.y = 0;
536
537
// Get the client rectangle size
538
if (!GetClientRect(hwnd, rect))
539
return FALSE;
540
541
// Get the client rectangle position
542
if (!ClientToScreen(hwnd, &topleft))
543
return FALSE;
544
545
// Now adjust the window rectangle
546
rect->left += topleft.x;
547
rect->top += topleft.y;
548
rect->right += topleft.x;
549
rect->bottom += topleft.y;
550
551
return TRUE;
552
}
553
554
// Routine to send a CopyRect message to WinVNC
555
inline void SendCopyWindowRect(HWND hWnd)
556
{
557
WPARAM vwParam;
558
559
// All we send back is the handle of the window to be moved
560
vwParam = (LPARAM) hWnd;
561
562
// Send the update to Veneto
563
PostMessage(
564
hVeneto,
565
CopyRectMessage,
566
vwParam,
567
0
568
);
569
}
570
571
// Routine to send an UpdateRect message to Veneto
572
inline void SendUpdateRect(SHORT x, SHORT y, SHORT x2, SHORT y2)
573
{
574
WPARAM vwParam;
575
LPARAM vlParam;
576
577
vwParam = MAKELONG(x, y);
578
vlParam = MAKELONG(x2, y2);
579
580
// Send the update to Veneto
581
PostMessage(
582
hVeneto,
583
UpdateRectMessage,
584
vwParam,
585
vlParam
586
);
587
}
588
589
// Send a window's position to Veneto
590
591
inline void SendWindowRect(HWND hWnd)
592
{
593
RECT wrect;
594
595
// Get the rectangle position
596
if (GetWindowRect(hWnd, &wrect) && IsWindowVisible(hWnd))
597
{
598
// Send the position
599
SendUpdateRect(
600
(SHORT) wrect.left,
601
(SHORT) wrect.top,
602
(SHORT) wrect.right,
603
(SHORT) wrect.bottom
604
);
605
}
606
}
607
608
// Send a deferred message into this Window's message queue, so that
609
// we'll intercept it again only after the message that triggered it has been
610
// handled
611
612
inline void SendDeferredUpdateRect(HWND hWnd, SHORT x, SHORT y, SHORT x2, SHORT y2)
613
{
614
WPARAM vwParam;
615
LPARAM vlParam;
616
617
vwParam = MAKELONG(x, y);
618
vlParam = MAKELONG(x2, y2);
619
620
if (prf_use_Deferral)
621
{
622
// Send the update back to the window
623
PostMessage(
624
hWnd,
625
VNC_DEFERRED_UPDATE,
626
vwParam,
627
vlParam
628
);
629
}
630
else
631
{
632
// Send the update to WinRFB
633
PostMessage(
634
hVeneto,
635
UpdateRectMessage,
636
vwParam,
637
vlParam
638
);
639
}
640
}
641
642
inline void SendDeferredWindowRect(HWND hWnd)
643
{
644
RECT wrect;
645
646
// Get the rectangle position
647
if (::GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))
648
{
649
// Send the position
650
SendDeferredUpdateRect(
651
hWnd,
652
(SHORT) wrect.left,
653
(SHORT) wrect.top,
654
(SHORT) wrect.right,
655
(SHORT) wrect.bottom
656
);
657
}
658
}
659
660
inline void SendDeferredBorderRect(HWND hWnd)
661
{
662
RECT wrect;
663
RECT crect;
664
665
// Get the rectangle position
666
if (GetWindowRect(hWnd, &wrect) && ::IsWindowVisible(hWnd))
667
{
668
// Get the client rectangle position
669
if (GetAbsoluteClientRect(hWnd, &crect))
670
{
671
// Send the four border rectangles
672
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) crect.top);
673
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) wrect.top, (SHORT) crect.left, (SHORT) wrect.bottom);
674
SendDeferredUpdateRect(hWnd, (SHORT) wrect.left, (SHORT) crect.bottom, (SHORT) wrect.right, (SHORT) wrect.bottom);
675
SendDeferredUpdateRect(hWnd, (SHORT) crect.right, (SHORT) wrect.top, (SHORT) wrect.right, (SHORT) wrect.bottom);
676
}
677
}
678
}
679
680
// Generic hook-handler
681
682
inline BOOL HookHandle(UINT MessageId, HWND hWnd, WPARAM wParam, LPARAM lParam)
683
{
684
////////////////////////////////////////////////////////////////
685
// *** HANDLE DEFERRED UPDATES ***
686
687
// Is this a deferred-update message?
688
if (MessageId == VNC_DEFERRED_UPDATE)
689
{
690
691
// NOTE : NEVER use the SendDeferred- routines to send updates
692
// from here, or you'll get an infinite loop....!
693
694
// NB : The format of DEFERRED_UPDATE matches that of UpdateRectMessage,
695
// so just send the exact same message data to WinRFB:
696
697
PostMessage(
698
hVeneto,
699
UpdateRectMessage,
700
wParam,
701
lParam
702
);
703
704
return FALSE;
705
}
706
707
// *** Could use WM_COPYDATA to send data to WinVNC
708
709
/*
710
if (GetClassLong(hWnd, GCW_ATOM) == 32768)
711
{
712
_RPT4(_CRT_WARN, "DBG : popup menu message (hwnd=%d, msg=%d, l=%d, w=%d)\n",
713
hWnd, MessageId, lParam, wParam);
714
}
715
*/
716
717
////////////////////////////////////////////////////////////////
718
// *** UPDATE-TRIGGERING MESSAGES ***
719
720
// Do something dependent upon message type
721
switch (MessageId)
722
{
723
724
////////////////////////////////////////////////////////////////
725
// Messages indicating only a border repaint.
726
case WM_NCPAINT:
727
case WM_NCACTIVATE:
728
SendDeferredBorderRect(hWnd);
729
break;
730
731
////////////////////////////////////////////////////////////////
732
// Messages indicating a client area repaint
733
case WM_CHAR:
734
case WM_KEYUP: // Handle key-presses
735
if (prf_use_KeyPress)
736
SendDeferredWindowRect(hWnd);
737
break;
738
739
case WM_LBUTTONUP: // Handle LMB clicks
740
if (prf_use_LButtonUp)
741
SendDeferredWindowRect(hWnd);
742
break;
743
744
case WM_MBUTTONUP: // Handle MMB clicks
745
if (prf_use_MButtonUp)
746
SendDeferredWindowRect(hWnd);
747
break;
748
749
case WM_RBUTTONUP: // Handle RMB clicks
750
if (prf_use_RButtonUp)
751
SendDeferredWindowRect(hWnd);
752
break;
753
754
case WM_TIMER:
755
if (prf_use_Timer)
756
SendDeferredWindowRect(hWnd);
757
break;
758
759
case WM_HSCROLL:
760
case WM_VSCROLL:
761
if (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL))
762
SendDeferredWindowRect(hWnd);
763
break;
764
765
case 485: // HACK to handle popup menus
766
{
767
// Get the old popup menu selection value
768
HANDLE prop = GetProp(hWnd, (LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0));
769
if (prop != (HANDLE) wParam)
770
{
771
// It did, so update the menu & the selection value
772
SendDeferredWindowRect(hWnd);
773
SetProp(hWnd,
774
(LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0),
775
(HANDLE) wParam);
776
}
777
}
778
break;
779
780
////////////////////////////////////////////////////////////////
781
// Messages indicating a full window update
782
case WM_SYSCOLORCHANGE:
783
case WM_PALETTECHANGED:
784
case WM_SETTEXT:
785
case WM_ENABLE:
786
case BM_SETCHECK:
787
case BM_SETSTATE:
788
case EM_SETSEL:
789
//case WM_MENUSELECT:
790
SendDeferredWindowRect(hWnd);
791
break;
792
793
////////////////////////////////////////////////////////////////
794
// Messages indicating that an area of the window needs updating
795
// Uses GetUpdateRect to find out which
796
case WM_PAINT:
797
if (prf_use_GetUpdateRect)
798
{
799
HRGN region;
800
region = CreateRectRgn(0, 0, 0, 0);
801
802
// Get the affected region
803
if (GetUpdateRgn(hWnd, region, FALSE) != ERROR)
804
{
805
int buffsize;
806
UINT x;
807
RGNDATA *buff;
808
POINT TopLeft;
809
810
// Get the top-left point of the client area
811
TopLeft.x = 0;
812
TopLeft.y = 0;
813
if (!ClientToScreen(hWnd, &TopLeft))
814
break;
815
816
// Get the size of buffer required
817
buffsize = GetRegionData(region, 0, 0);
818
if (buffsize != 0)
819
{
820
buff = (RGNDATA *) new BYTE [buffsize];
821
if (buff == NULL)
822
break;
823
824
// Now get the region data
825
if(GetRegionData(region, buffsize, buff))
826
{
827
for (x=0; x<(buff->rdh.nCount); x++)
828
{
829
// Obtain the rectangles from the list
830
RECT *urect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + (x * sizeof(RECT)));
831
SendDeferredUpdateRect(
832
hWnd,
833
(SHORT) (TopLeft.x + urect->left),
834
(SHORT) (TopLeft.y + urect->top),
835
(SHORT) (TopLeft.x + urect->right),
836
(SHORT) (TopLeft.y + urect->bottom)
837
);
838
}
839
}
840
841
delete [] buff;
842
}
843
}
844
845
// Now free the region
846
if (region != NULL)
847
DeleteObject(region);
848
}
849
else
850
SendDeferredWindowRect(hWnd);
851
break;
852
853
////////////////////////////////////////////////////////////////
854
// Messages indicating full repaint of this and a different window
855
// Send the new position of the window
856
case WM_WINDOWPOSCHANGING:
857
if (IsWindowVisible(hWnd))
858
SendWindowRect(hWnd);
859
break;
860
861
case WM_WINDOWPOSCHANGED:
862
if (IsWindowVisible(hWnd))
863
SendDeferredWindowRect(hWnd);
864
break;
865
866
////////////////////////////////////////////////////////////////
867
// WinRFB also wants to know about mouse movement
868
case WM_NCMOUSEMOVE:
869
case WM_MOUSEMOVE:
870
// Inform WinRFB that the mouse has moved and pass it the current cursor handle
871
PostMessage(
872
hVeneto,
873
MouseMoveMessage,
874
(ULONG) GetCursor(),
875
0
876
);
877
break;
878
879
////////////////////////////////////////////////////////////////
880
// VNCHOOKS PROPERTIES HANDLING WINDOWS
881
case WM_DESTROY:
882
RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_WINDOWPOS_ATOM, 0));
883
RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_POPUPSELN_ATOM, 0));
884
break;
885
886
}
887
888
return TRUE;
889
}
890
891
// Hook procedure for CallWindow hook
892
893
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
894
{
895
// Do we have to handle this message?
896
if (nCode == HC_ACTION)
897
{
898
// Process the hook if the Veneto window handle is valid
899
if (hVeneto != NULL)
900
{
901
CWPSTRUCT *cwpStruct = (CWPSTRUCT *) lParam;
902
HookHandle(cwpStruct->message, cwpStruct->hwnd, cwpStruct->wParam, cwpStruct->lParam);
903
}
904
}
905
906
// Call the next handler in the chain
907
return CallNextHookEx (hCallWndHook, nCode, wParam, lParam);
908
}
909
910
// Hook procedure for GetMessageProc hook
911
912
LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
913
{
914
// Do we have to handle this message?
915
if (nCode == HC_ACTION)
916
{
917
// Process the hook only if the Veneto window is valid
918
if (hVeneto != NULL)
919
{
920
MSG *msg = (MSG *) lParam;
921
922
// Only handle application messages if they're being removed:
923
if (wParam & PM_REMOVE)
924
{
925
// Handle the message
926
HookHandle(msg->message, msg->hwnd, msg->wParam, msg->lParam);
927
}
928
}
929
}
930
931
// Call the next handler in the chain
932
return CallNextHookEx (hGetMsgHook, nCode, wParam, lParam);
933
}
934
935
// Hook procedure for DialogMessageProc hook
936
937
LRESULT CALLBACK DialogMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
938
{
939
// Do we have to handle this message?
940
if (nCode >= 0)
941
{
942
// Process the hook only if the Veneto window is valid
943
if (hVeneto != NULL)
944
{
945
MSG *msg = (MSG *) lParam;
946
947
// Handle the message
948
HookHandle(msg->message, msg->hwnd, msg->wParam, msg->lParam);
949
}
950
}
951
952
// Call the next handler in the chain
953
return CallNextHookEx (hGetMsgHook, nCode, wParam, lParam);
954
}
955
956
// Hook procedure for LowLevel Keyboard filtering
957
958
#ifdef WH_KEYBOARD_LL
959
LRESULT CALLBACK LowLevelKeyboardFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
960
{
961
// Are we expected to handle this callback?
962
if (nCode == HC_ACTION)
963
{
964
// Is this keyboard event "real" or "injected"
965
// i.e. hardware or software-produced?
966
KBDLLHOOKSTRUCT *hookStruct = (KBDLLHOOKSTRUCT*)lParam;
967
if (!(hookStruct->flags & LLKHF_INJECTED)) {
968
// Message was not injected - reject it!
969
return TRUE;
970
}
971
}
972
973
// Otherwise, pass on the message
974
return CallNextHookEx(hLLKeyboardHook, nCode, wParam, lParam);
975
}
976
977
LRESULT CALLBACK LowLevelKeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam)
978
{
979
// Are we expected to handle this callback?
980
// do we have a target window handle?
981
if (nCode == HC_ACTION && hKeyboardPriorityWindow != NULL)
982
{
983
// Is this keyboard event "real" or "injected"
984
// i.e. hardware or software-produced?
985
KBDLLHOOKSTRUCT *hookStruct = (KBDLLHOOKSTRUCT*)lParam;
986
if (!(hookStruct->flags & LLKHF_INJECTED)) {
987
// Message was not injected - send RFB_LOCAL_KEYBOARD msg!
988
// Remote event will be blocked
989
PostMessage(
990
hKeyboardPriorityWindow,
991
LocalKeyboardMessage,
992
0,
993
0
994
);
995
}
996
}
997
998
// Otherwise, pass on the message
999
return CallNextHookEx(hLLKeyboardPrHook, nCode, wParam, lParam);
1000
}
1001
1002
#endif
1003
1004
// Hook procedure for LowLevel Mouse filtering
1005
1006
#ifdef WH_MOUSE_LL
1007
LRESULT CALLBACK LowLevelMouseFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
1008
{
1009
// Are we expected to handle this callback?
1010
if (nCode == HC_ACTION)
1011
{
1012
// Is this mouse event "real" or "injected"
1013
// i.e. hardware or software-produced?
1014
MSLLHOOKSTRUCT *hookStruct = (MSLLHOOKSTRUCT*)lParam;
1015
if (!(hookStruct->flags & LLMHF_INJECTED)) {
1016
1017
return TRUE;
1018
}
1019
}
1020
1021
// Otherwise, pass on the message
1022
return CallNextHookEx(hLLMouseHook, nCode, wParam, lParam);
1023
}
1024
1025
LRESULT CALLBACK LowLevelMousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam)
1026
{
1027
// Are we expected to handle this callback?
1028
// do we have a target window handle?
1029
if (nCode == HC_ACTION && hMousePriorityWindow != NULL)
1030
{
1031
// Is this mouse event "real" or "injected"
1032
// i.e. hardware or software-produced?
1033
MSLLHOOKSTRUCT *hookStruct = (MSLLHOOKSTRUCT*)lParam;
1034
if (!(hookStruct->flags & LLMHF_INJECTED)) {
1035
// Message was not injected - send RFB_LOCAL_MOUSE msg!
1036
// Remote event will be blocked
1037
PostMessage(
1038
hMousePriorityWindow,
1039
LocalMouseMessage,
1040
0,
1041
0
1042
);
1043
}
1044
}
1045
1046
// Otherwise, pass on the message
1047
return CallNextHookEx(hLLMousePrHook, nCode, wParam, lParam);
1048
}
1049
1050
#endif
1051
1052
LRESULT CALLBACK KeyboardPriorityProc(int nCode, WPARAM wParam, LPARAM lParam)
1053
{
1054
// Are we expected to handle this callback?
1055
// do we have a target window handle?
1056
if (nCode == HC_ACTION && hKeyboardPriorityWindow != NULL)
1057
{
1058
PostMessage(
1059
hKeyboardPriorityWindow,
1060
LocalKeyboardMessage,
1061
0,
1062
0
1063
);
1064
1065
}
1066
1067
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
1068
}
1069
1070
1071
LRESULT CALLBACK MousePriorityProc(int nCode, WPARAM wParam, LPARAM lParam)
1072
{
1073
// Are we expected to handle this callback?
1074
// do we have a target window handle?
1075
if (nCode == HC_ACTION && hMousePriorityWindow != NULL)
1076
{
1077
if ( (wParam == WM_LBUTTONDOWN) || (wParam == WM_RBUTTONDOWN) || (wParam == WM_MBUTTONDOWN) || (wParam == WM_MOUSEMOVE) )
1078
PostMessage(
1079
hMousePriorityWindow,
1080
LocalMouseMessage,
1081
0,
1082
0
1083
);
1084
}
1085
1086
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
1087
}
1088
1089
1090
char * NameFromPath(const char *path)
1091
{
1092
int x;
1093
int l = strlen(path);
1094
char *temp = NULL;
1095
1096
// Find the file part of a filename
1097
for (x=l-1; x>0; x--)
1098
{
1099
if (path[x] == '\\')
1100
{
1101
temp = strdup(&(path[x+1]));
1102
break;
1103
}
1104
}
1105
1106
// If we didn't fine a \ then just return a copy of the original
1107
if (temp == NULL)
1108
temp = strdup(path);
1109
1110
return temp;
1111
}
1112
1113
/////////////////////////////////////////////////////////////////////////////
1114
// Initialise / Exit routines.
1115
// These functions handle the update settings for any apps used with WinVNC.
1116
1117
static const TCHAR szSoftware[] = "Software";
1118
static const TCHAR szCompany[] = "ORL";
1119
static const TCHAR szProfile[] = "VNCHooks";
1120
1121
HKEY GetRegistryKey()
1122
{
1123
HKEY hAppKey = NULL;
1124
HKEY hSoftKey = NULL;
1125
HKEY hCompanyKey = NULL;
1126
if (RegOpenKeyEx(HKEY_CURRENT_USER, szSoftware, 0, KEY_WRITE|KEY_READ,
1127
&hSoftKey) == ERROR_SUCCESS)
1128
{
1129
DWORD dw;
1130
if (RegCreateKeyEx(hSoftKey, szCompany, 0, REG_NONE,
1131
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,
1132
&hCompanyKey, &dw) == ERROR_SUCCESS)
1133
{
1134
RegCreateKeyEx(hCompanyKey, szProfile, 0, REG_NONE,
1135
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,
1136
&hAppKey, &dw);
1137
}
1138
}
1139
if (hSoftKey != NULL)
1140
RegCloseKey(hSoftKey);
1141
if (hCompanyKey != NULL)
1142
RegCloseKey(hCompanyKey);
1143
1144
return hAppKey;
1145
}
1146
1147
HKEY GetModuleKey(const char *proc_name)
1148
{
1149
HKEY hModule = NULL;
1150
1151
// Work out the registry key to save this under
1152
sModulePrefs = (char *) malloc(strlen(sPrefSegment) + strlen(proc_name) + 1);
1153
if (sModulePrefs == NULL)
1154
return FALSE;
1155
sprintf(sModulePrefs, "%s%s", sPrefSegment, proc_name);
1156
1157
// Check whether the library's entry exists!
1158
HKEY hAppKey = GetRegistryKey();
1159
if (hAppKey == NULL)
1160
return NULL;
1161
1162
// Attempt to open the section for this application
1163
if (RegOpenKeyEx(hAppKey,
1164
sModulePrefs,
1165
0, KEY_WRITE|KEY_READ,
1166
&hModule
1167
) != ERROR_SUCCESS)
1168
{
1169
// Cut off the app directory and just use the name
1170
char *file_name = NameFromPath(proc_name);
1171
1172
if (file_name == NULL)
1173
{
1174
RegCloseKey(hAppKey);
1175
return NULL;
1176
}
1177
1178
// Adjust the moduleprefs name
1179
sprintf(sModulePrefs, "%s%s", sPrefSegment, file_name);
1180
free(file_name);
1181
1182
// Now get the module key again
1183
DWORD dw;
1184
if (RegCreateKeyEx(hAppKey,
1185
sModulePrefs,
1186
0, REG_NONE, REG_OPTION_NON_VOLATILE,
1187
KEY_WRITE|KEY_READ,
1188
NULL,
1189
&hModule,
1190
&dw) != ERROR_SUCCESS)
1191
{
1192
// Couldn't find/create the key - fail!
1193
RegCloseKey(hAppKey);
1194
return NULL;
1195
}
1196
}
1197
1198
// Close the application registry key
1199
RegCloseKey(hAppKey);
1200
1201
return hModule;
1202
}
1203
1204
int GetProfileInt(LPTSTR key, int def)
1205
{
1206
DWORD type;
1207
DWORD value;
1208
ULONG size = sizeof(value);
1209
1210
if (RegQueryValueEx(
1211
hModuleKey,
1212
key,
1213
NULL,
1214
&type,
1215
(unsigned char *)&value,
1216
&size) == ERROR_SUCCESS)
1217
{
1218
// Is the value of the right type?
1219
if (type != REG_DWORD)
1220
{
1221
return def;
1222
}
1223
else
1224
{
1225
return value;
1226
}
1227
}
1228
else
1229
{
1230
return def;
1231
}
1232
}
1233
1234
void WriteProfileInt(LPTSTR key, int value)
1235
{
1236
RegSetValueEx(
1237
hModuleKey,
1238
key,
1239
0,
1240
REG_DWORD,
1241
(unsigned char *)&value,
1242
sizeof(value));
1243
}
1244
1245
BOOL InitInstance()
1246
{
1247
// Create the global atoms
1248
VNC_WINDOWPOS_ATOM = GlobalAddAtom(VNC_WINDOWPOS_ATOMNAME);
1249
if (VNC_WINDOWPOS_ATOM == NULL)
1250
return FALSE;
1251
VNC_POPUPSELN_ATOM = GlobalAddAtom(VNC_POPUPSELN_ATOMNAME);
1252
if (VNC_POPUPSELN_ATOM == NULL)
1253
return FALSE;
1254
1255
// Get the module name
1256
char proc_name[_MAX_PATH];
1257
DWORD size;
1258
1259
// Attempt to get the program/module name
1260
if ((size = GetModuleFileName(
1261
GetModuleHandle(NULL),
1262
(char *) &proc_name,
1263
_MAX_PATH
1264
)) == 0)
1265
return FALSE;
1266
1267
// Get the key for the module
1268
hModuleKey = GetModuleKey(proc_name);
1269
if (hModuleKey == NULL)
1270
return FALSE;
1271
1272
// Read in the prefs
1273
prf_use_GetUpdateRect = GetProfileInt(
1274
"use_GetUpdateRect",
1275
TRUE
1276
);
1277
1278
prf_use_Timer = GetProfileInt(
1279
"use_Timer",
1280
FALSE
1281
);
1282
prf_use_KeyPress = GetProfileInt(
1283
"use_KeyPress",
1284
TRUE
1285
);
1286
prf_use_LButtonUp = GetProfileInt(
1287
"use_LButtonUp",
1288
TRUE
1289
);
1290
prf_use_MButtonUp = GetProfileInt(
1291
"use_MButtonUp",
1292
TRUE
1293
);
1294
prf_use_RButtonUp = GetProfileInt(
1295
"use_RButtonUp",
1296
TRUE
1297
);
1298
prf_use_Deferral = GetProfileInt(
1299
"use_Deferral",
1300
#ifdef HORIZONLIVE
1301
FALSE // we use full screen polling anyway
1302
#else
1303
TRUE
1304
#endif
1305
);
1306
1307
return TRUE;
1308
}
1309
1310
BOOL ExitInstance()
1311
{
1312
// Free the created atoms
1313
if (VNC_WINDOWPOS_ATOM != NULL)
1314
{
1315
GlobalDeleteAtom(VNC_WINDOWPOS_ATOM);
1316
VNC_WINDOWPOS_ATOM = NULL;
1317
}
1318
if (VNC_POPUPSELN_ATOM != NULL)
1319
{
1320
GlobalDeleteAtom(VNC_POPUPSELN_ATOM);
1321
VNC_POPUPSELN_ATOM = NULL;
1322
}
1323
1324
// Write the module settings to disk
1325
if (sModulePrefs != NULL)
1326
{
1327
WriteProfileInt(
1328
"use_GetUpdateRect",
1329
prf_use_GetUpdateRect
1330
);
1331
1332
WriteProfileInt(
1333
"use_Timer",
1334
prf_use_Timer
1335
);
1336
1337
WriteProfileInt(
1338
"use_KeyPress",
1339
prf_use_KeyPress
1340
);
1341
1342
WriteProfileInt(
1343
"use_LButtonUp",
1344
prf_use_LButtonUp
1345
);
1346
1347
WriteProfileInt(
1348
"use_MButtonUp",
1349
prf_use_MButtonUp
1350
);
1351
1352
WriteProfileInt(
1353
"use_RButtonUp",
1354
prf_use_RButtonUp
1355
);
1356
1357
WriteProfileInt(
1358
"use_Deferral",
1359
prf_use_Deferral
1360
);
1361
1362
free(sModulePrefs);
1363
sModulePrefs = NULL;
1364
}
1365
1366
// Close the registry key for this module
1367
if (hModuleKey != NULL)
1368
RegCloseKey(hModuleKey);
1369
1370
return TRUE;
1371
}
1372
1373