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