00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CSynergyHook.h"
00016 #include "ProtocolTypes.h"
00017 #include <zmouse.h>
00018 #include <tchar.h>
00019
00020 #if _MSC_VER >= 1400
00021
00022 #undef assert
00023 #if _DEBUG
00024 #define assert(_X_) if (!(_X_)) __debugbreak()
00025 #else
00026 #define assert(_X_) __noop()
00027 #endif
00028
00029
00030 #pragma function(memcpy)
00031 #endif
00032
00033
00034
00035
00036
00037
00038
00039 #define NO_GRAB_KEYBOARD 0
00040
00041
00042
00043
00044
00045 #define NO_LOWLEVEL_HOOKS 0
00046
00047
00048
00049
00050
00051 enum EWheelSupport {
00052 kWheelNone,
00053 kWheelOld,
00054 kWheelWin2000,
00055 kWheelModern
00056 };
00057
00058
00059 typedef struct tagMOUSEHOOKSTRUCTWin2000 {
00060 MOUSEHOOKSTRUCT mhs;
00061 DWORD mouseData;
00062 } MOUSEHOOKSTRUCTWin2000;
00063
00064 #if !defined(SM_MOUSEWHEELPRESENT)
00065 #define SM_MOUSEWHEELPRESENT 75
00066 #endif
00067
00068
00069 #if !defined(WM_XBUTTONDOWN)
00070 #define WM_XBUTTONDOWN 0x020B
00071 #define WM_XBUTTONUP 0x020C
00072 #define WM_XBUTTONDBLCLK 0x020D
00073 #define WM_NCXBUTTONDOWN 0x00AB
00074 #define WM_NCXBUTTONUP 0x00AC
00075 #define WM_NCXBUTTONDBLCLK 0x00AD
00076 #define MOUSEEVENTF_XDOWN 0x0080
00077 #define MOUSEEVENTF_XUP 0x0100
00078 #define XBUTTON1 0x0001
00079 #define XBUTTON2 0x0002
00080 #endif
00081
00082
00083
00084
00085
00086
00087 #if defined(_MSC_VER)
00088 #pragma comment(linker, "-section:shared,rws")
00089 #pragma data_seg("shared")
00090 #endif
00091
00092
00093 static HINSTANCE g_hinstance = NULL;
00094 static DWORD g_processID = 0;
00095 static EWheelSupport g_wheelSupport = kWheelNone;
00096 static UINT g_wmMouseWheel = 0;
00097 static DWORD g_threadID = 0;
00098 static HHOOK g_keyboard = NULL;
00099 static HHOOK g_mouse = NULL;
00100 static HHOOK g_getMessage = NULL;
00101 static HHOOK g_keyboardLL = NULL;
00102 static HHOOK g_mouseLL = NULL;
00103 static bool g_screenSaver = false;
00104 static EHookMode g_mode = kHOOK_DISABLE;
00105 static UInt32 g_zoneSides = 0;
00106 static SInt32 g_zoneSize = 0;
00107 static SInt32 g_xScreen = 0;
00108 static SInt32 g_yScreen = 0;
00109 static SInt32 g_wScreen = 0;
00110 static SInt32 g_hScreen = 0;
00111 static WPARAM g_deadVirtKey = 0;
00112 static WPARAM g_deadRelease = 0;
00113 static LPARAM g_deadLParam = 0;
00114 static BYTE g_deadKeyState[256] = { 0 };
00115 static DWORD g_hookThread = 0;
00116 static DWORD g_attachedThread = 0;
00117 static bool g_fakeInput = false;
00118
00119 #if defined(_MSC_VER)
00120 #pragma data_seg()
00121 #endif
00122
00123
00124
00125
00126 #ifndef _DEBUG
00127 extern "C" {
00128 int _fltused=0;
00129 }
00130 #endif
00131
00132
00133
00134
00135
00136
00137 static
00138 void
00139 detachThread()
00140 {
00141 if (g_attachedThread != 0 && g_hookThread != g_attachedThread) {
00142 AttachThreadInput(g_hookThread, g_attachedThread, FALSE);
00143 g_attachedThread = 0;
00144 }
00145 }
00146
00147 static
00148 bool
00149 attachThreadToForeground()
00150 {
00151
00152
00153
00154
00155
00156
00157 if (g_hookThread != 0) {
00158 HWND window = GetForegroundWindow();
00159 DWORD threadID = GetWindowThreadProcessId(window, NULL);
00160
00161 if (g_attachedThread != threadID) {
00162
00163 detachThread();
00164
00165
00166 if (threadID != 0 && threadID != g_hookThread) {
00167 AttachThreadInput(g_hookThread, threadID, TRUE);
00168 g_attachedThread = threadID;
00169 }
00170 return true;
00171 }
00172 }
00173 return false;
00174 }
00175
00176 #if !NO_GRAB_KEYBOARD
00177 static
00178 WPARAM
00179 makeKeyMsg(UINT virtKey, char c, bool noAltGr)
00180 {
00181 return MAKEWPARAM(MAKEWORD(virtKey & 0xff, (BYTE)c), noAltGr ? 1 : 0);
00182 }
00183
00184 static
00185 void
00186 keyboardGetState(BYTE keys[256])
00187 {
00188
00189
00190
00191
00192 SHORT key;
00193 for (int i = 0; i < 256; ++i) {
00194 key = GetAsyncKeyState(i);
00195 keys[i] = (BYTE)((key < 0) ? 0x80u : 0);
00196 }
00197 key = GetKeyState(VK_CAPITAL);
00198 keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
00199 }
00200
00201 static
00202 bool
00203 doKeyboardHookHandler(WPARAM wParam, LPARAM lParam)
00204 {
00205
00206
00207
00208
00209 if (wParam == SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY &&
00210 ((lParam >> 16) & 0xffu) == SYNERGY_HOOK_FAKE_INPUT_SCANCODE) {
00211
00212 g_fakeInput = ((lParam & 0x80000000u) == 0);
00213 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00214 0xff000000u | wParam, lParam);
00215
00216
00217 return true;
00218 }
00219
00220
00221
00222 if (g_fakeInput) {
00223 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00224 0xfe000000u | wParam, lParam);
00225 return false;
00226 }
00227
00228
00229
00230 if (wParam == VK_RSHIFT) {
00231 lParam &= ~0x01000000u;
00232 }
00233
00234
00235 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, wParam, lParam);
00236
00237
00238 if ((g_deadVirtKey == wParam || g_deadRelease == wParam) &&
00239 (lParam & 0x80000000u) != 0) {
00240 g_deadRelease = 0;
00241 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00242 wParam | 0x04000000, lParam);
00243 return false;
00244 }
00245
00246
00247 BYTE keys[256];
00248 keyboardGetState(keys);
00249
00250
00251
00252
00253
00254 UINT control = keys[VK_CONTROL] | keys[VK_LCONTROL] | keys[VK_RCONTROL];
00255 UINT menu = keys[VK_MENU] | keys[VK_LMENU] | keys[VK_RMENU];
00256 if ((control & 0x80) == 0 || (menu & 0x80) == 0) {
00257 keys[VK_LCONTROL] = 0;
00258 keys[VK_RCONTROL] = 0;
00259 keys[VK_CONTROL] = 0;
00260 }
00261 else {
00262 keys[VK_LCONTROL] = 0x80;
00263 keys[VK_RCONTROL] = 0x80;
00264 keys[VK_CONTROL] = 0x80;
00265 keys[VK_LMENU] = 0x80;
00266 keys[VK_RMENU] = 0x80;
00267 keys[VK_MENU] = 0x80;
00268 }
00269
00270
00271
00272
00273
00274
00275 UINT flags = 0;
00276 if ((menu & 0x80) != 0)
00277 flags |= 1;
00278
00279
00280
00281
00282
00283
00284 if (g_mode != kHOOK_RELAY_EVENTS) {
00285
00286
00287
00288 UINT sc = (lParam & 0x01ff0000u) >> 16;
00289 if (menu &&
00290 (sc >= 0x47u && sc <= 0x52u && sc != 0x4au && sc != 0x4eu)) {
00291 return false;
00292 }
00293 }
00294
00295 WORD c = 0;
00296
00297
00298
00299 if (g_deadVirtKey != 0) {
00300 if(ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
00301 g_deadKeyState, &c, flags) == 2)
00302 {
00303
00304
00305
00306
00307 ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
00308 g_deadKeyState, &c, flags);
00309
00310
00311
00312
00313 g_deadRelease = g_deadVirtKey;
00314 }
00315 }
00316
00317 UINT scanCode = ((lParam & 0x10ff0000u) >> 16);
00318 int n = ToAscii(wParam, scanCode, keys, &c, flags);
00319
00320
00321
00322
00323
00324
00325
00326 bool noAltGr = false;
00327 if (n == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) {
00328 noAltGr = true;
00329 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00330 wParam | 0x05000000, lParam);
00331 if (g_deadVirtKey != 0) {
00332 if(ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
00333 g_deadKeyState, &c, flags) == 2)
00334 {
00335 ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
00336 g_deadKeyState, &c, flags);
00337 g_deadRelease = g_deadVirtKey;
00338 }
00339 }
00340 BYTE keys2[256];
00341 for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) {
00342 keys2[i] = keys[i];
00343 }
00344 keys2[VK_LCONTROL] = 0;
00345 keys2[VK_RCONTROL] = 0;
00346 keys2[VK_CONTROL] = 0;
00347 keys2[VK_LMENU] = 0;
00348 keys2[VK_RMENU] = 0;
00349 keys2[VK_MENU] = 0;
00350 n = ToAscii(wParam, scanCode, keys2, &c, flags);
00351 }
00352
00353 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00354 wParam | ((c & 0xff) << 8) |
00355 ((n & 0xff) << 16) | 0x06000000,
00356 lParam);
00357 WPARAM charAndVirtKey = 0;
00358 bool clearDeadKey = false;
00359 switch (n) {
00360 default:
00361
00362
00363 if(lParam & 0x80000000u)
00364
00365
00366
00367
00368
00369 break;
00370
00371 g_deadVirtKey = wParam;
00372 g_deadLParam = lParam;
00373 for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) {
00374 g_deadKeyState[i] = keys[i];
00375 }
00376 break;
00377
00378 case 0:
00379
00380
00381 charAndVirtKey = makeKeyMsg(wParam, (char)0, noAltGr);
00382 break;
00383
00384 case 1:
00385
00386 charAndVirtKey = makeKeyMsg(wParam, (char)LOBYTE(c), noAltGr);
00387 clearDeadKey = true;
00388 break;
00389
00390 case 2: {
00391
00392
00393 WPARAM deadCharAndVirtKey =
00394 makeKeyMsg(g_deadVirtKey, (char)LOBYTE(c), noAltGr);
00395 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY,
00396 deadCharAndVirtKey, g_deadLParam & 0x7fffffffu);
00397 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY,
00398 deadCharAndVirtKey, g_deadLParam | 0x80000000u);
00399
00400
00401 charAndVirtKey = makeKeyMsg(wParam, (char)HIBYTE(c), noAltGr);
00402 clearDeadKey = true;
00403 break;
00404 }
00405 }
00406
00407
00408 if (g_deadVirtKey != 0) {
00409 ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
00410 g_deadKeyState, &c, flags);
00411 }
00412
00413
00414 if (clearDeadKey) {
00415 g_deadVirtKey = 0;
00416 g_deadLParam = 0;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 if (charAndVirtKey != 0) {
00426 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
00427 charAndVirtKey | 0x07000000, lParam);
00428 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, charAndVirtKey, lParam);
00429 }
00430
00431 if (g_mode == kHOOK_RELAY_EVENTS) {
00432
00433 switch (wParam) {
00434 case VK_CAPITAL:
00435 case VK_NUMLOCK:
00436 case VK_SCROLL:
00437
00438
00439
00440 break;
00441
00442 case VK_HANGUL:
00443
00444
00445 if (g_hookThread == 0) {
00446 return true;
00447 }
00448 break;
00449
00450 default:
00451
00452 return true;
00453 }
00454 }
00455
00456 return false;
00457 }
00458
00459 static
00460 bool
00461 keyboardHookHandler(WPARAM wParam, LPARAM lParam)
00462 {
00463 attachThreadToForeground();
00464 return doKeyboardHookHandler(wParam, lParam);
00465 }
00466 #endif
00467
00468 static
00469 bool
00470 doMouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
00471 {
00472 switch (wParam) {
00473 case WM_LBUTTONDOWN:
00474 case WM_MBUTTONDOWN:
00475 case WM_RBUTTONDOWN:
00476 case WM_XBUTTONDOWN:
00477 case WM_LBUTTONDBLCLK:
00478 case WM_MBUTTONDBLCLK:
00479 case WM_RBUTTONDBLCLK:
00480 case WM_XBUTTONDBLCLK:
00481 case WM_LBUTTONUP:
00482 case WM_MBUTTONUP:
00483 case WM_RBUTTONUP:
00484 case WM_XBUTTONUP:
00485 case WM_NCLBUTTONDOWN:
00486 case WM_NCMBUTTONDOWN:
00487 case WM_NCRBUTTONDOWN:
00488 case WM_NCXBUTTONDOWN:
00489 case WM_NCLBUTTONDBLCLK:
00490 case WM_NCMBUTTONDBLCLK:
00491 case WM_NCRBUTTONDBLCLK:
00492 case WM_NCXBUTTONDBLCLK:
00493 case WM_NCLBUTTONUP:
00494 case WM_NCMBUTTONUP:
00495 case WM_NCRBUTTONUP:
00496 case WM_NCXBUTTONUP:
00497
00498 PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data);
00499 return (g_mode == kHOOK_RELAY_EVENTS);
00500
00501 case WM_MOUSEWHEEL:
00502 if (g_mode == kHOOK_RELAY_EVENTS) {
00503
00504 PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0);
00505 }
00506 return (g_mode == kHOOK_RELAY_EVENTS);
00507
00508 case WM_NCMOUSEMOVE:
00509 case WM_MOUSEMOVE:
00510 if (g_mode == kHOOK_RELAY_EVENTS) {
00511
00512 PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y);
00513 return true;
00514 }
00515 else if (g_mode == kHOOK_WATCH_JUMP_ZONE) {
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 bool bogus = false;
00526 if (x < g_xScreen) {
00527 x = g_xScreen;
00528 bogus = true;
00529 }
00530 else if (x >= g_xScreen + g_wScreen) {
00531 x = g_xScreen + g_wScreen - 1;
00532 bogus = true;
00533 }
00534 if (y < g_yScreen) {
00535 y = g_yScreen;
00536 bogus = true;
00537 }
00538 else if (y >= g_yScreen + g_hScreen) {
00539 y = g_yScreen + g_hScreen - 1;
00540 bogus = true;
00541 }
00542
00543
00544 bool inside = false;
00545 if (!inside && (g_zoneSides & kLeftMask) != 0) {
00546 inside = (x < g_xScreen + g_zoneSize);
00547 }
00548 if (!inside && (g_zoneSides & kRightMask) != 0) {
00549 inside = (x >= g_xScreen + g_wScreen - g_zoneSize);
00550 }
00551 if (!inside && (g_zoneSides & kTopMask) != 0) {
00552 inside = (y < g_yScreen + g_zoneSize);
00553 }
00554 if (!inside && (g_zoneSides & kBottomMask) != 0) {
00555 inside = (y >= g_yScreen + g_hScreen - g_zoneSize);
00556 }
00557
00558
00559 PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y);
00560
00561
00562 return inside && !bogus;
00563 }
00564 }
00565
00566
00567 return false;
00568 }
00569
00570 static
00571 bool
00572 mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
00573 {
00574
00575 return doMouseHookHandler(wParam, x, y, data);
00576 }
00577
00578 #if !NO_GRAB_KEYBOARD
00579 static
00580 LRESULT CALLBACK
00581 keyboardHook(int code, WPARAM wParam, LPARAM lParam)
00582 {
00583 if (code >= 0) {
00584
00585 if (keyboardHookHandler(wParam, lParam)) {
00586 return 1;
00587 }
00588 }
00589
00590 return CallNextHookEx(g_keyboard, code, wParam, lParam);
00591 }
00592 #endif
00593
00594 static
00595 LRESULT CALLBACK
00596 mouseHook(int code, WPARAM wParam, LPARAM lParam)
00597 {
00598 if (code >= 0) {
00599
00600 const MOUSEHOOKSTRUCT* info = (const MOUSEHOOKSTRUCT*)lParam;
00601 SInt32 x = (SInt32)info->pt.x;
00602 SInt32 y = (SInt32)info->pt.y;
00603 SInt32 w = 0;
00604 if (wParam == WM_MOUSEWHEEL) {
00605
00606
00607
00608
00609
00610 switch (g_wheelSupport) {
00611 case kWheelModern:
00612 w = static_cast<SInt16>(LOWORD(info->dwExtraInfo));
00613 break;
00614
00615 case kWheelWin2000: {
00616 const MOUSEHOOKSTRUCTWin2000* info2k =
00617 (const MOUSEHOOKSTRUCTWin2000*)lParam;
00618 w = static_cast<SInt16>(HIWORD(info2k->mouseData));
00619 break;
00620 }
00621
00622 default:
00623 break;
00624 }
00625 }
00626
00627
00628
00629
00630
00631 if (mouseHookHandler(wParam, x, y, w)) {
00632 return 1;
00633 }
00634 }
00635
00636 return CallNextHookEx(g_mouse, code, wParam, lParam);
00637 }
00638
00639 static
00640 LRESULT CALLBACK
00641 getMessageHook(int code, WPARAM wParam, LPARAM lParam)
00642 {
00643 if (code >= 0) {
00644 if (g_screenSaver) {
00645 MSG* msg = reinterpret_cast<MSG*>(lParam);
00646 if (msg->message == WM_SYSCOMMAND &&
00647 msg->wParam == SC_SCREENSAVE) {
00648
00649 PostThreadMessage(g_threadID,
00650 SYNERGY_MSG_SCREEN_SAVER, TRUE, 0);
00651 }
00652 }
00653 if (g_mode == kHOOK_RELAY_EVENTS) {
00654 MSG* msg = reinterpret_cast<MSG*>(lParam);
00655 if (g_wheelSupport == kWheelOld && msg->message == g_wmMouseWheel) {
00656
00657 PostThreadMessage(g_threadID,
00658 SYNERGY_MSG_MOUSE_WHEEL,
00659 static_cast<SInt16>(msg->wParam & 0xffffu), 0);
00660
00661
00662
00663 msg->wParam = 0;
00664 }
00665 }
00666 }
00667
00668 return CallNextHookEx(g_getMessage, code, wParam, lParam);
00669 }
00670
00671 #if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS
00672
00673
00674
00675
00676
00677
00678
00679 #if !NO_GRAB_KEYBOARD
00680 static
00681 LRESULT CALLBACK
00682 keyboardLLHook(int code, WPARAM wParam, LPARAM lParam)
00683 {
00684 if (code >= 0) {
00685
00686 KBDLLHOOKSTRUCT* info = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
00687 WPARAM wParam = info->vkCode;
00688 LPARAM lParam = 1;
00689 lParam |= (info->scanCode << 16);
00690 if (info->flags & LLKHF_EXTENDED) {
00691 lParam |= (1lu << 24);
00692 }
00693 if (info->flags & LLKHF_ALTDOWN) {
00694 lParam |= (1lu << 29);
00695 }
00696 if (info->flags & LLKHF_UP) {
00697 lParam |= (1lu << 31);
00698 }
00699
00700
00701
00702
00703
00704 if (keyboardHookHandler(wParam, lParam)) {
00705 return 1;
00706 }
00707 }
00708
00709 return CallNextHookEx(g_keyboardLL, code, wParam, lParam);
00710 }
00711 #endif
00712
00713
00714
00715
00716
00717
00718 static
00719 LRESULT CALLBACK
00720 mouseLLHook(int code, WPARAM wParam, LPARAM lParam)
00721 {
00722 if (code >= 0) {
00723
00724 MSLLHOOKSTRUCT* info = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
00725 SInt32 x = static_cast<SInt32>(info->pt.x);
00726 SInt32 y = static_cast<SInt32>(info->pt.y);
00727 SInt32 w = static_cast<SInt16>(HIWORD(info->mouseData));
00728
00729
00730 if (mouseHookHandler(wParam, x, y, w)) {
00731 return 1;
00732 }
00733 }
00734
00735 return CallNextHookEx(g_mouseLL, code, wParam, lParam);
00736 }
00737
00738 #endif
00739
00740 static
00741 EWheelSupport
00742 getWheelSupport()
00743 {
00744
00745 OSVERSIONINFO info;
00746 info.dwOSVersionInfoSize = sizeof(info);
00747 if (!GetVersionEx(&info)) {
00748 return kWheelNone;
00749 }
00750
00751
00752 if (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) {
00753
00754 if (info.dwPlatformId == VER_PLATFORM_WIN32_NT &&
00755 info.dwMajorVersion == 5 &&
00756 info.dwMinorVersion == 0) {
00757 return kWheelWin2000;
00758 }
00759 return kWheelModern;
00760 }
00761
00762
00763 #if defined(MSH_WHEELSUPPORT)
00764 UINT wheelSupportMsg = RegisterWindowMessage(MSH_WHEELSUPPORT);
00765 HWND wheelSupportWindow = FindWindow(MSH_WHEELMODULE_CLASS,
00766 MSH_WHEELMODULE_TITLE);
00767 if (wheelSupportWindow != NULL && wheelSupportMsg != 0) {
00768 if (SendMessage(wheelSupportWindow, wheelSupportMsg, 0, 0) != 0) {
00769 g_wmMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
00770 if (g_wmMouseWheel != 0) {
00771 return kWheelOld;
00772 }
00773 }
00774 }
00775 #endif
00776
00777
00778
00779
00780
00781
00782 return kWheelModern;
00783 }
00784
00785
00786
00787
00788
00789
00790 BOOL WINAPI
00791 DllMain(HINSTANCE instance, DWORD reason, LPVOID)
00792 {
00793 if (reason == DLL_PROCESS_ATTACH) {
00794 DisableThreadLibraryCalls(instance);
00795 if (g_processID == 0) {
00796 g_hinstance = instance;
00797 g_processID = GetCurrentProcessId();
00798 }
00799 }
00800 else if (reason == DLL_PROCESS_DETACH) {
00801 if (g_processID == GetCurrentProcessId()) {
00802 uninstall();
00803 uninstallScreenSaver();
00804 g_processID = 0;
00805 g_hinstance = NULL;
00806 }
00807 }
00808 return TRUE;
00809 }
00810
00811 extern "C" {
00812
00813
00814 #if _MSC_VER >= 1400
00815 BOOL WINAPI _DllMainCRTStartup(
00816 HINSTANCE instance, DWORD reason, LPVOID lpreserved)
00817 {
00818 return DllMain(instance, reason, lpreserved);
00819 }
00820
00821
00822
00823 void * __cdecl memcpy(void * _Dst, const void * _Src, size_t _MaxCount)
00824 {
00825 void * _DstBackup = _Dst;
00826 switch (_MaxCount & 3) {
00827 case 3:
00828 ((char*)_Dst)[0] = ((char*)_Src)[0];
00829 ++(char*&)_Dst;
00830 ++(char*&)_Src;
00831 --_MaxCount;
00832 case 2:
00833 ((char*)_Dst)[0] = ((char*)_Src)[0];
00834 ++(char*&)_Dst;
00835 ++(char*&)_Src;
00836 --_MaxCount;
00837 case 1:
00838 ((char*)_Dst)[0] = ((char*)_Src)[0];
00839 ++(char*&)_Dst;
00840 ++(char*&)_Src;
00841 --_MaxCount;
00842 break;
00843 case 0:
00844 break;
00845
00846 default:
00847 __assume(0);
00848 break;
00849 }
00850
00851
00852 const size_t max = _MaxCount / sizeof(UINT_PTR);
00853 for (size_t i = 0; i < max; ++i) {
00854 ((UINT_PTR*)_Dst)[i] = ((UINT_PTR*)_Src)[i];
00855 }
00856
00857 (UINT_PTR*&)_Dst += max;
00858 (UINT_PTR*&)_Src += max;
00859
00860 switch (_MaxCount & 3) {
00861 case 3:
00862 ((char*)_Dst)[0] = ((char*)_Src)[0];
00863 ++(char*&)_Dst;
00864 ++(char*&)_Src;
00865 case 2:
00866 ((char*)_Dst)[0] = ((char*)_Src)[0];
00867 ++(char*&)_Dst;
00868 ++(char*&)_Src;
00869 case 1:
00870 ((char*)_Dst)[0] = ((char*)_Src)[0];
00871 ++(char*&)_Dst;
00872 ++(char*&)_Src;
00873 break;
00874 case 0:
00875 break;
00876
00877 default:
00878 __assume(0);
00879 break;
00880 }
00881
00882 return _DstBackup;
00883 }
00884 #endif
00885
00886 int
00887 init(DWORD threadID)
00888 {
00889 assert(g_hinstance != NULL);
00890
00891
00892
00893 if (g_processID != 0 && g_processID != GetCurrentProcessId()) {
00894 HANDLE process = OpenProcess(STANDARD_RIGHTS_REQUIRED,
00895 FALSE, g_processID);
00896 if (process != NULL) {
00897
00898
00899
00900 CloseHandle(process);
00901 return 0;
00902 }
00903
00904
00905
00906 g_hinstance = GetModuleHandle(_T("synrgyhk"));
00907 g_processID = GetCurrentProcessId();
00908 g_wheelSupport = kWheelNone;
00909 g_threadID = 0;
00910 g_keyboard = NULL;
00911 g_mouse = NULL;
00912 g_getMessage = NULL;
00913 g_keyboardLL = NULL;
00914 g_mouseLL = NULL;
00915 g_screenSaver = false;
00916 }
00917
00918
00919
00920 g_threadID = threadID;
00921
00922
00923 g_mode = kHOOK_DISABLE;
00924 g_zoneSides = 0;
00925 g_zoneSize = 0;
00926 g_xScreen = 0;
00927 g_yScreen = 0;
00928 g_wScreen = 0;
00929 g_hScreen = 0;
00930
00931 return 1;
00932 }
00933
00934 int
00935 cleanup(void)
00936 {
00937 assert(g_hinstance != NULL);
00938
00939 if (g_processID == GetCurrentProcessId()) {
00940 g_threadID = 0;
00941 }
00942
00943 return 1;
00944 }
00945
00946 EHookResult
00947 install()
00948 {
00949 assert(g_hinstance != NULL);
00950 assert(g_keyboard == NULL);
00951 assert(g_mouse == NULL);
00952 assert(g_getMessage == NULL || g_screenSaver);
00953
00954
00955 if (g_threadID == 0) {
00956 return kHOOK_FAILED;
00957 }
00958
00959
00960 g_deadVirtKey = 0;
00961 g_deadLParam = 0;
00962
00963
00964 g_fakeInput = false;
00965
00966
00967 g_wheelSupport = getWheelSupport();
00968
00969
00970 if (g_wheelSupport == kWheelOld && g_getMessage == NULL) {
00971 g_getMessage = SetWindowsHookEx(WH_GETMESSAGE,
00972 &getMessageHook,
00973 g_hinstance,
00974 0);
00975 }
00976
00977
00978 #if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS
00979 g_mouseLL = SetWindowsHookEx(WH_MOUSE_LL,
00980 &mouseLLHook,
00981 g_hinstance,
00982 0);
00983 #if !NO_GRAB_KEYBOARD
00984 g_keyboardLL = SetWindowsHookEx(WH_KEYBOARD_LL,
00985 &keyboardLLHook,
00986 g_hinstance,
00987 0);
00988 if (g_mouseLL == NULL || g_keyboardLL == NULL) {
00989 if (g_keyboardLL != NULL) {
00990 UnhookWindowsHookEx(g_keyboardLL);
00991 g_keyboardLL = NULL;
00992 }
00993 if (g_mouseLL != NULL) {
00994 UnhookWindowsHookEx(g_mouseLL);
00995 g_mouseLL = NULL;
00996 }
00997 }
00998 #endif
00999 #endif
01000
01001
01002 if (g_mouseLL == NULL) {
01003 g_mouse = SetWindowsHookEx(WH_MOUSE,
01004 &mouseHook,
01005 g_hinstance,
01006 0);
01007 }
01008 #if !NO_GRAB_KEYBOARD
01009 if (g_keyboardLL == NULL) {
01010 g_keyboard = SetWindowsHookEx(WH_KEYBOARD,
01011 &keyboardHook,
01012 g_hinstance,
01013 0);
01014 }
01015 #endif
01016
01017
01018 if ((g_getMessage == NULL && g_wheelSupport == kWheelOld) ||
01019 #if !NO_GRAB_KEYBOARD
01020 (g_keyboardLL == NULL && g_keyboard == NULL) ||
01021 #endif
01022 (g_mouseLL == NULL && g_mouse == NULL)) {
01023 uninstall();
01024 return kHOOK_FAILED;
01025 }
01026
01027 if (g_keyboardLL != NULL || g_mouseLL != NULL) {
01028 g_hookThread = GetCurrentThreadId();
01029 return kHOOK_OKAY_LL;
01030 }
01031
01032 return kHOOK_OKAY;
01033 }
01034
01035 int
01036 uninstall(void)
01037 {
01038 assert(g_hinstance != NULL);
01039
01040
01041 g_deadVirtKey = 0;
01042 g_deadLParam = 0;
01043
01044
01045 detachThread();
01046
01047
01048 if (g_keyboardLL != NULL) {
01049 UnhookWindowsHookEx(g_keyboardLL);
01050 g_keyboardLL = NULL;
01051 }
01052 if (g_mouseLL != NULL) {
01053 UnhookWindowsHookEx(g_mouseLL);
01054 g_mouseLL = NULL;
01055 }
01056 if (g_keyboard != NULL) {
01057 UnhookWindowsHookEx(g_keyboard);
01058 g_keyboard = NULL;
01059 }
01060 if (g_mouse != NULL) {
01061 UnhookWindowsHookEx(g_mouse);
01062 g_mouse = NULL;
01063 }
01064 if (g_getMessage != NULL && !g_screenSaver) {
01065 UnhookWindowsHookEx(g_getMessage);
01066 g_getMessage = NULL;
01067 }
01068 g_wheelSupport = kWheelNone;
01069
01070 return 1;
01071 }
01072
01073 int
01074 installScreenSaver(void)
01075 {
01076 assert(g_hinstance != NULL);
01077
01078
01079 if (g_threadID == 0) {
01080 return 0;
01081 }
01082
01083
01084 g_screenSaver = true;
01085
01086
01087 if (g_getMessage == NULL) {
01088 g_getMessage = SetWindowsHookEx(WH_GETMESSAGE,
01089 &getMessageHook,
01090 g_hinstance,
01091 0);
01092 }
01093
01094 return (g_getMessage != NULL) ? 1 : 0;
01095 }
01096
01097 int
01098 uninstallScreenSaver(void)
01099 {
01100 assert(g_hinstance != NULL);
01101
01102
01103 if (g_getMessage != NULL && g_wheelSupport != kWheelOld) {
01104 UnhookWindowsHookEx(g_getMessage);
01105 g_getMessage = NULL;
01106 }
01107
01108
01109 g_screenSaver = false;
01110
01111 return 1;
01112 }
01113
01114 void
01115 setSides(UInt32 sides)
01116 {
01117 g_zoneSides = sides;
01118 }
01119
01120 void
01121 setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h, SInt32 jumpZoneSize)
01122 {
01123 g_zoneSize = jumpZoneSize;
01124 g_xScreen = x;
01125 g_yScreen = y;
01126 g_wScreen = w;
01127 g_hScreen = h;
01128 }
01129
01130 void
01131 setMode(EHookMode mode)
01132 {
01133 if (mode == g_mode) {
01134
01135 return;
01136 }
01137 g_mode = mode;
01138 }
01139
01140 }