Changeset 2763


Ignore:
Timestamp:
Aug 13, 2006, 12:50:25 PM (19 years ago)
Author:
bird
Message:

Grr. HK_MSGINPUT / PM sucks. Got mouse working, but the hook code contains seriously bad hacks.

Location:
trunk/synergy
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/synergy/Makefile.kmk

    r2755 r2763  
    243243synrgyhk_ASTOOL.os2 = NASM
    244244synrgyhk_ASFLAGS.os2 = -f obj
     245synrgyhk_CXXFLAGS.os2 = -fno-exceptions
     246synrgyhk_LDFLAGS.os2 = -nostdlib -los2 -v -lend
    245247synrgyhk_SOURCES.nt = \
    246248        lib/platform/CSynergyHook.cpp
  • trunk/synergy/lib/platform/CPMKeyState.cpp

    r2761 r2763  
    650650        switch (keystroke.m_type) {
    651651        case Keystroke::kButton: {
    652                 LOG((CLOG_DEBUG1 "  %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up"));
     652                LOG((CLOG_DEBUG1 "  %03x (%08x) %s%s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client,
     653             keystroke.m_data.m_button.m_press ? "down" : "up", keystroke.m_data.m_button.m_repeat ? " repeate" : ""));
    653654                KeyButton button = keystroke.m_data.m_button.m_button;
    654655
  • trunk/synergy/lib/platform/CPMScreen.cpp

    r2762 r2763  
    7171        assert(s_screen == NULL);
    7272        s_screen = this;
     73    LOG((CLOG_DEBUG1 "CPMScreen: isPrimary=%d", isPrimary));
    7374   
    7475    // create the event queue buffer first so we know there is a message queue.
     
    9394
    9495        try {
    95                 if (m_isPrimary)
    96                         m_hmodHook = openHookLibrary("synrgyhk");
     96                m_hmodHook = openHookLibrary("synrgyhk");
    9797                m_screensaver = new CPMScreenSaver();
    9898                m_keyState    = new CPMKeyState(getEventTarget());
     
    528528}
    529529
     530/**
     531 * Injects a fake input message.
     532 *
     533 * @param   msg     The message id.
     534 * @param   mp1     Message param 1.
     535 * @param   mp1     Message param 2.
     536 */
     537void
     538CPMScreen::fakeMessage(ULONG msg, MPARAM mp1, MPARAM mp2) const
     539{
     540    QMSG qmsg;
     541    qmsg.hwnd = NULLHANDLE;
     542    qmsg.msg = msg;
     543    qmsg.mp1 = mp1;
     544    qmsg.mp2 = mp2;
     545    qmsg.time = WinGetCurrentTime(m_hab);
     546    qmsg.ptl.x = 0;     ///@todo check the qmsg.ptl.
     547    qmsg.ptl.y = 0;
     548    qmsg.reserved = 0;
     549LOG((CLOG_DEBUG "fakeMessage: msg=%#lx mp1=%#lx mp2=%#lx...", msg, mp1, mp2));
     550    const char *pszError = m_fakeMsg(m_hab, &qmsg);
     551    if (pszError) {
     552        LOG((CLOG_CRIT "fakeMessage: msg=%#lx mp1=%#lx mp2=%#lx failed: %s", msg, mp1, mp2, pszError));
     553    }
     554else LOG((CLOG_DEBUG "fakeMessage: done"));
     555}
     556
     557/**
     558 * Injects a fake input message generating mp2.
     559 * @param   msg     The message id.
     560 * @param   mp1     The mouse coordinates.
     561 */
     562void
     563CPMScreen::fakeMouseMessage(ULONG msg, MPARAM mp1) const
     564{
     565    /* hittest stuff is taken care off.. dunno about KC_*. */
     566    fakeMessage(msg, mp1, 0);
     567}
     568
    530569void
    531570CPMScreen::fakeMouseButton(ButtonID id, bool press) const
    532571{
    533         //m_desks->fakeMouseButton(id, press);
     572    // determin the message.
     573    ULONG msg;
     574    switch (id) {
     575        case kButtonLeft:
     576            msg = press ? WM_BUTTON1DOWN : WM_BUTTON1UP;
     577            break;
     578        case kButtonRight:
     579            msg = press ? WM_BUTTON2DOWN : WM_BUTTON2UP;
     580            break;
     581        case kButtonMiddle:
     582            msg = press ? WM_BUTTON3DOWN : WM_BUTTON3UP;
     583            break;
     584        default:
     585            return;
     586    }
     587
     588    // mp1
     589    POINTL ptl;
     590    if (!WinQueryPointerPos(HWND_DESKTOP, &ptl)) {
     591        LOG((CLOG_CRIT "fakeMouseButton: failed %#lx", WinGetLastError(CPMUtil::getHAB())));
     592        ptl.x = m_xCenter;
     593        ptl.y = m_yCenter;
     594    }
     595
     596    // forge the message.
     597    fakeMouseMessage(msg, MPFROM2SHORT(ptl.x, ptl.y));
    534598}
    535599
     
    539603    LOG((CLOG_DEBUG "fakeMouseMove: %d,%d (y=%d)", x, m_cy - y, y));
    540604    if (WinSetPointerPos(HWND_DESKTOP, x, m_cy - y)) {
     605        // check x limits
     606        if (x > 0x7fff) x = 0x7fff;
     607        else if (x < -0x8000) x = -0x8000;
     608
     609        // wrap y and check the limits.
     610        y = m_cy - y;
     611        if (y > 0x7fff) y = 0x7fff;
     612        else if (y < -0x8000) y = -0x8000;
     613
     614        // forge the message.
     615        fakeMouseMessage(WM_MOUSEMOVE, MPFROM2SHORT(x, y));
    541616        return;
    542617    }
     
    550625    if (WinQueryPointerPos(HWND_DESKTOP, &ptl)) {
    551626        LOG((CLOG_DEBUG "fakeMouseRelativeMove: %d,%d (%d,%d +/- %d,%d)", ptl.x + dx, ptl.y - dy, ptl.y, ptl.x, dx, dy));
    552         if (WinSetPointerPos(HWND_DESKTOP, ptl.x + dx, ptl.y - dy)) {
    553             return;
     627        fakeMouseMove(ptl.x + dx, ptl.y - dy - m_cy);
     628        return;
     629    }
     630    LOG((CLOG_CRIT "fakeMouseRelativeMove: failed %#lx", WinGetLastError(CPMUtil::getHAB())));
     631}
     632
     633void
     634CPMScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
     635{   
     636#if 0 /** @todo send scroll messages the the window beneath the cursor. */
     637    POINTL ptl;
     638    if (WinQueryPointerPos(HWND_DESKTOP, &ptl)) {
     639    }
     640#else
     641    /* dead simple arrow movement. */
     642    yDelta /= 30;
     643    while (yDelta != 0) {
     644        if (yDelta < 0) {
     645            yDelta++;
     646            fakeMessage(WM_CHAR, MPFROMSH2CH(KC_VIRTUALKEY | KC_SCANCODE, 1, 0x66), MPFROM2SHORT(0x50e0, VK_DOWN));
     647            fakeMessage(WM_CHAR, MPFROMSH2CH(KC_VIRTUALKEY | KC_SCANCODE | KC_KEYUP | KC_LONEKEY | KC_TOGGLE, 1, 0x66), MPFROM2SHORT(0x50e0, VK_DOWN));
     648        } else {
     649            yDelta--;
     650            fakeMessage(WM_CHAR, MPFROMSH2CH(KC_VIRTUALKEY | KC_SCANCODE, 1, 0x61), MPFROM2SHORT(0x48e0, VK_UP));
     651            fakeMessage(WM_CHAR, MPFROMSH2CH(KC_VIRTUALKEY | KC_SCANCODE | KC_KEYUP | KC_LONEKEY | KC_TOGGLE, 1, 0x61), MPFROM2SHORT(0x48e0, VK_UP));
    554652        }
    555653    }
    556     LOG((CLOG_CRIT "fakeMouseRelativeMove: failed %#lx", WinGetLastError(CPMUtil::getHAB())));
    557 }
    558 
    559 void
    560 CPMScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
    561 {
    562         //m_desks->fakeMouseWheel(xDelta, yDelta);
     654#endif
    563655}
    564656
     
    602694CPMScreen::openHookLibrary(const char* name)
    603695{
    604         // load the hook library
    605         HMODULE hmod;
    606         APIRET rc = DosLoadModule(NULL, 0, (PCSZ)name, &hmod);
     696        // load the hook library - try with qualified name first.
     697        HMODULE hmod = NULLHANDLE;
     698    APIRET rc = ERROR_FILE_NOT_FOUND;
     699    char szFullName[CCHMAXPATH + 10];
     700    if (!_execname(szFullName, CCHMAXPATH)) {
     701        char *psz = strrchr(szFullName, '\\');
     702        if (!psz || strrchr(psz, '/')) {
     703            psz = strrchr(psz, '/');
     704        }
     705        if (psz) {
     706            strcat(strcpy(psz + 1, name), ".DLL");
     707        }
     708            rc = DosLoadModule(NULL, 0, (PCSZ)szFullName, &hmod);
     709    }
     710
     711    // if that failed, try with the bare name.
     712    if (rc != NO_ERROR) {
     713            rc = DosLoadModule(NULL, 0, (PCSZ)name, &hmod);
     714    } else {
     715        name = szFullName;
     716    }
    607717        if (rc != NO_ERROR) {
    608718                LOG((CLOG_ERR "Failed to load hook library (%s), rc=%d ", name, rc));
     
    611721
    612722        // look up functions
    613         if (    (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setSides",      (PPFN)&m_setSides)) != NO_ERROR
     723        if (    (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_fakeMsg",       (PPFN)&m_fakeMsg )) != NO_ERROR
     724        ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setSides",      (PPFN)&m_setSides)) != NO_ERROR
    614725                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setZone",       (PPFN)&m_setZone )) != NO_ERROR
    615726                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setMode",       (PPFN)&m_setMode )) != NO_ERROR
     
    627738                throw XScreenOpenFailure();
    628739        }
     740    LOG((CLOG_DEBUG1 "openHookLibrary: hmod=%#lx '%s'", hmod, name));
    629741        return hmod;
    630742}
     
    633745CPMScreen::closeHookLibrary(HMODULE hmod) const
    634746{
     747    LOG((CLOG_DEBUG1 "closeHookLibrary: hmod=%#lx\n", hmod));
    635748        if (hmod != NULL) {
    636749                m_cleanup(m_hab);
  • trunk/synergy/lib/platform/CPMScreen.h

    r2755 r2763  
    100100        HWND                            createWindow(const char* name);
    101101        void                            destroyWindow(HWND) const;
     102   
     103    // fake message injection
     104    void                fakeMessage(ULONG msg, MPARAM mp1, MPARAM mp2) const;
     105    void                fakeMouseMessage(ULONG msg, MPARAM mp1) const;
    102106
    103107        // convenience function to send events
     
    227231        SetZoneFunc                     m_setZone;
    228232        SetModeFunc                     m_setMode;
     233        FakeMsgFunc                     m_fakeMsg;
    229234
    230235        // keyboard stuff
  • trunk/synergy/lib/platform/CPMSynergyHook.cpp

    r2755 r2763  
    1717#include "ProtocolTypes.h"
    1818#include <sys/builtin.h>
     19#if 0
    1920#include <stdlib.h>
    2021#include <unistd.h>
     22#include <InnoTekLIBC/FastInfoBlocks.h>
     23#else
     24unsigned long fibGetMsCount(void )
     25{
     26    ULONG ul = 0;
     27    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ul, sizeof(ul));
     28    return ul;
     29}
     30
     31int getpid(void)
     32{
     33    PTIB pTib;
     34    PPIB pPib;
     35    DosGetInfoBlocks(&pTib, &pPib);
     36    return pPib->pib_ulpid;
     37}
     38
     39int _gettid(void)
     40{
     41    PTIB pTib;
     42    PPIB pPib;
     43    DosGetInfoBlocks(&pTib, &pPib);
     44    return pTib->tib_ptib2->tib2_ultid;
     45}
     46
     47void _assert (__const__ char * pszExpr, __const__ char *pszFile, unsigned iLine)
     48{
     49    __asm__ ("int3\n");
     50}
     51
     52#endif
    2153
    2254//
    23 // globals - system wide (defined in .asm)
     55// globals - system wide
    2456//
    25 extern "C" {
    2657/** @name The synergy server/client thread
    2758 * @{ */
    28 extern HMQ                  g_hmqSynergy;
    29 extern int                  g_pidSynergy;
    30 extern int                  g_tidSynergy;
     59HMQ                  g_hmqSynergy;
     60int                  g_pidSynergy;
     61int                  g_tidSynergy;
    3162/** @} */
    3263
    3364/** The current mode.*/
    34 extern EHookMode volatile   g_enmMode;
     65EHookMode volatile   g_enmMode;
    3566
    3667/** Which sides do we have warp zones on. */
    37 extern UInt32               g_zoneSides;
     68UInt32               g_zoneSides;
    3869/** The warp zone size in pixels. */
    39 extern SInt32               g_zoneSize;
     70SInt32               g_zoneSize;
    4071/** @name The screen size.
    4172 * @{ */
    42 extern SInt32               g_xScreen;
    43 extern SInt32               g_yScreen;
    44 extern SInt32               g_cxScreen;
    45 extern SInt32               g_cyScreen;
     73SInt32               g_xScreen;
     74SInt32               g_yScreen;
     75SInt32               g_cxScreen;
     76SInt32               g_cyScreen;
    4677/** @} */
    4778
    4879/** Set if the hook is installed. */
    49 extern bool                 g_fInputHookInstalled;
     80bool                 g_fInputHookInstalled;
    5081/** Set if we're faking input. */
    51 extern bool                 g_fFakingInput;
    52 
    53 } /* extern "C" */
     82bool                 g_fFakingInput;
     83
     84/** @name Input Message Faking.
     85 * @{ */
     86/** The event semaphore we're waiting on while faking messages. */
     87HEV                  g_hev;
     88/** The pending message. */
     89QMSG                 g_qmsg;
     90/** Indicator set by the MsgInputHook function when the message 'skipped'. */
     91volatile bool        g_fMsgInjected;
     92/** Error description. */
     93const char          *g_pszErrorMsg;
     94/** Set if the dummy hook is installed. */
     95bool                 g_fDummyHook;
     96/** @} */
     97
     98/** The handle of the hook dll. */
     99HMODULE             g_hmod = NULLHANDLE;
     100/** Indicator whether the init() function has been called successfully. */
     101bool                g_fSynergyInitialized = false;
     102
    54103
    55104
    56105//
    57 // Globals - per process.
     106// Internal Functions
    58107//
    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;
    64108
    65109
     
    244288
    245289
     290#define NO_DUMMY_HOOK 1
     291#ifndef NO_DUMMY_HOOK
     292/**
     293 * Dummy hook.
     294 */
     295static VOID EXPENTRY SendMsgHook(HAB hab, PSMHSTRUCT psmh, BOOL fInterTask)
     296{
     297    /* nop */
     298}
     299#endif
     300
     301
     302
    246303//
    247304// external functions
     
    255312    switch (ulReason) {
    256313    /* init */
    257     case 0:
     314    case 0: {
     315        HEV hev = g_hev;
     316        if (hev != NULLHANDLE) {
     317            DosOpenEventSem(NULL, &hev);
     318        }
    258319        g_hmod = hmod;
    259         g_pid = getpid();
    260320        break;
     321    }
    261322
    262323    /* term */
    263324    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        }
    269328        break;
    270329    }
     
    294353
    295354    /*
     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    /*
    296368     * Initialize the globals.
    297369     */
     
    302374    /* only do this if the hook is inactive. */
    303375    if (g_enmMode == kHOOK_DISABLE) {
    304         g_enmMode      = kHOOK_DISABLE;
    305376        g_zoneSides = 0;
    306377        g_zoneSize  = 0;
     
    311382    }
    312383
     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;
    313397    return true;
    314398}
     
    324408{
    325409    assert(g_hmod != NULLHANDLE);
     410    assert(g_fSynergyInitialized == true);
    326411
    327412    /*
     
    336421    uninstall(hab);
    337422
     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
    338429    g_hmqSynergy = NULLHANDLE;
    339430    g_pidSynergy = 0;
    340431    g_tidSynergy = 0;
     432    g_fSynergyInitialized = false;
    341433    return true;
    342434}
     
    346438{
    347439    // must be initialized
    348     if (g_tidSynergy == 0) {
     440    if (    g_tidSynergy == 0
     441        ||  !g_fSynergyInitialized) {
    349442        return kHOOK_FAILED;
    350443    }
     
    384477    assert(g_pidSynergy == getpid());
    385478    assert(g_tidSynergy == _gettid());
     479    assert(g_fSynergyInitialized);
     480    if (!g_fSynergyInitialized) {
     481        return false;
     482    }
    386483
    387484    //// discard old dead keys
     
    409506    assert(g_pidSynergy == getpid());
    410507    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    }
    412512}
    413513
     
    426526    assert(g_pidSynergy == getpid());
    427527    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    }
    433536}
    434537
     
    443546    assert(g_pidSynergy == getpid());
    444547    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            }
    455561        }
    456562    }
    457563}
    458564
     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 */
     579static 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 */
     637CSYNERGYHOOK_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
  • trunk/synergy/lib/platform/CPMSynergyHook.def

    r2755 r2763  
    11LIBRARY SYNRGYHK INITINSTANCE TERMINSTANCE
    2 ;DATA MULTIPLE
    3 CODE SHARED
    4 SEGMENTS
    5     'SHAREDDATA32' CLASS 'SHAREDDATA' SHARED READWRITE
     2DATA SHARED
    63
  • trunk/synergy/lib/platform/CPMSynergyHook.h

    r2755 r2763  
    7777typedef void            (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
    7878typedef void            (*SetModeFunc)(int);
     79typedef const char *    (*FakeMsgFunc)(HAB hab, const QMSG *pQmsg);
    7980
    8081CSYNERGYHOOK_API bool   init(HMQ hmq, int tid, int pid);
     
    8485CSYNERGYHOOK_API void   setSides(UInt32 sides);
    8586CSYNERGYHOOK_API void   setZone(SInt32 x, SInt32 y, SInt32 cx, SInt32 cy, SInt32 jumpZoneSize);
    86 CSYNERGYHOOK_API void   setMode(EHookMode mode);
     87CSYNERGYHOOK_API const char * fakeMsg(HAB hab, const QMSG *pQmsg);
    8788
    8889#endif
  • trunk/synergy/lib/platform/CPMSynergyHookData.asm

    r2755 r2763  
    1313; */
    1414
     15;
     16; no dll0/crt0.
     17;
     18SEGMENT CODE32 CLASS=CODE USE32 FLAT PUBLIC
     19..start:
     20    jmp _DLL_InitTerm
     21extern _DLL_InitTerm
    1522
    16 SEGMENT SHAREDDATA32 CLASS=SHAREDDATA USE32 FLAT
    17 
    18 %define NAME(name) _ %+ name
    19 
    20 %macro GLOBALVAR 2,
    21 global NAME(%1)
    22 NAME(%1):
    23 dd %2
    24 %endmacro
    25 
    26 GLOBALVAR g_hmqSynergy, 0
    27 GLOBALVAR g_pidSynergy, 0
    28 GLOBALVAR g_tidSynergy, 0
    29 GLOBALVAR g_enmMode, 0
    30 GLOBALVAR g_zoneSides, 0
    31 GLOBALVAR g_zoneSize, 0
    32 GLOBALVAR g_xScreen, 0
    33 GLOBALVAR g_yScreen, 0
    34 GLOBALVAR g_cxScreen, 0
    35 GLOBALVAR g_cyScreen, 0
    36 GLOBALVAR g_fInputHookInstalled, 0
    37 GLOBALVAR g_fFakingInput, 0
    38 
Note: See TracChangeset for help on using the changeset viewer.