Beispiel #1
0
BOOL FASTCALL
UserRegisterHotKey(PWND pWnd,
                   int id,
                   UINT fsModifiers,
                   UINT vk)
{
    PHOT_KEY pHotKey;
    PTHREADINFO pHotKeyThread;

    /* Find hotkey thread */
    if (pWnd == NULL || pWnd == PWND_BOTTOM)
    {
        pHotKeyThread = PsGetCurrentThreadWin32Thread();
    }
    else
    {
        pHotKeyThread = pWnd->head.pti;
    }

    /* Check for existing hotkey */
    if (IsHotKey(fsModifiers, vk))
    {
        EngSetLastError(ERROR_HOTKEY_ALREADY_REGISTERED);
        WARN("Hotkey already exists\n");
        return FALSE;
    }

    /* Create new hotkey */
    pHotKey = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY), USERTAG_HOTKEY);
    if (pHotKey == NULL)
    {
        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }

    pHotKey->pti = pHotKeyThread;
    pHotKey->pWnd = pWnd;
    pHotKey->fsModifiers = fsModifiers;
    pHotKey->vk = vk;
    pHotKey->id = id;

    /* Insert hotkey to the global list */
    pHotKey->pNext = gphkFirst;
    gphkFirst = pHotKey;

    return TRUE;
}
Beispiel #2
0
BOOL xxxDoHotKeyStuff(
    UINT vk,
    BOOL fBreak,
    DWORD fsReserveKeys)
{
#ifdef WINDOWS_NOT_HOT
    static BOOL fOnlyWinKey = FALSE;
#endif
    static UINT fsModifiers = 0;
    static UINT fsModOnlyCandidate = 0;
    UINT fsModOnlyHotkey;
    UINT fs;
    PHOTKEY phk;
    PWND pwnd;
    BOOL fCancel;
    BOOL fEatDebugKeyBreak = FALSE;

    CheckCritIn();

    /*
     * Update fsModifiers.
     */
    fs = 0;
    fsModOnlyHotkey = 0;

    switch (vk) {
    case VK_RSHIFT:
        fs = MOD_RSHIFT;
    case VK_LSHIFT:
    case VK_SHIFT:
        vk = VK_SHIFT;
        fs |= MOD_SHIFT;
        break;

    case VK_RCONTROL:
        fs = MOD_RCONTROL;
    case VK_LCONTROL:
        vk = VK_CONTROL;
    case VK_CONTROL:
        fs |= MOD_CONTROL;
        break;

    case VK_RMENU:
        fs = MOD_RALT;
    case VK_LMENU:
        vk = VK_MENU;
    case VK_MENU:
        fs |= MOD_ALT;
        break;

    case VK_LWIN:
    case VK_RWIN:
        fs = MOD_WIN;
        break;

    default:
        /*
         * A non-modifier key rules out Modifier-Only hotkeys
         */
        fsModOnlyCandidate = 0;
        break;
    }

    if (fBreak) {
        fsModifiers &= ~fs;
        /*
         * If a modifier key is coming up, the current modifier only hotkey
         * candidate must be tested to see if it is a hotkey.  Store this
         * in fsModOnlyHotkey, and prevent the next key release from
         * being a candidate by clearing fsModOnlyCandidate.
         */
        if (fs != 0) {
            fsModOnlyHotkey = fsModOnlyCandidate;
            fsModOnlyCandidate = 0;
        }
    } else {
        fsModifiers |= fs;
        /*
         * If a modifier key is going down, we have a modifier-only hotkey
         * candidate.  Save current modifier state until the following break.
         */
        if (fs != 0) {
            fsModOnlyCandidate = fsModifiers;
        }
    }

    if (vk == VK_DELETE) {
        /*
         * Special case for SAS (Ctrl+Alt+Del) - examine physical key state!
         *
         * An evil daemon process can fool convincingly pretend to be winlogon
         * by registering Alt+Del as a hotkey, and spinning another thread that
         * continually calls keybd_event() to send the Ctrl key up: when the
         * user types Ctrl+Alt+Del, only Alt+Del will be seen by the system,
         * the evil daemon will get woken by WM_HOTKEY and can pretend to be
         * winlogon.  So look at gafPhysKeyState in this case, to see what keys
         * were physically pressed.
         * NOTE: If hotkeys are ever made to work under journal playback, make
         * sure they don't affect the gafPhysKeyState!  - IanJa.
         */
        UINT fPhysMods =
                (TestKeyDownBit(gafPhysKeyState, VK_MENU) ? MOD_ALT : 0) |
                (TestKeyDownBit(gafPhysKeyState, VK_SHIFT) ? MOD_SHIFT : 0) |
                (TestKeyDownBit(gafPhysKeyState, VK_CONTROL) ? MOD_CONTROL : 0);
        if ((fPhysMods & (MOD_CONTROL|MOD_ALT)) == MOD_CONTROL|MOD_ALT) {
            /*
             * Use physical modifiers keys
             */
            fsModifiers = fPhysMods;
        }
    }

#ifdef WINDOWS_NOT_HOT
    /*
     * track whether any key has been pressed since a Windows key went down
     */
    if (vk == VK_LWIN || vk == VK_RWIN) {
        if (!fBreak) {
            fOnlyWinKey = TRUE;
        } else if (fOnlyWinKey) {
            fOnlyWinKey = FALSE;
            CancelJournalling();

            pwnd = GETDESKINFO(PtiCurrent())->spwndShell;
            if (pwnd != NULL) {
                _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0);
                return TRUE;
            }
        }

    } else {
        fOnlyWinKey = FALSE;
    }
