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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.