Changeset 2763 for trunk/synergy/lib/platform/CPMSynergyHook.cpp
- Timestamp:
- Aug 13, 2006, 12:50:25 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/synergy/lib/platform/CPMSynergyHook.cpp
r2755 r2763 17 17 #include "ProtocolTypes.h" 18 18 #include <sys/builtin.h> 19 #if 0 19 20 #include <stdlib.h> 20 21 #include <unistd.h> 22 #include <InnoTekLIBC/FastInfoBlocks.h> 23 #else 24 unsigned long fibGetMsCount(void ) 25 { 26 ULONG ul = 0; 27 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ul, sizeof(ul)); 28 return ul; 29 } 30 31 int getpid(void) 32 { 33 PTIB pTib; 34 PPIB pPib; 35 DosGetInfoBlocks(&pTib, &pPib); 36 return pPib->pib_ulpid; 37 } 38 39 int _gettid(void) 40 { 41 PTIB pTib; 42 PPIB pPib; 43 DosGetInfoBlocks(&pTib, &pPib); 44 return pTib->tib_ptib2->tib2_ultid; 45 } 46 47 void _assert (__const__ char * pszExpr, __const__ char *pszFile, unsigned iLine) 48 { 49 __asm__ ("int3\n"); 50 } 51 52 #endif 21 53 22 54 // 23 // globals - system wide (defined in .asm)55 // globals - system wide 24 56 // 25 extern "C" {26 57 /** @name The synergy server/client thread 27 58 * @{ */ 28 externHMQ g_hmqSynergy;29 externint g_pidSynergy;30 externint g_tidSynergy;59 HMQ g_hmqSynergy; 60 int g_pidSynergy; 61 int g_tidSynergy; 31 62 /** @} */ 32 63 33 64 /** The current mode.*/ 34 externEHookMode volatile g_enmMode;65 EHookMode volatile g_enmMode; 35 66 36 67 /** Which sides do we have warp zones on. */ 37 externUInt32 g_zoneSides;68 UInt32 g_zoneSides; 38 69 /** The warp zone size in pixels. */ 39 externSInt32 g_zoneSize;70 SInt32 g_zoneSize; 40 71 /** @name The screen size. 41 72 * @{ */ 42 externSInt32 g_xScreen;43 externSInt32 g_yScreen;44 externSInt32 g_cxScreen;45 externSInt32 g_cyScreen;73 SInt32 g_xScreen; 74 SInt32 g_yScreen; 75 SInt32 g_cxScreen; 76 SInt32 g_cyScreen; 46 77 /** @} */ 47 78 48 79 /** Set if the hook is installed. */ 49 externbool g_fInputHookInstalled;80 bool g_fInputHookInstalled; 50 81 /** Set if we're faking input. */ 51 extern bool g_fFakingInput; 52 53 } /* extern "C" */ 82 bool g_fFakingInput; 83 84 /** @name Input Message Faking. 85 * @{ */ 86 /** The event semaphore we're waiting on while faking messages. */ 87 HEV g_hev; 88 /** The pending message. */ 89 QMSG g_qmsg; 90 /** Indicator set by the MsgInputHook function when the message 'skipped'. */ 91 volatile bool g_fMsgInjected; 92 /** Error description. */ 93 const char *g_pszErrorMsg; 94 /** Set if the dummy hook is installed. */ 95 bool g_fDummyHook; 96 /** @} */ 97 98 /** The handle of the hook dll. */ 99 HMODULE g_hmod = NULLHANDLE; 100 /** Indicator whether the init() function has been called successfully. */ 101 bool g_fSynergyInitialized = false; 102 54 103 55 104 56 105 // 57 // Globals - per process.106 // Internal Functions 58 107 // 59 60 /** The handle of the hook dll. */61 static HMODULE g_hmod = NULLHANDLE;62 /** The pid of the current process. */63 static int g_pid = 0;64 108 65 109 … … 244 288 245 289 290 #define NO_DUMMY_HOOK 1 291 #ifndef NO_DUMMY_HOOK 292 /** 293 * Dummy hook. 294 */ 295 static VOID EXPENTRY SendMsgHook(HAB hab, PSMHSTRUCT psmh, BOOL fInterTask) 296 { 297 /* nop */ 298 } 299 #endif 300 301 302 246 303 // 247 304 // external functions … … 255 312 switch (ulReason) { 256 313 /* init */ 257 case 0: 314 case 0: { 315 HEV hev = g_hev; 316 if (hev != NULLHANDLE) { 317 DosOpenEventSem(NULL, &hev); 318 } 258 319 g_hmod = hmod; 259 g_pid = getpid();260 320 break; 321 } 261 322 262 323 /* term */ 263 324 case 1: 264 g_pid = 0; 265 g_hmod = NULLHANDLE; 266 break; 267 268 default: 325 if (g_hev != NULLHANDLE) { 326 DosCloseEventSem(g_hev); 327 } 269 328 break; 270 329 } … … 294 353 295 354 /* 355 * Create the event semaphore. 356 */ 357 ULONG cPosts; 358 if ( g_hev == NULLHANDLE 359 || DosQueryEventSem(g_hev, &cPosts) != NO_ERROR 360 ) { 361 g_hev = NULLHANDLE; 362 APIRET rc = DosCreateEventSem(NULL, &g_hev, DC_SEM_SHARED, FALSE); 363 if (rc != NO_ERROR) 364 return false; 365 } 366 367 /* 296 368 * Initialize the globals. 297 369 */ … … 302 374 /* only do this if the hook is inactive. */ 303 375 if (g_enmMode == kHOOK_DISABLE) { 304 g_enmMode = kHOOK_DISABLE;305 376 g_zoneSides = 0; 306 377 g_zoneSize = 0; … … 311 382 } 312 383 384 #ifndef NO_DUMMY_HOOK 385 /* 386 * Install the fake hook. 387 */ 388 if (g_fDummyHook) 389 WinReleaseHook(WinQueryAnchorBlock(HWND_DESKTOP), NULLHANDLE, HK_SENDMSG, (PFN)SendMsgHook, g_hmod); 390 g_fDummyHook = WinSetHook(WinQueryAnchorBlock(HWND_DESKTOP), NULLHANDLE, HK_SENDMSG, (PFN)SendMsgHook, g_hmod); 391 if (!g_fDummyHook) { 392 return false; 393 } 394 #endif 395 396 g_fSynergyInitialized = true; 313 397 return true; 314 398 } … … 324 408 { 325 409 assert(g_hmod != NULLHANDLE); 410 assert(g_fSynergyInitialized == true); 326 411 327 412 /* … … 336 421 uninstall(hab); 337 422 423 #ifndef NO_DUMMY_HOOK 424 // release the dummy hook. 425 if (WinReleaseHook(hab, NULLHANDLE, HK_SENDMSG, (PFN)SendMsgHook, g_hmod)) 426 g_fDummyHook = false; 427 #endif 428 338 429 g_hmqSynergy = NULLHANDLE; 339 430 g_pidSynergy = 0; 340 431 g_tidSynergy = 0; 432 g_fSynergyInitialized = false; 341 433 return true; 342 434 } … … 346 438 { 347 439 // must be initialized 348 if (g_tidSynergy == 0) { 440 if ( g_tidSynergy == 0 441 || !g_fSynergyInitialized) { 349 442 return kHOOK_FAILED; 350 443 } … … 384 477 assert(g_pidSynergy == getpid()); 385 478 assert(g_tidSynergy == _gettid()); 479 assert(g_fSynergyInitialized); 480 if (!g_fSynergyInitialized) { 481 return false; 482 } 386 483 387 484 //// discard old dead keys … … 409 506 assert(g_pidSynergy == getpid()); 410 507 assert(g_tidSynergy == _gettid()); 411 __atomic_xchg((unsigned volatile *)&g_zoneSides, (unsigned)sides); 508 assert(g_fSynergyInitialized); 509 if (g_fSynergyInitialized) { 510 __atomic_xchg((unsigned volatile *)&g_zoneSides, (unsigned)sides); 511 } 412 512 } 413 513 … … 426 526 assert(g_pidSynergy == getpid()); 427 527 assert(g_tidSynergy == _gettid()); 428 __atomic_xchg((unsigned volatile *)&g_zoneSize, (unsigned)jumpZoneSize); 429 __atomic_xchg((unsigned volatile *)&g_xScreen, (unsigned)x); 430 __atomic_xchg((unsigned volatile *)&g_yScreen, (unsigned)y); 431 __atomic_xchg((unsigned volatile *)&g_cxScreen, (unsigned)cx); 432 __atomic_xchg((unsigned volatile *)&g_cyScreen, (unsigned)cy); 528 assert(g_fSynergyInitialized); 529 if (g_fSynergyInitialized) { 530 __atomic_xchg((unsigned volatile *)&g_zoneSize, (unsigned)jumpZoneSize); 531 __atomic_xchg((unsigned volatile *)&g_xScreen, (unsigned)x); 532 __atomic_xchg((unsigned volatile *)&g_yScreen, (unsigned)y); 533 __atomic_xchg((unsigned volatile *)&g_cxScreen, (unsigned)cx); 534 __atomic_xchg((unsigned volatile *)&g_cyScreen, (unsigned)cy); 535 } 433 536 } 434 537 … … 443 546 assert(g_pidSynergy == getpid()); 444 547 assert(g_tidSynergy == _gettid()); 445 if (mode != g_enmMode) { 446 switch (mode) { 447 case kHOOK_DISABLE: 448 case kHOOK_WATCH_JUMP_ZONE: 449 case kHOOK_RELAY_EVENTS: 450 __atomic_xchg((unsigned volatile *)&g_enmMode, (unsigned)mode); 451 break; 452 default: 453 __atomic_xchg((unsigned volatile *)&g_enmMode, kHOOK_DISABLE); 454 break; 548 assert(g_fSynergyInitialized); 549 if (g_fSynergyInitialized) { 550 if (mode != g_enmMode) { 551 switch (mode) { 552 case kHOOK_DISABLE: 553 case kHOOK_WATCH_JUMP_ZONE: 554 case kHOOK_RELAY_EVENTS: 555 __atomic_xchg((unsigned volatile *)&g_enmMode, (unsigned)mode); 556 break; 557 default: 558 __atomic_xchg((unsigned volatile *)&g_enmMode, kHOOK_DISABLE); 559 break; 560 } 455 561 } 456 562 } 457 563 } 458 564 565 566 /** 567 * Hook callback used to insert message into the system queue. 568 * 569 * @returns TRUE if we've got a message. 570 * @returns FALSE if we haven't got a message handy. 571 * @param hab The hab of the current thread. 572 * @param pqmsg Where to put the message. 573 * @param fSkip Skip message flag. 574 * If TRUE we should just skip a message (pqmsg is NULL). If no futher 575 * messages are queued, we must release the hook. 576 * If FALSE we should return the current pending message. 577 * @param pfNoRecord Record message flag. 578 */ 579 static BOOL EXPENTRY MsgInputHook(HAB hab, PQMSG pqmsg, BOOL fSkip, PBOOL pfNoRecord) 580 { 581 /* 582 * FUCKING HELL! 583 * 584 * For whatever fucking reason, PM fails to load the hook dll into 585 * a bunch of processes. We still get here for some peculiar reasons, 586 * and thus we can try deal with it... 587 */ 588 BOOL fUnload = FALSE; 589 HMODULE hmod; 590 ULONG offObj, iObj; 591 APIRET rc = DosQueryModFromEIP(&hmod, &iObj, 0, NULL, &offObj, (ULONG)&MsgInputHook); 592 if (rc != NO_ERROR) { 593 if (DosLoadModule(NULL, 0, (PCSZ)"d:/coding/libc/trunk/out/os2.x86/debug/dist/bin/synrgyhk.dll", &hmod)) { 594 return FALSE; 595 } 596 fUnload = TRUE; 597 } 598 599 /* 600 * We've only got one message, so everything is dead simple. 601 */ 602 if (fSkip) { 603 __atomic_xchg((unsigned volatile *)&g_fMsgInjected, 1); 604 if (WinReleaseHook(hab, NULLHANDLE, HK_MSGINPUT, (PFN)MsgInputHook, g_hmod)) { 605 HEV hev = g_hev; 606 APIRET rc = DosPostEventSem(hev); 607 if ( rc != ERROR_INVALID_HANDLE 608 || DosOpenEventSem(NULL, &hev) != NO_ERROR 609 || DosPostEventSem(hev) != NO_ERROR) 610 g_pszErrorMsg = "failed to post event semaphore"; 611 } else { 612 g_pszErrorMsg = "failed to release hook"; 613 } 614 } else { 615 *pqmsg = g_qmsg; 616 } 617 618 /* 619 * If we loaded the dll we must unload it. 620 * Don't wanna have any DLLs stuck in foreign processes. 621 */ 622 if (fUnload) 623 DosFreeModule(hmod); 624 return TRUE; 625 } 626 627 628 /** 629 * Inserts a fake input message. 630 * 631 * @returns NULL on success. 632 * @returns String describing the error on failure. 633 * @param hab The anchor block of the calling thread. 634 * @param pQmsg Pointer to the message. 635 * @remark The caller must serialize calls to this function! 636 */ 637 CSYNERGYHOOK_API const char *fakeMsg(HAB hab, const QMSG *pQmsg) 638 { 639 const char *pszRet; 640 assert(g_fSynergyInitialized); 641 if (g_fSynergyInitialized) { 642 /* 643 * Reset the event semaphore and queue the message for MsgInputHook. 644 */ 645 ULONG cPosts; 646 APIRET rc = DosResetEventSem(g_hev, &cPosts); 647 if (rc == NO_ERROR || rc == ERROR_ALREADY_RESET) { 648 g_qmsg = *pQmsg; 649 g_pszErrorMsg = NULL; 650 __atomic_xchg((unsigned volatile *)&g_fMsgInjected, 0); 651 652 /* 653 * Install the hook and wait for the message to be delivered. 654 */ 655 WinCheckInput(hab); 656 if (WinSetHook(hab, NULLHANDLE, HK_MSGINPUT, (PFN)MsgInputHook, g_hmod)) { 657 WinCheckInput(hab); 658 rc = DosWaitEventSem(g_hev, 1000 /* 33 */); 659 if (rc == NO_ERROR || g_fMsgInjected) { 660 return NULL; 661 } 662 663 /* 664 * It took a bit longer than expected. We'll wait for some 2-3 665 * seconds before we give up. This might be a bit paranoid, but 666 * I'd rather drop a message than locking up PM. 667 */ 668 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT) { 669 ULONG ulStart = fibGetMsCount(); /* monotone time in milliseconds */ 670 for (;;) { 671 WinCheckInput(hab); 672 rc = DosWaitEventSem(g_hev, 33); 673 if (rc == NO_ERROR || g_fMsgInjected) { 674 return NULL; 675 } 676 if (rc != ERROR_TIMEOUT && rc != ERROR_SEM_TIMEOUT && rc != ERROR_INTERRUPT) { 677 break; 678 } 679 if (fibGetMsCount() - ulStart > 2500) { 680 break; 681 } 682 } 683 } 684 685 /* 686 * Since we probably didn't manage to inject the message, we should 687 * release the hook to make sure we're not overwriting g_qmsg while 688 * some other thread is reading it from MsgInputHook. 689 */ 690 WinReleaseHook(hab, NULLHANDLE, HK_MSGINPUT, (PFN)MsgInputHook, g_hmod); 691 DosSleep(10); 692 pszRet = g_pszErrorMsg; 693 return pszRet ? pszRet : "timed out"; 694 } 695 pszRet = "WinSetHook failed"; 696 } else { 697 pszRet = "DosResetEventSem failed"; 698 } 699 } else { 700 pszRet = "!g_fSynergyInitialized"; 701 } 702 DosSleep(0); 703 return pszRet; 704 } 705
Note:
See TracChangeset
for help on using the changeset viewer.