#endif

    /*
     * If the key is not a hotkey then we're done but first check if the
     * key is an Alt-Escape if so we need to cancel journalling.
     *
     * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0
     */
    if (fsModOnlyHotkey && fBreak) {
        /*
         * A hotkey involving only VK_SHIFT, VK_CONTROL, VK_MENU or VK_WINDOWS
         * must only operate on a key release.
         */
        if ((phk = IsHotKey(LOWORD(fsModOnlyHotkey), VK_NONE)) == NULL) {
            return FALSE;
        }
    } else if ((phk = IsHotKey(LOWORD(fsModifiers), vk)) == NULL) {
        return FALSE;
    }

    if (phk->id == IDHOT_WINDOWS) {
        pwnd = GETDESKINFO(PtiCurrent())->spwndShell;
        if (pwnd != NULL) {
            _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0);
            return TRUE;
        }
    }

    if ((phk->id == IDHOT_DEBUG) || (phk->id == IDHOT_DEBUGSERVER)) {

        if (!fBreak) {
            /*
             * The DEBUG key has been pressed.  Break the appropriate
             * thread into the debugger.
             */
            fEatDebugKeyBreak = xxxActivateDebugger(phk->fsModifiers);
        }

        /*
         * This'll eat the debug key down and break if we broke into
         * the debugger on the server only on the down.
         */
        return fEatDebugKeyBreak;
    }

    /*
     * don't allow hotkeys(except for ones owned by the logon process)
     * if the window station is locked.
     */

    if (((grpdeskRitInput->rpwinstaParent->dwFlags & WSF_SWITCHLOCK) != 0) &&
            (phk->pti->Thread->Cid.UniqueProcess != gpidLogon)) {
        return FALSE;
    }

    if ((fsModOnlyHotkey == 0) && fBreak) {
        /*
         * Do Modifier-Only hotkeys on break events, else return here.
         */
        return FALSE;
    }

    /*
     * Unhook hooks if a control-escape, alt-escape, or control-alt-del
     * comes through, so the user can cancel if the system seems hung.
     *
     * Note the hook may be locked so even if the unhook succeeds it
     * won't remove the hook from the global asphkStart array.  So
     * we have to walk the list manually.  This code works because
     * we are in the critical section and we know other hooks won't
     * be deleted.
     *
     * Once we've unhooked, post a WM_CANCELJOURNAL message to the app
     * that set the hook so it knows we did this.
     *
     * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0
     */
    fCancel = FALSE;
    if (vk == VK_ESCAPE && LOWORD(fsModifiers) == MOD_CONTROL) {
        fCancel = TRUE;
    }

    if (vk == VK_DELETE && (fsModifiers & (MOD_CONTROL | MOD_ALT)) ==
            (MOD_CONTROL | MOD_ALT)) {
        fCancel = TRUE;
    }

    if (fCancel)
        CancelJournalling();

    /*
     * See if the key is reserved by a console window.  If it is,
     * return FALSE so the key will be passed to the console.
     */
    if (fsReserveKeys != 0) {
        switch (vk) {
        case VK_TAB:
            if ((fsReserveKeys & CONSOLE_ALTTAB) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) {
                return FALSE;
            }
            break;
        case VK_ESCAPE:
            if ((fsReserveKeys & CONSOLE_ALTESC) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) {
                return FALSE;
            }
            if ((fsReserveKeys & CONSOLE_CTRLESC) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_CONTROL)) {
                return FALSE;
            }
            break;
        case VK_RETURN:
            if ((fsReserveKeys & CONSOLE_ALTENTER) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) {
                return FALSE;
            }
            break;
        case VK_SNAPSHOT:
            if ((fsReserveKeys & CONSOLE_PRTSC) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == 0)) {
                return FALSE;
            }
            if ((fsReserveKeys & CONSOLE_ALTPRTSC) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) {
                return FALSE;
            }
            break;
        case VK_SPACE:
            if ((fsReserveKeys & CONSOLE_ALTSPACE) &&
                    ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) {
                return FALSE;
            }
            break;
        }
    }

    /*
     * If this is the task-list hotkey, go ahead and set foreground
     * status to the task-list queue right now.  This prevents problems
     * where the user hits ctrl-esc and types-ahead before the task-list
     * processes the hotkey and brings up the task-list window.
     */
    if ((LOWORD(fsModifiers) == MOD_CONTROL) && (vk == VK_ESCAPE) && !fBreak) {
        PWND pwndSwitch;
        TL tlpwndSwitch;

        if (ghwndSwitch != NULL) {
            pwndSwitch = PW(ghwndSwitch);
            ThreadLock(pwndSwitch, &tlpwndSwitch);
            xxxSetForegroundWindow2(pwndSwitch, NULL, 0);
            ThreadUnlock(&tlpwndSwitch);
        }
    }

    /*
     * Get the hot key contents.
     */
    if (phk->spwnd == NULL) {
        _PostThreadMessage(
                phk->pti, WM_HOTKEY, phk->id,
                MAKELONG(LOWORD(fsModifiers), vk));
    } else {
        if (phk->spwnd == PWND_INPUTOWNER) {
            if (gpqForeground != NULL) {
                pwnd = gpqForeground->spwndFocus;
            } else {
                return FALSE;
            }

        } else {
            pwnd = phk->spwnd;
        }

        if (pwnd) {
            if (pwnd == pwnd->head.rpdesk->pDeskInfo->spwndShell && phk->id == SC_TASKLIST) {
                _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0);
            } else {
                _PostMessage(pwnd, WM_HOTKEY, phk->id, MAKELONG(LOWORD(fsModifiers), vk));
            }
        }
    }

    /*
     * If this is a Modifier-Only hotkey, let the modifier break through
     * by returning FALSE, otherwise we will have modifier keys stuck down.
     */
    return (fsModOnlyHotkey == 0);
}
Beispiel #3
0
BOOL APIENTRY
NtUserRegisterHotKey(HWND hWnd,
                     int id,
                     UINT fsModifiers,
                     UINT vk)
{
    PHOT_KEY pHotKey;
    PWND pWnd = NULL;
    PTHREADINFO pHotKeyThread;
    BOOL bRet = FALSE;

    TRACE("Enter NtUserRegisterHotKey\n");

    if (fsModifiers & ~(MOD_ALT|MOD_CONTROL|MOD_SHIFT|MOD_WIN)) // FIXME: Does Win2k3 support MOD_NOREPEAT?
    {
        WARN("Invalid modifiers: %x\n", fsModifiers);
        EngSetLastError(ERROR_INVALID_FLAGS);
        return 0;
    }

    UserEnterExclusive();

    /* Find hotkey thread */
    if (hWnd == NULL)
    {
        pHotKeyThread = gptiCurrent;
    }
    else
    {
        pWnd = UserGetWindowObject(hWnd);
        if (!pWnd)
            goto cleanup;

        pHotKeyThread = pWnd->head.pti;

        /* Fix wine msg "Window on another thread" test_hotkey */
        if (pWnd->head.pti != gptiCurrent)
        {
           EngSetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
           WARN("Must be from the same Thread.\n");
           goto cleanup;
        }
    }

    /* Check for existing hotkey */
    if (IsHotKey(fsModifiers, vk))
    {
        EngSetLastError(ERROR_HOTKEY_ALREADY_REGISTERED);
        WARN("Hotkey already exists\n");
        goto cleanup;
    }

    /* Create new hotkey */
    pHotKey = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY), USERTAG_HOTKEY);
    if (pHotKey == NULL)
    {
        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
        goto cleanup;
    }

    pHotKey->pti = pHotKeyThread;
    pHotKey->pWnd = pWnd;
    pHotKey->fsModifiers = fsModifiers;
    pHotKey->vk = vk;
    pHotKey->id = id;

    /* Insert hotkey to the global list */
    pHotKey->pNext = gphkFirst;
    gphkFirst = pHotKey;

    bRet = TRUE;

cleanup:
    TRACE("Leave NtUserRegisterHotKey, ret=%i\n", bRet);
    UserLeave();
    return bRet;
}
Beispiel #4
0
/*
 * co_UserProcessHotKeys
 *
 * Sends WM_HOTKEY message if given keys are hotkey
 */
BOOL NTAPI
co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
{
    UINT fModifiers;
    PHOT_KEY pHotKey;
    PWND pWnd;
    BOOL DoNotPostMsg = FALSE;
    BOOL IsModifier = FALSE;

    if (wVk == VK_SHIFT || wVk == VK_CONTROL || wVk == VK_MENU ||
        wVk == VK_LWIN || wVk == VK_RWIN)
    {
        /* Remember that this was a modifier */
        IsModifier = TRUE;
    }

    fModifiers = IntGetModifiers(gafAsyncKeyState);

    if (bIsDown)
    {
        if (IsModifier)
        {
            /* Modifier key down -- no hotkey trigger, but remember this */
            gfsModOnlyCandidate = fModifiers;
            return FALSE;
        }
        else
        {
            /* Regular key down -- check for hotkey, and reset mod candidates */
            pHotKey = IsHotKey(fModifiers, wVk);
            gfsModOnlyCandidate = 0;
        }
    }
    else
    {
        if (IsModifier)
        {
            /* Modifier key up -- modifier-only keys are triggered here */
            pHotKey = IsHotKey(gfsModOnlyCandidate, 0);
            gfsModOnlyCandidate = 0;
        }
        else
        {
            /* Regular key up -- no hotkey, but reset mod-only candidates */
            gfsModOnlyCandidate = 0;
            return FALSE;
        }
    }

    if (pHotKey)
    {
        TRACE("Hot key pressed (pWnd %p, id %d)\n", pHotKey->pWnd, pHotKey->id);

        /* FIXME: See comment about "UserDebuggerHotKey" on top of this file. */
        if (pHotKey->id == IDHK_SHIFTF12 || pHotKey->id == IDHK_F12)
        {
            if (bIsDown)
            {
                ERR("Hot key pressed for Debug Activation! ShiftF12 = %d or F12 = %d\n",pHotKey->id == IDHK_SHIFTF12 , pHotKey->id == IDHK_F12);
                //DoNotPostMsg = co_ActivateDebugger(); // FIXME
            }
            return DoNotPostMsg;
        }

        /* WIN and F12 keys are not hardcoded here. See comments on top of this file. */
        if (pHotKey->id == IDHK_WINKEY)
        {
            ASSERT(!bIsDown);
            pWnd = ValidateHwndNoErr(InputWindowStation->ShellWindow);
            if (pWnd)
            {
               TRACE("System Hot key Id %d Key %u\n", pHotKey->id, wVk );
               UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
               co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
               return FALSE;
            }
        }
        
        if (pHotKey->id == IDHK_SNAP_LEFT ||
            pHotKey->id == IDHK_SNAP_RIGHT ||
            pHotKey->id == IDHK_SNAP_UP ||
            pHotKey->id == IDHK_SNAP_DOWN)
        {
            HWND topWnd = UserGetForegroundWindow();
            if (topWnd)
            {
                UserPostMessage(topWnd, WM_KEYDOWN, wVk, 0);
            }
            return TRUE;
        }

        if (!pHotKey->pWnd)
        {
            TRACE("UPTM Hot key Id %d Key %u\n", pHotKey->id, wVk );
            UserPostThreadMessage(pHotKey->pti, WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
            //ptiLastInput = pHotKey->pti;
            return TRUE; /* Don't send any message */
        }
        else
        {
            pWnd = pHotKey->pWnd;
            if (pWnd == PWND_BOTTOM)
            {
                if (gpqForeground == NULL)
                    return FALSE;

                pWnd = gpqForeground->spwndFocus;
            }

            if (pWnd)
            {
                //  pWnd->head.rpdesk->pDeskInfo->spwndShell needs testing.
                if (pWnd == ValidateHwndNoErr(InputWindowStation->ShellWindow) && pHotKey->id == SC_TASKLIST)
                {
                    UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
                    co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
                }
                else
                {
                    TRACE("UPM Hot key Id %d Key %u\n", pHotKey->id, wVk );
                    UserPostMessage(UserHMGetHandle(pWnd), WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
                }
                //ptiLastInput = pWnd->head.pti;
                return TRUE; /* Don't send any message */
            }
        }
    }
    return FALSE;
}
Beispiel #5
0
/*
 * co_UserProcessHotKeys
 *
 * Sends WM_HOTKEY message if given keys are hotkey
 */
BOOL NTAPI
co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
{
    UINT fModifiers;
    PHOT_KEY pHotKey;
    PWND pWnd;
    BOOL DoNotPostMsg = FALSE;

    if (wVk == VK_SHIFT || wVk == VK_CONTROL || wVk == VK_MENU ||
        wVk == VK_LWIN || wVk == VK_RWIN)
    {
        /* Those keys are specified by modifiers */
        wVk = 0;
    }

    fModifiers = IntGetModifiers(gafAsyncKeyState);

    /* Check if it is a hotkey */
    pHotKey = IsHotKey(fModifiers, wVk);

    if (pHotKey)
    {
        TRACE("Hot key pressed (pWnd %p, id %d)\n", pHotKey->pWnd, pHotKey->id);

        /* FIXME: See comment about "UserDebuggerHotKey" on top of this file. */
        if (pHotKey->id == IDHK_SHIFTF12 || pHotKey->id == IDHK_F12)
        {
            if (bIsDown)
            {
                ERR("Hot key pressed for Debug Activation! ShiftF12 = %d or F12 = %d\n",pHotKey->id == IDHK_SHIFTF12 , pHotKey->id == IDHK_F12);
                //DoNotPostMsg = co_ActivateDebugger(); // FIXME
            }
            return DoNotPostMsg;
        }

        /* Process hotkey if it is key up event */
        if (!bIsDown)
        {
            /* WIN and F12 keys are not hardcoded here. See comments on top of this file. */
            if (pHotKey->id == IDHK_WINKEY && bWinHotkeyActive)
            {
                pWnd = ValidateHwndNoErr(InputWindowStation->ShellWindow);
                if (pWnd)
                {
                   TRACE("System Hot key Id %d Key %d\n",pHotKey->id, wVk );
                   UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
                   co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
                   bWinHotkeyActive = FALSE;
                   return FALSE;
                }
            }
        }
        else
        {    /* The user pressed the win key */
            if (pHotKey->id == IDHK_WINKEY)
            {
               bWinHotkeyActive = TRUE;
               return FALSE;
            }
        }

        if (bIsDown)
        {
            if (!pHotKey->pWnd)
            {
                TRACE("UPTM Hot key Id %d Key %d\n",pHotKey->id, wVk );
                UserPostThreadMessage(pHotKey->pti, WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
                //ptiLastInput = pHotKey->pti;
                return TRUE; /* Don't send any message */
            }
            else
            {
               if (pHotKey->pWnd == PWND_BOTTOM)
               {
                   if (gpqForeground != NULL)
                   {
                      pWnd = gpqForeground->spwndFocus;
                   }
                   else
                      return FALSE;
                }
                else
                {
                   pWnd = pHotKey->pWnd;
                }
                if (pWnd)
                {          //  pWnd->head.rpdesk->pDeskInfo->spwndShell needs testing.
                   if (pWnd == ValidateHwndNoErr(InputWindowStation->ShellWindow) && pHotKey->id == SC_TASKLIST)
                   {
                      ERR("Sending to shell window w/o IDHK_WINKEY..\n");
                      UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
                   }
                   else
                   {
                      TRACE("UPM Hot key Id %d Key %d\n",pHotKey->id, wVk );
                      UserPostMessage(UserHMGetHandle(pWnd), WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
                   }
                   //ptiLastInput = pWnd->head.pti;
                   return TRUE; /* Don't send any message */
                }
            }
        }
    }
    return FALSE;
}