"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/keyboard_mouse.cpp" (8 May 2021, 260502 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "keyboard_mouse.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 AutoHotkey
    3 
    4 Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
    5 
    6 This program is free software; you can redistribute it and/or
    7 modify it under the terms of the GNU General Public License
    8 as published by the Free Software Foundation; either version 2
    9 of the License, or (at your option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 */
   16 
   17 #include "stdafx.h" // pre-compiled headers
   18 #include "keyboard_mouse.h"
   19 #include "globaldata.h" // for g->KeyDelay
   20 #include "application.h" // for MsgSleep()
   21 #include "util.h"  // for strlicmp()
   22 #include "window.h" // for IsWindowHung()
   23 
   24 
   25 // Added for v1.0.25.  Search on sPrevEventType for more comments:
   26 static KeyEventTypes sPrevEventType;
   27 static vk_type sPrevVK = 0;
   28 // For v1.0.25, the below is static to track it in between sends, so that the below will continue
   29 // to work:
   30 // Send {LWinDown}
   31 // Send {LWinUp}  ; Should still open the Start Menu even though it's a separate Send.
   32 static vk_type sPrevEventModifierDown = 0;
   33 static modLR_type sModifiersLR_persistent = 0; // Tracks this script's own lifetime/persistent modifiers (the ones it caused to be persistent and thus is responsible for tracking).
   34 static modLR_type sModifiersLR_remapped = 0;
   35 
   36 // v1.0.44.03: Below supports multiple keyboard layouts better by having script adapt to active window's layout.
   37 #define MAX_CACHED_LAYOUTS 10  // Hard to imagine anyone using more languages/layouts than this, but even if they do it will still work; performance would just be a little worse due to being uncached.
   38 static CachedLayoutType sCachedLayout[MAX_CACHED_LAYOUTS] = {{0}};
   39 static HKL sTargetKeybdLayout;           // Set by SendKeys() for use by the functions it calls directly and indirectly.
   40 static ResultType sTargetLayoutHasAltGr; //
   41 
   42 // v1.0.43: Support for SendInput() and journal-playback hook:
   43 #define MAX_INITIAL_EVENTS_SI 500UL  // sizeof(INPUT) == 28 as of 2006. Since Send is called so often, and since most Sends are short, reducing the load on the stack is also a deciding factor for these.
   44 #define MAX_INITIAL_EVENTS_PB 1500UL // sizeof(PlaybackEvent) == 8, so more events are justified before resorting to malloc().
   45 static LPINPUT sEventSI;        // No init necessary.  An array that's allocated/deallocated by SendKeys().
   46 static PlaybackEvent *&sEventPB = (PlaybackEvent *&)sEventSI;
   47 static UINT sEventCount, sMaxEvents; // Number of items in the above arrays and the current array capacity.
   48 static UINT sCurrentEvent;
   49 static modLR_type sEventModifiersLR; // Tracks the modifier state to following the progress/building of the SendInput array.
   50 static POINT sSendInputCursorPos;    // Tracks/predicts cursor position as SendInput array is built.
   51 static HookType sHooksToRemoveDuringSendInput;
   52 static SendModes sSendMode = SM_EVENT; // Whether a SendInput or Hook array is currently being constructed.
   53 static bool sAbortArraySend;         // No init needed.
   54 static bool sFirstCallForThisEvent;  //
   55 static bool sInBlindMode;            //
   56 static DWORD sThisEventTime;         //
   57 
   58 
   59 void DisguiseWinAltIfNeeded(vk_type aVK)
   60 // For v1.0.25, the following situation is fixed by the code below: If LWin or LAlt
   61 // becomes a persistent modifier (e.g. via Send {LWin down}) and the user physically
   62 // releases LWin immediately before: 1) the {LWin up} is scheduled; and 2) SendKey()
   63 // returns.  Then SendKey() will push the modifier back down so that it is in effect
   64 // for other things done by its caller (SendKeys) and also so that if the Send
   65 // operation ends, the key will still be down as the user intended (to modify future
   66 // keystrokes, physical or simulated).  However, since that down-event is followed
   67 // immediately by an up-event, the Start Menu appears for WIN-key or the active
   68 // window's menu bar is activated for ALT-key.  SOLUTION: Disguise Win-up and Alt-up
   69 // events in these cases.  This workaround has been successfully tested.  It's also
   70 // limited is scope so that a script can still explicitly invoke the Start Menu with
   71 // "Send {LWin}", or activate the menu bar with "Send {Alt}".
   72 // The check of sPrevEventModifierDown allows "Send {LWinDown}{LWinUp}" etc., to
   73 // continue to work.
   74 // v1.0.40: For maximum flexibility and minimum interference while in blind mode,
   75 // don't disguise Win and Alt keystrokes then.
   76 {
   77     // Caller has ensured that aVK is about to have a key-up event, so if the event immediately
   78     // prior to this one is a key-down of the same type of modifier key, it's our job here
   79     // to send the disguising keystrokes now (if appropriate).
   80     if (sPrevEventType == KEYDOWN && sPrevEventModifierDown != aVK && !sInBlindMode
   81         // SendPlay mode can't display Start Menu, so no need for disguise keystrokes (such keystrokes might cause
   82         // unwanted effects in certain games):
   83         && ((aVK == VK_LWIN || aVK == VK_RWIN) && (sPrevVK == VK_LWIN || sPrevVK == VK_RWIN) && sSendMode != SM_PLAY
   84             || (aVK == VK_LMENU || (aVK == VK_RMENU && sTargetLayoutHasAltGr != CONDITION_TRUE)) && (sPrevVK == VK_LMENU || sPrevVK == VK_RMENU)))
   85         KeyEventMenuMask(KEYDOWNANDUP); // Disguise it to suppress Start Menu or prevent activation of active window's menu bar.
   86 }
   87 
   88 
   89 
   90 // moved from SendKeys
   91 void SendUnicodeChar(wchar_t aChar, modLR_type aModifiers)
   92 {
   93     // Set modifier keystate as specified by caller.  Generally this will be 0, since
   94     // key combinations with Unicode packets either do nothing at all or do the same as
   95     // without the modifiers.  All modifiers are known to interfere in some applications.
   96     SetModifierLRState(aModifiers, sSendMode ? sEventModifiersLR : GetModifierLRState(), NULL, false, true, KEY_IGNORE);
   97 
   98     if (sSendMode == SM_INPUT)
   99     {
  100         // Calling SendInput() now would cause characters to appear out of sequence.
  101         // Instead, put them into the array and allow them to be sent in sequence.
  102         PutKeybdEventIntoArray(0, 0, aChar, KEYEVENTF_UNICODE, KEY_IGNORE_LEVEL(g->SendLevel));
  103         PutKeybdEventIntoArray(0, 0, aChar, KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, KEY_IGNORE_LEVEL(g->SendLevel));
  104         return;
  105     }
  106     //else caller has ensured sSendMode is SM_EVENT. In that mode, events are sent one at a time,
  107     // so it is safe to immediately call SendInput(). SM_PLAY is not supported; for simplicity,
  108     // SendASC() is called instead of this function. Although this means Unicode chars probably
  109     // won't work, it seems better than sending chars out of order. One possible alternative could
  110     // be to "flush" the event array, but since SendInput and SendEvent are probably much more common,
  111     // this is left for a future version.
  112 
  113     INPUT u_input[2];
  114 
  115     u_input[0].type = INPUT_KEYBOARD;
  116     u_input[0].ki.wVk = 0;
  117     u_input[0].ki.wScan = aChar;
  118     u_input[0].ki.dwFlags = KEYEVENTF_UNICODE;
  119     u_input[0].ki.time = 0;
  120     // L25: Set dwExtraInfo to ensure AutoHotkey ignores the event; otherwise it may trigger a SCxxx hotkey (where xxx is u_code).
  121     u_input[0].ki.dwExtraInfo = KEY_IGNORE_LEVEL(g->SendLevel);
  122     
  123     u_input[1].type = INPUT_KEYBOARD;
  124     u_input[1].ki.wVk = 0;
  125     u_input[1].ki.wScan = aChar;
  126     u_input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
  127     u_input[1].ki.time = 0;
  128     u_input[1].ki.dwExtraInfo = KEY_IGNORE_LEVEL(g->SendLevel);
  129 
  130     SendInput(2, u_input, sizeof(INPUT));
  131 }
  132 
  133 
  134 
  135 void SendKeys(LPTSTR aKeys, SendRawModes aSendRaw, SendModes aSendModeOrig, HWND aTargetWindow)
  136 // The aKeys string must be modifiable (not constant), since for performance reasons,
  137 // it's allowed to be temporarily altered by this function.  mThisHotkeyModifiersLR, if non-zero,
  138 // should be the set of modifiers used to trigger the hotkey that called the subroutine
  139 // containing the Send that got us here.  If any of those modifiers are still down,
  140 // they will be released prior to sending the batch of keys specified in <aKeys>.
  141 // v1.0.43: aSendModeOrig was added.
  142 {
  143     if (!*aKeys)
  144         return;
  145     global_struct &g = *::g; // Reduces code size and may improve performance.
  146 
  147     DWORD orig_last_script_rest = g_script.mLastScriptRest;
  148 
  149     // For performance and also to reserve future flexibility, recognize {Blind} only when it's the first item
  150     // in the string.
  151     if (sInBlindMode = !aSendRaw && !_tcsnicmp(aKeys, _T("{Blind}"), 7)) // Don't allow {Blind} while in raw mode due to slight chance {Blind} is intended to be sent as a literal string.
  152         // Blind Mode (since this seems too obscure to document, it's mentioned here):  Blind Mode relies
  153         // on modifiers already down for something like ^c because ^c is saying "manifest a ^c", which will
  154         // happen if ctrl is already down.  By contrast, Blind does not release shift to produce lowercase
  155         // letters because avoiding that adds flexibility that couldn't be achieved otherwise.
  156         // Thus, ^c::Send {Blind}c produces the same result when ^c is substituted for the final c.
  157         // But Send {Blind}{LControl down} will generate the extra events even if ctrl already down.
  158         aKeys += 7; // Remove "{Blind}" from further consideration.
  159 
  160     if (!aSendRaw && !_tcsnicmp(aKeys, _T("{Text}"), 6))
  161     {
  162         // Setting this early allows CapsLock and the Win+L workaround to be skipped:
  163         aSendRaw = SCM_RAW_TEXT;
  164         aKeys += 6;
  165     }
  166 
  167     int orig_key_delay = g.KeyDelay;
  168     int orig_press_duration = g.PressDuration;
  169     if (aSendModeOrig == SM_INPUT || aSendModeOrig == SM_INPUT_FALLBACK_TO_PLAY) // Caller has ensured aTargetWindow==NULL for SendInput and SendPlay modes.
  170     {
  171         // Both of these modes fall back to a different mode depending on whether some other script
  172         // is running with a keyboard/mouse hook active.  Of course, the detection of this isn't foolproof
  173         // because older versions of AHK may be running and/or other apps with LL keyboard hooks. It's
  174         // just designed to add a lot of value for typical usage because SendInput is preferred due to it
  175         // being considerably faster than SendPlay, especially for long replacements when the CPU is under
  176         // heavy load.
  177         if (   SystemHasAnotherKeybdHook() // This function has been benchmarked to ensure it doesn't yield our timeslice, etc.  200 calls take 0ms according to tick-count, even when CPU is maxed.
  178             || !aSendRaw && SystemHasAnotherMouseHook() && tcscasestr(aKeys, _T("{Click"))   ) // Ordered for short-circuit boolean performance.  v1.0.43.09: Fixed to be strcasestr vs. !strcasestr
  179         {
  180             // Need to detect in advance what type of array to build (for performance and code size).  That's why
  181             // it done this way, and here are the comments about it:
  182             // strcasestr() above has an unwanted amount of overhead if aKeys is huge, but it seems acceptable
  183             // because it's called only when system has another mouse hook but *not* another keybd hook (very rare).
  184             // Also, for performance reasons, {LButton and such are not checked for, which is documented and seems
  185             // justified because the new {Click} method is expected to become prevalent, especially since this
  186             // whole section only applies when the new SendInput mode is in effect.
  187             // Finally, checking aSendRaw isn't foolproof because the string might contain {Raw} prior to {Click,
  188             // but the complexity and performance of checking for that seems unjustified given the rarity,
  189             // especially since there are almost never any consequences to reverting to hook mode vs. SendInput.
  190             if (aSendModeOrig == SM_INPUT_FALLBACK_TO_PLAY)
  191                 aSendModeOrig = SM_PLAY;
  192             else // aSendModeOrig == SM_INPUT, so fall back to EVENT.
  193             {
  194                 aSendModeOrig = SM_EVENT;
  195                 // v1.0.43.08: When SendInput reverts to SendEvent mode, the majority of users would want
  196                 // a fast sending rate that is more comparable to SendInput's speed that the default KeyDelay
  197                 // of 10ms.  PressDuration may be generally superior to KeyDelay because it does a delay after
  198                 // each changing of modifier state (which tends to improve reliability for certain apps).
  199                 // The following rules seem likely to be the best benefit in terms of speed and reliability:
  200                 // KeyDelay 0+,-1+ --> -1, 0
  201                 // KeyDelay -1, 0+ --> -1, 0
  202                 // KeyDelay -1,-1 --> -1, -1
  203                 g.PressDuration = (g.KeyDelay < 0 && g.PressDuration < 0) ? -1 : 0;
  204                 g.KeyDelay = -1; // Above line must be done before this one.
  205             }
  206         }
  207         else // SendInput is available and no other impacting hooks are obviously present on the system, so use SendInput unconditionally.
  208             aSendModeOrig = SM_INPUT; // Resolve early so that other sections don't have to consider SM_INPUT_FALLBACK_TO_PLAY a valid value.
  209     }
  210 
  211     // Might be better to do this prior to changing capslock state.  UPDATE: In v1.0.44.03, the following section
  212     // has been moved to the top of the function because:
  213     // 1) For ControlSend, GetModifierLRState() might be more accurate if the threads are attached beforehand.
  214     // 2) Determines sTargetKeybdLayout and sTargetLayoutHasAltGr early (for maintainability).
  215     bool threads_are_attached = false; // Set default.
  216     DWORD keybd_layout_thread = 0;     //
  217     DWORD target_thread; // Doesn't need init.
  218     if (aTargetWindow) // Caller has ensured this is NULL for SendInput and SendPlay modes.
  219     {
  220         if ((target_thread = GetWindowThreadProcessId(aTargetWindow, NULL)) // Assign.
  221             && target_thread != g_MainThreadID && !IsWindowHung(aTargetWindow))
  222         {
  223             threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;
  224             keybd_layout_thread = target_thread; // Testing shows that ControlSend benefits from the adapt-to-layout technique too.
  225         }
  226         //else no target thread, or it's our thread, or it's hung; so keep keybd_layout_thread at its default.
  227     }
  228     else
  229     {
  230         // v1.0.48.01: On Vista or later, work around the fact that an "L" keystroke (physical or artificial) will
  231         // lock the computer whenever either Windows key is physically pressed down (artificially releasing the
  232         // Windows key isn't enough to solve it because Win+L is apparently detected aggressively like
  233         // Ctrl-Alt-Delete.  Unlike the handling of SM_INPUT in another section, this one here goes into
  234         // effect for all Sends because waiting for an "L" keystroke to be sent would be too late since the
  235         // Windows would have already been artificially released by then, so IsKeyDownAsync() wouldn't be
  236         // able to detect when the user physically releases the key.
  237         if (   (g_script.mThisHotkeyModifiersLR & (MOD_LWIN|MOD_RWIN)) // Limit the scope to only those hotkeys that have a Win modifier, since anything outside that scope hasn't been fully analyzed.
  238             && (GetTickCount() - g_script.mThisHotkeyStartTime) < (DWORD)50 // Ensure g_script.mThisHotkeyModifiersLR is up-to-date enough to be reliable.
  239             && aSendModeOrig != SM_PLAY // SM_PLAY is reported to be incapable of locking the computer.
  240             && !sInBlindMode // The philosophy of blind-mode is that the script should have full control, so don't do any waiting during blind mode.
  241             && aSendRaw != SCM_RAW_TEXT // {Text} mode does not trigger Win+L.
  242             && g_os.IsWinVistaOrLater() // Only Vista (and presumably later OSes) check the physical state of the Windows key for Win+L.
  243             && GetCurrentThreadId() == g_MainThreadID // Exclude the hook thread because it isn't allowed to call anything like MsgSleep, nor are any calls from the hook thread within the understood/analyzed scope of this workaround.
  244             )
  245         {
  246             bool wait_for_win_key_release;
  247             if (aSendRaw)
  248                 wait_for_win_key_release = StrChrAny(aKeys, _T("Ll")) != NULL;
  249             else
  250             {
  251                 // It seems worthwhile to scan for any "L" characters to avoid waiting for the release
  252                 // of the Windows key when there are no L's.  For performance and code size, the check
  253                 // below isn't comprehensive (e.g. it fails to consider things like {L} and #L).
  254                 // Although RegExMatch() could be used instead of the below, that would use up one of
  255                 // the RegEx cache entries, plus it would probably perform worse.  So scan manually.
  256                 LPTSTR L_pos, brace_pos;
  257                 for (wait_for_win_key_release = false, brace_pos = aKeys; L_pos = StrChrAny(brace_pos, _T("Ll"));)
  258                 {
  259                     // Encountering a #L seems too rare, and the consequences too mild (or nonexistent), to
  260                     // justify the following commented-out section:
  261                     //if (L_pos > aKeys && L_pos[-1] == '#') // A simple check; it won't detect things like #+L.
  262                     //  brace_pos = L_pos + 1;
  263                     //else
  264                     if (!(brace_pos = StrChrAny(L_pos + 1, _T("{}"))) || *brace_pos == '{') // See comment below.
  265                     {
  266                         wait_for_win_key_release = true;
  267                         break;
  268                     }
  269                     //else it found a '}' without a preceding '{', which means this "L" is inside braces.
  270                     // For simplicity, ignore such L's (probably not a perfect check, but seems worthwhile anyway).
  271                 }
  272             }
  273             if (wait_for_win_key_release)
  274                 while (IsKeyDownAsync(VK_LWIN) || IsKeyDownAsync(VK_RWIN)) // Even if the keyboard hook is installed, it seems best to use IsKeyDownAsync() vs. g_PhysicalKeyState[] because it's more likely to produce consistent behavior.
  275                     SLEEP_WITHOUT_INTERRUPTION(INTERVAL_UNSPECIFIED); // Seems best not to allow other threads to launch, for maintainability and because SendKeys() isn't designed to be interruptible.
  276         }
  277 
  278         // v1.0.44.03: The following change is meaningful only to people who use more than one keyboard layout.
  279         // It seems that the vast majority of them would want the Send command (as well as other features like
  280         // Hotstrings and the Input command) to adapt to the keyboard layout of the active window (or target window
  281         // in the case of ControlSend) rather than sticking with the script's own keyboard layout.  In addition,
  282         // testing shows that this adapt-to-layout method costs almost nothing in performance, especially since
  283         // the active window, its thread, and its layout are retrieved only once for each Send rather than once
  284         // for each keystroke.
  285         // v1.1.27.01: Use the thread of the focused control, which may differ from the active window.
  286         keybd_layout_thread = GetFocusedCtrlThread();
  287     }
  288     sTargetKeybdLayout = GetKeyboardLayout(keybd_layout_thread); // If keybd_layout_thread==0, this will get our thread's own layout, which seems like the best/safest default.
  289     sTargetLayoutHasAltGr = LayoutHasAltGr(sTargetKeybdLayout);  // Note that WM_INPUTLANGCHANGEREQUEST is not monitored by MsgSleep for the purpose of caching our thread's keyboard layout.  This is because it would be unreliable if another msg pump such as MsgBox is running.  Plus it hardly helps perf. at all, and hurts maintainability.
  290 
  291     // Below is now called with "true" so that the hook's modifier state will be corrected (if necessary)
  292     // prior to every send.
  293     modLR_type mods_current = GetModifierLRState(true); // Current "logical" modifier state.
  294 
  295     // For any modifiers put in the "down" state by {xxx DownR}, keep only those which
  296     // are still logically down before each Send starts.  Otherwise each Send would reset
  297     // the modifier to "down" even after the user "releases" it by some other means.
  298     sModifiersLR_remapped &= mods_current;
  299 
  300     // Make a best guess of what the physical state of the keys is prior to starting (there's no way
  301     // to be certain without the keyboard hook). Note: We only want those physical
  302     // keys that are also logically down (it's possible for a key to be down physically
  303     // but not logically such as when R-control, for example, is a suffix hotkey and the
  304     // user is physically holding it down):
  305     modLR_type mods_down_physically_orig, mods_down_physically_and_logically
  306         , mods_down_physically_but_not_logically_orig;
  307     if (g_KeybdHook)
  308     {
  309         // Since hook is installed, use its more reliable tracking to determine which
  310         // modifiers are down.
  311         mods_down_physically_orig = g_modifiersLR_physical;
  312         mods_down_physically_and_logically = g_modifiersLR_physical & g_modifiersLR_logical; // intersect
  313         mods_down_physically_but_not_logically_orig = g_modifiersLR_physical & ~g_modifiersLR_logical;
  314     }
  315     else // Use best-guess instead.
  316     {
  317         // Even if TickCount has wrapped due to system being up more than about 49 days,
  318         // DWORD subtraction still gives the right answer as long as g_script.mThisHotkeyStartTime
  319         // itself isn't more than about 49 days ago:
  320         if ((GetTickCount() - g_script.mThisHotkeyStartTime) < (DWORD)g_HotkeyModifierTimeout) // Elapsed time < timeout-value
  321             mods_down_physically_orig = mods_current & g_script.mThisHotkeyModifiersLR; // Bitwise AND is set intersection.
  322         else
  323             // Since too much time as passed since the user pressed the hotkey, it seems best,
  324             // based on the action that will occur below, to assume that no hotkey modifiers
  325             // are physically down:
  326             mods_down_physically_orig = 0;
  327         mods_down_physically_and_logically = mods_down_physically_orig;
  328         mods_down_physically_but_not_logically_orig = 0; // There's no way of knowing, so assume none.
  329     }
  330 
  331     // Any of the external modifiers that are down but NOT due to the hotkey are probably
  332     // logically down rather than physically (perhaps from a prior command such as
  333     // "Send, {CtrlDown}".  Since there's no way to be sure without the keyboard hook or some
  334     // driver-level monitoring, it seems best to assume that
  335     // they are logically vs. physically down.  This value contains the modifiers that
  336     // we will not attempt to change (e.g. "Send, A" will not release the LWin
  337     // before sending "A" if this value indicates that LWin is down).  The below sets
  338     // the value to be all the down-keys in mods_current except any that are physically
  339     // down due to the hotkey itself.  UPDATE: To improve the above, we now exclude from
  340     // the set of persistent modifiers any that weren't made persistent by this script.
  341     // Such a policy seems likely to do more good than harm as there have been cases where
  342     // a modifier was detected as persistent just because #HotkeyModifier had timed out
  343     // while the user was still holding down the key, but then when the user released it,
  344     // this logic here would think it's still persistent and push it back down again
  345     // to enforce it as "always-down" during the send operation.  Thus, the key would
  346     // basically get stuck down even after the send was over:
  347     sModifiersLR_persistent &= mods_current & ~mods_down_physically_and_logically;
  348     modLR_type persistent_modifiers_for_this_SendKeys, extra_persistent_modifiers_for_blind_mode;
  349     if (sInBlindMode)
  350     {
  351         // The following value is usually zero unless the user is currently holding down
  352         // some modifiers as part of a hotkey. These extra modifiers are the ones that
  353         // this send operation (along with all its calls to SendKey and similar) should
  354         // consider to be down for the duration of the Send (unless they go up via an
  355         // explicit {LWin up}, etc.)
  356         extra_persistent_modifiers_for_blind_mode = mods_current & ~sModifiersLR_persistent;
  357         persistent_modifiers_for_this_SendKeys = mods_current;
  358     }
  359     else
  360     {
  361         extra_persistent_modifiers_for_blind_mode = 0;
  362         persistent_modifiers_for_this_SendKeys = sModifiersLR_persistent;
  363     }
  364     // Above:
  365     // Keep sModifiersLR_persistent and persistent_modifiers_for_this_SendKeys in sync with each other from now on.
  366     // By contrast to persistent_modifiers_for_this_SendKeys, sModifiersLR_persistent is the lifetime modifiers for
  367     // this script that stay in effect between sends.  For example, "Send {LAlt down}" leaves the alt key down
  368     // even after the Send ends, by design.
  369     //
  370     // It seems best not to change persistent_modifiers_for_this_SendKeys in response to the user making physical
  371     // modifier changes during the course of the Send.  This is because it seems more often desirable that a constant
  372     // state of modifiers be kept in effect for the entire Send rather than having the user's release of a hotkey
  373     // modifier key, which typically occurs at some unpredictable time during the Send, to suddenly alter the nature
  374     // of the Send in mid-stride.  Another reason is to make the behavior of Send consistent with that of SendInput.
  375 
  376     // The default behavior is to turn the capslock key off prior to sending any keys
  377     // because otherwise lowercase letters would come through as uppercase and vice versa.
  378     ToggleValueType prior_capslock_state;
  379     // Remember that apps like MS Word have an auto-correct feature that might make it
  380     // wrongly seem that the turning off of Capslock below needs a Sleep(0) to take effect.
  381     prior_capslock_state = g.StoreCapslockMode && !sInBlindMode && aSendRaw != SCM_RAW_TEXT
  382         ? ToggleKeyState(VK_CAPITAL, TOGGLED_OFF)
  383         : TOGGLE_INVALID; // In blind mode, don't do store capslock (helps remapping and also adds flexibility).
  384 
  385     // sSendMode must be set only after setting Capslock state above, because the hook method
  386     // is incapable of changing the on/off state of toggleable keys like Capslock.
  387     // However, it can change Capslock state as seen in the window to which playback events are being
  388     // sent; but the behavior seems inconsistent and might vary depending on OS type, so it seems best
  389     // not to rely on it.
  390     sSendMode = aSendModeOrig;
  391     if (sSendMode) // Build an array.  We're also responsible for setting sSendMode to SM_EVENT prior to returning.
  392     {
  393         size_t mem_size;
  394         if (sSendMode == SM_INPUT)
  395         {
  396             mem_size = MAX_INITIAL_EVENTS_SI * sizeof(INPUT);
  397             sMaxEvents = MAX_INITIAL_EVENTS_SI;
  398         }
  399         else // Playback type.
  400         {
  401             mem_size = MAX_INITIAL_EVENTS_PB * sizeof(PlaybackEvent);
  402             sMaxEvents = MAX_INITIAL_EVENTS_PB;
  403         }
  404         // _alloca() is used to avoid the overhead of malloc/free (99% of Sends will thus fit in stack memory).
  405         // _alloca() never returns a failure code, it just raises an exception (e.g. stack overflow).
  406         InitEventArray(_alloca(mem_size), sMaxEvents, mods_current);
  407     }
  408 
  409     bool blockinput_prev = g_BlockInput;
  410     bool do_selective_blockinput = (g_BlockInputMode == TOGGLE_SEND || g_BlockInputMode == TOGGLE_SENDANDMOUSE)
  411         && !sSendMode && !aTargetWindow;
  412     if (do_selective_blockinput)
  413         Line::ScriptBlockInput(true); // Turn it on unconditionally even if it was on, since Ctrl-Alt-Del might have disabled it.
  414 
  415     vk_type vk;
  416     sc_type sc;
  417     modLR_type key_as_modifiersLR = 0;
  418     modLR_type mods_for_next_key = 0;
  419     // Above: For v1.0.35, it was changed to modLR vs. mod so that AltGr keys such as backslash and '{'
  420     // are supported on layouts such as German when sending to apps such as Putty that are fussy about
  421     // which ALT key is held down to produce the character.
  422     vk_type this_event_modifier_down;
  423     size_t key_text_length, key_name_length;
  424     TCHAR *end_pos, *space_pos, *next_word, old_char;
  425     KeyEventTypes event_type;
  426     int repeat_count, click_x, click_y;
  427     bool move_offset;
  428     enum { KEYDOWN_TEMP = 0, KEYDOWN_PERSISTENT, KEYDOWN_REMAP } key_down_type;
  429     DWORD placeholder;
  430 
  431     LONG_OPERATION_INIT  // Needed even for SendInput/Play.
  432 
  433     for (; *aKeys; ++aKeys, sPrevEventModifierDown = this_event_modifier_down)
  434     {
  435         this_event_modifier_down = 0; // Set default for this iteration, overridden selectively below.
  436         if (!sSendMode)
  437             LONG_OPERATION_UPDATE_FOR_SENDKEYS // This does not measurably affect the performance of SendPlay/Event.
  438 
  439         if (!aSendRaw && _tcschr(_T("^+!#{}"), *aKeys))
  440         {
  441             switch (*aKeys)
  442             {
  443             case '^':
  444                 if (!(persistent_modifiers_for_this_SendKeys & (MOD_LCONTROL|MOD_RCONTROL)))
  445                     mods_for_next_key |= MOD_LCONTROL;
  446                 // else don't add it, because the value of mods_for_next_key may also used to determine
  447                 // which keys to release after the key to which this modifier applies is sent.
  448                 // We don't want persistent modifiers to ever be released because that's how
  449                 // AutoIt2 behaves and it seems like a reasonable standard.
  450                 continue;
  451             case '+':
  452                 if (!(persistent_modifiers_for_this_SendKeys & (MOD_LSHIFT|MOD_RSHIFT)))
  453                     mods_for_next_key |= MOD_LSHIFT;
  454                 continue;
  455             case '!':
  456                 if (!(persistent_modifiers_for_this_SendKeys & (MOD_LALT|MOD_RALT)))
  457                     mods_for_next_key |= MOD_LALT;
  458                 continue;
  459             case '#':
  460                 if (!(persistent_modifiers_for_this_SendKeys & (MOD_LWIN|MOD_RWIN)))
  461                     mods_for_next_key |= MOD_LWIN;
  462                 continue;
  463             case '}': continue;  // Important that these be ignored.  Be very careful about changing this, see below.
  464             case '{':
  465             {
  466                 if (   !(end_pos = _tcschr(aKeys + 1, '}'))   ) // Ignore it and due to rarity, don't reset mods_for_next_key.
  467                     continue; // This check is relied upon by some things below that assume a '}' is present prior to the terminator.
  468                 aKeys = omit_leading_whitespace(aKeys + 1); // v1.0.43: Skip leading whitespace inside the braces to be more flexible.
  469                 if (   !(key_text_length = end_pos - aKeys)   )
  470                 {
  471                     if (end_pos[1] == '}')
  472                     {
  473                         // The literal string "{}}" has been encountered, which is interpreted as a single "}".
  474                         ++end_pos;
  475                         key_text_length = 1;
  476                     }
  477                     else if (IS_SPACE_OR_TAB(end_pos[1])) // v1.0.48: Support "{} down}", "{} downtemp}" and "{} up}".
  478                     {
  479                         next_word = omit_leading_whitespace(end_pos + 1);
  480                         if (   !_tcsnicmp(next_word, _T("Down"), 4) // "Down" or "DownTemp" (or likely enough).
  481                             || !_tcsnicmp(next_word, _T("Up"), 2)   )
  482                         {
  483                             if (   !(end_pos = _tcschr(next_word, '}'))   ) // See comments at similar section above.
  484                                 continue;
  485                             key_text_length = end_pos - aKeys; // This result must be non-zero due to the checks above.
  486                         }
  487                         else
  488                             goto brace_case_end;  // The loop's ++aKeys will now skip over the '}', ignoring it.
  489                     }
  490                     else // Empty braces {} were encountered (or all whitespace, but literal whitespace isn't sent).
  491                         goto brace_case_end;  // The loop's ++aKeys will now skip over the '}', ignoring it.
  492                 }
  493 
  494                 if (!_tcsnicmp(aKeys, _T("Click"), 5))
  495                 {
  496                     *end_pos = '\0';  // Temporarily terminate the string here to omit the closing brace from consideration below.
  497                     ParseClickOptions(omit_leading_whitespace(aKeys + 5), click_x, click_y, vk
  498                         , event_type, repeat_count, move_offset);
  499                     *end_pos = '}';  // Undo temp termination.
  500                     if (repeat_count < 1) // Allow {Click 100, 100, 0} to do a mouse-move vs. click (but modifiers like ^{Click..} aren't supported in this case.
  501                         MouseMove(click_x, click_y, placeholder, g.DefaultMouseSpeed, move_offset);
  502                     else // Use SendKey because it supports modifiers (e.g. ^{Click}) SendKey requires repeat_count>=1.
  503                         SendKey(vk, 0, mods_for_next_key, persistent_modifiers_for_this_SendKeys
  504                             , repeat_count, event_type, 0, aTargetWindow, click_x, click_y, move_offset);
  505                     goto brace_case_end; // This {} item completely handled, so move on to next.
  506                 }
  507                 else if (!_tcsnicmp(aKeys, _T("Raw"), 3)) // This is used by auto-replace hotstrings too.
  508                 {
  509                     // As documented, there's no way to switch back to non-raw mode afterward since there's no
  510                     // correct way to support special (non-literal) strings such as {Raw Off} while in raw mode.
  511                     aSendRaw = SCM_RAW;
  512                     goto brace_case_end; // This {} item completely handled, so move on to next.
  513                 }
  514                 else if (!_tcsnicmp(aKeys, _T("Text"), 4)) // Added in v1.1.27
  515                 {
  516                     if (omit_leading_whitespace(aKeys + 4) == end_pos)
  517                         aSendRaw = SCM_RAW_TEXT;
  518                     //else: ignore this {Text something} to reserve for future use.
  519                     goto brace_case_end; // This {} item completely handled, so move on to next.
  520                 }
  521 
  522                 // Since above didn't "goto", this item isn't {Click}.
  523                 event_type = KEYDOWNANDUP;         // Set defaults.
  524                 repeat_count = 1;                  //
  525                 key_name_length = key_text_length; //
  526                 *end_pos = '\0';  // Temporarily terminate the string here to omit the closing brace from consideration below.
  527 
  528                 if (space_pos = StrChrAny(aKeys, _T(" \t"))) // Assign. Also, it relies on the fact that {} key names contain no spaces.
  529                 {
  530                     old_char = *space_pos;
  531                     *space_pos = '\0';  // Temporarily terminate here so that TextToVK() can properly resolve a single char.
  532                     key_name_length = space_pos - aKeys; // Override the default value set above.
  533                     next_word = omit_leading_whitespace(space_pos + 1);
  534                     UINT next_word_length = (UINT)(end_pos - next_word);
  535                     if (next_word_length > 0)
  536                     {
  537                         if (!_tcsnicmp(next_word, _T("Down"), 4))
  538                         {
  539                             event_type = KEYDOWN;
  540                             // v1.0.44.05: Added key_down_is_persistent (which is not initialized except here because
  541                             // it's only applicable when event_type==KEYDOWN).  It avoids the following problem:
  542                             // When a key is remapped to become a modifier (such as F1::Control), launching one of
  543                             // the script's own hotkeys via F1 would lead to bad side-effects if that hotkey uses
  544                             // the Send command. This is because the Send command assumes that any modifiers pressed
  545                             // down by the script itself (such as Control) are intended to stay down during all
  546                             // keystrokes generated by that script. To work around this, something like KeyWait F1
  547                             // would otherwise be needed. within any hotkey triggered by the F1 key.
  548                             if (!_tcsnicmp(next_word + 4, _T("Temp"), 4)) // "DownTemp" means non-persistent.
  549                                 key_down_type = KEYDOWN_TEMP;
  550                             else if (toupper(next_word[4] == 'R')) // "DownR" means treated as a physical modifier (R = remap); i.e. not kept down during Send, but restored after Send (unlike Temp).
  551                                 key_down_type = KEYDOWN_REMAP;
  552                             else
  553                                 key_down_type = KEYDOWN_PERSISTENT;
  554                         }
  555                         else if (!_tcsicmp(next_word, _T("Up")))
  556                             event_type = KEYUP;
  557                         else
  558                             repeat_count = ATOI(next_word);
  559                             // Above: If negative or zero, that is handled further below.
  560                             // There is no complaint for values <1 to support scripts that want to conditionally send
  561                             // zero keystrokes, e.g. Send {a %Count%}
  562                     }
  563                 }
  564 
  565                 TextToVKandSC(aKeys, vk, sc, &mods_for_next_key, sTargetKeybdLayout);
  566 
  567                 if (space_pos)  // undo the temporary termination
  568                     *space_pos = old_char;
  569                 *end_pos = '}';  // undo the temporary termination
  570                 if (repeat_count < 1)
  571                     goto brace_case_end; // Gets rid of one level of indentation. Well worth it.
  572 
  573                 if (vk || sc)
  574                 {
  575                     if (key_as_modifiersLR = KeyToModifiersLR(vk, sc)) // Assign
  576                     {
  577                         if (!aTargetWindow)
  578                         {
  579                             if (event_type == KEYDOWN) // i.e. make {Shift down} have the same effect {ShiftDown}
  580                             {
  581                                 this_event_modifier_down = vk;
  582                                 if (key_down_type == KEYDOWN_PERSISTENT) // v1.0.44.05.
  583                                     sModifiersLR_persistent |= key_as_modifiersLR;
  584                                 else if (key_down_type == KEYDOWN_REMAP) // v1.1.27.00
  585                                     sModifiersLR_remapped |= key_as_modifiersLR;
  586                                 persistent_modifiers_for_this_SendKeys |= key_as_modifiersLR; // v1.0.44.06: Added this line to fix the fact that "DownTemp" should keep the key pressed down after the send.
  587                             }
  588                             else if (event_type == KEYUP) // *not* KEYDOWNANDUP, since that would be an intentional activation of the Start Menu or menu bar.
  589                             {
  590                                 DisguiseWinAltIfNeeded(vk);
  591                                 sModifiersLR_persistent &= ~key_as_modifiersLR;
  592                                 sModifiersLR_remapped &= ~key_as_modifiersLR;
  593                                 // By contrast with KEYDOWN, KEYUP should also remove this modifier
  594                                 // from extra_persistent_modifiers_for_blind_mode if it happens to be
  595                                 // in there.  For example, if "#i::Send {LWin Up}" is a hotkey,
  596                                 // LWin should become persistently up in every respect.
  597                                 extra_persistent_modifiers_for_blind_mode &= ~key_as_modifiersLR;
  598                                 // Fix for v1.0.43: Also remove LControl if this key happens to be AltGr.
  599                                 if (vk == VK_RMENU && sTargetLayoutHasAltGr == CONDITION_TRUE) // It is AltGr.
  600                                     extra_persistent_modifiers_for_blind_mode &= ~MOD_LCONTROL;
  601                                 // Since key_as_modifiersLR isn't 0, update to reflect any changes made above:
  602                                 persistent_modifiers_for_this_SendKeys = sModifiersLR_persistent | extra_persistent_modifiers_for_blind_mode;
  603                             }
  604                             // else must never change sModifiersLR_persistent in response to KEYDOWNANDUP
  605                             // because that would break existing scripts.  This is because that same
  606                             // modifier key may have been pushed down via {ShiftDown} rather than "{Shift Down}".
  607                             // In other words, {Shift} should never undo the effects of a prior {ShiftDown}
  608                             // or {Shift down}.
  609                         }
  610                         //else don't add this event to sModifiersLR_persistent because it will not be
  611                         // manifest via keybd_event.  Instead, it will done via less intrusively
  612                         // (less interference with foreground window) via SetKeyboardState() and
  613                         // PostMessage().  This change is for ControlSend in v1.0.21 and has been
  614                         // documented.
  615                     }
  616                     // Below: sModifiersLR_persistent stays in effect (pressed down) even if the key
  617                     // being sent includes that same modifier.  Surprisingly, this is how AutoIt2
  618                     // behaves also, which is good.  Example: Send, {AltDown}!f  ; this will cause
  619                     // Alt to still be down after the command is over, even though F is modified
  620                     // by Alt.
  621                     SendKey(vk, sc, mods_for_next_key, persistent_modifiers_for_this_SendKeys
  622                         , repeat_count, event_type, key_as_modifiersLR, aTargetWindow);
  623                 }
  624 
  625                 else if (key_name_length == 1) // No vk/sc means a char of length one is sent via special method.
  626                 {
  627                     // v1.0.40: SendKeySpecial sends only keybd_event keystrokes, not ControlSend style
  628                     // keystrokes.
  629                     // v1.0.43.07: Added check of event_type!=KEYUP, which causes something like Send {ð up} to
  630                     // do nothing if the curr. keyboard layout lacks such a key.  This is relied upon by remappings
  631                     // such as F1::ð (i.e. a destination key that doesn't have a VK, at least in English).
  632                     if (event_type != KEYUP) // In this mode, mods_for_next_key and event_type are ignored due to being unsupported.
  633                     {
  634                         if (aTargetWindow)
  635                         {
  636                             // Although MSDN says WM_CHAR uses UTF-16, it seems to really do automatic
  637                             // translation between ANSI and UTF-16; we rely on this for correct results:
  638                             for (int i = 0; i < repeat_count; ++i)
  639                                 PostMessage(aTargetWindow, WM_CHAR, aKeys[0], 0);
  640                         }
  641                         else
  642                             SendKeySpecial(aKeys[0], repeat_count, mods_for_next_key | persistent_modifiers_for_this_SendKeys);
  643                     }
  644                 }
  645 
  646                 // See comment "else must never change sModifiersLR_persistent" above about why
  647                 // !aTargetWindow is used below:
  648                 else if (vk = TextToSpecial(aKeys, key_text_length, event_type
  649                     , persistent_modifiers_for_this_SendKeys, !aTargetWindow)) // Assign.
  650                 {
  651                     if (!aTargetWindow)
  652                     {
  653                         if (event_type == KEYDOWN)
  654                             this_event_modifier_down = vk;
  655                         else // It must be KEYUP because TextToSpecial() never returns KEYDOWNANDUP.
  656                             DisguiseWinAltIfNeeded(vk);
  657                     }
  658                     // Since we're here, repeat_count > 0.
  659                     // v1.0.42.04: A previous call to SendKey() or SendKeySpecial() might have left modifiers
  660                     // in the wrong state (e.g. Send +{F1}{ControlDown}).  Since modifiers can sometimes affect
  661                     // each other, make sure they're in the state intended by the user before beginning:
  662                     SetModifierLRState(persistent_modifiers_for_this_SendKeys
  663                         , sSendMode ? sEventModifiersLR : GetModifierLRState()
  664                         , aTargetWindow, false, false); // It also does DoKeyDelay(g->PressDuration).
  665                     for (int i = 0; i < repeat_count; ++i)
  666                     {
  667                         // Don't tell it to save & restore modifiers because special keys like this one
  668                         // should have maximum flexibility (i.e. nothing extra should be done so that the
  669                         // user can have more control):
  670                         KeyEvent(event_type, vk, 0, aTargetWindow, true);
  671                         if (!sSendMode)
  672                             LONG_OPERATION_UPDATE_FOR_SENDKEYS
  673                     }
  674                 }
  675 
  676                 else if (key_text_length > 4 && !_tcsnicmp(aKeys, _T("ASC "), 4) && !aTargetWindow) // {ASC nnnnn}
  677                 {
  678                     // Include the trailing space in "ASC " to increase uniqueness (selectivity).
  679                     // Also, sending the ASC sequence to window doesn't work, so don't even try:
  680                     SendASC(omit_leading_whitespace(aKeys + 3));
  681                     // Do this only once at the end of the sequence:
  682                     DoKeyDelay(); // It knows not to do the delay for SM_INPUT.
  683                 }
  684 
  685                 else if (key_text_length > 2 && !_tcsnicmp(aKeys, _T("U+"), 2))
  686                 {
  687                     // L24: Send a unicode value as shown by Character Map.
  688                     UINT u_code = (UINT) _tcstol(aKeys + 2, NULL, 16);
  689                     wchar_t wc1, wc2;
  690                     if (u_code >= 0x10000)
  691                     {
  692                         // Supplementary characters are encoded as UTF-16 and split into two messages.
  693                         u_code -= 0x10000;
  694                         wc1 = 0xd800 + ((u_code >> 10) & 0x3ff);
  695                         wc2 = 0xdc00 + (u_code & 0x3ff);
  696                     }
  697                     else
  698                     {
  699                         wc1 = (wchar_t) u_code;
  700                         wc2 = 0;
  701                     }
  702                     if (aTargetWindow)
  703                     {
  704                         // Although MSDN says WM_CHAR uses UTF-16, PostMessageA appears to truncate it to 8-bit.
  705                         // This probably means it does automatic translation between ANSI and UTF-16.  Since we
  706                         // specifically want to send a Unicode character value, use PostMessageW:
  707                         PostMessageW(aTargetWindow, WM_CHAR, wc1, 0);
  708                         if (wc2)
  709                             PostMessageW(aTargetWindow, WM_CHAR, wc2, 0);
  710                     }
  711                     else
  712                     {
  713                         // Use SendInput in unicode mode if available, otherwise fall back to SendASC.
  714                         // To know why the following requires sSendMode != SM_PLAY, see SendUnicodeChar.
  715                         if (sSendMode != SM_PLAY)
  716                         {
  717                             SendUnicodeChar(wc1, mods_for_next_key | persistent_modifiers_for_this_SendKeys);
  718                             if (wc2)
  719                                 SendUnicodeChar(wc2, mods_for_next_key | persistent_modifiers_for_this_SendKeys);
  720                         }
  721                         else // Note that this method generally won't work with Unicode characters except
  722                         {    // with specific controls which support it, such as RichEdit (tested on WordPad).
  723                             TCHAR asc[8];
  724                             *asc = '0';
  725                             _itot(u_code, asc + 1, 10);
  726                             SendASC(asc);
  727                         }
  728                     }
  729                     DoKeyDelay();
  730                 }
  731 
  732                 //else do nothing since it isn't recognized as any of the above "else if" cases (see below).
  733 
  734                 // If what's between {} is unrecognized, such as {Bogus}, it's safest not to send
  735                 // the contents literally since that's almost certainly not what the user intended.
  736                 // In addition, reset the modifiers, since they were intended to apply only to
  737                 // the key inside {}.  Also, the below is done even if repeat-count is zero.
  738 
  739 brace_case_end: // This label is used to simplify the code without sacrificing performance.
  740                 aKeys = end_pos;  // In prep for aKeys++ done by the loop.
  741                 mods_for_next_key = 0;
  742                 continue;
  743             } // case '{'
  744             } // switch()
  745         } // if (!aSendRaw && strchr("^+!#{}", *aKeys))
  746 
  747         else // Encountered a character other than ^+!#{} ... or we're in raw mode.
  748         {
  749             if (aSendRaw == SCM_RAW_TEXT)
  750             {
  751                 // \b needs to produce VK_BACK for auto-replace hotstrings to work (this is more useful anyway).
  752                 // \r and \n need to produce VK_RETURN for decent compatibility.  SendKeySpecial('\n') works for
  753                 // some controls (such as Scintilla) but has no effect in other common applications.
  754                 // \t has more utility if translated to VK_TAB.  SendKeySpecial('\t') has no effect in many
  755                 // common cases, and seems to only work in cases where {tab} would work just as well.
  756                 switch (*aKeys)
  757                 {
  758                 case '\r': // Translate \r but ignore any trailing \n, since \r\n -> {Enter 2} is counter-intuitive.
  759                     if (aKeys[1] == '\n')
  760                         ++aKeys;
  761                     // Fall through:
  762                 case '\n': vk = VK_RETURN; break;
  763                 case '\b': vk = VK_BACK; break;
  764                 case '\t': vk = VK_TAB; break;
  765                 default: vk = 0; break; // Send all other characters via SendKeySpecial()/WM_CHAR.
  766                 }
  767             }
  768             else
  769             {
  770                 // Best to call this separately, rather than as first arg in SendKey, since it changes the
  771                 // value of modifiers and the updated value is *not* guaranteed to be passed.
  772                 // In other words, SendKey(TextToVK(...), modifiers, ...) would often send the old
  773                 // value for modifiers.
  774                 vk = CharToVKAndModifiers(*aKeys, &mods_for_next_key, sTargetKeybdLayout
  775                     , (mods_for_next_key | persistent_modifiers_for_this_SendKeys) != 0 && !aSendRaw); // v1.1.27.00: Disable the a-z to vk41-vk5A fallback translation when modifiers are present since it would produce the wrong printable characters.
  776                 // CharToVKAndModifiers() takes no measurable time compared to the amount of time SendKey takes.
  777             }
  778             if (vk)
  779                 SendKey(vk, 0, mods_for_next_key, persistent_modifiers_for_this_SendKeys, 1, KEYDOWNANDUP
  780                     , 0, aTargetWindow);
  781             else // Try to send it by alternate means.
  782             {
  783                 // In this mode, mods_for_next_key is ignored due to being unsupported.
  784                 if (aTargetWindow) 
  785                     // Although MSDN says WM_CHAR uses UTF-16, it seems to really do automatic
  786                     // translation between ANSI and UTF-16; we rely on this for correct results:
  787                     PostMessage(aTargetWindow, WM_CHAR, *aKeys, 0);
  788                 else
  789                     SendKeySpecial(*aKeys, 1, mods_for_next_key | persistent_modifiers_for_this_SendKeys);
  790             }
  791             mods_for_next_key = 0;  // Safest to reset this regardless of whether a key was sent.
  792         }
  793     } // for()
  794 
  795     modLR_type mods_to_set;
  796     if (sSendMode)
  797     {
  798         int final_key_delay = -1;  // Set default.
  799         if (!sAbortArraySend && sEventCount > 0) // Check for zero events for performance, but more importantly because playback hook will not operate correctly with zero.
  800         {
  801             // Add more events to the array (prior to sending) to support the following:
  802             // Restore the modifiers to match those the user is physically holding down, but do it as *part*
  803             // of the single SendInput/Play call.  The reasons it's done here as part of the array are:
  804             // 1) It avoids the need for #HotkeyModifierTimeout (and it's superior to it) for both SendInput
  805             //    and SendPlay.
  806             // 2) The hook will not be present during the SendInput, nor can it be reinstalled in time to
  807             //    catch any physical events generated by the user during the Send. Consequently, there is no
  808             //    known way to reliably detect physical keystate changes.
  809             // 3) Changes made to modifier state by SendPlay are seen only by the active window's thread.
  810             //    Thus, it would be inconsistent and possibly incorrect to adjust global modifier state
  811             //    after (or during) a SendPlay.
  812             // So rather than resorting to #HotkeyModifierTimeout, we can restore the modifiers within the
  813             // protection of SendInput/Play's uninterruptibility, allowing the user's buffered keystrokes
  814             // (if any) to hit against the correct modifier state when the SendInput/Play completes.
  815             // For example, if #c:: is a hotkey and the user releases Win during the SendInput/Play, that
  816             // release would hit after SendInput/Play restores Win to the down position, and thus Win would
  817             // not be stuck down.  Furthermore, if the user didn't release Win, Win would be in the
  818             // correct/intended position.
  819             // This approach has a few weaknesses (but the strengths appear to outweigh them):
  820             // 1) Hitting SendInput's 5000 char limit would omit the tail-end keystrokes, which would mess up
  821             //    all the assumptions here.  But hitting that limit should be very rare, especially since it's
  822             //    documented and thus scripts will avoid it.
  823             // 2) SendInput's assumed uninterruptibility is false if any other app or script has an LL hook
  824             //    installed.  This too is documented, so scripts should generally avoid using SendInput when
  825             //    they know there are other LL hooks in the system.  In any case, there's no known solution
  826             //    for it, so nothing can be done.
  827             mods_to_set = persistent_modifiers_for_this_SendKeys
  828                 | sModifiersLR_remapped // Restore any modifiers which were put in the down state by remappings or {key DownR} prior to this Send.
  829                 | (sInBlindMode ? 0 : (mods_down_physically_orig & ~mods_down_physically_but_not_logically_orig)); // The last item is usually 0.
  830             // Above: When in blind mode, don't restore physical modifiers.  This is done to allow a hotkey
  831             // such as the following to release Shift:
  832             //    +space::SendInput/Play {Blind}{Shift up}
  833             // Note that SendPlay can make such a change only from the POV of the target window; i.e. it can
  834             // release shift as seen by the target window, but not by any other thread; so the shift key would
  835             // still be considered to be down for the purpose of firing hotkeys (it can't change global key state
  836             // as seen by GetAsyncKeyState).
  837             // For more explanation of above, see a similar section for the non-array/old Send below.
  838             SetModifierLRState(mods_to_set, sEventModifiersLR, NULL, true, true); // Disguise in case user released or pressed Win/Alt during the Send (seems best to do it even for SendPlay, though it probably needs only Alt, not Win).
  839             // mods_to_set is used further below as the set of modifiers that were explicitly put into effect at the tail end of SendInput.
  840             SendEventArray(final_key_delay, mods_to_set);
  841         }
  842         CleanupEventArray(final_key_delay);
  843     }
  844     else // A non-array send is in effect, so a more elaborate adjustment to logical modifiers is called for.
  845     {
  846         // Determine (or use best-guess, if necessary) which modifiers are down physically now as opposed
  847         // to right before the Send began.
  848         modLR_type mods_down_physically; // As compared to mods_down_physically_orig.
  849         if (g_KeybdHook)
  850             mods_down_physically = g_modifiersLR_physical;
  851         else // No hook, so consult g_HotkeyModifierTimeout to make the determination.
  852             // Assume that the same modifiers that were phys+logically down before the Send are still
  853             // physically down (though not necessarily logically, since the Send may have released them),
  854             // but do this only if the timeout period didn't expire (or the user specified that it never
  855             // times out; i.e. elapsed time < timeout-value; DWORD subtraction gives the right answer even if
  856             // tick-count has wrapped around).
  857             mods_down_physically = (g_HotkeyModifierTimeout < 0 // It never times out or...
  858                 || (GetTickCount() - g_script.mThisHotkeyStartTime) < (DWORD)g_HotkeyModifierTimeout) // It didn't time out.
  859                 ? mods_down_physically_orig : 0;
  860 
  861         // Put any modifiers in sModifiersLR_remapped back into effect, as if they were physically down.
  862         mods_down_physically |= sModifiersLR_remapped;
  863 
  864         // Restore the state of the modifiers to be those the user is physically holding down right now.
  865         // Any modifiers that are logically "persistent", as detected upon entrance to this function
  866         // (e.g. due to something such as a prior "Send, {LWinDown}"), are also pushed down if they're not already.
  867         // Don't press back down the modifiers that were used to trigger this hotkey if there's
  868         // any doubt that they're still down, since doing so when they're not physically down
  869         // would cause them to be stuck down, which might cause unwanted behavior when the unsuspecting
  870         // user resumes typing.
  871         // v1.0.42.04: Now that SendKey() is lazy about releasing Ctrl and/or Shift (but not Win/Alt),
  872         // the section below also releases Ctrl/Shift if appropriate.  See SendKey() for more details.
  873         mods_to_set = persistent_modifiers_for_this_SendKeys; // Set default.
  874         if (sInBlindMode) // This section is not needed for the array-sending modes because they exploit uninterruptibility to perform a more reliable restoration.
  875         {
  876             // At the end of a blind-mode send, modifiers are restored differently than normal. One
  877             // reason for this is to support the explicit ability for a Send to turn off a hotkey's
  878             // modifiers even if the user is still physically holding them down.  For example:
  879             //   #space::Send {LWin up}  ; Fails to release it, by design and for backward compatibility.
  880             //   #space::Send {Blind}{LWin up}  ; Succeeds, allowing LWin to be logically up even though it's physically down.
  881             modLR_type mods_changed_physically_during_send = mods_down_physically_orig ^ mods_down_physically;
  882             // Fix for v1.0.42.04: To prevent keys from getting stuck down, compensate for any modifiers
  883             // the user physically pressed or released during the Send (especially those released).
  884             // Remove any modifiers physically released during the send so that they don't get pushed back down:
  885             mods_to_set &= ~(mods_changed_physically_during_send & mods_down_physically_orig); // Remove those that changed from down to up.
  886             // Conversely, add any modifiers newly, physically pressed down during the Send, because in
  887             // most cases the user would want such modifiers to be logically down after the Send.
  888             // Obsolete comment from v1.0.40: For maximum flexibility and minimum interference while
  889             // in blind mode, never restore modifiers to the down position then.
  890             mods_to_set |= mods_changed_physically_during_send & mods_down_physically; // Add those that changed from up to down.
  891         }
  892         else // Regardless of whether the keyboard hook is present, the following formula applies.
  893             mods_to_set |= mods_down_physically & ~mods_down_physically_but_not_logically_orig; // The second item is usually 0.
  894             // Above takes into account the fact that the user may have pressed and/or released some modifiers
  895             // during the Send.
  896             // So it includes all keys that are physically down except those that were down physically but not
  897             // logically at the *start* of the send operation (since the send operation may have changed the
  898             // logical state).  In other words, we want to restore the keys to their former logical-down
  899             // position to match the fact that the user is still holding them down physically.  The
  900             // previously-down keys we don't do this for are those that were physically but not logically down,
  901             // such as a naked Control key that's used as a suffix without being a prefix.  More details:
  902             // mods_down_physically_but_not_logically_orig is used to distinguish between the following two cases,
  903             // allowing modifiers to be properly restored to the down position when the hook is installed:
  904             // 1) A naked modifier key used only as suffix: when the user phys. presses it, it isn't
  905             //    logically down because the hook suppressed it.
  906             // 2) A modifier that is a prefix, that triggers a hotkey via a suffix, and that hotkey sends
  907             //    that modifier.  The modifier will go back up after the SEND, so the key will be physically
  908             //    down but not logically.
  909 
  910         // Use KEY_IGNORE_ALL_EXCEPT_MODIFIER to tell the hook to adjust g_modifiersLR_logical_non_ignored
  911         // because these keys being put back down match the physical pressing of those same keys by the
  912         // user, and we want such modifiers to be taken into account for the purpose of deciding whether
  913         // other hotkeys should fire (or the same one again if auto-repeating):
  914         // v1.0.42.04: A previous call to SendKey() might have left Shift/Ctrl in the down position
  915         // because by procrastinating, extraneous keystrokes in examples such as "Send ABCD" are
  916         // eliminated (previously, such that example released the shift key after sending each key,
  917         // only to have to press it down again for the next one.  For this reason, some modifiers
  918         // might get released here in addition to any that need to get pressed down.  That's why
  919         // SetModifierLRState() is called rather than the old method of pushing keys down only,
  920         // never releasing them.
  921         // Put the modifiers in mods_to_set into effect.  Although "true" is passed to disguise up-events,
  922         // there generally shouldn't be any up-events for Alt or Win because SendKey() would have already
  923         // released them.  One possible exception to this is when the user physically released Alt or Win
  924         // during the send (perhaps only during specific sensitive/vulnerable moments).
  925         // g_modifiersLR_numpad_mask is used to work around an issue where our changes to shift-key state
  926         // trigger the system's shift-numpad handling (usually in combination with actual user input),
  927         // which in turn causes the Shift key to stick down.  If non-zero, the Shift key is currently "up"
  928         // but should be "released" anyway, since the system will inject Shift-down either before the next
  929         // keyboard event or after the Numpad key is released.  Find "fake shift" for more details.
  930         SetModifierLRState(mods_to_set, GetModifierLRState() | g_modifiersLR_numpad_mask, aTargetWindow, true, true); // It also does DoKeyDelay(g->PressDuration).
  931     } // End of non-array Send.
  932 
  933     // For peace of mind and because that's how it was tested originally, the following is done
  934     // only after adjusting the modifier state above (since that adjustment might be able to
  935     // affect the global variables used below in a meaningful way).
  936     if (g_KeybdHook)
  937     {
  938         // Ensure that g_modifiersLR_logical_non_ignored does not contain any down-modifiers
  939         // that aren't down in g_modifiersLR_logical.  This is done mostly for peace-of-mind,
  940         // since there might be ways, via combinations of physical user input and the Send
  941         // commands own input (overlap and interference) for one to get out of sync with the
  942         // other.  The below uses ^ to find the differences between the two, then uses & to
  943         // find which are down in non_ignored that aren't in logical, then inverts those bits
  944         // in g_modifiersLR_logical_non_ignored, which sets those keys to be in the up position:
  945         g_modifiersLR_logical_non_ignored &= ~((g_modifiersLR_logical ^ g_modifiersLR_logical_non_ignored)
  946             & g_modifiersLR_logical_non_ignored);
  947     }
  948 
  949     if (prior_capslock_state == TOGGLED_ON) // The current user setting requires us to turn it back on.
  950         ToggleKeyState(VK_CAPITAL, TOGGLED_ON);
  951 
  952     // Might be better to do this after changing capslock state, since having the threads attached
  953     // tends to help with updating the global state of keys (perhaps only under Win9x in this case):
  954     if (threads_are_attached)
  955         AttachThreadInput(g_MainThreadID, target_thread, FALSE);
  956 
  957     if (do_selective_blockinput && !blockinput_prev) // Turn it back off only if it was off before we started.
  958         Line::ScriptBlockInput(false);
  959 
  960     // The following MsgSleep(-1) solves unwanted buffering of hotkey activations while SendKeys is in progress
  961     // in a non-Critical thread.  Because SLEEP_WITHOUT_INTERRUPTION is used to perform key delays, any incoming
  962     // hotkey messages would be left in the queue.  It is not until the next interruptible sleep that hotkey
  963     // messages may be processed, and potentially discarded due to #MaxThreadsPerHotkey (even #MaxThreadsBuffer
  964     // should only allow one buffered activation).  But if the hotkey thread just calls Send in a loop and then
  965     // returns, it never performs an interruptible sleep, so the hotkey messages are processed one by one after
  966     // each new hotkey thread returns, even though Critical was not used.  Also note SLEEP_WITHOUT_INTERRUPTION
  967     // causes g_script.mLastScriptRest to be reset, so it's unlikely that a sleep would occur between Send calls.
  968     // To solve this, call MsgSleep(-1) now (unless no delays were performed, or the thread is uninterruptible):
  969     if (aSendModeOrig == SM_EVENT && g_script.mLastScriptRest != orig_last_script_rest && IsInterruptible())
  970         MsgSleep(-1);
  971 
  972     // v1.0.43.03: Someone reported that when a non-autoreplace hotstring calls us to do its backspacing, the
  973     // hotstring's subroutine can execute a command that activates another window owned by the script before
  974     // the original window finished receiving its backspaces.  Although I can't reproduce it, this behavior
  975     // fits with expectations since our thread won't necessarily have a chance to process the incoming
  976     // keystrokes before executing the command that comes after SendInput.  If those command(s) activate
  977     // another of this thread's windows, that window will most likely intercept the keystrokes (assuming
  978     // that the message pump dispatches buffered keystrokes to whichever window is active at the time the
  979     // message is processed).
  980     // This fix does not apply to the SendPlay or SendEvent modes, the former due to the fact that it sleeps
  981     // a lot while the playback is running, and the latter due to key-delay and because testing has never shown
  982     // a need for it.
  983     if (aSendModeOrig == SM_INPUT && GetWindowThreadProcessId(GetForegroundWindow(), NULL) == g_MainThreadID) // GetWindowThreadProcessId() tolerates a NULL hwnd.
  984         SLEEP_WITHOUT_INTERRUPTION(-1);
  985 
  986     // v1.0.43.08: Restore the original thread key-delay values in case above temporarily overrode them.
  987     g.KeyDelay = orig_key_delay;
  988     g.PressDuration = orig_press_duration;
  989 }
  990 
  991 
  992 
  993 void SendKey(vk_type aVK, sc_type aSC, modLR_type aModifiersLR, modLR_type aModifiersLRPersistent
  994     , int aRepeatCount, KeyEventTypes aEventType, modLR_type aKeyAsModifiersLR, HWND aTargetWindow
  995     , int aX, int aY, bool aMoveOffset)
  996 // Caller has ensured that: 1) vk or sc may be zero, but not both; 2) aRepeatCount > 0.
  997 // This function is responsible for first setting the correct state of the modifier keys
  998 // (as specified by the caller) before sending the key.  After sending, it should put the
  999 // modifier keys  back to the way they were originally (UPDATE: It does this only for Win/Alt
 1000 // for the reasons described near the end of this function).
 1001 {
 1002     // Caller is now responsible for verifying this:
 1003     // Avoid changing modifier states and other things if there is nothing to be sent.
 1004     // Otherwise, menu bar might activated due to ALT keystrokes that don't modify any key,
 1005     // the Start Menu might appear due to WIN keystrokes that don't modify anything, etc:
 1006     //if ((!aVK && !aSC) || aRepeatCount < 1)
 1007     //  return;
 1008 
 1009     // I thought maybe it might be best not to release unwanted modifier keys that are already down
 1010     // (perhaps via something like "Send, {altdown}{esc}{altup}"), but that harms the case where
 1011     // modifier keys are down somehow, unintentionally: The send command wouldn't behave as expected.
 1012     // e.g. "Send, abc" while the control key is held down by other means, would send ^a^b^c,
 1013     // possibly dangerous.  So it seems best to default to making sure all modifiers are in the
 1014     // proper down/up position prior to sending any Keybd events.  UPDATE: This has been changed
 1015     // so that only modifiers that were actually used to trigger that hotkey are released during
 1016     // the send.  Other modifiers that are down may be down intentionally, e.g. due to a previous
 1017     // call to Send such as: Send {ShiftDown}.
 1018     // UPDATE: It seems best to save the initial state only once, prior to sending the key-group,
 1019     // because only at the beginning can the original state be determined without having to
 1020     // save and restore it in each loop iteration.
 1021     // UPDATE: Not saving and restoring at all anymore, due to interference (side-effects)
 1022     // caused by the extra keybd events.
 1023 
 1024     // The combination of aModifiersLR and aModifiersLRPersistent are the modifier keys that
 1025     // should be down prior to sending the specified aVK/aSC. aModifiersLR are the modifiers
 1026     // for this particular aVK keystroke, but aModifiersLRPersistent are the ones that will stay
 1027     // in pressed down even after it's sent.
 1028     modLR_type modifiersLR_specified = aModifiersLR | aModifiersLRPersistent;
 1029     bool vk_is_mouse = IsMouseVK(aVK); // Caller has ensured that VK is non-zero when it wants a mouse click.
 1030 
 1031     LONG_OPERATION_INIT
 1032     for (int i = 0; i < aRepeatCount; ++i)
 1033     {
 1034         if (!sSendMode)
 1035             LONG_OPERATION_UPDATE_FOR_SENDKEYS  // This does not measurably affect the performance of SendPlay/Event.
 1036         // These modifiers above stay in effect for each of these keypresses.
 1037         // Always on the first iteration, and thereafter only if the send won't be essentially
 1038         // instantaneous.  The modifiers are checked before every key is sent because
 1039         // if a high repeat-count was specified, the user may have time to release one or more
 1040         // of the modifier keys that were used to trigger a hotkey.  That physical release
 1041         // will cause a key-up event which will cause the state of the modifiers, as seen
 1042         // by the system, to change.  For example, if user releases control-key during the operation,
 1043         // some of the D's won't be control-D's:
 1044         // ^c::Send,^{d 15}
 1045         // Also: Seems best to do SetModifierLRState() even if Keydelay < 0:
 1046         // Update: If this key is itself a modifier, don't change the state of the other
 1047         // modifier keys just for it, since most of the time that is unnecessary and in
 1048         // some cases, the extra generated keystrokes would cause complications/side-effects.
 1049         if (!aKeyAsModifiersLR)
 1050         {
 1051             // DISGUISE UP: Pass "true" to disguise UP-events on WIN and ALT due to hotkeys such as:
 1052             // !a::Send test
 1053             // !a::Send {LButton}
 1054             // v1.0.40: It seems okay to tell SetModifierLRState to disguise Win/Alt regardless of
 1055             // whether our caller is in blind mode.  This is because our caller already put any extra
 1056             // blind-mode modifiers into modifiersLR_specified, which prevents any actual need to
 1057             // disguise anything (only the release of Win/Alt is ever disguised).
 1058             // DISGUISE DOWN: Pass "false" to avoid disguising DOWN-events on Win and Alt because Win/Alt
 1059             // will be immediately followed by some key for them to "modify".  The exceptions to this are
 1060             // when aVK is a mouse button (e.g. sending !{LButton} or #{LButton}).  But both of those are
 1061             // so rare that the flexibility of doing exactly what the script specifies seems better than
 1062             // a possibly unwanted disguising.  Also note that hotkeys such as #LButton automatically use
 1063             // both hooks so that the Start Menu doesn't appear when the Win key is released, so we're
 1064             // not responsible for that type of disguising here.
 1065             SetModifierLRState(modifiersLR_specified, sSendMode ? sEventModifiersLR : GetModifierLRState()
 1066                 , aTargetWindow, false, true, g->SendLevel ? KEY_IGNORE_LEVEL(g->SendLevel) : KEY_IGNORE); // See keyboard_mouse.h for explanation of KEY_IGNORE.
 1067             // Above: Fixed for v1.1.27 to use KEY_IGNORE except when SendLevel is non-zero (since that
 1068             // would indicate that the script probably wants to trigger a hotkey).  KEY_IGNORE is used
 1069             // (and was prior to v1.1.06.00) to prevent the temporary modifier state changes here from
 1070             // interfering with the use of hotkeys while a Send is in progress.
 1071             // SetModifierLRState() also does DoKeyDelay(g->PressDuration).
 1072         }
 1073 
 1074         // v1.0.42.04: Mouse clicks are now handled here in the same loop as keystrokes so that the modifiers
 1075         // will be readjusted (above) if the user presses/releases modifier keys during the mouse clicks.
 1076         if (vk_is_mouse && !aTargetWindow)
 1077             MouseClick(aVK, aX, aY, 1, g->DefaultMouseSpeed, aEventType, aMoveOffset);
 1078             // Above: Since it's rare to send more than one click, it seems best to simplify and reduce code size
 1079             // by not doing more than one click at a time event when mode is SendInput/Play.
 1080         else
 1081             // Sending mouse clicks via ControlSend is not supported, so in that case fall back to the
 1082             // old method of sending the VK directly (which probably has no effect 99% of the time):
 1083             KeyEvent(aEventType, aVK, aSC, aTargetWindow, true, KEY_IGNORE_LEVEL(g->SendLevel));
 1084     } // for() [aRepeatCount]
 1085 
 1086     // The final iteration by the above loop does a key or mouse delay (KeyEvent and MouseClick do it internally)
 1087     // prior to us changing the modifiers below.  This is a good thing because otherwise the modifiers would
 1088     // sometimes be released so soon after the keys they modify that the modifiers are not in effect.
 1089     // This can be seen sometimes when/ ctrl-shift-tabbing back through a multi-tabbed dialog:
 1090     // The last ^+{tab} might otherwise not take effect because the CTRL key would be released too quickly.
 1091 
 1092     // Release any modifiers that were pressed down just for the sake of the above
 1093     // event (i.e. leave any persistent modifiers pressed down).  The caller should
 1094     // already have verified that aModifiersLR does not contain any of the modifiers
 1095     // in aModifiersLRPersistent.  Also, call GetModifierLRState() again explicitly
 1096     // rather than trying to use a saved value from above, in case the above itself
 1097     // changed the value of the modifiers (i.e. aVk/aSC is a modifier).  Admittedly,
 1098     // that would be pretty strange but it seems the most correct thing to do (another
 1099     // reason is that the user may have pressed or released modifier keys during the
 1100     // final mouse/key delay that was done above).
 1101     if (!aKeyAsModifiersLR) // See prior use of this var for explanation.
 1102     {
 1103         // It seems best not to use KEY_IGNORE_ALL_EXCEPT_MODIFIER in this case, though there's
 1104         // a slight chance that a script or two might be broken by not doing so.  The chance
 1105         // is very slight because the only thing KEY_IGNORE_ALL_EXCEPT_MODIFIER would allow is
 1106         // something like the following example.  Note that the hotkey below must be a hook
 1107         // hotkey (even more rare) because registered hotkeys will still see the logical modifier
 1108         // state and thus fire regardless of whether g_modifiersLR_logical_non_ignored says that
 1109         // they shouldn't:
 1110         // #b::Send, {CtrlDown}{AltDown}
 1111         // $^!a::MsgBox You pressed the A key after pressing the B key.
 1112         // In the above, making ^!a a hook hotkey prevents it from working in conjunction with #b.
 1113         // UPDATE: It seems slightly better to have it be KEY_IGNORE_ALL_EXCEPT_MODIFIER for these reasons:
 1114         // 1) Persistent modifiers are fairly rare.  When they're in effect, it's usually for a reason
 1115         //    and probably a pretty good one and from a user who knows what they're doing.
 1116         // 2) The condition that g_modifiersLR_logical_non_ignored was added to fix occurs only when
 1117         //    the user physically presses a suffix key (or auto-repeats one by holding it down)
 1118         //    during the course of a SendKeys() operation.  Since the persistent modifiers were
 1119         //    (by definition) already in effect prior to the Send, putting them back down for the
 1120         //    purpose of firing hook hotkeys does not seem unreasonable, and may in fact add value.
 1121         // DISGUISE DOWN: When SetModifierLRState() is called below, it should only release keys, not press
 1122         // any down (except if the user's physical keystrokes interfered).  Therefore, passing true or false
 1123         // for the disguise-down-events parameter doesn't matter much (but pass "true" in case the user's
 1124         // keystrokes did interfere in a way that requires a Alt or Win to be pressed back down, because
 1125         // disguising it seems best).
 1126         // DISGUISE UP: When SetModifierLRState() is called below, it is passed "false" for disguise-up
 1127         // to avoid generating unnecessary disguise-keystrokes.  They are not needed because if our keystrokes
 1128         // were modified by either WIN or ALT, the release of the WIN or ALT key will already be disguised due to
 1129         // its having modified something while it was down.  The exceptions to this are when aVK is a mouse button
 1130         // (e.g. sending !{LButton} or #{LButton}).  But both of those are so rare that the flexibility of doing
 1131         // exactly what the script specifies seems better than a possibly unwanted disguising.
 1132         // UPDATE for v1.0.42.04: Only release Win and Alt (if appropriate), not Ctrl and Shift, since we know
 1133         // Win/Alt don't have to be disguised but our caller would have trouble tracking that info or making that
 1134         // determination.  This avoids extra keystrokes, while still procrastinating the release of Ctrl/Shift so
 1135         // that those can be left down if the caller's next keystroke happens to need them.
 1136         modLR_type state_now = sSendMode ? sEventModifiersLR : GetModifierLRState();
 1137         modLR_type win_alt_to_be_released = (state_now & ~aModifiersLRPersistent) // The modifiers to be released...
 1138             & (MOD_LWIN|MOD_RWIN|MOD_LALT|MOD_RALT); // ... but restrict them to only Win/Alt.
 1139         if (win_alt_to_be_released)
 1140         {
 1141             // Originally used the following for mods new/now: state_now & ~win_alt_to_be_released, state_now
 1142             // When AltGr is to be released, the above formula passes LCtrl+RAlt as the current state and just
 1143             // LCtrl as the new state, which results in LCtrl being pushed back down after it is released via
 1144             // AltGr.  Although our caller releases LCtrl if needed, it usually uses KEY_IGNORE, so if we put
 1145             // LCtrl down here, it would be wrongly stuck down in g_modifiersLR_logical_non_ignored, which
 1146             // causes ^-modified hotkeys to fire when they shouldn't and prevents non-^ hotkeys from firing.
 1147             // By ignoring the current modifier state and only specifying the modifiers we want released,
 1148             // we avoid any chance of sending any unwanted key-down:
 1149             SetModifierLRState(0, win_alt_to_be_released, aTargetWindow, true, false); // It also does DoKeyDelay(g->PressDuration).
 1150         }
 1151     }
 1152 }
 1153 
 1154 
 1155 
 1156 void SendKeySpecial(TCHAR aChar, int aRepeatCount, modLR_type aModifiersLR)
 1157 // Caller must be aware that keystrokes are sent directly (i.e. never to a target window via ControlSend mode).
 1158 // It must also be aware that the event type KEYDOWNANDUP is always what's used since there's no way
 1159 // to support anything else.  Furthermore, there's no way to support "modifiersLR_for_next_key" such as ^€
 1160 // (assuming € is a character for which SendKeySpecial() is required in the current layout) with ASC mode.
 1161 // This function uses some of the same code as SendKey() above, so maintain them together.
 1162 {
 1163     // Caller must verify that aRepeatCount >= 1.
 1164     // Avoid changing modifier states and other things if there is nothing to be sent.
 1165     // Otherwise, menu bar might activated due to ALT keystrokes that don't modify any key,
 1166     // the Start Menu might appear due to WIN keystrokes that don't modify anything, etc:
 1167     //if (aRepeatCount < 1)
 1168     //  return;
 1169 
 1170     // v1.0.40: This function was heavily simplified because the old method of simulating
 1171     // characters via dead keys apparently never executed under any keyboard layout.  It never
 1172     // got past the following on the layouts I tested (Russian, German, Danish, Spanish):
 1173     //      if (!send1 && !send2) // Can't simulate aChar.
 1174     //          return;
 1175     // This might be partially explained by the fact that the following old code always exceeded
 1176     // the bounds of the array (because aChar was always between 0 and 127), so it was never valid
 1177     // in the first place:
 1178     //      asc_int = cAnsiToAscii[(int)((aChar - 128) & 0xff)] & 0xff;
 1179 
 1180     // Producing ANSI characters via Alt+Numpad and a leading zero appears standard on most languages
 1181     // and layouts (at least those whose active code page is 1252/Latin 1 US/Western Europe).  However,
 1182     // Russian (code page 1251 Cyrillic) is apparently one exception as shown by the fact that sending
 1183     // all of the characters above Chr(127) while under Russian layout produces Cyrillic characters
 1184     // if the active window's focused control is an Edit control (even if its an ANSI app).
 1185     // I don't know the difference between how such characters are actually displayed as opposed to how
 1186     // they're stored in memory (in notepad at least, there appears to be some kind of on-the-fly
 1187     // translation to Unicode as shown when you try to save such a file).  But for now it doesn't matter
 1188     // because for backward compatibility, it seems best not to change it until some alternative is
 1189     // discovered that's high enough in value to justify breaking existing scripts that run under Russian
 1190     // and other non-code-page-1252 layouts.
 1191     //
 1192     // Production of ANSI characters above 127 has been tested on both Windows XP and 98se (but not the
 1193     // Win98 command prompt).
 1194 
 1195     bool use_sendasc = sSendMode == SM_PLAY; // See SendUnicodeChar for why it isn't called for SM_PLAY.
 1196     TCHAR asc_string[16];
 1197     WCHAR wc;
 1198 
 1199     if (use_sendasc)
 1200     {
 1201         // The following range isn't checked because this function appears never to be called for such
 1202         // characters (tested in English and Russian so far), probably because VkKeyScan() finds a way to
 1203         // manifest them via Control+VK combinations:
 1204         //if (aChar > -1 && aChar < 32)
 1205         //  return;
 1206         TCHAR *cp = asc_string;
 1207         if (aChar & ~127)    // Try using ANSI.
 1208             *cp++ = '0';  // ANSI mode is achieved via leading zero in the Alt+Numpad keystrokes.
 1209         //else use Alt+Numpad without the leading zero, which allows the characters a-z, A-Z, and quite
 1210         // a few others to be produced in Russian and perhaps other layouts, which was impossible in versions
 1211         // prior to 1.0.40.
 1212         _itot((TBYTE)aChar, cp, 10); // Convert to UCHAR in case aChar < 0.
 1213     }
 1214     else
 1215     {
 1216 #ifdef UNICODE
 1217         wc = aChar;
 1218 #else
 1219         // Convert our ANSI character to Unicode for sending.
 1220         if (!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &aChar, 1, &wc, 1))
 1221             return;
 1222 #endif
 1223     }
 1224 
 1225     LONG_OPERATION_INIT
 1226     for (int i = 0; i < aRepeatCount; ++i)
 1227     {
 1228         if (!sSendMode)
 1229             LONG_OPERATION_UPDATE_FOR_SENDKEYS
 1230         if (use_sendasc)
 1231             SendASC(asc_string);
 1232         else
 1233             SendUnicodeChar(wc, aModifiersLR);
 1234         DoKeyDelay(); // It knows not to do the delay for SM_INPUT.
 1235     }
 1236 
 1237     // It is not necessary to do SetModifierLRState() to put a caller-specified set of persistent modifier
 1238     // keys back into effect because:
 1239     // 1) Our call to SendASC above (if any) at most would have released some of the modifiers (though never
 1240     //    WIN because it isn't necessary); but never pushed any new modifiers down (it even releases ALT
 1241     //    prior to returning).
 1242     // 2) Our callers, if they need to push ALT back down because we didn't do it, will either disguise it
 1243     //    or avoid doing so because they're about to send a keystroke (just about anything) that ALT will
 1244     //    modify and thus not need to be disguised.
 1245 }
 1246 
 1247 
 1248 
 1249 void SendASC(LPCTSTR aAscii)
 1250 // Caller must be aware that keystrokes are sent directly (i.e. never to a target window via ControlSend mode).
 1251 // aAscii is a string to support explicit leading zeros because sending 216, for example, is not the same as
 1252 // sending 0216.  The caller is also responsible for restoring any desired modifier keys to the down position
 1253 // (this function needs to release some of them if they're down).
 1254 {
 1255     // UPDATE: In v1.0.42.04, the left Alt key is always used below because:
 1256     // 1) It might be required on Win95/NT (though testing shows that RALT works okay on Windows 98se).
 1257     // 2) It improves maintainability because if the keyboard layout has AltGr, and the Control portion
 1258     //    of AltGr is released without releasing the RAlt portion, anything that expects LControl to
 1259     //    be down whenever RControl is down would be broken.
 1260     // The following test demonstrates that on previous versions under German layout, the right-Alt key
 1261     // portion of AltGr could be used to manifest Alt+Numpad combinations:
 1262     //   Send {RAlt down}{Asc 67}{RAlt up}  ; Should create a C character even when both the active window an AHK are set to German layout.
 1263     //   KeyHistory  ; Shows that the right-Alt key was successfully used rather than the left.
 1264     // Changing the modifier state via SetModifierLRState() (rather than some more error-prone multi-step method)
 1265     // also ensures that the ALT key is pressed down only after releasing any shift key that needed it above.
 1266     // Otherwise, the OS's switch-keyboard-layout hotkey would be triggered accidentally; e.g. the following
 1267     // in English layout: Send ~~âÂ{^}.
 1268     //
 1269     // Make sure modifier state is correct: ALT pressed down and other modifiers UP
 1270     // because CTRL and SHIFT seem to interfere with this technique if they are down,
 1271     // at least under WinXP (though the Windows key doesn't seem to be a problem).
 1272     // Specify KEY_IGNORE so that this action does not affect the modifiers that the
 1273     // hook uses to determine which hotkey should be triggered for a suffix key that
 1274     // has more than one set of triggering modifiers (for when the user is holding down
 1275     // that suffix to auto-repeat it -- see keyboard_mouse.h for details).
 1276     modLR_type modifiersLR_now = sSendMode ? sEventModifiersLR : GetModifierLRState();
 1277     SetModifierLRState((modifiersLR_now | MOD_LALT) & ~(MOD_RALT | MOD_LCONTROL | MOD_RCONTROL | MOD_LSHIFT | MOD_RSHIFT)
 1278         , modifiersLR_now, NULL, false // Pass false because there's no need to disguise the down-event of LALT.
 1279         , true, KEY_IGNORE); // Pass true so that any release of RALT is disguised (Win is never released here).
 1280     // Note: It seems best never to press back down any key released above because the
 1281     // act of doing so may do more harm than good (i.e. the keystrokes may caused
 1282     // unexpected side-effects.
 1283 
 1284     // Known limitation (but obscure): There appears to be some OS limitation that prevents the following
 1285     // AltGr hotkey from working more than once in a row:
 1286     // <^>!i::Send {ASC 97}
 1287     // Key history indicates it's doing what it should, but it doesn't actually work.  You have to press the
 1288     // left-Alt key (not RAlt) once to get the hotkey working again.
 1289 
 1290     // This is not correct because it is possible to generate unicode characters by typing
 1291     // Alt+256 and beyond:
 1292     // int value = ATOI(aAscii);
 1293     // if (value < 0 || value > 255) return 0; // Sanity check.
 1294 
 1295     // Known issue: If the hotkey that triggers this Send command is CONTROL-ALT
 1296     // (and maybe either CTRL or ALT separately, as well), the {ASC nnnn} method
 1297     // might not work reliably due to strangeness with that OS feature, at least on
 1298     // WinXP.  I already tried adding delays between the keystrokes and it didn't help.
 1299 
 1300     // Caller relies upon us to stop upon reaching the first non-digit character:
 1301     for (LPCTSTR cp = aAscii; *cp >= '0' && *cp <= '9'; ++cp)
 1302         // A comment from AutoIt3: ASCII 0 is 48, NUMPAD0 is 96, add on 48 to the ASCII.
 1303         // Also, don't do WinDelay after each keypress in this case because it would make
 1304         // such keys take up to 3 or 4 times as long to send (AutoIt3 avoids doing the
 1305         // delay also).  Note that strings longer than 4 digits are allowed because
 1306         // some or all OSes support Unicode characters 0 through 65535.
 1307         KeyEvent(KEYDOWNANDUP, *cp + 48);
 1308 
 1309     // Must release the key regardless of whether it was already down, so that the sequence will take effect
 1310     // immediately.  Otherwise, our caller might not release the Alt key (since it might need to stay down for
 1311     // other purposes), in which case Alt+Numpad character would never appear and the caller's subsequent
 1312     // keystrokes might get absorbed by the OS's special state of "waiting for Alt+Numpad sequence to complete".
 1313     // Another reason is that the user may be physically holding down Alt, in which case the caller might never
 1314     // release it.  In that case, we want the Alt+Numpad character to appear immediately rather than waiting for
 1315     // the user to release Alt (in the meantime, the caller will likely press Alt back down to match the physical
 1316     // state).
 1317     KeyEvent(KEYUP, VK_MENU);
 1318 }
 1319 
 1320 
 1321 
 1322 LRESULT CALLBACK PlaybackProc(int aCode, WPARAM wParam, LPARAM lParam)
 1323 // Journal playback hook.
 1324 {
 1325     static bool sThisEventHasBeenLogged, sThisEventIsScreenCoord;
 1326 
 1327     switch (aCode)
 1328     {
 1329     case HC_GETNEXT:
 1330     {
 1331         if (sFirstCallForThisEvent)
 1332         {
 1333             // Gather the delay(s) for this event, if any, and calculate the time the keystroke should be sent.
 1334             // NOTE: It must be done this way because testing shows that simply returning the desired delay
 1335             // for the first call of each event is not reliable, at least not for the first few events (they
 1336             // tend to get sent much more quickly than specified).  More details:
 1337             // MSDN says, "When the system ...calls the hook procedure [after the first time] with code set to
 1338             // HC_GETNEXT to retrieve the same message... the return value... should be zero."
 1339             // Apparently the above is overly cautious wording with the intent to warn people not to write code
 1340             // that gets stuck in infinite playback due to never returning 0, because returning non-zero on
 1341             // calls after the first works fine as long as 0 is eventually returned.  Furthermore, I've seen
 1342             // other professional code examples that uses this "countdown" approach, so it seems valid.
 1343             sFirstCallForThisEvent = false;
 1344             sThisEventHasBeenLogged = false;
 1345             sThisEventIsScreenCoord = false;
 1346             for (sThisEventTime = GetTickCount()
 1347                 ; !sEventPB[sCurrentEvent].message // HC_SKIP has ensured there is a non-delay event, so no need to check sCurrentEvent < sEventCount.
 1348                 ; sThisEventTime += sEventPB[sCurrentEvent++].time_to_wait); // Overflow is okay.
 1349         }
 1350         // Above has ensured that sThisEventTime is valid regardless of whether this is the first call
 1351         // for this event.  It has also incremented sCurrentEvent, if needed, for use below.
 1352 
 1353         // Copy the current mouse/keyboard event to the EVENTMSG structure (lParam).
 1354         // MSDN says that HC_GETNEXT can be received multiple times consecutively, in which case the
 1355         // same event should be copied into the structure each time.
 1356         PlaybackEvent &source_event = sEventPB[sCurrentEvent];
 1357         EVENTMSG &event = *(PEVENTMSG)lParam;  // For convenience, maintainability, and possibly performance.
 1358         // Currently, the following isn't documented entirely accurately at MSDN, but other sources confirm
 1359         // the below are the proper values to store.  In addition, the extended flag as set below has been
 1360         // confirmed to work properly by monitoring the resulting WM_KEYDOWN message in a main message loop.
 1361         //
 1362         // Strip off extra bits early for maintainability.  It must be stripped off the source event itself
 1363         // because if HC_GETNEXT is called again for this same event, don't want to apply the offset again.
 1364         bool has_coord_offset;
 1365         if (has_coord_offset = source_event.message & MSG_OFFSET_MOUSE_MOVE)
 1366             source_event.message &= ~MSG_OFFSET_MOUSE_MOVE;
 1367         event.message = source_event.message;
 1368         // The following members are not set because testing confirms that they're ignored:
 1369         // event.hwnd: ignored even if assigned the HWND of an existing window or control.
 1370         // event.time: Apparently ignored in favor of this playback proc's return value.  Furthermore,
 1371         // testing shows that the posted keystroke message (e.g. WM_KEYDOWN) has the correct timestamp
 1372         // even when event.time is left as a random time, which shows that the member is completely
 1373         // ignored during playback, at least on XP.
 1374         bool is_keyboard_not_mouse;
 1375         if (is_keyboard_not_mouse = (source_event.message >= WM_KEYFIRST && source_event.message <= WM_KEYLAST)) // Keyboard event.
 1376         {
 1377             event.paramL = (source_event.sc << 8) | source_event.vk;
 1378             event.paramH = source_event.sc & 0xFF; // 0xFF omits the extended-key-bit, if present.
 1379             if (source_event.sc & 0x100) // It's an extended key.
 1380                 event.paramH |= 0x8000; // So mark it that way using EVENTMSG's convention.
 1381             // Notes about inability of playback to simulate LWin and RWin in a way that performs their native function:
 1382             // For the following reasons, it seems best not to send LWin/RWin via keybd_event inside the playback hook:
 1383             // 1) Complexities such as having to check for an array that consists entirely of LWin/RWin events,
 1384             //    in which case the playback hook mustn't be activated because it requires that we send
 1385             //    at least one event through it.  Another complexity is that all keys modified by Win would
 1386             //    have to be flagged in the array as needing to be sent via keybd_event.
 1387             // 2) It might preserve some flexibility to be able to send LWin/RWin events directly to a window,
 1388             //    similar to ControlSend (perhaps for shells other than Explorer, who might allow apps to make
 1389             //    use of LWin/RWin internally). The window should receive LWIN/RWIN as WM_KEYDOWN messages when
 1390             //    sent via playback.  Note: unlike the neutral SHIFT/ALT/CTRL keys, which are detectible via the
 1391             //    target thread's call to GetKeyState(), LWin and RWin aren't detectible that way.
 1392             // 3) Code size and complexity.
 1393             //
 1394             // Related: LWin and RWin are released and pressed down during playback for simplicity and also
 1395             // on the off-chance the target window takes note of the incoming WM_KEYDOWN on VK_LWIN/RWIN and
 1396             // changes state until the up-event is received (however, the target thread's call of GetKeyState
 1397             // can't see a any effect for hook-sent LWin/RWin).
 1398             //
 1399             // Related: If LWin or RWin is logically down at start of SendPlay, SendPlay's events won't be
 1400             // able to release it from the POV of the target thread's calls to GetKeyState().  That might mess
 1401             // things up for apps that check the logical state of the Win keys.  But due to rarity: in those
 1402             // cases, a workaround would be to do an explicit old-style Send {Blind} (as the first line of the
 1403             // hotkey) to release the modifier logically prior to SendPlay commands.
 1404             //
 1405             // Related: Although some apps might not like receiving SendPlay's LWin/RWin if shell==Explorer
 1406             // (since there may be no normal way for such keystrokes to arrive as WM_KEYDOWN events) maybe it's
 1407             // best not to omit/ignore LWin/RWin if it is possible in other shells, or adds flexibility.
 1408             // After all, sending {LWin/RWin} via hook should be rare, especially if it has no effect (except
 1409             // for cases where a Win hotkey releases LWin as part of SendPlay, but even that can be worked
 1410             // around via an explicit Send {Blind}{LWin up} beforehand).
 1411         }
 1412         else // MOUSE EVENT.
 1413         {
 1414             // Unlike keybd_event() and SendInput(), explicit coordinates must be specified for each mouse event.
 1415             // The builder of this array must ensure that coordinates are valid or set to COORD_UNSPECIFIED_SHORT.
 1416             if (source_event.x == COORD_UNSPECIFIED_SHORT || has_coord_offset)
 1417             {
 1418                 // For simplicity with calls such as CoordToScreen(), the one who set up this array has ensured
 1419                 // that both X and Y are either COORD_UNSPECIFIED_SHORT or not so (i.e. not a combination).
 1420                 // Since the user nor anything else can move the cursor during our playback, GetCursorPos()
 1421                 // should accurately reflect the position set by any previous mouse-move done by this playback.
 1422                 // This seems likely to be true even for DirectInput games, though hasn't been tested yet.
 1423                 POINT cursor;
 1424                 GetCursorPos(&cursor);
 1425                 event.paramL = cursor.x;
 1426                 event.paramH = cursor.y;
 1427                 if (has_coord_offset) // The specified coordinates are offsets to be applied to the cursor's current position.
 1428                 {
 1429                     event.paramL += source_event.x;
 1430                     event.paramH += source_event.y;
 1431                     // Update source array in case HC_GETNEXT is called again for this same event, in which case
 1432                     // don't want to apply the offset again (the has-offset flag has already been removed from the
 1433                     // source event higher above).
 1434                     source_event.x = event.paramL;
 1435                     source_event.y = event.paramH;
 1436                     sThisEventIsScreenCoord = true; // Mark the above as absolute vs. relative in case HC_GETNEXT is called again for this event.
 1437                 }
 1438             }
 1439             else
 1440             {
 1441                 event.paramL = source_event.x;
 1442                 event.paramH = source_event.y;
 1443                 if (!sThisEventIsScreenCoord) // Coordinates are relative to the window that is active now (during realtime playback).
 1444                     CoordToScreen((int &)event.paramL, (int &)event.paramH, COORD_MODE_MOUSE); // Playback uses screen coords.
 1445             }
 1446         }
 1447         LRESULT time_until_event = (int)(sThisEventTime - GetTickCount()); // Cast to int to avoid loss of negatives from DWORD subtraction.
 1448         if (time_until_event > 0)
 1449             return time_until_event;
 1450         // Otherwise, the event is scheduled to occur immediately (or is overdue).  In case HC_GETNEXT can be
 1451         // called multiple times even when we previously returned 0, ensure the event is logged only once.
 1452         if (!sThisEventHasBeenLogged && is_keyboard_not_mouse) // Mouse events aren't currently logged for consistency with other send methods.
 1453         {
 1454             // The event is logged here rather than higher above so that its timestamp is accurate.
 1455             // It's also so that events aren't logged if the user cancel's the operation in the middle
 1456             // (by pressing Ctrl-Alt-Del or Ctrl-Esc).
 1457             UpdateKeyEventHistory(source_event.message == WM_KEYUP || source_event.message == WM_SYSKEYUP
 1458                 , source_event.vk, source_event.sc);
 1459             sThisEventHasBeenLogged = true;
 1460         }
 1461         return 0; // No CallNextHookEx(). See comments further below.
 1462     } // case HC_GETNEXT.
 1463 
 1464     case HC_SKIP: // Advance to the next mouse/keyboard event, if any.
 1465         // Advance to the next item, which is either a delay or an event (preps for next HC_GETNEXT).
 1466         ++sCurrentEvent;
 1467         // Although caller knows it has to do the tail-end delay (if any) since there's no way to
 1468         // do a trailing delay at the end of playback, it may have put a delay at the end of the
 1469         // array anyway for code simplicity.  For that reason and maintainability:
 1470         // Skip over any delays that are present to discover if there is a next event.
 1471         UINT u;
 1472         for (u = sCurrentEvent; u < sEventCount && !sEventPB[u].message; ++u);
 1473         if (u == sEventCount) // No more events.
 1474         {
 1475             // MSDN implies in the following statement that it's acceptable (and perhaps preferable in
 1476             // the case of a playback hook) for the hook to unhook itself: "The hook procedure can be in the
 1477             // state of being called by another thread even after UnhookWindowsHookEx returns."
 1478             UnhookWindowsHookEx(g_PlaybackHook);
 1479             g_PlaybackHook = NULL; // Signal the installer of the hook that it's gone now.
 1480             // The following is an obsolete method from pre-v1.0.44.  Do not reinstate it without adding handling
 1481             // to MainWindowProc() to do "g_PlaybackHook = NULL" upon receipt of WM_CANCELJOURNAL.
 1482             // PostMessage(g_hWnd, WM_CANCELJOURNAL, 0, 0); // v1.0.44: Post it to g_hWnd vs. NULL because it's a little safer (SEE COMMENTS in MsgSleep's WM_CANCELJOURNAL for why it's almost completely safe with NULL).
 1483             // Above: By using WM_CANCELJOURNAL instead of a custom message, the creator of this hook can easily
 1484             // use a message filter to watch for both a system-generated removal of the hook (via the user
 1485             // pressing Ctrl-Esc. or Ctrl-Alt-Del) or one we generate here (though it's currently not implemented
 1486             // that way because it would prevent journal playback to one of our thread's own windows).
 1487         }
 1488         else
 1489             sFirstCallForThisEvent = true; // Reset to prepare for next HC_GETNEXT.
 1490         return 0; // MSDN: The return value is used only if the hook code is HC_GETNEXT; otherwise, it is ignored.
 1491 
 1492     default:
 1493         // Covers the following cases:
 1494         //case HC_NOREMOVE: // MSDN: An application has called the PeekMessage function with wRemoveMsg set to PM_NOREMOVE, indicating that the message is not removed from the message queue after PeekMessage processing.
 1495         //case HC_SYSMODALON:  // MSDN: A system-modal dialog box is being displayed. Until the dialog box is destroyed, the hook procedure must stop playing back messages.
 1496         //case HC_SYSMODALOFF: // MSDN: A system-modal dialog box has been destroyed. The hook procedure must resume playing back the messages.
 1497         //case(...aCode < 0...): MSDN docs specify that the hook should return in this case.
 1498         //
 1499         // MS gives some sample code at http://support.microsoft.com/default.aspx?scid=KB;EN-US;124835
 1500         // about the proper values to return to avoid hangs on NT (it seems likely that this implementation
 1501         // is compliant enough if you read between the lines).  Their sample code indicates that
 1502         // "return CallNextHook()"  should be done for basically everything except HC_SKIP/HC_GETNEXT, so
 1503         // as of 1.0.43.08, that is what is done here.
 1504         // Testing shows that when a so-called system modal dialog is displayed (even if it isn't the
 1505         // active window) playback stops automatically, probably because the system doesn't call the hook
 1506         // during such times (only a "MsgBox 4096" has been tested so far).
 1507         //
 1508         // The first parameter uses g_PlaybackHook rather than NULL because MSDN says it's merely
 1509         // "currently ignored", but in the older "Win32 hooks" article, it says that the behavior
 1510         // may change in the future.
 1511         return CallNextHookEx(g_PlaybackHook, aCode, wParam, lParam);
 1512         // Except for the cases above, CallNextHookEx() is not called for performance and also because from
 1513         // what I can tell from the MSDN docs and other examples, it is neither required nor desirable to do so
 1514         // during playback's SKIP/GETNEXT.
 1515         // MSDN: The return value is used only if the hook code is HC_GETNEXT; otherwise, it is ignored.
 1516     } // switch().
 1517 
 1518     // Execution should never reach since all cases do their own custom return above.
 1519 }
 1520 
 1521 
 1522 
 1523 #ifdef JOURNAL_RECORD_MODE
 1524 LRESULT CALLBACK RecordProc(int aCode, WPARAM wParam, LPARAM lParam)
 1525 {
 1526     switch (aCode)
 1527     {
 1528     case HC_ACTION:
 1529     {
 1530         EVENTMSG &event = *(PEVENTMSG)lParam;
 1531         PlaybackEvent &dest_event = sEventPB[sEventCount];
 1532         dest_event.message = event.message;
 1533         if (event.message >= WM_MOUSEFIRST && event.message <= WM_MOUSELAST) // Mouse event, including wheel.
 1534         {
 1535             if (event.message != WM_MOUSEMOVE)
 1536             {
 1537                 // WHEEL: No info comes in about which direction the wheel was turned (nor by how many notches).
 1538                 // In addition, it appears impossible to specify such info when playing back the event.
 1539                 // Therefore, playback usually produces downward wheel movement (but upward in some apps like
 1540                 // Visual Studio).
 1541                 dest_event.x = event.paramL;
 1542                 dest_event.y = event.paramH;
 1543                 ++sEventCount;
 1544             }
 1545         }
 1546         else // Keyboard event.
 1547         {
 1548             dest_event.vk = event.paramL & 0x00FF;
 1549             dest_event.sc = (event.paramL & 0xFF00) >> 8;
 1550             if (event.paramH & 0x8000) // Extended key.
 1551                 dest_event.sc |= 0x100;
 1552             if (dest_event.vk == VK_CANCEL) // Ctrl+Break.
 1553             {
 1554                 UnhookWindowsHookEx(g_PlaybackHook);
 1555                 g_PlaybackHook = NULL; // Signal the installer of the hook that it's gone now.
 1556                 // Obsolete method, pre-v1.0.44:
 1557                 //PostMessage(g_hWnd, WM_CANCELJOURNAL, 0, 0); // v1.0.44: Post it to g_hWnd vs. NULL so that it isn't lost when script is displaying a MsgBox or other dialog.
 1558             }
 1559             ++sEventCount;
 1560         }
 1561         break;
 1562     }
 1563 
 1564     //case HC_SYSMODALON:  // A system-modal dialog box is being displayed. Until the dialog box is destroyed, the hook procedure must stop playing back messages.
 1565     //case HC_SYSMODALOFF: // A system-modal dialog box has been destroyed. The hook procedure must resume playing back the messages.
 1566     //  break;
 1567     }
 1568 
 1569     // Unlike the playback hook, it seems more correct to call CallNextHookEx() unconditionally so that
 1570     // any other journal record hooks can also record the event.  But MSDN is quite vague about this.
 1571     return CallNextHookEx(g_PlaybackHook, aCode, wParam, lParam);
 1572     // Return value is ignored, except possibly when aCode < 0 (MSDN is unclear).
 1573 }
 1574 #endif
 1575 
 1576 
 1577 
 1578 void KeyEvent(KeyEventTypes aEventType, vk_type aVK, sc_type aSC, HWND aTargetWindow
 1579     , bool aDoKeyDelay, DWORD aExtraInfo)
 1580 // aSC or aVK (but not both), can be zero to cause the default to be used.
 1581 // For keys like NumpadEnter -- that have a unique scancode but a non-unique virtual key --
 1582 // caller can just specify the sc.  In addition, the scan code should be specified for keys
 1583 // like NumpadPgUp and PgUp.  In that example, the caller would send the same scan code for
 1584 // both except that PgUp would be extended.   sc_to_vk() would map both of them to the same
 1585 // virtual key, which is fine since it's the scan code that matters to apps that can
 1586 // differentiate between keys with the same vk.
 1587 //
 1588 // Thread-safe: This function is not fully thread-safe because keystrokes can get interleaved,
 1589 // but that's always a risk with anything short of SendInput.  In fact,
 1590 // when the hook ISN'T installed, keystrokes can occur in another thread, causing the key state to
 1591 // change in the middle of KeyEvent, which is the same effect as not having thread-safe key-states
 1592 // such as GetKeyboardState in here.  Also, the odds of both our threads being in here simultaneously
 1593 // is greatly reduced by the fact that the hook thread never passes "true" for aDoKeyDelay, thus
 1594 // its calls should always be very fast.  Even if a collision does occur, there are thread-safety
 1595 // things done in here that should reduce the impact to nearly as low as having a dedicated
 1596 // KeyEvent function solely for calling by the hook thread (which might have other problems of its own).
 1597 {
 1598     if (!(aVK | aSC)) // MUST USE BITWISE-OR (see comment below).
 1599         return;
 1600     // The above implements the rule "if neither VK nor SC was specified, return".  But they must be done as
 1601     // bitwise-OR rather than logical-AND/OR, otherwise MSVC++ 7.1 generates 16KB of extra OBJ size for some reason.
 1602     // That results in an 2 KB increase in compressed EXE size, and I think about 6 KB uncompressed.
 1603     // I tried all kids of variations and reconfigurations, but the above is the only simple one that works.
 1604     // Strangely, the same logic above (but with the preferred logical-AND/OR operator) appears elsewhere in the
 1605     // code but doesn't bloat there.  Examples:
 1606     //   !aVK && !aSC
 1607     //   !vk && !sc
 1608     //   !(aVK || aSC)
 1609 
 1610     if (!aExtraInfo) // Shouldn't be called this way because 0 is considered false in some places below (search on " = aExtraInfo" to find them).
 1611         aExtraInfo = KEY_IGNORE_ALL_EXCEPT_MODIFIER; // Seems slightly better to use a standard default rather than something arbitrary like 1.
 1612 
 1613     // Since calls from the hook thread could come in even while the SendInput array is being constructed,
 1614     // don't let those events get interspersed with the script's explicit use of SendInput.
 1615     bool caller_is_keybd_hook = (GetCurrentThreadId() == g_HookThreadID);
 1616     bool put_event_into_array = sSendMode && !caller_is_keybd_hook;
 1617     if (sSendMode == SM_INPUT || caller_is_keybd_hook) // First check is necessary but second is just for maintainability.
 1618         aDoKeyDelay = false;
 1619 
 1620     // Even if the sc_to_vk() mapping results in a zero-value vk, don't return.
 1621     // I think it may be valid to send keybd_events that have a zero vk.
 1622     // In any case, it's unlikely to hurt anything:
 1623     if (!aVK)
 1624         aVK = sc_to_vk(aSC);
 1625     else
 1626         if (!aSC)
 1627             // In spite of what the MSDN docs say, the scan code parameter *is* used, as evidenced by
 1628             // the fact that the hook receives the proper scan code as sent by the below, rather than
 1629             // zero like it normally would.  Even though the hook would try to use MapVirtualKey() to
 1630             // convert zero-value scan codes, it's much better to send it here also for full compatibility
 1631             // with any apps that may rely on scan code (and such would be the case if the hook isn't
 1632             // active because the user doesn't need it; also for some games maybe).
 1633             aSC = vk_to_sc(aVK);
 1634 
 1635     BYTE aSC_lobyte = LOBYTE(aSC);
 1636     DWORD event_flags = HIBYTE(aSC) ? KEYEVENTF_EXTENDEDKEY : 0;
 1637 
 1638     // v1.0.43: Apparently, the journal playback hook requires neutral modifier keystrokes
 1639     // rather than left/right ones.  Otherwise, the Shift key can't capitalize letters, etc.
 1640     if (sSendMode == SM_PLAY)
 1641     {
 1642         switch(aVK)
 1643         {
 1644         case VK_LCONTROL:
 1645         case VK_RCONTROL: aVK = VK_CONTROL; break; // But leave scan code set to a left/right specific value rather than converting it to "left" unconditionally.
 1646         case VK_LSHIFT:
 1647         case VK_RSHIFT: aVK = VK_SHIFT; break;
 1648         case VK_LMENU:
 1649         case VK_RMENU: aVK = VK_MENU; break;
 1650         }
 1651     }
 1652 
 1653     // aTargetWindow is almost always passed in as NULL by our caller, even if the overall command
 1654     // being executed is ControlSend.  This is because of the following reasons:
 1655     // 1) Modifiers need to be logically changed via keybd_event() when using ControlSend against
 1656     //    a cmd-prompt, console, or possibly other types of windows.
 1657     // 2) If a hotkey triggered the ControlSend that got us here and that hotkey is a naked modifier
 1658     //    such as RAlt:: or modified modifier such as ^#LShift, that modifier would otherwise auto-repeat
 1659     //    an possibly interfere with the send operation.  This auto-repeat occurs because unlike a normal
 1660     //    send, there are no calls to keybd_event() (keybd_event() stop the auto-repeat as a side-effect).
 1661     // One exception to this is something like "ControlSend, Edit1, {Control down}", which explicitly
 1662     // calls us with a target window.  This exception is by design and has been bug-fixed and documented
 1663     // in ControlSend for v1.0.21:
 1664     if (aTargetWindow) // This block shouldn't affect overall thread-safety because hook thread never calls it in this mode.
 1665     {
 1666         if (KeyToModifiersLR(aVK, aSC))
 1667         {
 1668             // When sending modifier keystrokes directly to a window, use the AutoIt3 SetKeyboardState()
 1669             // technique to improve the reliability of changes to modifier states.  If this is not done,
 1670             // sometimes the state of the SHIFT key (and perhaps other modifiers) will get out-of-sync
 1671             // with what's intended, resulting in uppercase vs. lowercase problems (and that's probably
 1672             // just the tip of the iceberg).  For this to be helpful, our caller must have ensured that
 1673             // our thread is attached to aTargetWindow's (but it seems harmless to do the below even if
 1674             // that wasn't done for any reason).  Doing this here in this function rather than at a
 1675             // higher level probably isn't best in terms of performance (e.g. in the case where more
 1676             // than one modifier is being changed, the multiple calls to Get/SetKeyboardState() could
 1677             // be consolidated into one call), but it is much easier to code and maintain this way
 1678             // since many different functions might call us to change the modifier state:
 1679             BYTE state[256];
 1680             GetKeyboardState((PBYTE)&state);
 1681             if (aEventType == KEYDOWN)
 1682                 state[aVK] |= 0x80;
 1683             else if (aEventType == KEYUP)
 1684                 state[aVK] &= ~0x80;
 1685             // else KEYDOWNANDUP, in which case it seems best (for now) not to change the state at all.
 1686             // It's rarely if ever called that way anyway.
 1687 
 1688             // If aVK is a left/right specific key, be sure to also update the state of the neutral key:
 1689             switch(aVK)
 1690             {
 1691             case VK_LCONTROL: 
 1692             case VK_RCONTROL:
 1693                 if ((state[VK_LCONTROL] & 0x80) || (state[VK_RCONTROL] & 0x80))
 1694                     state[VK_CONTROL] |= 0x80;
 1695                 else
 1696                     state[VK_CONTROL] &= ~0x80;
 1697                 break;
 1698             case VK_LSHIFT:
 1699             case VK_RSHIFT:
 1700                 if ((state[VK_LSHIFT] & 0x80) || (state[VK_RSHIFT] & 0x80))
 1701                     state[VK_SHIFT] |= 0x80;
 1702                 else
 1703                     state[VK_SHIFT] &= ~0x80;
 1704                 break;
 1705             case VK_LMENU:
 1706             case VK_RMENU:
 1707                 if ((state[VK_LMENU] & 0x80) || (state[VK_RMENU] & 0x80))
 1708                     state[VK_MENU] |= 0x80;
 1709                 else
 1710                     state[VK_MENU] &= ~0x80;
 1711                 break;
 1712             }
 1713 
 1714             SetKeyboardState((PBYTE)&state);
 1715             // Even after doing the above, we still continue on to send the keystrokes
 1716             // themselves to the window, for greater reliability (same as AutoIt3).
 1717         }
 1718 
 1719         // lowest 16 bits: repeat count: always 1 for up events, probably 1 for down in our case.
 1720         // highest order bits: 11000000 (0xC0) for keyup, usually 00000000 (0x00) for keydown.
 1721         LPARAM lParam = (LPARAM)(aSC << 16);
 1722         if (aEventType != KEYUP)  // i.e. always do it for KEYDOWNANDUP
 1723             PostMessage(aTargetWindow, WM_KEYDOWN, aVK, lParam | 0x00000001);
 1724         // The press-duration delay is done only when this is a down-and-up because otherwise,
 1725         // the normal g->KeyDelay will be in effect.  In other words, it seems undesirable in
 1726         // most cases to do both delays for only "one half" of a keystroke:
 1727         if (aDoKeyDelay && aEventType == KEYDOWNANDUP)
 1728             DoKeyDelay(g->PressDuration); // Since aTargetWindow!=NULL, sSendMode!=SM_PLAY, so no need for to ever use the SendPlay press-duration.
 1729         if (aEventType != KEYDOWN)  // i.e. always do it for KEYDOWNANDUP
 1730             PostMessage(aTargetWindow, WM_KEYUP, aVK, lParam | 0xC0000001);
 1731     }
 1732     else // Keystrokes are to be sent with keybd_event() or the event array rather than PostMessage().
 1733     {
 1734         // The following static variables are intentionally NOT thread-safe because their whole purpose
 1735         // is to watch the combined stream of keystrokes from all our threads.  Due to our threads'
 1736         // keystrokes getting interleaved with the user's and those of other threads, this kind of
 1737         // monitoring is never 100% reliable.  All we can do is aim for an astronomically low chance
 1738         // of failure.
 1739         // Users of the below want them updated only for keybd_event() keystrokes (not PostMessage ones):
 1740         sPrevEventType = aEventType;
 1741         sPrevVK = aVK;
 1742         // Turn off BlockInput momentarily to support sending of the ALT key.
 1743         // Jon Bennett noted: "As many of you are aware BlockInput was "broken" by a SP1 hotfix under
 1744         // Windows XP so that the ALT key could not be sent. I just tried it under XP SP2 and it seems
 1745         // to work again."  In light of this, it seems best to unconditionally and momentarily disable
 1746         // input blocking regardless of which OS is being used.
 1747         // For thread safety, allow block-input modification only by the main thread.  This should avoid
 1748         // any chance that block-input will get stuck on due to two threads simultaneously reading+changing
 1749         // g_BlockInput (changes occur via calls to ScriptBlockInput).
 1750         bool we_turned_blockinput_off = g_BlockInput && (aVK == VK_MENU || aVK == VK_LMENU || aVK == VK_RMENU)
 1751             && !caller_is_keybd_hook; // Ordered for short-circuit performance.
 1752         if (we_turned_blockinput_off)
 1753             Line::ScriptBlockInput(false);
 1754 
 1755         vk_type control_vk;      // When not set somewhere below, these are left uninitialized to help catch bugs.
 1756         HKL target_keybd_layout; //
 1757         ResultType r_mem, &target_layout_has_altgr = caller_is_keybd_hook ? r_mem : sTargetLayoutHasAltGr; // Same as above.
 1758         bool hookable_ralt, lcontrol_was_down, do_detect_altgr;
 1759         if (do_detect_altgr = hookable_ralt = (aVK == VK_RMENU && !put_event_into_array && g_KeybdHook)) // This is an RALT that the hook will be able to monitor.
 1760         {
 1761             if (!caller_is_keybd_hook) // sTargetKeybdLayout is set/valid only by SendKeys().
 1762                 target_keybd_layout = sTargetKeybdLayout;
 1763             else
 1764             {
 1765                 target_keybd_layout = GetFocusedKeybdLayout();
 1766                 target_layout_has_altgr = LayoutHasAltGr(target_keybd_layout); // In the case of this else's "if", target_layout_has_altgr was already set properly higher above.
 1767             }
 1768             if (target_layout_has_altgr != LAYOUT_UNDETERMINED) // This layout's AltGr status is already known with certainty.
 1769                 do_detect_altgr = false; // So don't go through the detection steps here and other places later below.
 1770             else
 1771             {
 1772                 control_vk = VK_LCONTROL;
 1773                 lcontrol_was_down = IsKeyDownAsync(control_vk);
 1774                 // Add extra detection of AltGr if hook is installed, which has been show to be useful for some
 1775                 // scripts where the other AltGr detection methods don't occur in a timely enough fashion.
 1776                 // The following method relies upon the fact that it's impossible for the hook to receive
 1777                 // events from the user while it's processing our keybd_event() here.  This is because
 1778                 // any physical keystrokes that happen to occur at the exact moment of our keybd_event()
 1779                 // will stay queued until the main event loop routes them to the hook via GetMessage().
 1780                 g_HookReceiptOfLControlMeansAltGr = aExtraInfo;
 1781                 // Thread-safe: g_HookReceiptOfLControlMeansAltGr isn't thread-safe, but by its very nature it probably
 1782                 // shouldn't be (ways to do it might introduce an unwarranted amount of complexity and performance loss
 1783                 // given that the odds of collision might be astronomically low in this case, and the consequences too
 1784                 // mild).  The whole point of g_HookReceiptOfLControlMeansAltGr and related altgr things below is to
 1785                 // watch what keystrokes the hook receives in response to simulating a press of the right-alt key.
 1786                 // Due to their global/system nature, keystrokes are never thread-safe in the sense that any process
 1787                 // in the entire system can be sending keystrokes simultaneously with ours.
 1788             }
 1789         }
 1790 
 1791         // Calculated only once for performance (and avoided entirely if not needed):
 1792         modLR_type key_as_modifiersLR = put_event_into_array ? KeyToModifiersLR(aVK, aSC) : 0;
 1793 
 1794         bool do_key_history = !caller_is_keybd_hook // If caller is hook, don't log because it does logs it.
 1795             && sSendMode != SM_PLAY  // In playback mode, the journal hook logs so that timestamps are accurate.
 1796             && (!g_KeybdHook || sSendMode == SM_INPUT); // In the remaining cases, log only when the hook isn't installed or won't be at the time of the event.
 1797 
 1798         if (aEventType != KEYUP)  // i.e. always do it for KEYDOWNANDUP
 1799         {
 1800             if (put_event_into_array)
 1801                 PutKeybdEventIntoArray(key_as_modifiersLR, aVK, aSC, event_flags, aExtraInfo);
 1802             else
 1803             {
 1804                 // In v1.0.35.07, g_IgnoreNextLControlDown/Up was added.
 1805                 // The following global is used to flag as our own the keyboard driver's LControl-down keystroke
 1806                 // that is triggered by RAlt-down (AltGr).  This prevents it from triggering hotkeys such as
 1807                 // "*Control::".  It probably fixes other obscure side-effects and bugs also, since the
 1808                 // event should be considered script-generated even though indirect.  Note: The problem with
 1809                 // having the hook detect AltGr's automatic LControl-down is that the keyboard driver seems
 1810                 // to generate the LControl-down *before* notifying the system of the RAlt-down.  That makes
 1811                 // it impossible for the hook to flag the LControl keystroke in advance, so it would have to
 1812                 // retroactively undo the effects.  But that is impossible because the previous keystroke might
 1813                 // already have wrongly fired a hotkey.
 1814                 if (hookable_ralt && target_layout_has_altgr == CONDITION_TRUE)
 1815                     g_IgnoreNextLControlDown = aExtraInfo; // Must be set prior to keybd_event() to be effective.
 1816                 keybd_event(aVK, aSC_lobyte // naked scan code (the 0xE0 prefix, if any, is omitted)
 1817                     , event_flags, aExtraInfo);
 1818                 // The following is done by us rather than by the hook to avoid problems where:
 1819                 // 1) The hook is removed at a critical point during the operation, preventing the variable from
 1820                 //    being reset to false.
 1821                 // 2) For some reason this AltGr keystroke done above did not cause LControl to go down (perhaps
 1822                 //    because the current keyboard layout doesn't have AltGr as we thought), which would be a bug
 1823                 //    because some other Ctrl keystroke would then be wrongly ignored.
 1824                 g_IgnoreNextLControlDown = 0; // Unconditional reset.
 1825                 if (do_detect_altgr)
 1826                 {
 1827                     do_detect_altgr = false; // Indicate to the KEYUP section later below that detection has already been done.
 1828                     if (g_HookReceiptOfLControlMeansAltGr)
 1829                     {
 1830                         g_HookReceiptOfLControlMeansAltGr = 0; // Must reset promptly in case key-delay below routes physical keystrokes to hook.
 1831                         // The following line is multipurpose:
 1832                         // 1) Retrieves an updated value of target_layout_has_altgr in case the hook just changed it.
 1833                         // 2) If the hook didn't change it, the target keyboard layout doesn't have an AltGr key.
 1834                         //    Only in that case will the following line set it to FALSE (because LayoutHasAltGr only
 1835                         //    changes the value if it's currently undetermined).
 1836                         // Finally, this also updates sTargetLayoutHasAltGr in cases where target_layout_has_altgr
 1837                         // is an alias/reference for it.
 1838                         target_layout_has_altgr = LayoutHasAltGr(target_keybd_layout, CONDITION_FALSE);
 1839                     }
 1840                     else if (!lcontrol_was_down) // i.e. if LControl was already down, this detection method isn't possible.
 1841                         // Called this way, it updates the specified layout as long as keybd_event's call to the hook didn't already determine it to be FALSE or TRUE:
 1842                         target_layout_has_altgr = LayoutHasAltGr(target_keybd_layout, IsKeyDownAsync(control_vk) ? CONDITION_TRUE : CONDITION_FALSE);
 1843                         // Above also updates sTargetLayoutHasAltGr in cases where target_layout_has_altgr is an alias/reference for it.
 1844                 }
 1845             }
 1846 
 1847             if (do_key_history)
 1848                 UpdateKeyEventHistory(false, aVK, aSC); // Should be thread-safe since if no hook means only one thread ever sends keystrokes (with possible exception of mouse hook, but that seems too rare).
 1849         }
 1850         // The press-duration delay is done only when this is a down-and-up because otherwise,
 1851         // the normal g->KeyDelay will be in effect.  In other words, it seems undesirable in
 1852         // most cases to do both delays for only "one half" of a keystroke:
 1853         if (aDoKeyDelay && aEventType == KEYDOWNANDUP) // Hook should never specify a delay, so no need to check if caller is hook.
 1854             DoKeyDelay(sSendMode == SM_PLAY ? g->PressDurationPlay : g->PressDuration); // DoKeyDelay() is not thread safe but since the hook thread should never pass true for aKeyDelay, it shouldn't be an issue.
 1855         if (aEventType != KEYDOWN)  // i.e. always do it for KEYDOWNANDUP
 1856         {
 1857             event_flags |= KEYEVENTF_KEYUP;
 1858             if (put_event_into_array)
 1859                 PutKeybdEventIntoArray(key_as_modifiersLR, aVK, aSC, event_flags, aExtraInfo);
 1860             else
 1861             {
 1862                 if (hookable_ralt && target_layout_has_altgr == CONDITION_TRUE) // See comments in similar section above for details.
 1863                     g_IgnoreNextLControlUp = aExtraInfo; // Must be set prior to keybd_event() to be effective.
 1864                 keybd_event(aVK, aSC_lobyte, event_flags, aExtraInfo);
 1865                 g_IgnoreNextLControlUp = 0; // Unconditional reset (see similar section above).
 1866                 if (do_detect_altgr) // This should be true only when aEventType==KEYUP because otherwise the KEYDOWN event above would have set it to false.
 1867                 {
 1868                     if (g_HookReceiptOfLControlMeansAltGr)
 1869                     {
 1870                         g_HookReceiptOfLControlMeansAltGr = 0; // Must reset promptly in case key-delay below routes physical keystrokes to hook.
 1871                         target_layout_has_altgr = LayoutHasAltGr(target_keybd_layout, CONDITION_FALSE); // See similar section above for comments.
 1872                     }
 1873                     else if (lcontrol_was_down) // i.e. if LControl was already up, this detection method isn't possible.
 1874                         // See similar section above for comments:
 1875                         target_layout_has_altgr = LayoutHasAltGr(target_keybd_layout, IsKeyDownAsync(control_vk) ? CONDITION_FALSE : CONDITION_TRUE);
 1876                 }
 1877             }
 1878             // The following is done to avoid an extraneous artificial {LCtrl Up} later on,
 1879             // since the keyboard driver should insert one in response to this {RAlt Up}:
 1880             if (target_layout_has_altgr && aSC == SC_RALT)
 1881                 sEventModifiersLR &= ~MOD_LCONTROL;
 1882 
 1883             if (do_key_history)
 1884                 UpdateKeyEventHistory(true, aVK, aSC);
 1885         }
 1886 
 1887         if (we_turned_blockinput_off)  // Already made thread-safe by action higher above.
 1888             Line::ScriptBlockInput(true);  // Turn BlockInput back on.
 1889     }
 1890 
 1891     if (aDoKeyDelay) // SM_PLAY also uses DoKeyDelay(): it stores the delay item in the event array.
 1892         DoKeyDelay(); // Thread-safe because only called by main thread in this mode.  See notes above.
 1893 }
 1894 
 1895 
 1896 
 1897 void KeyEventMenuMask(KeyEventTypes aEventType, DWORD aExtraInfo)
 1898 // Send a menu masking key event (use of this function reduces code size).
 1899 {
 1900     KeyEvent(aEventType, g_MenuMaskKeyVK, g_MenuMaskKeySC, NULL, false, aExtraInfo);
 1901 }
 1902 
 1903 
 1904 
 1905 ///////////////////
 1906 // Mouse related //
 1907 ///////////////////
 1908 
 1909 ResultType PerformClick(LPTSTR aOptions)
 1910 {
 1911     int x, y;
 1912     vk_type vk;
 1913     KeyEventTypes event_type;
 1914     int repeat_count;
 1915     bool move_offset;
 1916 
 1917     ParseClickOptions(aOptions, x, y, vk, event_type, repeat_count, move_offset);
 1918     PerformMouseCommon(repeat_count < 1 ? ACT_MOUSEMOVE : ACT_MOUSECLICK // Treat repeat-count<1 as a move (like {click}).
 1919         , vk, x, y, 0, 0, repeat_count, event_type, g->DefaultMouseSpeed, move_offset);
 1920 
 1921     return OK; // For caller convenience.
 1922 }
 1923 
 1924 
 1925 
 1926 void ParseClickOptions(LPTSTR aOptions, int &aX, int &aY, vk_type &aVK, KeyEventTypes &aEventType
 1927     , int &aRepeatCount, bool &aMoveOffset)
 1928 // Caller has trimmed leading whitespace from aOptions, but not necessarily the trailing whitespace.
 1929 // aOptions must be a modifiable string because this function temporarily alters it.
 1930 {
 1931     // Set defaults for all output parameters for caller.
 1932     aX = COORD_UNSPECIFIED;
 1933     aY = COORD_UNSPECIFIED;
 1934     aVK = VK_LBUTTON_LOGICAL; // v1.0.43: Logical vs. physical for {Click} and Click-cmd, in case user has buttons swapped via control panel.
 1935     aEventType = KEYDOWNANDUP;
 1936     aRepeatCount = 1;
 1937     aMoveOffset = false;
 1938 
 1939     TCHAR *next_option, *option_end, orig_char;
 1940     vk_type temp_vk;
 1941 
 1942     for (next_option = aOptions; *next_option; next_option = omit_leading_whitespace(option_end))
 1943     {
 1944         // Allow optional commas to make scripts more readable.  Don't support g_delimiter because StrChrAny
 1945         // below doesn't.
 1946         while (*next_option == ',') // Ignore all commas.
 1947             if (!*(next_option = omit_leading_whitespace(next_option + 1)))
 1948                 goto break_both; // Entire option string ends in a comma.
 1949         // Find the end of this option item:
 1950         if (   !(option_end = StrChrAny(next_option, _T(" \t,")))   )  // Space, tab, comma.
 1951             option_end = next_option + _tcslen(next_option); // Set to position of zero terminator instead.
 1952 
 1953         // Temp termination for IsPureNumeric(), ConvertMouseButton(), and peace-of-mind.
 1954         orig_char = *option_end;
 1955         *option_end = '\0';
 1956 
 1957         // Parameters can occur in almost any order to enhance usability (at the cost of
 1958         // slightly diminishing the ability unambiguously add more parameters in the future).
 1959         // Seems okay to support floats because ATOI() will just omit the decimal portion.
 1960         if (IsPureNumeric(next_option, true, false, true))
 1961         {
 1962             // Any numbers present must appear in the order: X, Y, RepeatCount
 1963             // (optionally with other options between them).
 1964             if (aX == COORD_UNSPECIFIED) // This will be converted into repeat-count if it is later discovered there's no Y coordinate.
 1965                 aX = ATOI(next_option);
 1966             else if (aY == COORD_UNSPECIFIED)
 1967                 aY = ATOI(next_option);
 1968             else // Third number is the repeat-count (but if there's only one number total, that's repeat count too, see further below).
 1969                 aRepeatCount = ATOI(next_option); // If negative or zero, caller knows to handle it as a MouseMove vs. Click.
 1970         }
 1971         else // Mouse button/name and/or Down/Up/Repeat-count is present.
 1972         {
 1973             if (temp_vk = Line::ConvertMouseButton(next_option, true, true))
 1974                 aVK = temp_vk;
 1975             else
 1976             {
 1977                 switch (ctoupper(*next_option))
 1978                 {
 1979                 case 'D': aEventType = KEYDOWN; break;
 1980                 case 'U': aEventType = KEYUP; break;
 1981                 case 'R': aMoveOffset = true; break; // Since it wasn't recognized as the right mouse button, it must have other letters after it, e.g. Rel/Relative.
 1982                 // default: Ignore anything else to reserve them for future use.
 1983                 }
 1984             }
 1985         }
 1986 
 1987         // If the item was not handled by the above, ignore it because it is unknown.
 1988         *option_end = orig_char; // Undo the temporary termination because the caller needs aOptions to be unaltered.
 1989     } // for() each item in option list
 1990 
 1991 break_both:
 1992     if (aX != COORD_UNSPECIFIED && aY == COORD_UNSPECIFIED)
 1993     {
 1994         // When only one number is present (e.g. {Click 2}, it's assumed to be the repeat count.
 1995         aRepeatCount = aX;
 1996         aX = COORD_UNSPECIFIED;
 1997     }
 1998 }
 1999 
 2000 
 2001 
 2002 ResultType PerformMouse(ActionTypeType aActionType, LPTSTR aButton, LPTSTR aX1, LPTSTR aY1, LPTSTR aX2, LPTSTR aY2
 2003     , LPTSTR aSpeed, LPTSTR aOffsetMode, LPTSTR aRepeatCount, LPTSTR aDownUp)
 2004 {
 2005     vk_type vk;
 2006     if (aActionType == ACT_MOUSEMOVE)
 2007         vk = 0;
 2008     else
 2009         // ConvertMouseButton() treats blank as "Left":
 2010         if (   !(vk = Line::ConvertMouseButton(aButton, aActionType == ACT_MOUSECLICK))   )
 2011             vk = VK_LBUTTON; // See below.
 2012             // v1.0.43: Seems harmless (due to rarity) to treat invalid button names as "Left" (keeping in
 2013             // mind that due to loadtime validation, invalid buttons are possible only when the button name is
 2014             // contained in a variable, e.g. MouseClick %ButtonName%.
 2015 
 2016     KeyEventTypes event_type = KEYDOWNANDUP;  // Set defaults.
 2017     int repeat_count = 1;                     //
 2018 
 2019     if (aActionType == ACT_MOUSECLICK)
 2020     {
 2021         if (*aRepeatCount)
 2022             repeat_count = ATOI(aRepeatCount);
 2023         switch(*aDownUp)
 2024         {
 2025         case 'u':
 2026         case 'U':
 2027             event_type = KEYUP;
 2028             break;
 2029         case 'd':
 2030         case 'D':
 2031             event_type = KEYDOWN;
 2032             break;
 2033         // Otherwise, leave it set to the default.
 2034         }
 2035     }
 2036 
 2037     PerformMouseCommon(aActionType, vk
 2038         , *aX1 ? ATOI(aX1) : COORD_UNSPECIFIED  // If no starting coords are specified, mark it as "use the
 2039         , *aY1 ? ATOI(aY1) : COORD_UNSPECIFIED  // current mouse position":
 2040         , *aX2 ? ATOI(aX2) : COORD_UNSPECIFIED  // These two are blank except for dragging.
 2041         , *aY2 ? ATOI(aY2) : COORD_UNSPECIFIED  //
 2042         , repeat_count, event_type
 2043         , *aSpeed ? ATOI(aSpeed) : g->DefaultMouseSpeed
 2044         , ctoupper(*aOffsetMode) == 'R'); // aMoveOffset.
 2045 
 2046     return OK; // For caller convenience.
 2047 }
 2048 
 2049 
 2050 
 2051 void PerformMouseCommon(ActionTypeType aActionType, vk_type aVK, int aX1, int aY1, int aX2, int aY2
 2052     , int aRepeatCount, KeyEventTypes aEventType, int aSpeed, bool aMoveOffset)
 2053 {
 2054     // The maximum number of events, which in this case would be from a MouseClickDrag.  To be conservative
 2055     // (even though INPUT is a much larger struct than PlaybackEvent and SendInput doesn't use mouse-delays),
 2056     // include room for the maximum number of mouse delays too.
 2057     // Drag consists of at most:
 2058     // 1) Move; 2) Delay; 3) Down; 4) Delay; 5) Move; 6) Delay; 7) Delay (dupe); 8) Up; 9) Delay.
 2059     #define MAX_PERFORM_MOUSE_EVENTS 10
 2060     INPUT event_array[MAX_PERFORM_MOUSE_EVENTS]; // Use type INPUT vs. PlaybackEvent since the former is larger (i.e. enough to hold either one).
 2061 
 2062     sSendMode = g->SendMode;
 2063     if (sSendMode == SM_INPUT || sSendMode == SM_INPUT_FALLBACK_TO_PLAY)
 2064     {
 2065         if (SystemHasAnotherMouseHook()) // See similar section in SendKeys() for details.
 2066             sSendMode = (sSendMode == SM_INPUT) ? SM_EVENT : SM_PLAY;
 2067         else
 2068             sSendMode = SM_INPUT; // Resolve early so that other sections don't have to consider SM_INPUT_FALLBACK_TO_PLAY a valid value.
 2069     }
 2070     if (sSendMode) // We're also responsible for setting sSendMode to SM_EVENT prior to returning.
 2071         InitEventArray(event_array, MAX_PERFORM_MOUSE_EVENTS, 0);
 2072 
 2073     // Turn it on unconditionally even if it was on, since Ctrl-Alt-Del might have disabled it.
 2074     // Turn it back off only if it wasn't ON before we started.
 2075     bool blockinput_prev = g_BlockInput;
 2076     bool do_selective_blockinput = (g_BlockInputMode == TOGGLE_MOUSE || g_BlockInputMode == TOGGLE_SENDANDMOUSE)
 2077         && !sSendMode;
 2078     if (do_selective_blockinput) // It seems best NOT to use g_BlockMouseMove for this, since often times the user would want keyboard input to be disabled too, until after the mouse event is done.
 2079         Line::ScriptBlockInput(true); // Turn it on unconditionally even if it was on, since Ctrl-Alt-Del might have disabled it.
 2080 
 2081     switch (aActionType)
 2082     {
 2083     case ACT_MOUSEMOVE:
 2084         DWORD unused;
 2085         MouseMove(aX1, aY1, unused, aSpeed, aMoveOffset); // Does nothing if coords are invalid.
 2086         break;
 2087     case ACT_MOUSECLICK:
 2088         MouseClick(aVK, aX1, aY1, aRepeatCount, aSpeed, aEventType, aMoveOffset); // Does nothing if coords are invalid.
 2089         break;
 2090     case ACT_MOUSECLICKDRAG:
 2091         MouseClickDrag(aVK, aX1, aY1, aX2, aY2, aSpeed, aMoveOffset); // Does nothing if coords are invalid.
 2092         break;
 2093     } // switch()
 2094 
 2095     if (sSendMode)
 2096     {
 2097         int final_key_delay = -1; // Set default.
 2098         if (!sAbortArraySend && sEventCount > 0)
 2099             SendEventArray(final_key_delay, 0); // Last parameter is ignored because keybd hook isn't removed for a pure-mouse SendInput.
 2100         CleanupEventArray(final_key_delay);
 2101     }
 2102 
 2103     if (do_selective_blockinput && !blockinput_prev)  // Turn it back off only if it was off before we started.
 2104         Line::ScriptBlockInput(false);
 2105 }
 2106 
 2107 
 2108 
 2109 void MouseClickDrag(vk_type aVK, int aX1, int aY1, int aX2, int aY2, int aSpeed, bool aMoveOffset)
 2110 {
 2111     // Check if one of the coordinates is missing, which can happen in cases where this was called from
 2112     // a source that didn't already validate it. Can't call Line::ValidateMouseCoords() because that accepts strings.
 2113     if (   (aX1 == COORD_UNSPECIFIED && aY1 != COORD_UNSPECIFIED) || (aX1 != COORD_UNSPECIFIED && aY1 == COORD_UNSPECIFIED)
 2114         || (aX2 == COORD_UNSPECIFIED && aY2 != COORD_UNSPECIFIED) || (aX2 != COORD_UNSPECIFIED && aY2 == COORD_UNSPECIFIED)   )
 2115         return;
 2116 
 2117     // I asked Jon, "Have you discovered that insta-drags almost always fail?" and he said
 2118     // "Yeah, it was weird, absolute lack of drag... Don't know if it was my config or what."
 2119     // However, testing reveals "insta-drags" work ok, at least on my system, so leaving them enabled.
 2120     // User can easily increase the speed if there's any problem:
 2121     //if (aSpeed < 2)
 2122     //  aSpeed = 2;
 2123 
 2124     // v1.0.43: Translate logical buttons into physical ones.  Which physical button it becomes depends
 2125     // on whether the mouse buttons are swapped via the Control Panel.  Note that journal playback doesn't
 2126     // need the swap because every aspect of it is "logical".
 2127     if (aVK == VK_LBUTTON_LOGICAL)
 2128         aVK = sSendMode != SM_PLAY && GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON;
 2129     else if (aVK == VK_RBUTTON_LOGICAL)
 2130         aVK = sSendMode != SM_PLAY && GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON;
 2131 
 2132     // MSDN: If [event_flags] is not MOUSEEVENTF_WHEEL, [MOUSEEVENTF_HWHEEL,] MOUSEEVENTF_XDOWN,
 2133     // or MOUSEEVENTF_XUP, then [event_data] should be zero. 
 2134     DWORD event_down, event_up, event_flags = 0, event_data = 0; // Set defaults for some.
 2135     switch (aVK)
 2136     {
 2137     case VK_LBUTTON:
 2138         event_down = MOUSEEVENTF_LEFTDOWN;
 2139         event_up = MOUSEEVENTF_LEFTUP;
 2140         break;
 2141     case VK_RBUTTON:
 2142         event_down = MOUSEEVENTF_RIGHTDOWN;
 2143         event_up = MOUSEEVENTF_RIGHTUP;
 2144         break;
 2145     case VK_MBUTTON:
 2146         event_down = MOUSEEVENTF_MIDDLEDOWN;
 2147         event_up = MOUSEEVENTF_MIDDLEUP;
 2148         break;
 2149     case VK_XBUTTON1:
 2150     case VK_XBUTTON2:
 2151         event_down = MOUSEEVENTF_XDOWN;
 2152         event_up = MOUSEEVENTF_XUP;
 2153         event_data = (aVK == VK_XBUTTON1) ? XBUTTON1 : XBUTTON2;
 2154         break;
 2155     }
 2156 
 2157     // If the drag isn't starting at the mouse's current position, move the mouse to the specified position:
 2158     if (aX1 != COORD_UNSPECIFIED && aY1 != COORD_UNSPECIFIED)
 2159     {
 2160         // The movement must be a separate event from the click, otherwise it's completely unreliable with
 2161         // SendInput() and probably keybd_event() too.  SendPlay is unknown, but it seems best for
 2162         // compatibility and peace-of-mind to do it for that too.  For example, some apps may be designed
 2163         // to expect mouse movement prior to a click at a *new* position, which is not unreasonable given
 2164         // that this would be the case 99.999% of the time if the user were moving the mouse physically.
 2165         MouseMove(aX1, aY1, event_flags, aSpeed, aMoveOffset); // It calls DoMouseDelay() and also converts aX1 and aY1 to MOUSEEVENTF_ABSOLUTE coordinates.
 2166         // v1.0.43: event_flags was added to improve reliability.  Explanation: Since the mouse was just moved to an
 2167         // explicitly specified set of coordinates, use those coordinates with subsequent clicks.  This has been
 2168         // shown to significantly improve reliability in cases where the user is moving the mouse during the
 2169         // MouseClick/Drag commands.
 2170     }
 2171     MouseEvent(event_flags | event_down, event_data, aX1, aY1); // It ignores aX and aY when MOUSEEVENTF_MOVE is absent.
 2172     DoMouseDelay(); // Inserts delay for all modes except SendInput, for which it does nothing.
 2173     // Now that the mouse button has been pushed down, move the mouse to perform the drag:
 2174     MouseMove(aX2, aY2, event_flags, aSpeed, aMoveOffset); // It calls DoMouseDelay() and also converts aX2 and aY2 to MOUSEEVENTF_ABSOLUTE coordinates.
 2175     DoMouseDelay(); // Duplicate, see below.
 2176     // Above is a *duplicate* delay because MouseMove() already did one. But it seems best to keep it because:
 2177     // 1) MouseClickDrag can be a CPU intensive operation for the target window depending on what it does
 2178     //    during the drag (selecting objects, etc.)  Thus, and extra delay might help a lot of things.
 2179     // 2) It would probably break some existing scripts to remove the delay, due to timing issues.
 2180     // 3) Dragging is pretty rarely used, so the added performance of removing the delay wouldn't be
 2181     //    a big benefit.
 2182     MouseEvent(event_flags | event_up, event_data, aX2, aY2); // It ignores aX and aY when MOUSEEVENTF_MOVE is absent.
 2183     DoMouseDelay();
 2184     // Above line: It seems best to always do this delay too in case the script line that
 2185     // caused us to be called here is followed immediately by another script line which
 2186     // is either another mouse click or something that relies upon this mouse drag
 2187     // having been completed:
 2188 }
 2189 
 2190 
 2191 
 2192 void MouseClick(vk_type aVK, int aX, int aY, int aRepeatCount, int aSpeed, KeyEventTypes aEventType
 2193     , bool aMoveOffset)
 2194 {
 2195     // Check if one of the coordinates is missing, which can happen in cases where this was called from
 2196     // a source that didn't already validate it (such as MouseClick, %x%, %BlankVar%).
 2197     // Allow aRepeatCount<1 to simply "do nothing", because it increases flexibility in the case where
 2198     // the number of clicks is a dereferenced script variable that may sometimes (by intent) resolve to
 2199     // zero or negative.  For backward compatibility, a RepeatCount <1 does not move the mouse (unlike
 2200     // the Click command and Send {Click}).
 2201     if (   (aX == COORD_UNSPECIFIED && aY != COORD_UNSPECIFIED) || (aX != COORD_UNSPECIFIED && aY == COORD_UNSPECIFIED)
 2202         || (aRepeatCount < 1)   )
 2203         return;
 2204 
 2205     DWORD event_flags = 0; // Set default.
 2206 
 2207     if (!(aX == COORD_UNSPECIFIED || aY == COORD_UNSPECIFIED)) // Both coordinates were specified.
 2208     {
 2209         // The movement must be a separate event from the click, otherwise it's completely unreliable with
 2210         // SendInput() and probably keybd_event() too.  SendPlay is unknown, but it seems best for
 2211         // compatibility and peace-of-mind to do it for that too.  For example, some apps may be designed
 2212         // to expect mouse movement prior to a click at a *new* position, which is not unreasonable given
 2213         // that this would be the case 99.999% of the time if the user were moving the mouse physically.
 2214         MouseMove(aX, aY, event_flags, aSpeed, aMoveOffset); // It calls DoMouseDelay() and also converts aX and aY to MOUSEEVENTF_ABSOLUTE coordinates.
 2215         // v1.0.43: event_flags was added to improve reliability.  Explanation: Since the mouse was just moved to an
 2216         // explicitly specified set of coordinates, use those coordinates with subsequent clicks.  This has been
 2217         // shown to significantly improve reliability in cases where the user is moving the mouse during the
 2218         // MouseClick/Drag commands.
 2219     }
 2220     // Above must be done prior to below because initial mouse-move is supported even for wheel turning.
 2221 
 2222     // For wheel turning, if the user activated this command via a hotkey, and that hotkey
 2223     // has a modifier such as CTRL, the user is probably still holding down the CTRL key
 2224     // at this point.  Therefore, there's some merit to the fact that we should release
 2225     // those modifier keys prior to turning the mouse wheel (since some apps disable the
 2226     // wheel or give it different behavior when the CTRL key is down -- for example, MSIE
 2227     // changes the font size when you use the wheel while CTRL is down).  However, if that
 2228     // were to be done, there would be no way to ever hold down the CTRL key explicitly
 2229     // (via Send, {CtrlDown}) unless the hook were installed.  The same argument could probably
 2230     // be made for mouse button clicks: modifier keys can often affect their behavior.  But
 2231     // changing this function to adjust modifiers for all types of events would probably break
 2232     // some existing scripts.  Maybe it can be a script option in the future.  In the meantime,
 2233     // it seems best not to adjust the modifiers for any mouse events and just document that
 2234     // behavior in the MouseClick command.
 2235     switch (aVK)
 2236     {
 2237     case VK_WHEEL_UP:
 2238         MouseEvent(event_flags | MOUSEEVENTF_WHEEL, aRepeatCount * WHEEL_DELTA, aX, aY);  // It ignores aX and aY when MOUSEEVENTF_MOVE is absent.
 2239         return;
 2240     case VK_WHEEL_DOWN:
 2241         MouseEvent(event_flags | MOUSEEVENTF_WHEEL, -(aRepeatCount * WHEEL_DELTA), aX, aY);
 2242         return;
 2243     // v1.0.48: Lexikos: Support horizontal scrolling in Windows Vista and later.
 2244     case VK_WHEEL_LEFT:
 2245         MouseEvent(event_flags | MOUSEEVENTF_HWHEEL, -(aRepeatCount * WHEEL_DELTA), aX, aY);
 2246         return;
 2247     case VK_WHEEL_RIGHT:
 2248         MouseEvent(event_flags | MOUSEEVENTF_HWHEEL, aRepeatCount * WHEEL_DELTA, aX, aY);
 2249         return;
 2250     }
 2251     // Since above didn't return:
 2252 
 2253     // Although not thread-safe, the following static vars seem okay because:
 2254     // 1) This function is currently only called by the main thread.
 2255     // 2) Even if that isn't true, the serialized nature of simulated mouse clicks makes it likely that
 2256     //    the statics will produce the correct behavior anyway.
 2257     // 3) Even if that isn't true, the consequences of incorrect behavior seem minimal in this case.
 2258     static vk_type sWorkaroundVK = 0;
 2259     static LRESULT sWorkaroundHitTest; // Not initialized because the above will be the sole signal of whether the workaround is in progress.
 2260     DWORD event_down, event_up, event_data = 0; // Set default.
 2261     // MSDN: If [event_flags] is not MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP, then [event_data]
 2262     // should be zero. 
 2263 
 2264     // v1.0.43: Translate logical buttons into physical ones.  Which physical button it becomes depends
 2265     // on whether the mouse buttons are swapped via the Control Panel.
 2266     if (aVK == VK_LBUTTON_LOGICAL)
 2267         aVK = sSendMode != SM_PLAY && GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON;
 2268     else if (aVK == VK_RBUTTON_LOGICAL)
 2269         aVK = sSendMode != SM_PLAY && GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON;
 2270 
 2271     switch (aVK)
 2272     {
 2273     case VK_LBUTTON:
 2274     case VK_RBUTTON:
 2275         // v1.0.43 The first line below means: We're not in SendInput/Play mode or we are but this
 2276         // will be the first event inside the array.  The latter case also implies that no initial
 2277         // mouse-move was done above (otherwise there would already be a MouseMove event in the array,
 2278         // and thus the click here wouldn't be the first item).  It doesn't seem necessary to support
 2279         // the MouseMove case above because the workaround generally isn't needed in such situations
 2280         // (see detailed comments below).  Furthermore, if the MouseMove were supported in array-mode,
 2281         // it would require that GetCursorPos() below be conditionally replaced with something like
 2282         // the following (since when in array-mode, the cursor hasn't actually moved *yet*):
 2283         //      CoordToScreen(aX_orig, aY_orig, COORD_MODE_MOUSE);  // Moving mouse relative to the active window.
 2284         // Known limitation: the work-around described below isn't as complete for SendPlay as it is
 2285         // for the other modes: because dragging the title bar of one of this thread's windows with a
 2286         // remap such as F1::LButton doesn't work if that remap uses SendPlay internally (the window
 2287         // gets stuck to the mouse cursor).
 2288         if (   (!sSendMode || !sEventCount) // See above.
 2289             && (aEventType == KEYDOWN || (aEventType == KEYUP && sWorkaroundVK))   ) // i.e. this is a down-only event or up-only event.
 2290         {
 2291             // v1.0.40.01: The following section corrects misbehavior caused by a thread sending
 2292             // simulated mouse clicks to one of its own windows.  A script consisting only of the
 2293             // following two lines can reproduce this issue:
 2294             // F1::LButton
 2295             // F2::RButton
 2296             // The problems came about from the following sequence of events:
 2297             // 1) Script simulates a left-click-down in the title bar's close, minimize, or maximize button.
 2298             // 2) WM_NCLBUTTONDOWN is sent to the window's window proc, which then passes it on to
 2299             //    DefWindowProc or DefDlgProc, which then apparently enters a loop in which no messages
 2300             //    (or a very limited subset) are pumped.
 2301             // 3) Thus, if the user presses a hotkey while the thread is in this state, that hotkey is
 2302             //    queued/buffered until DefWindowProc/DefDlgProc exits its loop.
 2303             // 4) But the buffered hotkey is the very thing that's supposed to exit the loop via sending a
 2304             //    simulated left-click-up event.
 2305             // 5) Thus, a deadlock occurs.
 2306             // 6) A similar situation arises when a right-click-down is sent to the title bar or sys-menu-icon.
 2307             //
 2308             // The following workaround operates by suppressing qualified click-down events until the
 2309             // corresponding click-up occurs, at which time the click-up is transformed into a down+up if the
 2310             // click-up is still in the same cursor position as the down. It seems preferable to fix this here
 2311             // rather than changing each window proc. to always respond to click-down rather vs. click-up
 2312             // because that would make all of the script's windows behave in a non-standard way, possibly
 2313             // producing side-effects and defeating other programs' attempts to interact with them.
 2314             // (Thanks to Shimanov for this solution.)
 2315             //
 2316             // Remaining known limitations:
 2317             // 1) Title bar buttons are not visibly in a pressed down state when a simulated click-down is sent
 2318             //    to them.
 2319             // 2) A window that should not be activated, such as AlwaysOnTop+Disabled, is activated anyway
 2320             //    by SetForegroundWindowEx().  Not yet fixed due to its rarity and minimal consequences.
 2321             // 3) A related problem for which no solution has been discovered (and perhaps it's too obscure
 2322             //    an issue to justify any added code size): If a remapping such as "F1::LButton" is in effect,
 2323             //    pressing and releasing F1 while the cursor is over a script window's title bar will cause the
 2324             //    window to move slightly the next time the mouse is moved.
 2325             // 4) Clicking one of the script's window's title bar with a key/button that has been remapped to
 2326             //    become the left mouse button sometimes causes the button to get stuck down from the window's
 2327             //    point of view.  The reasons are related to those in #1 above.  In both #1 and #2, the workaround
 2328             //    is not at fault because it's not in effect then.  Instead, the issue is that DefWindowProc enters
 2329             //    a non-msg-pumping loop while it waits for the user to drag-move the window.  If instead the user
 2330             //    releases the button without dragging, the loop exits on its own after a 500ms delay or so.
 2331             // 5) Obscure behavior caused by keyboard's auto-repeat feature: Use a key that's been remapped to
 2332             //    become the left mouse button to click and hold the minimize button of one of the script's windows.
 2333             //    Drag to the left.  The window starts moving.  This is caused by the fact that the down-click is
 2334             //    suppressed, thus the remap's hotkey subroutine thinks the mouse button is down, thus its
 2335             //    auto-repeat suppression doesn't work and it sends another click.
 2336             POINT point;
 2337             GetCursorPos(&point); // Assuming success seems harmless.
 2338             // Despite what MSDN says, WindowFromPoint() appears to fetch a non-NULL value even when the
 2339             // mouse is hovering over a disabled control (at least on XP).
 2340             HWND child_under_cursor, parent_under_cursor;
 2341             if (   (child_under_cursor = WindowFromPoint(point))
 2342                 && (parent_under_cursor = GetNonChildParent(child_under_cursor)) // WM_NCHITTEST below probably requires parent vs. child.
 2343                 && GetWindowThreadProcessId(parent_under_cursor, NULL) == g_MainThreadID   ) // It's one of our thread's windows.
 2344             {
 2345                 LRESULT hit_test = SendMessage(parent_under_cursor, WM_NCHITTEST, 0, MAKELPARAM(point.x, point.y));
 2346                 if (   aVK == VK_LBUTTON && (hit_test == HTCLOSE || hit_test == HTMAXBUTTON // Title bar buttons: Close, Maximize.
 2347                         || hit_test == HTMINBUTTON || hit_test == HTHELP) // Title bar buttons: Minimize, Help.
 2348                     || aVK == VK_RBUTTON && (hit_test == HTCAPTION || hit_test == HTSYSMENU)   )
 2349                 {
 2350                     if (aEventType == KEYDOWN)
 2351                     {
 2352                         // Ignore this event and substitute for it: Activate the window when one
 2353                         // of its title bar buttons is down-clicked.
 2354                         sWorkaroundVK = aVK;
 2355                         sWorkaroundHitTest = hit_test;
 2356                         SetForegroundWindowEx(parent_under_cursor); // Try to reproduce customary behavior.
 2357                         // For simplicity, aRepeatCount>1 is ignored and DoMouseDelay() is not done.
 2358                         return;
 2359                     }
 2360                     else // KEYUP
 2361                     {
 2362                         if (sWorkaroundHitTest == hit_test) // To weed out cases where user clicked down on a button then released somewhere other than the button.
 2363                             aEventType = KEYDOWNANDUP; // Translate this click-up into down+up to make up for the fact that the down was previously suppressed.
 2364                         //else let the click-up occur in case it does something or user wants it.
 2365                     }
 2366                 }
 2367             } // Work-around for sending mouse clicks to one of our thread's own windows.
 2368         }
 2369         // sWorkaroundVK is reset later below.
 2370 
 2371         // Since above didn't return, the work-around isn't in effect and normal click(s) will be sent:
 2372         if (aVK == VK_LBUTTON)
 2373         {
 2374             event_down = MOUSEEVENTF_LEFTDOWN;
 2375             event_up = MOUSEEVENTF_LEFTUP;
 2376         }
 2377         else // aVK == VK_RBUTTON
 2378         {
 2379             event_down = MOUSEEVENTF_RIGHTDOWN;
 2380             event_up = MOUSEEVENTF_RIGHTUP;
 2381         }
 2382         break;
 2383 
 2384     case VK_MBUTTON:
 2385         event_down = MOUSEEVENTF_MIDDLEDOWN;
 2386         event_up = MOUSEEVENTF_MIDDLEUP;
 2387         break;
 2388 
 2389     case VK_XBUTTON1:
 2390     case VK_XBUTTON2:
 2391         event_down = MOUSEEVENTF_XDOWN;
 2392         event_up = MOUSEEVENTF_XUP;
 2393         event_data = (aVK == VK_XBUTTON1) ? XBUTTON1 : XBUTTON2;
 2394         break;
 2395     } // switch()
 2396 
 2397     // For simplicity and possibly backward compatibility, LONG_OPERATION_INIT/UPDATE isn't done.
 2398     // In addition, some callers might do it for themselves, at least when aRepeatCount==1.
 2399     for (int i = 0; i < aRepeatCount; ++i)
 2400     {
 2401         if (aEventType != KEYUP) // It's either KEYDOWN or KEYDOWNANDUP.
 2402         {
 2403             // v1.0.43: Reliability is significantly improved by specifying the coordinates with the event (if
 2404             // caller gave us coordinates).  This is mostly because of SetMouseDelay: In previously versions,
 2405             // the delay between a MouseClick's move and its click allowed time for the user to move the mouse
 2406             // away from the target position before the click was sent.
 2407             MouseEvent(event_flags | event_down, event_data, aX, aY); // It ignores aX and aY when MOUSEEVENTF_MOVE is absent.
 2408             // It seems best to always Sleep a certain minimum time between events
 2409             // because the click-down event may cause the target app to do something which
 2410             // changes the context or nature of the click-up event.  AutoIt3 has also been
 2411             // revised to do this. v1.0.40.02: Avoid doing the Sleep between the down and up
 2412             // events when the workaround is in effect because any MouseDelay greater than 10
 2413             // would cause DoMouseDelay() to pump messages, which would defeat the workaround:
 2414             if (!sWorkaroundVK)
 2415                 DoMouseDelay(); // Inserts delay for all modes except SendInput, for which it does nothing.
 2416         }
 2417         if (aEventType != KEYDOWN) // It's either KEYUP or KEYDOWNANDUP.
 2418         {
 2419             MouseEvent(event_flags | event_up, event_data, aX, aY); // It ignores aX and aY when MOUSEEVENTF_MOVE is absent.
 2420             // It seems best to always do this one too in case the script line that caused
 2421             // us to be called here is followed immediately by another script line which
 2422             // is either another mouse click or something that relies upon the mouse click
 2423             // having been completed:
 2424             DoMouseDelay(); // Inserts delay for all modes except SendInput, for which it does nothing.
 2425         }
 2426     } // for()
 2427 
 2428     sWorkaroundVK = 0; // Reset this indicator in all cases except those for which above already returned.
 2429 }
 2430 
 2431 
 2432 
 2433 void MouseMove(int &aX, int &aY, DWORD &aEventFlags, int aSpeed, bool aMoveOffset)
 2434 // This function also does DoMouseDelay() for the caller.
 2435 // This function converts aX and aY for the caller into MOUSEEVENTF_ABSOLUTE coordinates.
 2436 // The exception is when the playback mode is in effect, in which case such a conversion would be undesirable
 2437 // both here and by the caller.
 2438 // It also puts appropriate bit-flags into aEventFlags.
 2439 {
 2440     // Most callers have already validated this, but some haven't.  Since it doesn't take too long to check,
 2441     // do it here rather than requiring all callers to do (helps maintainability).
 2442     if (aX == COORD_UNSPECIFIED || aY == COORD_UNSPECIFIED)
 2443         return;
 2444 
 2445     if (sSendMode == SM_PLAY) // Journal playback mode.
 2446     {
 2447         // Mouse speed (aSpeed) is ignored for SendInput/Play mode: the mouse always moves instantaneously
 2448         // (though in the case of playback-mode, MouseDelay still applies between each movement and click).
 2449         // Playback-mode ignores mouse speed because the cases where the user would want to move the mouse more
 2450         // slowly (such as a demo) seem too rare to justify the code size and complexity, especially since the
 2451         // incremental-move code would have to be implemented in the hook itself to ensure reliability.  This is
 2452         // because calling GetCursorPos() before playback begins could cause the mouse to wind up at the wrong
 2453         // destination, especially if our thread is preempted while building the array (which would give the user
 2454         // a chance to physically move the mouse before uninterruptibility begins).
 2455         // For creating demonstrations that user slower mouse movement, the older MouseMove command can be used
 2456         // in conjunction with BlockInput. This also applies to SendInput because it's conceivable that mouse
 2457         // speed could be supported there (though it seems useless both visually and to improve reliability
 2458         // because no mouse delays are possible within SendInput).
 2459         //
 2460         // MSG_OFFSET_MOUSE_MOVE is used to have the playback hook apply the offset (rather than doing it here
 2461         // like is done for SendInput mode).  This adds flexibility in cases where a new window becomes active
 2462         // during playback, or the active window changes position -- if that were to happen, the offset would
 2463         // otherwise be wrong while CoordMode is Relative because the changes can only be observed and
 2464         // compensated for during playback.
 2465         PutMouseEventIntoArray(MOUSEEVENTF_MOVE | (aMoveOffset ? MSG_OFFSET_MOUSE_MOVE : 0)
 2466             , 0, aX, aY); // The playback hook uses normal vs. MOUSEEVENTF_ABSOLUTE coordinates.
 2467         DoMouseDelay();
 2468         if (aMoveOffset)
 2469         {
 2470             // Now that we're done using the old values of aX and aY above, reset them to COORD_UNSPECIFIED
 2471             // for the caller so that any subsequent clicks it does will be marked as "at current coordinates".
 2472             aX = COORD_UNSPECIFIED;
 2473             aY = COORD_UNSPECIFIED;
 2474         }
 2475         return; // Other parts below rely on this returning early to avoid converting aX/aY into MOUSEEVENTF_ABSOLUTE.
 2476     }
 2477 
 2478     // The playback mode returned from above doesn't need these flags added because they're ignored for clicks:
 2479     aEventFlags |= MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; // Done here for caller, for easier maintenance.
 2480 
 2481     POINT cursor_pos;
 2482     if (aMoveOffset)  // We're moving the mouse cursor relative to its current position.
 2483     {
 2484         if (sSendMode == SM_INPUT)
 2485         {
 2486             // Since GetCursorPos() can't be called to find out a future cursor position, use the position
 2487             // tracked for SendInput (facilitates MouseClickDrag's R-option as well as Send{Click}'s).
 2488             if (sSendInputCursorPos.x == COORD_UNSPECIFIED) // Initial/starting value hasn't yet been set.
 2489                 GetCursorPos(&sSendInputCursorPos); // Start it off where the cursor is now.
 2490             aX += sSendInputCursorPos.x;
 2491             aY += sSendInputCursorPos.y;
 2492         }
 2493         else
 2494         {
 2495             GetCursorPos(&cursor_pos); // None of this is done for playback mode since that mode already returned higher above.
 2496             aX += cursor_pos.x;
 2497             aY += cursor_pos.y;
 2498         }
 2499     }
 2500     else
 2501     {
 2502         // Convert relative coords to screen coords if necessary (depends on CoordMode).
 2503         // None of this is done for playback mode since that mode already returned higher above.
 2504         CoordToScreen(aX, aY, COORD_MODE_MOUSE);
 2505     }
 2506 
 2507     if (sSendMode == SM_INPUT) // Track predicted cursor position for use by subsequent events put into the array.
 2508     {
 2509         sSendInputCursorPos.x = aX; // Always stores normal coords (non-MOUSEEVENTF_ABSOLUTE).
 2510         sSendInputCursorPos.y = aY; // 
 2511     }
 2512 
 2513     // Find dimensions of primary monitor.
 2514     // Without the MOUSEEVENTF_VIRTUALDESK flag (supported only by SendInput, and then only on
 2515     // Windows 2000/XP or later), MOUSEEVENTF_ABSOLUTE coordinates are relative to the primary monitor.
 2516     int screen_width = GetSystemMetrics(SM_CXSCREEN);
 2517     int screen_height = GetSystemMetrics(SM_CYSCREEN);
 2518 
 2519     // Convert the specified screen coordinates to mouse event coordinates (MOUSEEVENTF_ABSOLUTE).
 2520     // MSDN: "In a multimonitor system, [MOUSEEVENTF_ABSOLUTE] coordinates map to the primary monitor."
 2521     // The above implies that values greater than 65535 or less than 0 are appropriate, but only on
 2522     // multi-monitor systems.  For simplicity, performance, and backward compatibility, no check for
 2523     // multi-monitor is done here. Instead, the system's default handling for out-of-bounds coordinates
 2524     // is used; for example, mouse_event() stops the cursor at the edge of the screen.
 2525     // UPDATE: In v1.0.43, the following formula was fixed (actually broken, see below) to always yield an
 2526     // in-range value. The previous formula had a +1 at the end:
 2527     // aX|Y = ((65535 * aX|Y) / (screen_width|height - 1)) + 1;
 2528     // The extra +1 would produce 65536 (an out-of-range value for a single-monitor system) if the maximum
 2529     // X or Y coordinate was input (e.g. x-position 1023 on a 1024x768 screen).  Although this correction
 2530     // seems inconsequential on single-monitor systems, it may fix certain misbehaviors that have been reported
 2531     // on multi-monitor systems. Update: according to someone I asked to test it, it didn't fix anything on
 2532     // multimonitor systems, at least those whose monitors vary in size to each other.  In such cases, he said
 2533     // that only SendPlay or DllCall("SetCursorPos") make mouse movement work properly.
 2534     // FIX for v1.0.44: Although there's no explanation yet, the v1.0.43 formula is wrong and the one prior
 2535     // to it was correct; i.e. unless +1 is present below, a mouse movement to coords near the upper-left corner of
 2536     // the screen is typically off by one pixel (only the y-coordinate is affected in 1024x768 resolution, but
 2537     // in other resolutions both might be affected).
 2538     // v1.0.44.07: The following old formula has been replaced:
 2539     // (((65535 * coord) / (width_or_height - 1)) + 1)
 2540     // ... with the new one below.  This is based on numEric's research, which indicates that mouse_event()
 2541     // uses the following inverse formula internally:
 2542     // x_or_y_coord = (x_or_y_abs_coord * screen_width_or_height) / 65536
 2543     #define MOUSE_COORD_TO_ABS(coord, width_or_height) (((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1))
 2544     aX = MOUSE_COORD_TO_ABS(aX, screen_width);
 2545     aY = MOUSE_COORD_TO_ABS(aY, screen_height);
 2546     // aX and aY MUST BE SET UNCONDITIONALLY because the output parameters must be updated for caller.
 2547     // The incremental-move section further below also needs it.
 2548 
 2549     if (aSpeed < 0)  // This can happen during script's runtime due to something like: MouseMove, X, Y, %VarContainingNegative%
 2550         aSpeed = 0;  // 0 is the fastest.
 2551     else
 2552         if (aSpeed > MAX_MOUSE_SPEED)
 2553             aSpeed = MAX_MOUSE_SPEED;
 2554     if (aSpeed == 0 || sSendMode == SM_INPUT) // Instantaneous move to destination coordinates with no incremental positions in between.
 2555     {
 2556         // See the comments in the playback-mode section at the top of this function for why SM_INPUT ignores aSpeed.
 2557         MouseEvent(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, 0, aX, aY);
 2558         DoMouseDelay(); // Inserts delay for all modes except SendInput, for which it does nothing.
 2559         return;
 2560     }
 2561 
 2562     // Since above didn't return, use the incremental mouse move to gradually move the cursor until
 2563     // it arrives at the destination coordinates.
 2564     // Convert the cursor's current position to mouse event coordinates (MOUSEEVENTF_ABSOLUTE).
 2565     GetCursorPos(&cursor_pos);
 2566     DoIncrementalMouseMove(
 2567           MOUSE_COORD_TO_ABS(cursor_pos.x, screen_width)  // Source/starting coords.
 2568         , MOUSE_COORD_TO_ABS(cursor_pos.y, screen_height) //
 2569         , aX, aY, aSpeed);                                // Destination/ending coords.
 2570 }
 2571 
 2572 
 2573 
 2574 void MouseEvent(DWORD aEventFlags, DWORD aData, DWORD aX, DWORD aY)
 2575 // Having this part outsourced to a function helps remember to use KEY_IGNORE so that our own mouse
 2576 // events won't be falsely detected as hotkeys by the hooks (if they are installed).
 2577 {
 2578     if (sSendMode)
 2579         PutMouseEventIntoArray(aEventFlags, aData, aX, aY);
 2580     else
 2581         mouse_event(aEventFlags
 2582             , aX == COORD_UNSPECIFIED ? 0 : aX // v1.0.43.01: Must be zero if no change in position is desired
 2583             , aY == COORD_UNSPECIFIED ? 0 : aY // (fixes compatibility with certain apps/games).
 2584             , aData, KEY_IGNORE_LEVEL(g->SendLevel));
 2585 }
 2586 
 2587 
 2588 ///////////////////////
 2589 // SUPPORT FUNCTIONS //
 2590 ///////////////////////
 2591 
 2592 void PutKeybdEventIntoArray(modLR_type aKeyAsModifiersLR, vk_type aVK, sc_type aSC, DWORD aEventFlags, DWORD aExtraInfo)
 2593 // This function is designed to be called from only one thread (the main thread) since it's not thread-safe.
 2594 // Playback hook only supports sending neutral modifiers.  Caller must ensure that any left/right modifiers
 2595 // such as VK_RCONTROL are translated into neutral (e.g. VK_CONTROL).
 2596 {
 2597     bool key_up = aEventFlags & KEYEVENTF_KEYUP;
 2598     // To make the SendPlay method identical in output to the other keystroke methods, have it generate
 2599     // a leading down/up LControl event immediately prior to each RAlt event (with no key-delay).
 2600     // This avoids having to add special handling to places like SetModifierLRState() to do AltGr things
 2601     // differently when sending via playback vs. other methods.  The event order recorded by the journal
 2602     // record hook is a little different than what the low-level keyboard hook sees, but I don't think
 2603     // the order should matter in this case:
 2604     //   sc  vk key  msg
 2605     //   138 12 Alt  syskeydown (right vs. left scan code)
 2606     //   01d 11 Ctrl keydown (left scan code) <-- In keyboard hook, normally this precedes Alt, not follows it. Seems inconsequential (testing confirms).
 2607     //   01d 11 Ctrl keyup  (left scan code)
 2608     //   138 12 Alt  syskeyup (right vs. left scan code)
 2609     // Check for VK_MENU not VK_RMENU because caller should have translated it to neutral:
 2610     if (aVK == VK_MENU && aSC == SC_RALT && sTargetLayoutHasAltGr == CONDITION_TRUE && sSendMode == SM_PLAY)
 2611         // Must pass VK_CONTROL rather than VK_LCONTROL because playback hook requires neutral modifiers.
 2612         PutKeybdEventIntoArray(MOD_LCONTROL, VK_CONTROL, SC_LCONTROL, aEventFlags, aExtraInfo); // Recursive call to self.
 2613 
 2614     // Above must be done prior to the capacity check below because above might add a new array item.
 2615     if (sEventCount == sMaxEvents) // Array's capacity needs expanding.
 2616         if (!ExpandEventArray())
 2617             return;
 2618 
 2619     // Keep track of the predicted modifier state for use in other places:
 2620     if (key_up)
 2621         sEventModifiersLR &= ~aKeyAsModifiersLR;
 2622     else
 2623         sEventModifiersLR |= aKeyAsModifiersLR;
 2624 
 2625     if (sSendMode == SM_INPUT)
 2626     {
 2627         INPUT &this_event = sEventSI[sEventCount]; // For performance and convenience.
 2628         this_event.type = INPUT_KEYBOARD;
 2629         this_event.ki.wVk = aVK;
 2630         this_event.ki.wScan = (aEventFlags & KEYEVENTF_UNICODE) ? aSC : LOBYTE(aSC);
 2631         this_event.ki.dwFlags = aEventFlags;
 2632         this_event.ki.dwExtraInfo = aExtraInfo; // Although our hook won't be installed (or won't detect, in the case of playback), that of other scripts might be, so set this for them.
 2633         this_event.ki.time = 0; // Let the system provide its own timestamp, which might be more accurate for individual events if this will be a very long SendInput.
 2634         sHooksToRemoveDuringSendInput |= HOOK_KEYBD; // Presence of keyboard hook defeats uninterruptibility of keystrokes.
 2635     }
 2636     else // Playback hook.
 2637     {
 2638         PlaybackEvent &this_event = sEventPB[sEventCount]; // For performance and convenience.
 2639         if (!(aVK || aSC)) // Caller is signaling that aExtraInfo contains a delay/sleep event.
 2640         {
 2641             // Although delays at the tail end of the playback array can't be implemented by the playback
 2642             // itself, caller wants them put in too.
 2643             this_event.message = 0; // Message number zero flags it as a delay rather than an actual event.
 2644             this_event.time_to_wait = aExtraInfo;
 2645         }
 2646         else // A normal (non-delay) event for playback.
 2647         {
 2648             // By monitoring incoming events in a message/event loop, the following key combinations were
 2649             // confirmed to be WM_SYSKEYDOWN vs. WM_KEYDOWN (up events weren't tested, so are assumed to
 2650             // be the same as down-events):
 2651             // Alt+Win
 2652             // Alt+Shift
 2653             // Alt+Capslock/Numlock/Scrolllock
 2654             // Alt+AppsKey
 2655             // Alt+F2/Delete/Home/End/Arrow/BS
 2656             // Alt+Space/Enter
 2657             // Alt+Numpad (tested all digits & most other keys, with/without Numlock ON)
 2658             // F10 (by itself) / Win+F10 / Alt+F10 / Shift+F10 (but not Ctrl+F10)
 2659             // By contrast, the following are not SYS: Alt+Ctrl, Alt+Esc, Alt+Tab (the latter two
 2660             // are never received by msg/event loop probably because the system intercepts them).
 2661             // So the rule appears to be: It's a normal (non-sys) key if Alt isn't down and the key
 2662             // isn't F10, or if Ctrl is down. Though a press of the Alt key itself is a syskey unless Ctrl is down.
 2663             // Update: The release of ALT is WM_KEYUP vs. WM_SYSKEYUP when it modified at least one key while it was down.
 2664             if (sEventModifiersLR & (MOD_LCONTROL | MOD_RCONTROL) // Control is down...
 2665                 || !(sEventModifiersLR & (MOD_LALT | MOD_RALT))   // ... or: Alt isn't down and this key isn't Alt or F10...
 2666                     && aVK != VK_F10 && !(aKeyAsModifiersLR & (MOD_LALT | MOD_RALT))
 2667                 || (sEventModifiersLR & (MOD_LALT | MOD_RALT)) && key_up) // ... or this is the release of Alt (for simplicity, assume that Alt modified something while it was down).
 2668                 this_event.message = key_up ? WM_KEYUP : WM_KEYDOWN;
 2669             else
 2670                 this_event.message = key_up ? WM_SYSKEYUP : WM_SYSKEYDOWN;
 2671             this_event.vk = aVK;
 2672             this_event.sc = aSC; // Don't omit the extended-key-bit because it is used later on.
 2673         }
 2674     }
 2675     ++sEventCount;
 2676 }
 2677 
 2678 
 2679 
 2680 void PutMouseEventIntoArray(DWORD aEventFlags, DWORD aData, DWORD aX, DWORD aY)
 2681 // This function is designed to be called from only one thread (the main thread) since it's not thread-safe.
 2682 // If the array-type is journal playback, caller should include MOUSEEVENTF_ABSOLUTE in aEventFlags if the
 2683 // the mouse coordinates aX and aY are relative to the screen rather than the active window.
 2684 {
 2685     if (sEventCount == sMaxEvents) // Array's capacity needs expanding.
 2686         if (!ExpandEventArray())
 2687             return;
 2688 
 2689     if (sSendMode == SM_INPUT)
 2690     {
 2691         INPUT &this_event = sEventSI[sEventCount]; // For performance and convenience.
 2692         this_event.type = INPUT_MOUSE;
 2693         this_event.mi.dx = (aX == COORD_UNSPECIFIED) ? 0 : aX; // v1.0.43.01: Must be zero if no change in position is
 2694         this_event.mi.dy = (aY == COORD_UNSPECIFIED) ? 0 : aY; // desired (fixes compatibility with certain apps/games).
 2695         this_event.mi.dwFlags = aEventFlags;
 2696         this_event.mi.mouseData = aData;
 2697         this_event.mi.dwExtraInfo = KEY_IGNORE_LEVEL(g->SendLevel); // Although our hook won't be installed (or won't detect, in the case of playback), that of other scripts might be, so set this for them.
 2698         this_event.mi.time = 0; // Let the system provide its own timestamp, which might be more accurate for individual events if this will be a very long SendInput.
 2699         sHooksToRemoveDuringSendInput |= HOOK_MOUSE; // Presence of mouse hook defeats uninterruptibility of mouse clicks/moves.
 2700     }
 2701     else // Playback hook.
 2702     {
 2703         // Note: Delay events (sleeps), which are supported in playback mode but not SendInput, are always inserted
 2704         // via PutKeybdEventIntoArray() rather than this function.
 2705         PlaybackEvent &this_event = sEventPB[sEventCount]; // For performance and convenience.
 2706         // Determine the type of event specified by caller, but also omit MOUSEEVENTF_MOVE so that the
 2707         // follow variations can be differentiated:
 2708         // 1) MOUSEEVENTF_MOVE by itself.
 2709         // 2) MOUSEEVENTF_MOVE with a click event or wheel turn (in this case MOUSEEVENTF_MOVE is permitted but
 2710         //    not required, since all mouse events in playback mode must have explicit coordinates at the
 2711         //    time they're played back).
 2712         // 3) A click event or wheel turn by itself (same remark as above).
 2713         // Bits are isolated in what should be a future-proof way (also omits MSG_OFFSET_MOUSE_MOVE bit).
 2714         switch (aEventFlags & (0x1FFF & ~MOUSEEVENTF_MOVE)) // v1.0.48: 0x1FFF vs. 0xFFF to support MOUSEEVENTF_HWHEEL.
 2715         {
 2716         case 0:                      this_event.message = WM_MOUSEMOVE; break; // It's a movement without a click.
 2717         // In cases other than the above, it's a click or wheel turn with optional WM_MOUSEMOVE too.
 2718         case MOUSEEVENTF_LEFTDOWN:   this_event.message = WM_LBUTTONDOWN; break;
 2719         case MOUSEEVENTF_LEFTUP:     this_event.message = WM_LBUTTONUP; break;
 2720         case MOUSEEVENTF_RIGHTDOWN:  this_event.message = WM_RBUTTONDOWN; break;
 2721         case MOUSEEVENTF_RIGHTUP:    this_event.message = WM_RBUTTONUP; break;
 2722         case MOUSEEVENTF_MIDDLEDOWN: this_event.message = WM_MBUTTONDOWN; break;
 2723         case MOUSEEVENTF_MIDDLEUP:   this_event.message = WM_MBUTTONUP; break;
 2724         case MOUSEEVENTF_XDOWN:      this_event.message = WM_XBUTTONDOWN; break;
 2725         case MOUSEEVENTF_XUP:        this_event.message = WM_XBUTTONUP; break;
 2726         case MOUSEEVENTF_WHEEL:      this_event.message = WM_MOUSEWHEEL; break;
 2727         case MOUSEEVENTF_HWHEEL:     this_event.message = WM_MOUSEHWHEEL; break; // v1.0.48
 2728         // WHEEL: No info comes into journal-record about which direction the wheel was turned (nor by how many
 2729         // notches).  In addition, it appears impossible to specify such info when playing back the event.
 2730         // Therefore, playback usually produces downward wheel movement (but upward in some apps like
 2731         // Visual Studio).
 2732         }
 2733         // COORD_UNSPECIFIED_SHORT is used so that the very first event can be a click with unspecified
 2734         // coordinates: it seems best to have the cursor's position fetched during playback rather than
 2735         // here because if done here, there might be time for the cursor to move physically before
 2736         // playback begins (especially if our thread is preempted while building the array).
 2737         this_event.x = (aX == COORD_UNSPECIFIED) ? COORD_UNSPECIFIED_SHORT : (WORD)aX;
 2738         this_event.y = (aY == COORD_UNSPECIFIED) ? COORD_UNSPECIFIED_SHORT : (WORD)aY;
 2739         if (aEventFlags & MSG_OFFSET_MOUSE_MOVE) // Caller wants this event marked as a movement relative to cursor's current position.
 2740             this_event.message |= MSG_OFFSET_MOUSE_MOVE;
 2741     }
 2742     ++sEventCount;
 2743 }
 2744 
 2745 
 2746 
 2747 ResultType ExpandEventArray()
 2748 // Returns OK or FAIL.
 2749 {
 2750     if (sAbortArraySend) // A prior call failed (might be impossible).  Avoid malloc() in this case.
 2751         return FAIL;
 2752     #define EVENT_EXPANSION_MULTIPLIER 2  // Should be very rare for array to need to expand more than a few times.
 2753     size_t event_size = (sSendMode == SM_INPUT) ? sizeof(INPUT) : sizeof(PlaybackEvent);
 2754     void *new_mem;
 2755     // SendInput() appears to be limited to 5000 chars (10000 events in array), at least on XP.  This is
 2756     // either an undocumented SendInput limit or perhaps it's due to the system setting that determines
 2757     // how many messages can get backlogged in each thread's msg queue before some start to get dropped.
 2758     // Note that SendInput()'s return value always seems to indicate that all the characters were sent
 2759     // even when the ones beyond the limit were clearly never received by the target window.
 2760     // In any case, it seems best not to restrict to 5000 here in case the limit can vary for any reason.
 2761     // The 5000 limit is documented in the help file.
 2762     if (   !(new_mem = malloc(EVENT_EXPANSION_MULTIPLIER * sMaxEvents * event_size))   )
 2763     {
 2764         sAbortArraySend = true; // Usually better to send nothing rather than partial.
 2765         // Leave sEventSI and sMaxEvents in their current valid state, to be freed by CleanupEventArray().
 2766         return FAIL;
 2767     }
 2768     else // Copy old array into new memory area (note that sEventSI and sEventPB are different views of the same variable).
 2769         memcpy(new_mem, sEventSI, sEventCount * event_size);
 2770     if (sMaxEvents > (sSendMode == SM_INPUT ? MAX_INITIAL_EVENTS_SI : MAX_INITIAL_EVENTS_PB))
 2771         free(sEventSI); // Previous block was malloc'd vs. _alloc'd, so free it.
 2772     sEventSI = (LPINPUT)new_mem; // Note that sEventSI and sEventPB are different views of the same variable.
 2773     sMaxEvents *= EVENT_EXPANSION_MULTIPLIER;
 2774     return OK;
 2775 }
 2776 
 2777 
 2778 
 2779 void InitEventArray(void *aMem, UINT aMaxEvents, modLR_type aModifiersLR)
 2780 {
 2781     sEventPB = (PlaybackEvent *)aMem; // Sets sEventSI too, since both are the same.
 2782     sMaxEvents = aMaxEvents;
 2783     sEventModifiersLR = aModifiersLR;
 2784     sSendInputCursorPos.x = COORD_UNSPECIFIED;
 2785     sSendInputCursorPos.y = COORD_UNSPECIFIED;
 2786     sHooksToRemoveDuringSendInput = 0;
 2787     sEventCount = 0;
 2788     sAbortArraySend = false; // If KeyEvent() ever sets it to true, that allows us to send nothing at all rather than a partial send.
 2789     sFirstCallForThisEvent = true;
 2790     // The above isn't a local static inside PlaybackProc because PlaybackProc might get aborted in the
 2791     // middle of a NEXT/SKIP pair by user pressing Ctrl-Esc, etc, which would make it unreliable.
 2792 }
 2793 
 2794 
 2795 
 2796 void SendEventArray(int &aFinalKeyDelay, modLR_type aModsDuringSend)
 2797 // aFinalKeyDelay (which the caller should have initialized to -1 prior to calling) may be changed here
 2798 // to the desired/final delay.  Caller must not act upon it until changing sTypeOfHookToBuild to something
 2799 // that will allow DoKeyDelay() to do a real delay.
 2800 {
 2801     if (sSendMode == SM_INPUT)
 2802     {
 2803         // Remove hook(s) temporarily because the presence of low-level (LL) keybd hook completely disables
 2804         // the uninterruptibility of SendInput's keystrokes (but the mouse hook doesn't affect them).
 2805         // The converse is also true.  This was tested via:
 2806         //  #space::
 2807         //  SendInput {Click 400, 400, 100}
 2808         //  MsgBox
 2809         //  ExitApp
 2810         // ... and also with BurnK6 running, a CPU maxing utility.  The mouse clicks were sent directly to the
 2811         // BurnK6 window, and were pretty slow, and also I could physically move the mouse cursor a little
 2812         // between each of sendinput's mouse clicks.  But removing the mouse-hook during SendInputs solves all that.
 2813         // Rather than removing both hooks unconditionally, it's better to
 2814         // remove only those that actually have corresponding events in the array.  This avoids temporarily
 2815         // losing visibility of physical key states (especially when the keyboard hook is removed).
 2816         HookType active_hooks;
 2817         if (active_hooks = GetActiveHooks())
 2818             AddRemoveHooks(active_hooks & ~sHooksToRemoveDuringSendInput, true);
 2819 
 2820         SendInput(sEventCount, sEventSI, sizeof(INPUT)); // Must call dynamically-resolved version for Win95/NT compatibility.
 2821         // The return value is ignored because it never seems to be anything other than sEventCount, even if
 2822         // the Send seems to partially fail (e.g. due to hitting 5000 event maximum).
 2823         // Typical speed of SendInput: 10ms or less for short sends (under 100 events).
 2824         // Typically 30ms for 500 events; and typically no more than 200ms for 5000 events (which is
 2825         // the apparent max).
 2826         // Testing shows that when SendInput returns to its caller, all of its key states are in effect
 2827         // even if the target window hasn't yet had time to receive them all.  For example, the
 2828         // following reports that LShift is down:
 2829         //   SendInput {a 4900}{LShift down}
 2830         //   MsgBox % GetKeyState("LShift")
 2831         // Furthermore, if the user manages to physically press or release a key during the call to
 2832         // SendInput, testing shows that such events are in effect immediately when SendInput returns
 2833         // to its caller, perhaps because SendInput clears out any backlog of physical keystrokes prior to
 2834         // returning, or perhaps because the part of the OS that updates key states is a very high priority.
 2835 
 2836         if (active_hooks)
 2837         {
 2838             if (active_hooks & sHooksToRemoveDuringSendInput & HOOK_KEYBD) // Keyboard hook was actually removed during SendInput.
 2839             {
 2840                 // The above call to SendInput() has not only sent its own events, it has also emptied
 2841                 // the buffer of any events generated outside but during the SendInput.  Since such
 2842                 // events are almost always physical events rather than simulated ones, it seems to do
 2843                 // more good than harm on average to consider any such changes to be physical.
 2844                 // The g_PhysicalKeyState array is also updated by GetModifierLRState(true), but only
 2845                 // for the modifier keys, not for all keys on the keyboard.  Even if adjust all keys
 2846                 // is possible, it seems overly complex and it might impact performance more than it's
 2847                 // worth given the rarity of the user changing physical key states during a SendInput
 2848                 // and then wanting to explicitly retrieve that state via GetKeyState(Key, "P").
 2849                 modLR_type mods_current = GetModifierLRState(true); // This also serves to correct the hook's logical modifiers, since hook was absent during the SendInput.
 2850                 modLR_type mods_changed_physically_during_send = aModsDuringSend ^ mods_current;
 2851                 g_modifiersLR_physical &= ~(mods_changed_physically_during_send & aModsDuringSend); // Remove those that changed from down to up.
 2852                 g_modifiersLR_physical |= mods_changed_physically_during_send & mods_current; // Add those that changed from up to down.
 2853                 g_HShwnd = GetForegroundWindow(); // An item done by ResetHook() that seems worthwhile here.
 2854                 // Most other things done by ResetHook() seem like they would do more harm than good to reset here
 2855                 // because of the the time the hook is typically missing is very short, usually under 30ms.
 2856             }
 2857             AddRemoveHooks(active_hooks, true); // Restore the hooks that were active before the SendInput.
 2858         }
 2859         return;
 2860     }
 2861 
 2862     // Since above didn't return, sSendMode == SM_PLAY.
 2863     // It seems best not to call IsWindowHung() here because:
 2864     // 1) It might improve script reliability to allow playback to a hung window because even though
 2865     //    the entire system would appear frozen, if the window becomes unhung, the keystrokes would
 2866     //    eventually get sent to it as intended (and the script may be designed to rely on this).
 2867     //    Furthermore, the user can press Ctrl-Alt-Del or Ctrl-Esc to unfreeze the system.
 2868     // 2) It might hurt performance.
 2869     //
 2870     // During journal playback, it appears that LL hook receives events in realtime; its just that
 2871     // keystrokes the hook passes through (or generates itself) don't actually hit the active window
 2872     // until after the playback is done.  Preliminary testing shows that the hook's disguise of Alt/Win
 2873     // still function properly for Win/Alt hotkeys that use the playback method.
 2874     sCurrentEvent = 0; // Reset for use by the hook below.  Should be done BEFORE the hook is installed in the next line.
 2875 #ifdef JOURNAL_RECORD_MODE
 2876 // To record and analyze events via the above:
 2877 // - Uncomment the line that defines this in the header file.
 2878 // - Put breakpoint after the hook removes itself (a few lines below).  Don't try to put breakpoint in RECORD hook
 2879 //   itself because it tends to freeze keyboard input (must press Ctrl-Alt-Del or Ctrl-Esc to unfreeze).
 2880 // - Have the script send a keystroke (best to use non-character keystroke such as SendPlay {Shift}).
 2881 // - It is now recording, so press the desired keys.
 2882 // - Press Ctrl+Break, Ctrl-Esc, or Ctrl-Alt-Del to stop recording (which should then hit breakpoint below).
 2883 // - Study contents of the sEventPB array, which contains the keystrokes just recorded.
 2884     sEventCount = 0; // Used by RecordProc().
 2885     if (   !(g_PlaybackHook = SetWindowsHookEx(WH_JOURNALRECORD, RecordProc, g_hInstance, 0))   )
 2886         return;
 2887 #else
 2888     if (   !(g_PlaybackHook = SetWindowsHookEx(WH_JOURNALPLAYBACK, PlaybackProc, g_hInstance, 0))   )
 2889         return;
 2890     // During playback, have the keybd hook (if it's installed) block presses of the Windows key.
 2891     // This is done because the Windows key is about the only key (other than Ctrl-Esc or Ctrl-Alt-Del)
 2892     // that takes effect immediately rather than getting buffered/postponed until after the playback.
 2893     // It should be okay to set this after the playback hook is installed because playback shouldn't
 2894     // actually begin until we have our thread do its first MsgSleep later below.
 2895     g_BlockWinKeys = true;
 2896 #endif
 2897 
 2898     // Otherwise, hook is installed, so:
 2899     // Wait for the hook to remove itself because the script should not be allowed to continue
 2900     // until the Send finishes.
 2901     // GetMessage(single_msg_filter) can't be used because then our thread couldn't playback
 2902     // keystrokes to one of its own windows.  In addition, testing shows that it wouldn't
 2903     // measurably improve performance anyway.
 2904     // Note: User can't activate tray icon with mouse (because mouse is blocked), so there's
 2905     // no need to call our main event loop merely to have the tray menu responsive.
 2906     // Sleeping for 0 performs at least 15% worse than INTERVAL_UNSPECIFIED. I think this is
 2907     // because the journal playback hook can operate only when this thread is in a message-pumping
 2908     // state, and message pumping is far more efficient with GetMessage than PeekMessage.
 2909     // Also note that both registered and hook hotkeys are noticed/caught during journal playback
 2910     // (confirmed through testing).  However, they are kept buffered until the Send finishes
 2911     // because ACT_SEND and such are designed to be uninterruptible by other script threads;
 2912     // also, it would be undesirable in almost any conceivable case.
 2913     //
 2914     // Use a loop rather than a single call to MsgSleep(WAIT_FOR_MESSAGES) because
 2915     // WAIT_FOR_MESSAGES is designed only for use by WinMain().  The loop doesn't measurably
 2916     // affect performance because there used to be the following here in place of the loop,
 2917     // and it didn't perform any better:
 2918     // GetMessage(&msg, NULL, WM_CANCELJOURNAL, WM_CANCELJOURNAL);
 2919     while (g_PlaybackHook)
 2920         SLEEP_WITHOUT_INTERRUPTION(INTERVAL_UNSPECIFIED); // For maintainability, macro is used rather than optimizing/splitting the code it contains.
 2921     g_BlockWinKeys = false;
 2922     // Either the hook unhooked itself or the OS did due to Ctrl-Esc or Ctrl-Alt-Del.
 2923     // MSDN: When an application sees a [system-generated] WM_CANCELJOURNAL message, it can assume
 2924     // two things: the user has intentionally cancelled the journal record or playback mode,
 2925     // and the system has already unhooked any journal record or playback hook procedures.
 2926     if (!sEventPB[sEventCount - 1].message) // Playback hook can't do the final delay, so we do it here.
 2927         // Don't do delay right here because the delay would be put into the array instead.
 2928         aFinalKeyDelay = sEventPB[sEventCount - 1].time_to_wait;
 2929     // GetModifierLRState(true) is not done because keystrokes generated by the playback hook
 2930     // aren't really keystrokes in the sense that they affect global key state or modifier state.
 2931     // They affect only the keystate retrieved when the target thread calls GetKeyState()
 2932     // (GetAsyncKeyState can never see such changes, even if called from the target thread).
 2933     // Furthermore, the hook (if present) continues to operate during journal playback, so it
 2934     // will keep its own modifiers up-to-date if any physical or simulate keystrokes happen to
 2935     // come in during playback (such keystrokes arrive in the hook in real time, but they don't
 2936     // actually hit the active window until the playback finishes).
 2937 }
 2938 
 2939 
 2940 
 2941 void CleanupEventArray(int aFinalKeyDelay)
 2942 {
 2943     if (sMaxEvents > (sSendMode == SM_INPUT ? MAX_INITIAL_EVENTS_SI : MAX_INITIAL_EVENTS_PB))
 2944         free(sEventSI); // Previous block was malloc'd vs. _alloc'd, so free it.  Note that sEventSI and sEventPB are different views of the same variable.
 2945     // The following must be done only after functions called above are done using it.  But it must also be done
 2946     // prior to our caller toggling capslock back on , to avoid the capslock keystroke from going into the array.
 2947     sSendMode = SM_EVENT;
 2948     DoKeyDelay(aFinalKeyDelay); // Do this only after resetting sSendMode above.  Should be okay for mouse events too.
 2949 }
 2950 
 2951 
 2952 
 2953 /////////////////////////////////
 2954 
 2955 
 2956 void DoKeyDelay(int aDelay)
 2957 // Doesn't need to be thread safe because it should only ever be called from main thread.
 2958 {
 2959     if (aDelay < 0) // To support user-specified KeyDelay of -1 (fastest send rate).
 2960         return;
 2961     if (sSendMode)
 2962     {
 2963         if (sSendMode == SM_PLAY && aDelay > 0) // Zero itself isn't supported by playback hook, so no point in inserting such delays into the array.
 2964             PutKeybdEventIntoArray(0, 0, 0, 0, aDelay); // Passing zero for vk and sc signals it that aExtraInfo contains the delay.
 2965         //else for other types of arrays, never insert a delay or do one now.
 2966         return;
 2967     }
 2968     SLEEP_WITHOUT_INTERRUPTION(aDelay);
 2969 }
 2970 
 2971 
 2972 
 2973 void DoMouseDelay() // Helper function for the mouse functions below.
 2974 {
 2975     int mouse_delay = sSendMode == SM_PLAY ? g->MouseDelayPlay : g->MouseDelay;
 2976     if (mouse_delay < 0) // To support user-specified KeyDelay of -1 (fastest send rate).
 2977         return;
 2978     if (sSendMode)
 2979     {
 2980         if (sSendMode == SM_PLAY && mouse_delay > 0) // Zero itself isn't supported by playback hook, so no point in inserting such delays into the array.
 2981             PutKeybdEventIntoArray(0, 0, 0, 0, mouse_delay); // Passing zero for vk and sc signals it that aExtraInfo contains the delay.
 2982         //else for other types of arrays, never insert a delay or do one now (caller should have already
 2983         // checked that, so it's written this way here only for maintainability).
 2984         return;
 2985     }
 2986     // I believe the varying sleep methods below were put in place to avoid issues when simulating
 2987     // clicks on the script's own windows.  There are extensive comments in MouseClick() and the
 2988     // hook about these issues.  Here are more details from an older comment:
 2989     // Always sleep a certain minimum amount of time between events to improve reliability,
 2990     // but allow the user to specify a higher time if desired.  A true sleep is done if the
 2991     // delay period is small.  This fixes a small issue where if LButton is a hotkey that
 2992     // includes "MouseClick left" somewhere in its subroutine, the script's own main window's
 2993     // title bar buttons for min/max/close would not properly respond to left-clicks.
 2994     if (mouse_delay < 11)
 2995         Sleep(mouse_delay);
 2996     else
 2997         SLEEP_WITHOUT_INTERRUPTION(mouse_delay)
 2998 }
 2999 
 3000 
 3001 
 3002 void UpdateKeyEventHistory(bool aKeyUp, vk_type aVK, sc_type aSC)
 3003 {
 3004     if (!g_KeyHistory) // Don't access the array if it doesn't exist (i.e. key history is disabled).
 3005         return;
 3006     g_KeyHistory[g_KeyHistoryNext].key_up = aKeyUp;
 3007     g_KeyHistory[g_KeyHistoryNext].vk = aVK;
 3008     g_KeyHistory[g_KeyHistoryNext].sc = aSC;
 3009     g_KeyHistory[g_KeyHistoryNext].event_type = 'i'; // Callers all want this.
 3010     g_HistoryTickNow = GetTickCount();
 3011     g_KeyHistory[g_KeyHistoryNext].elapsed_time = (g_HistoryTickNow - g_HistoryTickPrev) / (float)1000;
 3012     g_HistoryTickPrev = g_HistoryTickNow;
 3013     HWND fore_win = GetForegroundWindow();
 3014     if (fore_win)
 3015     {
 3016         if (fore_win != g_HistoryHwndPrev)
 3017             GetWindowText(fore_win, g_KeyHistory[g_KeyHistoryNext].target_window, _countof(g_KeyHistory[g_KeyHistoryNext].target_window));
 3018         else // i.e. avoid the call to GetWindowText() if possible.
 3019             *g_KeyHistory[g_KeyHistoryNext].target_window = '\0';
 3020     }
 3021     else
 3022         _tcscpy(g_KeyHistory[g_KeyHistoryNext].target_window, _T("N/A"));
 3023     g_HistoryHwndPrev = fore_win; // Update unconditionally in case it's NULL.
 3024     if (++g_KeyHistoryNext >= g_MaxHistoryKeys)
 3025         g_KeyHistoryNext = 0;
 3026 }
 3027 
 3028 
 3029 
 3030 ToggleValueType ToggleKeyState(vk_type aVK, ToggleValueType aToggleValue)
 3031 // Toggle the given aVK into another state.  For performance, it is the caller's responsibility to
 3032 // ensure that aVK is a toggleable key such as capslock, numlock, insert, or scrolllock.
 3033 // Returns the state the key was in before it was changed.
 3034 {
 3035     // Can't use IsKeyDownAsync/GetAsyncKeyState() because it doesn't have this info:
 3036     ToggleValueType starting_state = IsKeyToggledOn(aVK) ? TOGGLED_ON : TOGGLED_OFF;
 3037     if (aToggleValue != TOGGLED_ON && aToggleValue != TOGGLED_OFF) // Shouldn't be called this way.
 3038         return starting_state;
 3039     if (starting_state == aToggleValue) // It's already in the desired state, so just return the state.
 3040         return starting_state;
 3041     //if (aVK == VK_NUMLOCK) // v1.1.22.05: This also applies to CapsLock and ScrollLock.
 3042     {
 3043         // If the key is being held down, sending a KEYDOWNANDUP won't change its toggle
 3044         // state unless the key is "released" first.  This has been confirmed for NumLock,
 3045         // CapsLock and ScrollLock on Windows 2000 (in a VM) and Windows 10.
 3046         // Examples where problems previously occurred:
 3047         //   ~CapsLock & x::Send abc  ; Produced "ABC"
 3048         //   ~CapsLock::Send abc  ; Alternated between "abc" and "ABC", even without {Blind}
 3049         //   ~ScrollLock::SetScrollLockState Off  ; Failed to change state
 3050         // The behaviour can still be observed by sending the keystrokes manually:
 3051         //   ~NumLock::Send {NumLock}  ; No effect
 3052         //   ~NumLock::Send {NumLock up}{NumLock}  ; OK
 3053         // OLD COMMENTS:
 3054         // Sending an extra up-event first seems to prevent the problem where the Numlock
 3055         // key's indicator light doesn't change to reflect its true state (and maybe its
 3056         // true state doesn't change either).  This problem tends to happen when the key
 3057         // is pressed while the hook is forcing it to be either ON or OFF (or it suppresses
 3058         // it because it's a hotkey).  Needs more testing on diff. keyboards & OSes:
 3059         if (IsKeyDown(aVK))
 3060             KeyEvent(KEYUP, aVK);
 3061     }
 3062     // Since it's not already in the desired state, toggle it:
 3063     KeyEvent(KEYDOWNANDUP, aVK);
 3064     // Fix for v1.0.40: IsKeyToggledOn()'s call to GetKeyState() relies on our thread having
 3065     // processed messages.  Confirmed necessary 100% of the time if our thread owns the active window.
 3066     // v1.0.43: Extended the above fix to include all toggleable keys (not just Capslock) and to apply
 3067     // to both directions (ON and OFF) since it seems likely to be needed for them all.
 3068     bool our_thread_is_foreground;
 3069     if (our_thread_is_foreground = (GetWindowThreadProcessId(GetForegroundWindow(), NULL) == g_MainThreadID)) // GetWindowThreadProcessId() tolerates a NULL hwnd.
 3070         SLEEP_WITHOUT_INTERRUPTION(-1);
 3071     if (aVK == VK_CAPITAL && aToggleValue == TOGGLED_OFF && IsKeyToggledOn(aVK))
 3072     {
 3073         // Fix for v1.0.36.06: Since it's Capslock and it didn't turn off as attempted, it's probably because
 3074         // the OS is configured to turn Capslock off only in response to pressing the SHIFT key (via Ctrl Panel's
 3075         // Regional settings).  So send shift to do it instead:
 3076         KeyEvent(KEYDOWNANDUP, VK_SHIFT);
 3077         if (our_thread_is_foreground) // v1.0.43: Added to try to achieve 100% reliability in all situations.
 3078             SLEEP_WITHOUT_INTERRUPTION(-1); // Check msg queue to put SHIFT's turning off of Capslock into effect from our thread's POV.
 3079     }
 3080     return starting_state;
 3081 }
 3082 
 3083 
 3084 /*
 3085 void SetKeyState (vk_type vk, int aKeyUp)
 3086 {
 3087     if (!vk) return;
 3088     int key_already_up = !(GetKeyState(vk) & 0x8000);
 3089     if ((key_already_up && aKeyUp) || (!key_already_up && !aKeyUp))
 3090         return;
 3091     KeyEvent(aKeyUp, vk);
 3092 }
 3093 */
 3094 
 3095 
 3096 
 3097 void SetModifierLRState(modLR_type aModifiersLRnew, modLR_type aModifiersLRnow, HWND aTargetWindow
 3098     , bool aDisguiseDownWinAlt, bool aDisguiseUpWinAlt, DWORD aExtraInfo)
 3099 // This function is designed to be called from only the main thread; it's probably not thread-safe.
 3100 // Puts modifiers into the specified state, releasing or pressing down keys as needed.
 3101 // The modifiers are released and pressed down in a very delicate order due to their interactions with
 3102 // each other and their ability to show the Start Menu, activate the menu bar, or trigger the OS's language
 3103 // bar hotkeys.  Side-effects like these would occur if a more simple approach were used, such as releasing
 3104 // all modifiers that are going up prior to pushing down the ones that are going down.
 3105 // When the target layout has an altgr key, it is tempting to try to simplify things by removing MOD_LCONTROL
 3106 // from aModifiersLRnew whenever aModifiersLRnew contains MOD_RALT.  However, this a careful review how that
 3107 // would impact various places below where sTargetLayoutHasAltGr is checked indicates that it wouldn't help.
 3108 // Note that by design and as documented for ControlSend, aTargetWindow is not used as the target for the
 3109 // various calls to KeyEvent() here.  It is only used as a workaround for the GUI window issue described
 3110 // at the bottom.
 3111 {
 3112     if (aModifiersLRnow == aModifiersLRnew) // They're already in the right state, so avoid doing all the checks.
 3113         return; // Especially avoids the aTargetWindow check at the bottom.
 3114 
 3115     // Notes about modifier key behavior on Windows XP (these probably apply to NT/2k also, and has also
 3116     // been tested to be true on Win98): The WIN and ALT keys are the problem keys, because if either is
 3117     // released without having modified something (even another modifier), the WIN key will cause the
 3118     // Start Menu to appear, and the ALT key will activate the menu bar of the active window (if it has one).
 3119     // For example, a hook hotkey such as "$#c::Send text" (text must start with a lowercase letter
 3120     // to reproduce the issue, because otherwise WIN would be auto-disguised as a side effect of the SHIFT
 3121     // keystroke) would cause the Start Menu to appear if the disguise method below weren't used.
 3122     //
 3123     // Here are more comments formerly in SetModifierLRStateSpecific(), which has since been eliminated
 3124     // because this function is sufficient:
 3125     // To prevent it from activating the menu bar, the release of the ALT key should be disguised
 3126     // unless a CTRL key is currently down.  This is because CTRL always seems to avoid the
 3127     // activation of the menu bar (unlike SHIFT, which sometimes allows the menu to be activated,
 3128     // though this is hard to reproduce on XP).  Another reason not to use SHIFT is that the OS
 3129     // uses LAlt+Shift as a hotkey to switch languages.  Such a hotkey would be triggered if SHIFT
 3130     // were pressed down to disguise the release of LALT.
 3131     //
 3132     // Alt-down events are also disguised whenever they won't be accompanied by a Ctrl-down.
 3133     // This is necessary whenever our caller does not plan to disguise the key itself.  For example,
 3134     // if "!a::Send Test" is a registered hotkey, two things must be done to avoid complications:
 3135     // 1) Prior to sending the word test, ALT must be released in a way that does not activate the
 3136     //    menu bar.  This is done by sandwiching it between a CTRL-down and a CTRL-up.
 3137     // 2) After the send is complete, SendKeys() will restore the ALT key to the down position if
 3138     //    the user is still physically holding ALT down (this is done to make the logical state of
 3139     //    the key match its physical state, which allows the same hotkey to be fired twice in a row
 3140     //    without the user having to release and press down the ALT key physically).
 3141     // The #2 case above is the one handled below by ctrl_wont_be_down.  It is especially necessary
 3142     // when the user releases the ALT key prior to releasing the hotkey suffix, which would otherwise
 3143     // cause the menu bar (if any) of the active window to be activated.
 3144     //
 3145     // Some of the same comments above for ALT key apply to the WIN key.  More about this issue:
 3146     // Although the disguise of the down-event is usually not needed, it is needed in the rare case
 3147     // where the user releases the WIN or ALT key prior to releasing the hotkey's suffix.
 3148     // Although the hook could be told to disguise the physical release of ALT or WIN in these
 3149     // cases, it's best not to rely on the hook since it is not always installed.
 3150     //
 3151     // Registered WIN and ALT hotkeys that don't use the Send command work okay except ALT hotkeys,
 3152     // which if the user releases ALT prior the hotkey's suffix key, cause the menu bar to be activated.
 3153     // Since it is unusual for users to do this and because it is standard behavior for  ALT hotkeys
 3154     // registered in the OS, fixing it via the hook seems like a low priority, and perhaps isn't worth
 3155     // the added code complexity/size.  But if there is ever a need to do so, the following note applies:
 3156     // If the hook is installed, could tell it to disguise any need-to-be-disguised Alt-up that occurs
 3157     // after receipt of the registered ALT hotkey.  But what if that hotkey uses the send command:
 3158     // there might be interference?  Doesn't seem so, because the hook only disguises non-ignored events.
 3159 
 3160     // Set up some conditions so that the keystrokes that disguise the release of Win or Alt
 3161     // are only sent when necessary (which helps avoid complications caused by keystroke interaction,
 3162     // while improving performance):
 3163     modLR_type aModifiersLRunion = aModifiersLRnow | aModifiersLRnew; // The set of keys that were or will be down.
 3164     bool ctrl_not_down = !(aModifiersLRnow & (MOD_LCONTROL | MOD_RCONTROL)); // Neither CTRL key is down now.
 3165     bool ctrl_will_not_be_down = !(aModifiersLRnew & (MOD_LCONTROL | MOD_RCONTROL)) // Nor will it be.
 3166         && !(sTargetLayoutHasAltGr == CONDITION_TRUE && (aModifiersLRnew & MOD_RALT)); // Nor will it be pushed down indirectly due to AltGr.
 3167 
 3168     bool ctrl_nor_shift_nor_alt_down = ctrl_not_down                             // Neither CTRL key is down now.
 3169         && !(aModifiersLRnow & (MOD_LSHIFT | MOD_RSHIFT | MOD_LALT | MOD_RALT)); // Nor is any SHIFT/ALT key.
 3170 
 3171     bool ctrl_or_shift_or_alt_will_be_down = !ctrl_will_not_be_down             // CTRL will be down.
 3172         || (aModifiersLRnew & (MOD_LSHIFT | MOD_RSHIFT | MOD_LALT | MOD_RALT)); // or SHIFT or ALT will be.
 3173 
 3174     // If the required disguise keys aren't down now but will be, defer the release of Win and/or Alt
 3175     // until after the disguise keys are in place (since in that case, the caller wanted them down
 3176     // as part of the normal operation here):
 3177     bool defer_win_release = ctrl_nor_shift_nor_alt_down && ctrl_or_shift_or_alt_will_be_down;
 3178     bool defer_alt_release = ctrl_not_down && !ctrl_will_not_be_down;  // i.e. Ctrl not down but it will be.
 3179     bool release_shift_before_alt_ctrl = defer_alt_release // i.e. Control is moving into the down position or...
 3180         || !(aModifiersLRnow & (MOD_LALT | MOD_RALT)) && (aModifiersLRnew & (MOD_LALT | MOD_RALT)); // ...Alt is moving into the down position.
 3181     // Concerning "release_shift_before_alt_ctrl" above: Its purpose is to prevent unwanted firing of the OS's
 3182     // language bar hotkey.  See the bottom of this function for more explanation.
 3183 
 3184     // ALT:
 3185     bool disguise_alt_down = aDisguiseDownWinAlt && ctrl_not_down && ctrl_will_not_be_down; // Since this applies to both Left and Right Alt, don't take sTargetLayoutHasAltGr into account here. That is done later below.
 3186 
 3187     // WIN: The WIN key is successfully disguised under a greater number of conditions than ALT.
 3188     // Since SendPlay can't display Start Menu, there's no need to send the disguise-keystrokes (such
 3189     // keystrokes might cause unwanted effects in certain games):
 3190     bool disguise_win_down = aDisguiseDownWinAlt && sSendMode != SM_PLAY
 3191         && ctrl_not_down && ctrl_will_not_be_down
 3192         && !(aModifiersLRunion & (MOD_LSHIFT | MOD_RSHIFT)) // And neither SHIFT key is down, nor will it be.
 3193         && !(aModifiersLRunion & (MOD_LALT | MOD_RALT));    // And neither ALT key is down, nor will it be.
 3194 
 3195     bool release_lwin = (aModifiersLRnow & MOD_LWIN) && !(aModifiersLRnew & MOD_LWIN);
 3196     bool release_rwin = (aModifiersLRnow & MOD_RWIN) && !(aModifiersLRnew & MOD_RWIN);
 3197     bool release_lalt = (aModifiersLRnow & MOD_LALT) && !(aModifiersLRnew & MOD_LALT);
 3198     bool release_ralt = (aModifiersLRnow & MOD_RALT) && !(aModifiersLRnew & MOD_RALT);
 3199     bool release_lshift = (aModifiersLRnow & MOD_LSHIFT) && !(aModifiersLRnew & MOD_LSHIFT);
 3200     bool release_rshift = (aModifiersLRnow & MOD_RSHIFT) && !(aModifiersLRnew & MOD_RSHIFT);
 3201 
 3202     // Handle ALT and WIN prior to the other modifiers because the "disguise" methods below are
 3203     // only needed upon release of ALT or WIN.  This is because such releases tend to have a better
 3204     // chance of being "disguised" if SHIFT or CTRL is down at the time of the release.  Thus, the
 3205     // release of SHIFT or CTRL (if called for) is deferred until afterward.
 3206 
 3207     // ** WIN
 3208     // Must be done before ALT in case it is relying on ALT being down to disguise the release WIN.
 3209     // If ALT is going to be pushed down further below, defer_win_release should be true, which will make sure
 3210     // the WIN key isn't released until after the ALT key is pushed down here at the top.
 3211     // Also, WIN is a little more troublesome than ALT, so it is done first in case the ALT key
 3212     // is down but will be going up, since the ALT key being down might help the WIN key.
 3213     // For example, if you hold down CTRL, then hold down LWIN long enough for it to auto-repeat,
 3214     // then release CTRL before releasing LWIN, the Start Menu would appear, at least on XP.
 3215     // But it does not appear if CTRL is released after LWIN.
 3216     // Also note that the ALT key can disguise the WIN key, but not vice versa.
 3217     if (release_lwin)
 3218     {
 3219         if (!defer_win_release)
 3220         {
 3221             // Fixed for v1.0.25: To avoid triggering the system's LAlt+Shift language hotkey, the
 3222             // Control key is now used to suppress LWIN/RWIN (preventing the Start Menu from appearing)
 3223             // rather than the Shift key.  This is definitely needed for ALT, but is done here for
 3224             // WIN also in case ALT is down, which might cause the use of SHIFT as the disguise key
 3225             // to trigger the language switch.
 3226             if (ctrl_nor_shift_nor_alt_down && aDisguiseUpWinAlt // Nor will they be pushed down later below, otherwise defer_win_release would have been true and we couldn't get to this point.
 3227                 && sSendMode != SM_PLAY) // SendPlay can't display Start Menu, so disguise not needed (also, disguise might mess up some games).
 3228                 KeyEventMenuMask(KEYDOWNANDUP, aExtraInfo); // Disguise key release to suppress Start Menu.
 3229                 // The above event is safe because if we're here, it means VK_CONTROL will not be
 3230                 // pressed down further below.  In other words, we're not defeating the job
 3231                 // of this function by sending these disguise keystrokes.
 3232             KeyEvent(KEYUP, VK_LWIN, 0, NULL, false, aExtraInfo);
 3233         }
 3234         // else release it only after the normal operation of the function pushes down the disguise keys.
 3235     }
 3236     else if (!(aModifiersLRnow & MOD_LWIN) && (aModifiersLRnew & MOD_LWIN)) // Press down LWin.
 3237     {
 3238         if (disguise_win_down)
 3239             KeyEventMenuMask(KEYDOWN, aExtraInfo); // Ensures that the Start Menu does not appear.
 3240         KeyEvent(KEYDOWN, VK_LWIN, 0, NULL, false, aExtraInfo);
 3241         if (disguise_win_down)
 3242             KeyEventMenuMask(KEYUP, aExtraInfo); // Ensures that the Start Menu does not appear.
 3243     }
 3244 
 3245     if (release_rwin)
 3246     {
 3247         if (!defer_win_release)
 3248         {
 3249             if (ctrl_nor_shift_nor_alt_down && aDisguiseUpWinAlt && sSendMode != SM_PLAY)
 3250                 KeyEventMenuMask(KEYDOWNANDUP, aExtraInfo); // Disguise key release to suppress Start Menu.
 3251             KeyEvent(KEYUP, VK_RWIN, 0, NULL, false, aExtraInfo);
 3252         }
 3253         // else release it only after the normal operation of the function pushes down the disguise keys.
 3254     }
 3255     else if (!(aModifiersLRnow & MOD_RWIN) && (aModifiersLRnew & MOD_RWIN)) // Press down RWin.
 3256     {
 3257         if (disguise_win_down)
 3258             KeyEventMenuMask(KEYDOWN, aExtraInfo); // Ensures that the Start Menu does not appear.
 3259         KeyEvent(KEYDOWN, VK_RWIN, 0, NULL, false, aExtraInfo);
 3260         if (disguise_win_down)
 3261             KeyEventMenuMask(KEYUP, aExtraInfo); // Ensures that the Start Menu does not appear.
 3262     }
 3263 
 3264     // ** SHIFT (PART 1 OF 2)
 3265     if (release_shift_before_alt_ctrl)
 3266     {
 3267         if (release_lshift)
 3268             KeyEvent(KEYUP, VK_LSHIFT, 0, NULL, false, aExtraInfo);
 3269         if (release_rshift)
 3270             KeyEvent(KEYUP, VK_RSHIFT, 0, NULL, false, aExtraInfo);
 3271     }
 3272 
 3273     // ** ALT
 3274     if (release_lalt)
 3275     {
 3276         if (!defer_alt_release)
 3277         {
 3278             if (ctrl_not_down && aDisguiseUpWinAlt)
 3279                 KeyEventMenuMask(KEYDOWNANDUP, aExtraInfo); // Disguise key release to suppress menu activation.
 3280             KeyEvent(KEYUP, VK_LMENU, 0, NULL, false, aExtraInfo);
 3281         }
 3282     }
 3283     else if (!(aModifiersLRnow & MOD_LALT) && (aModifiersLRnew & MOD_LALT))
 3284     {
 3285         if (disguise_alt_down)
 3286             KeyEventMenuMask(KEYDOWN, aExtraInfo); // Ensures that menu bar is not activated.
 3287         KeyEvent(KEYDOWN, VK_LMENU, 0, NULL, false, aExtraInfo);
 3288         if (disguise_alt_down)
 3289             KeyEventMenuMask(KEYUP, aExtraInfo);
 3290     }
 3291 
 3292     if (release_ralt)
 3293     {
 3294         if (!defer_alt_release || sTargetLayoutHasAltGr == CONDITION_TRUE) // No need to defer if RAlt==AltGr. But don't change the value of defer_alt_release because LAlt uses it too.
 3295         {
 3296             if (sTargetLayoutHasAltGr == CONDITION_TRUE)
 3297             {
 3298                 // Indicate that control is up now, since the release of AltGr will cause that indirectly.
 3299                 // Fix for v1.0.43: Unlike the pressing down of AltGr in a later section, which callers want
 3300                 // to automatically press down LControl too (by the very nature of AltGr), callers do not want
 3301                 // the release of AltGr to release LControl unless they specifically asked for LControl to be
 3302                 // released too.  This is because the caller may need LControl down to manifest something
 3303                 // like ^c. So don't do: aModifiersLRnew &= ~MOD_LCONTROL.
 3304                 // Without this fix, a hotkey like <^>!m::Send ^c would send "c" vs. "^c" on the German layout.
 3305                 // See similar section below for more details.
 3306                 aModifiersLRnow &= ~MOD_LCONTROL; // To reflect what KeyEvent(KEYUP, VK_RMENU) below will do.
 3307             }
 3308             else // No AltGr, so check if disguise is necessary (AltGr itself never needs disguise).
 3309                 if (ctrl_not_down && aDisguiseUpWinAlt)
 3310                     KeyEventMenuMask(KEYDOWNANDUP, aExtraInfo); // Disguise key release to suppress menu activation.
 3311             KeyEvent(KEYUP, VK_RMENU, 0, NULL, false, aExtraInfo);
 3312         }
 3313     }
 3314     else if (!(aModifiersLRnow & MOD_RALT) && (aModifiersLRnew & MOD_RALT)) // Press down RALT.
 3315     {
 3316         // For the below: There should never be a need to disguise AltGr.  Doing so would likely cause unwanted
 3317         // side-effects. Also, disguise_alt_key does not take sTargetLayoutHasAltGr into account because
 3318         // disguise_alt_key also applies to the left alt key.
 3319         if (disguise_alt_down && sTargetLayoutHasAltGr != CONDITION_TRUE)
 3320         {
 3321             KeyEventMenuMask(KEYDOWN, aExtraInfo); // Ensures that menu bar is not activated.
 3322             KeyEvent(KEYDOWN, VK_RMENU, 0, NULL, false, aExtraInfo);
 3323             KeyEventMenuMask(KEYUP, aExtraInfo);
 3324         }
 3325         else // No disguise needed.
 3326         {
 3327             // v1.0.43: The following check was added to complement the other .43 fix higher above.
 3328             // It may also fix other things independently of that other fix.
 3329             // The following two lines release LControl before pushing down AltGr because otherwise,
 3330             // the next time RAlt is released (such as by the user), some quirk of the OS or driver
 3331             // prevents it from automatically releasing LControl like it normally does (perhaps
 3332             // because the OS is designed to leave LControl down if it was down before AltGr went down).
 3333             // This would cause LControl to get stuck down for hotkeys in German layout such as:
 3334             //   <^>!a::SendRaw, {
 3335             //   <^>!m::Send ^c
 3336             if (sTargetLayoutHasAltGr == CONDITION_TRUE)
 3337             {
 3338                 if (aModifiersLRnow & MOD_LCONTROL)
 3339                     KeyEvent(KEYUP, VK_LCONTROL, 0, NULL, false, aExtraInfo);
 3340                 if (aModifiersLRnow & MOD_RCONTROL)
 3341                 {
 3342                     // Release RCtrl before pressing AltGr, because otherwise the system will not put
 3343                     // LCtrl into effect, but it will still inject LCtrl-up when AltGr is released.
 3344                     // With LCtrl not in effect and RCtrl being released below, AltGr would instead
 3345                     // act as pure RAlt, which would not have the right effect.
 3346                     // RCtrl will be put back into effect below if aModifiersLRnew & MOD_RCONTROL.
 3347                     KeyEvent(KEYUP, VK_RCONTROL, 0, NULL, false, aExtraInfo);
 3348                     aModifiersLRnow &= ~MOD_RCONTROL;
 3349                 }
 3350             }
 3351             KeyEvent(KEYDOWN, VK_RMENU, 0, NULL, false, aExtraInfo);
 3352             if (sTargetLayoutHasAltGr == CONDITION_TRUE) // Note that KeyEvent() might have just changed the value of sTargetLayoutHasAltGr.
 3353             {
 3354                 // Indicate that control is both down and required down so that the section after this one won't
 3355                 // release it.  Without this fix, a hotkey that sends an AltGr char such as "^ä:: SendRaw, {"
 3356                 // would fail to work under German layout because left-alt would be released after right-alt
 3357                 // goes down.
 3358                 aModifiersLRnow |= MOD_LCONTROL; // To reflect what KeyEvent() did above.
 3359                 aModifiersLRnew |= MOD_LCONTROL; // All callers want LControl to be down if they wanted AltGr to be down.
 3360             }
 3361         }
 3362     }
 3363 
 3364     // CONTROL and SHIFT are done only after the above because the above might rely on them
 3365     // being down before for certain early operations.
 3366 
 3367     // ** CONTROL
 3368     if (   (aModifiersLRnow & MOD_LCONTROL) && !(aModifiersLRnew & MOD_LCONTROL) // Release LControl.
 3369         // v1.0.41.01: The following line was added to fix the fact that callers do not want LControl
 3370         // released when the new modifier state includes AltGr.  This solves a hotkey such as the following and
 3371         // probably several other circumstances:
 3372         // <^>!a::send \  ; Backslash is solved by this fix; it's manifest via AltGr+Dash on German layout.
 3373         && !((aModifiersLRnew & MOD_RALT) && sTargetLayoutHasAltGr == CONDITION_TRUE)   )
 3374         KeyEvent(KEYUP, VK_LCONTROL, 0, NULL, false, aExtraInfo);
 3375     else if (!(aModifiersLRnow & MOD_LCONTROL) && (aModifiersLRnew & MOD_LCONTROL)) // Press down LControl.
 3376         KeyEvent(KEYDOWN, VK_LCONTROL, 0, NULL, false, aExtraInfo);
 3377     if ((aModifiersLRnow & MOD_RCONTROL) && !(aModifiersLRnew & MOD_RCONTROL)) // Release RControl
 3378         KeyEvent(KEYUP, VK_RCONTROL, 0, NULL, false, aExtraInfo);
 3379     else if (!(aModifiersLRnow & MOD_RCONTROL) && (aModifiersLRnew & MOD_RCONTROL)) // Press down RControl.
 3380         KeyEvent(KEYDOWN, VK_RCONTROL, 0, NULL, false, aExtraInfo);
 3381     
 3382     // ** SHIFT (PART 2 OF 2)
 3383     // Must follow CTRL and ALT because a release of SHIFT while ALT/CTRL is down-but-soon-to-be-up
 3384     // would switch languages via the OS hotkey.  It's okay if defer_alt_release==true because in that case,
 3385     // CTRL just went down above (by definition of defer_alt_release), which will prevent the language hotkey
 3386     // from firing.
 3387     if (release_lshift && !release_shift_before_alt_ctrl) // Release LShift.
 3388         KeyEvent(KEYUP, VK_LSHIFT, 0, NULL, false, aExtraInfo);
 3389     else if (!(aModifiersLRnow & MOD_LSHIFT) && (aModifiersLRnew & MOD_LSHIFT)) // Press down LShift.
 3390         KeyEvent(KEYDOWN, VK_LSHIFT, 0, NULL, false, aExtraInfo);
 3391     if (release_rshift && !release_shift_before_alt_ctrl) // Release RShift.
 3392         KeyEvent(KEYUP, VK_RSHIFT, 0, NULL, false, aExtraInfo);
 3393     else if (!(aModifiersLRnow & MOD_RSHIFT) && (aModifiersLRnew & MOD_RSHIFT)) // Press down RShift.
 3394         KeyEvent(KEYDOWN, VK_RSHIFT, 0, NULL, false, aExtraInfo);
 3395 
 3396     // ** KEYS DEFERRED FROM EARLIER
 3397     if (defer_win_release) // Must be done before ALT because it might rely on ALT being down to disguise release of WIN key.
 3398     {
 3399         if (release_lwin)
 3400             KeyEvent(KEYUP, VK_LWIN, 0, NULL, false, aExtraInfo);
 3401         if (release_rwin)
 3402             KeyEvent(KEYUP, VK_RWIN, 0, NULL, false, aExtraInfo);
 3403     }
 3404     if (defer_alt_release)
 3405     {
 3406         if (release_lalt)
 3407             KeyEvent(KEYUP, VK_LMENU, 0, NULL, false, aExtraInfo);
 3408         if (release_ralt && sTargetLayoutHasAltGr != CONDITION_TRUE) // If AltGr is present, RAlt would already have been released earlier since defer_alt_release would have been ignored for it.
 3409             KeyEvent(KEYUP, VK_RMENU, 0, NULL, false, aExtraInfo);
 3410     }
 3411 
 3412     // When calling KeyEvent(), probably best not to specify a scan code unless
 3413     // absolutely necessary, since some keyboards may have non-standard scan codes
 3414     // which KeyEvent() will resolve into the proper vk translations for us.
 3415     // Decided not to Sleep() between keystrokes, even zero, out of concern that this
 3416     // would result in a significant delay (perhaps more than 10ms) while the system
 3417     // is under load.
 3418 
 3419     // Since the above didn't return early, keybd_event() has been used to change the state
 3420     // of at least one modifier.  As a result, if the caller gave a non-NULL aTargetWindow,
 3421     // it wants us to check if that window belongs to our thread.  If it does, we should do
 3422     // a short msg queue check to prevent an apparent synchronization problem when using
 3423     // ControlSend against the script's own GUI or other windows.  Here is an example of a
 3424     // line whose modifier would not be in effect in time for its keystroke to be modified
 3425     // by it:
 3426     // ControlSend, Edit1, ^{end}, Test Window
 3427     // Update: Another bug-fix for v1.0.21, as was the above: If the keyboard hook is installed,
 3428     // the modifier keystrokes must have a way to get routed through the hook BEFORE the
 3429     // keystrokes get sent via PostMessage().  If not, the correct modifier state will usually
 3430     // not be in effect (or at least not be in sync) for the keys sent via PostMessage() afterward.
 3431     // Notes about the macro below:
 3432     // aTargetWindow!=NULL means ControlSend mode is in effect.
 3433     // The g_KeybdHook check must come first (it should take precedence if both conditions are true).
 3434     // -1 has been verified to be insufficient, at least for the very first letter sent if it is
 3435     // supposed to be capitalized.
 3436     // g_MainThreadID is the only thread of our process that owns any windows.
 3437 
 3438     int press_duration = (sSendMode == SM_PLAY) ? g->PressDurationPlay : g->PressDuration;
 3439     if (press_duration > -1) // SM_PLAY does use DoKeyDelay() to store a delay item in the event array.
 3440         // Since modifiers were changed by the above, do a key-delay if the special intra-keystroke
 3441         // delay is in effect.
 3442         // Since there normally isn't a delay between a change in modifiers and the first keystroke,
 3443         // if a PressDuration is in effect, also do it here to improve reliability (I have observed
 3444         // cases where modifiers need to be left alone for a short time in order for the keystrokes
 3445         // that follow to be be modified by the intended set of modifiers).
 3446         DoKeyDelay(press_duration); // It knows not to do the delay for SM_INPUT.
 3447     else // Since no key-delay was done, check if a a delay is needed for any other reason.
 3448     {
 3449         // IMPORTANT UPDATE for v1.0.39: Now that the hooks are in a separate thread from the part
 3450         // of the program that sends keystrokes for the script, you might think synchronization of
 3451         // keystrokes would become problematic or at least change.  However, this is apparently not
 3452         // the case.  MSDN doesn't spell this out, but testing shows that what happens with a low-level
 3453         // hook is that the moment a keystroke comes into a thread (either physical or simulated), the OS
 3454         // immediately calls something similar to SendMessage() from that thread to notify the hook
 3455         // thread that a keystroke has arrived.  However, if the hook thread's priority is lower than
 3456         // some other thread next in line for a timeslice, it might take some time for the hook thread
 3457         // to get a timeslice (that's why the hook thread is given a high priority).
 3458         // The SendMessage() call doesn't return until its timeout expires (as set in the registry for
 3459         // hooks) or the hook thread processes the keystroke (which requires that it call something like
 3460         // GetMessage/PeekMessage followed by a HookProc "return").  This is good news because it serializes
 3461         // keyboard and mouse input to make the presence of the hook transparent to other threads (unless
 3462         // the hook does something to reveal itself, such as suppressing keystrokes). Serialization avoids
 3463         // any chance of synchronization problems such as a program that changes the state of a key then
 3464         // immediately checks the state of that same key via GetAsyncKeyState().  Another way to look at
 3465         // all of this is that in essence, a single-threaded hook program that simulates keystrokes or
 3466         // mouse clicks should behave the same when the hook is moved into a separate thread because from
 3467         // the program's point-of-view, keystrokes & mouse clicks result in a calling the hook almost
 3468         // exactly as if the hook were in the same thread.
 3469         if (aTargetWindow)
 3470         {
 3471             if (g_KeybdHook)
 3472                 SLEEP_WITHOUT_INTERRUPTION(0) // Don't use ternary operator to combine this with next due to "else if".
 3473             else if (GetWindowThreadProcessId(aTargetWindow, NULL) == g_MainThreadID)
 3474                 SLEEP_WITHOUT_INTERRUPTION(-1)
 3475         }
 3476     }
 3477 
 3478     // Commented out because a return value is no longer needed by callers (since we do the key-delay here,
 3479     // if appropriate).
 3480     //return aModifiersLRnow ^ aModifiersLRnew; // Calculate the set of modifiers that changed (currently excludes AltGr's change of LControl's state).
 3481 
 3482 
 3483     // NOTES about "release_shift_before_alt_ctrl":
 3484     // If going down on alt or control (but not both, though it might not matter), and shift is to be released:
 3485     //  Release shift first.
 3486     // If going down on shift, and control or alt (but not both) is to be released:
 3487     //  Release ctrl/alt first (this is already the case so nothing needs to be done).
 3488     //
 3489     // Release both shifts before going down on lalt/ralt or lctrl/rctrl (but not necessary if going down on
 3490     // *both* alt+ctrl?
 3491     // Release alt and both controls before going down on lshift/rshift.
 3492     // Rather than the below, do the above (for the reason below).
 3493     // But if do this, don't want to prevent a legit/intentional language switch such as:
 3494     //    Send {LAlt down}{Shift}{LAlt up}.
 3495     // If both Alt and Shift are down, Win or Ctrl (or any other key for that matter) must be pressed before either
 3496     // is released.
 3497     // If both Ctrl and Shift are down, Win or Alt (or any other key) must be pressed before either is released.
 3498     // remind: Despite what the Regional Settings window says, RAlt+Shift (and Shift+RAlt) is also a language hotkey (i.e. not just LAlt), at least when RAlt isn't AltGr!
 3499     // remind: Control being down suppresses language switch only once.  After that, control being down doesn't help if lalt is re-pressed prior to re-pressing shift.
 3500     //
 3501     // Language switch occurs when:
 3502     // alt+shift (upon release of shift)
 3503     // shift+alt (upon release of lalt)
 3504     // ctrl+shift (upon release of shift)
 3505     // shift+ctrl (upon release of ctrl)
 3506     // Because language hotkey only takes effect upon release of Shift, it can be disguised via a Control keystroke if that is ever needed.
 3507 
 3508     // NOTES: More details about disguising ALT and WIN:
 3509     // Registered Alt hotkeys don't quite work if the Alt key is released prior to the suffix.
 3510     // Key history for Alt-B hotkey released this way, which undesirably activates the menu bar:
 3511     // A4  038      d   0.03    Alt             
 3512     // 42  030      d   0.03    B               
 3513     // A4  038      u   0.24    Alt             
 3514     // 42  030      u   0.19    B               
 3515     // Testing shows that the above does not happen for a normal (non-hotkey) alt keystroke such as Alt-8,
 3516     // so the above behavior is probably caused by the fact that B-down is suppressed by the OS's hotkey
 3517     // routine, but not B-up.
 3518     // The above also happens with registered WIN hotkeys, but only if the Send cmd resulted in the WIN
 3519     // modifier being pushed back down afterward to match the fact that the user is still holding it down.
 3520     // This behavior applies to ALT hotkeys also.
 3521     // One solution: if the hook is installed, have it keep track of when the start menu or menu bar
 3522     // *would* be activated.  These tracking vars can be consulted by the Send command, and the hook
 3523     // can also be told when to use them after a registered hotkey has been pressed, so that the Alt-up
 3524     // or Win-up keystroke that belongs to it can be disguised.
 3525 
 3526     // The following are important ways in which other methods of disguise might not be sufficient:
 3527     // Sequence: shift-down win-down shift-up win-up: invokes Start Menu when WIN is held down long enough
 3528     // to auto-repeat.  Same when Ctrl or Alt is used in lieu of Shift.
 3529     // Sequence: shift-down alt-down alt-up shift-up: invokes menu bar.  However, as long as another key,
 3530     // even Shift, is pressed down *after* alt is pressed down, menu bar is not activated, e.g. alt-down
 3531     // shift-down shift-up alt-up.  In addition, CTRL always prevents ALT from activating the menu bar,
 3532     // even with the following sequences:
 3533     // ctrl-down alt-down alt-up ctrl-up
 3534     // alt-down ctrl-down ctrl-up alt-up
 3535     // (also seems true for all other permutations of Ctrl/Alt)
 3536 }
 3537 
 3538 
 3539 
 3540 modLR_type GetModifierLRState(bool aExplicitlyGet)
 3541 // Try to report a more reliable state of the modifier keys than GetKeyboardState alone could.
 3542 // Fix for v1.0.42.01: On Windows 2000/XP or later, GetAsyncKeyState() should be called rather than
 3543 // GetKeyState().  This is because our callers always want the current state of the modifier keys
 3544 // rather than their state at the time of the currently-in-process message was posted.  For example,
 3545 // if the control key wasn't down at the time our thread's current message was posted, but it's logically
 3546 // down according to the system, we would want to release that control key before sending non-control
 3547 // keystrokes, even if one of our thread's own windows has keyboard focus (because if it does, the
 3548 // control-up keystroke should wind up getting processed after our thread realizes control is down).
 3549 // This applies even when the keyboard/mouse hook call use because keystrokes routed to the hook via
 3550 // the hook's message pump aren't messages per se, and thus GetKeyState and GetAsyncKeyState probably
 3551 // return the exact same thing whenever there are no messages in the hook's thread-queue (which is almost
 3552 // always the case).
 3553 {
 3554     // If the hook is active, rely only on its tracked value rather than calling Get():
 3555     if (g_KeybdHook && !aExplicitlyGet)
 3556         return g_modifiersLR_logical;
 3557 
 3558     // Very old comment:
 3559     // Use GetKeyState() rather than GetKeyboardState() because it's the only way to get
 3560     // accurate key state when a console window is active, it seems.  I've also seen other
 3561     // cases where GetKeyboardState() is incorrect (at least under WinXP) when GetKeyState(),
 3562     // in its place, yields the correct info.  Very strange.
 3563 
 3564     modLR_type modifiersLR = 0;  // Allows all to default to up/off to simplify the below.
 3565     if (IsKeyDownAsync(VK_LSHIFT))   modifiersLR |= MOD_LSHIFT;
 3566     if (IsKeyDownAsync(VK_RSHIFT))   modifiersLR |= MOD_RSHIFT;
 3567     if (IsKeyDownAsync(VK_LCONTROL)) modifiersLR |= MOD_LCONTROL;
 3568     if (IsKeyDownAsync(VK_RCONTROL)) modifiersLR |= MOD_RCONTROL;
 3569     if (IsKeyDownAsync(VK_LMENU))    modifiersLR |= MOD_LALT;
 3570     if (IsKeyDownAsync(VK_RMENU))    modifiersLR |= MOD_RALT;
 3571     if (IsKeyDownAsync(VK_LWIN))     modifiersLR |= MOD_LWIN;
 3572     if (IsKeyDownAsync(VK_RWIN))     modifiersLR |= MOD_RWIN;
 3573 
 3574     // Thread-safe: The following section isn't thread-safe because either the hook thread
 3575     // or the main thread can be calling it.  However, given that anything dealing with
 3576     // keystrokes isn't thread-safe in the sense that keystrokes can be coming in simultaneously
 3577     // from multiple sources, it seems acceptable to keep it this way (especially since
 3578     // the consequences of a thread collision seem very mild in this case).
 3579     if (g_KeybdHook)
 3580     {
 3581         // Since hook is installed, fix any modifiers that it incorrectly thinks are down.
 3582         // Though rare, this situation does arise during periods when the hook cannot track
 3583         // the user's keystrokes, such as when the OS is doing something with the hardware,
 3584         // e.g. switching to TV-out or changing video resolutions.  There are probably other
 3585         // situations where this happens -- never fully explored and identified -- so it
 3586         // seems best to do this, at least when the caller specified aExplicitlyGet = true.
 3587         // To limit the scope of this workaround, only change the state of the hook modifiers
 3588         // to be "up" for those keys the hook thinks are logically down but which the OS thinks
 3589         // are logically up.  Note that it IS possible for a key to be physically down without
 3590         // being logically down (i.e. during a Send command where the user is physically holding
 3591         // down a modifier, but the Send command needs to put it up temporarily), so do not
 3592         // change the hook's physical state for such keys in that case.
 3593         // UPDATE: The following adjustment is now also relied upon by the SendInput method
 3594         // to correct physical modifier state during periods when the hook was temporarily removed
 3595         // to allow a SendInput to be uninterruptible.
 3596         // UPDATE: The modifier state might also become incorrect due to keyboard events which
 3597         // are missed due to User Interface Privelege Isolation; i.e. because a window belonging
 3598         // to a process with higher integrity level than our own became active while the key was
 3599         // down, so we saw the down event but not the up event.
 3600         modLR_type modifiers_wrongly_down = g_modifiersLR_logical & ~modifiersLR;
 3601         if (modifiers_wrongly_down)
 3602         {
 3603             // Adjust the physical and logical hook state to release the keys that are wrongly down.
 3604             // If a key is wrongly logically down, it seems best to release it both physically and
 3605             // logically, since the hook's failure to see the up-event probably makes its physical
 3606             // state wrong in most such cases.
 3607             g_modifiersLR_physical &= ~modifiers_wrongly_down;
 3608             g_modifiersLR_logical &= ~modifiers_wrongly_down;
 3609             g_modifiersLR_logical_non_ignored &= ~modifiers_wrongly_down;
 3610             // Also adjust physical state so that the GetKeyState command will retrieve the correct values:
 3611             AdjustKeyState(g_PhysicalKeyState, g_modifiersLR_physical);
 3612             // Also reset pPrefixKey if it is one of the wrongly-down modifiers.
 3613             if (pPrefixKey && (pPrefixKey->as_modifiersLR & modifiers_wrongly_down))
 3614                 pPrefixKey = NULL;
 3615         }
 3616     }
 3617 
 3618     return modifiersLR;
 3619 
 3620     // Only consider a modifier key to be really down if both the hook's tracking of it
 3621     // and GetKeyboardState() agree that it should be down.  The should minimize the impact
 3622     // of the inherent unreliability present in each method (and each method is unreliable in
 3623     // ways different from the other).  I have verified through testing that this eliminates
 3624     // many misfires of hotkeys.  UPDATE: Both methods are fairly reliable now due to starting
 3625     // to send scan codes with keybd_event(), using MapVirtualKey to resolve zero-value scan
 3626     // codes in the keyboardproc(), and using GetKeyState() rather than GetKeyboardState().
 3627     // There are still a few cases when they don't agree, so return the bitwise-and of both
 3628     // if the keyboard hook is active.  Bitwise and is used because generally it's safer
 3629     // to assume a modifier key is up, when in doubt (e.g. to avoid firing unwanted hotkeys):
 3630 //  return g_KeybdHook ? (g_modifiersLR_logical & g_modifiersLR_get) : g_modifiersLR_get;
 3631 }
 3632 
 3633 
 3634 
 3635 void AdjustKeyState(BYTE aKeyState[], modLR_type aModifiersLR)
 3636 // Caller has ensured that aKeyState is a 256-BYTE array of key states, in the same format used
 3637 // by GetKeyboardState() and ToAsciiEx().
 3638 {
 3639     aKeyState[VK_LSHIFT] = (aModifiersLR & MOD_LSHIFT) ? STATE_DOWN : 0;
 3640     aKeyState[VK_RSHIFT] = (aModifiersLR & MOD_RSHIFT) ? STATE_DOWN : 0;
 3641     aKeyState[VK_LCONTROL] = (aModifiersLR & MOD_LCONTROL) ? STATE_DOWN : 0;
 3642     aKeyState[VK_RCONTROL] = (aModifiersLR & MOD_RCONTROL) ? STATE_DOWN : 0;
 3643     aKeyState[VK_LMENU] = (aModifiersLR & MOD_LALT) ? STATE_DOWN : 0;
 3644     aKeyState[VK_RMENU] = (aModifiersLR & MOD_RALT) ? STATE_DOWN : 0;
 3645     aKeyState[VK_LWIN] = (aModifiersLR & MOD_LWIN) ? STATE_DOWN : 0;
 3646     aKeyState[VK_RWIN] = (aModifiersLR & MOD_RWIN) ? STATE_DOWN : 0;
 3647     // Update the state of neutral keys only after the above, in case both keys of the pair were wrongly down:
 3648     aKeyState[VK_SHIFT] = (aKeyState[VK_LSHIFT] || aKeyState[VK_RSHIFT]) ? STATE_DOWN : 0;
 3649     aKeyState[VK_CONTROL] = (aKeyState[VK_LCONTROL] || aKeyState[VK_RCONTROL]) ? STATE_DOWN : 0;
 3650     aKeyState[VK_MENU] = (aKeyState[VK_LMENU] || aKeyState[VK_RMENU]) ? STATE_DOWN : 0;
 3651 }
 3652 
 3653 
 3654 
 3655 modLR_type KeyToModifiersLR(vk_type aVK, sc_type aSC, bool *pIsNeutral)
 3656 // Convert the given virtual key / scan code to its equivalent bitwise modLR value.
 3657 // Callers rely upon the fact that we convert a neutral key such as VK_SHIFT into MOD_LSHIFT,
 3658 // not the bitwise combo of MOD_LSHIFT|MOD_RSHIFT.
 3659 // v1.0.43: VK_SHIFT should yield MOD_RSHIFT if the caller explicitly passed the right vs. left scan code.
 3660 // The SendPlay method relies on this to properly release AltGr, such as after "SendPlay @" in German.
 3661 // Other things may also rely on it because it is more correct.
 3662 {
 3663     bool placeholder;
 3664     bool &is_neutral = pIsNeutral ? *pIsNeutral : placeholder; // Simplifies other things below.
 3665     is_neutral = false; // Set default for output parameter for caller.
 3666 
 3667     if (!(aVK || aSC))
 3668         return 0;
 3669 
 3670     if (aVK) // Have vk take precedence over any non-zero sc.
 3671         switch(aVK)
 3672         {
 3673         case VK_SHIFT:
 3674             if (aSC == SC_RSHIFT)
 3675                 return MOD_RSHIFT;
 3676             //else aSC is omitted (0) or SC_LSHIFT.  Either way, most callers would probably want that considered "neutral".
 3677             is_neutral = true;
 3678             return MOD_LSHIFT;
 3679         case VK_LSHIFT: return MOD_LSHIFT;
 3680         case VK_RSHIFT: return MOD_RSHIFT;
 3681 
 3682         case VK_CONTROL:
 3683             if (aSC == SC_RCONTROL)
 3684                 return MOD_RCONTROL;
 3685             //else aSC is omitted (0) or SC_LCONTROL.  Either way, most callers would probably want that considered "neutral".
 3686             is_neutral = true;
 3687             return MOD_LCONTROL;
 3688         case VK_LCONTROL: return MOD_LCONTROL;
 3689         case VK_RCONTROL: return MOD_RCONTROL;
 3690 
 3691         case VK_MENU:
 3692             if (aSC == SC_RALT)
 3693                 return MOD_RALT;
 3694             //else aSC is omitted (0) or SC_LALT.  Either way, most callers would probably want that considered "neutral".
 3695             is_neutral = true;
 3696             return MOD_LALT;
 3697         case VK_LMENU: return MOD_LALT;
 3698         case VK_RMENU: return MOD_RALT;
 3699 
 3700         case VK_LWIN: return MOD_LWIN;
 3701         case VK_RWIN: return MOD_RWIN;
 3702 
 3703         default:
 3704             return 0;
 3705         }
 3706 
 3707     // If above didn't return, rely on the scan code instead, which is now known to be non-zero.
 3708     switch(aSC)
 3709     {
 3710     case SC_LSHIFT: return MOD_LSHIFT;
 3711     case SC_RSHIFT: return MOD_RSHIFT;
 3712     case SC_LCONTROL: return MOD_LCONTROL;
 3713     case SC_RCONTROL: return MOD_RCONTROL;
 3714     case SC_LALT: return MOD_LALT;
 3715     case SC_RALT: return MOD_RALT;
 3716     case SC_LWIN: return MOD_LWIN;
 3717     case SC_RWIN: return MOD_RWIN;
 3718     }
 3719     return 0;
 3720 }
 3721 
 3722 
 3723 
 3724 modLR_type ConvertModifiers(mod_type aModifiers)
 3725 // Convert the input param to a modifiersLR value and return it.
 3726 {
 3727     modLR_type modifiersLR = 0;
 3728     if (aModifiers & MOD_WIN) modifiersLR |= (MOD_LWIN | MOD_RWIN);
 3729     if (aModifiers & MOD_ALT) modifiersLR |= (MOD_LALT | MOD_RALT);
 3730     if (aModifiers & MOD_CONTROL) modifiersLR |= (MOD_LCONTROL | MOD_RCONTROL);
 3731     if (aModifiers & MOD_SHIFT) modifiersLR |= (MOD_LSHIFT | MOD_RSHIFT);
 3732     return modifiersLR;
 3733 }
 3734 
 3735 
 3736 
 3737 mod_type ConvertModifiersLR(modLR_type aModifiersLR)
 3738 // Convert the input param to a normal modifiers value and return it.
 3739 {
 3740     mod_type modifiers = 0;
 3741     if (aModifiersLR & (MOD_LWIN | MOD_RWIN)) modifiers |= MOD_WIN;
 3742     if (aModifiersLR & (MOD_LALT | MOD_RALT)) modifiers |= MOD_ALT;
 3743     if (aModifiersLR & (MOD_LSHIFT | MOD_RSHIFT)) modifiers |= MOD_SHIFT;
 3744     if (aModifiersLR & (MOD_LCONTROL | MOD_RCONTROL)) modifiers |= MOD_CONTROL;
 3745     return modifiers;
 3746 }
 3747 
 3748 
 3749 
 3750 LPTSTR ModifiersLRToText(modLR_type aModifiersLR, LPTSTR aBuf)
 3751 // Caller has ensured that aBuf is not NULL.
 3752 {
 3753     *aBuf = '\0';
 3754     if (aModifiersLR & MOD_LWIN) _tcscat(aBuf, _T("LWin "));
 3755     if (aModifiersLR & MOD_RWIN) _tcscat(aBuf, _T("RWin "));
 3756     if (aModifiersLR & MOD_LSHIFT) _tcscat(aBuf, _T("LShift "));
 3757     if (aModifiersLR & MOD_RSHIFT) _tcscat(aBuf, _T("RShift "));
 3758     if (aModifiersLR & MOD_LCONTROL) _tcscat(aBuf, _T("LCtrl "));
 3759     if (aModifiersLR & MOD_RCONTROL) _tcscat(aBuf, _T("RCtrl "));
 3760     if (aModifiersLR & MOD_LALT) _tcscat(aBuf, _T("LAlt "));
 3761     if (aModifiersLR & MOD_RALT) _tcscat(aBuf, _T("RAlt "));
 3762     return aBuf;
 3763 }
 3764 
 3765 
 3766 
 3767 DWORD GetFocusedCtrlThread(HWND *apControl, HWND aWindow)
 3768 {
 3769     // Determine the thread for which we want the keyboard layout.
 3770     // When no foreground window, the script's own layout seems like the safest default.
 3771     DWORD thread_id = 0;
 3772     if (aWindow)
 3773     {
 3774         // Get thread of aWindow (which should be the foreground window).
 3775         thread_id = GetWindowThreadProcessId(aWindow, NULL);
 3776         // Get focus.  Benchmarks showed this additional step added only 6% to the time,
 3777         // and the total was only around 4µs per iteration anyway (on a Core i5-4460).
 3778         // It is necessary for UWP apps such as Microsoft Edge, and any others where
 3779         // the top-level window belongs to a different thread than the focused control.
 3780         GUITHREADINFO thread_info;
 3781         thread_info.cbSize = sizeof(thread_info);
 3782         if (GetGUIThreadInfo(thread_id, &thread_info))
 3783         {
 3784             if (thread_info.hwndFocus)
 3785             {
 3786                 // Use the focused control's thread.
 3787                 thread_id = GetWindowThreadProcessId(thread_info.hwndFocus, NULL);
 3788                 if (apControl)
 3789                     *apControl = thread_info.hwndFocus;
 3790             }
 3791         }
 3792     }
 3793     return thread_id;
 3794 }
 3795 
 3796 
 3797 
 3798 HKL GetFocusedKeybdLayout(HWND aWindow)
 3799 {
 3800     return GetKeyboardLayout(GetFocusedCtrlThread(NULL, aWindow));
 3801 }
 3802 
 3803 
 3804 
 3805 bool ActiveWindowLayoutHasAltGr()
 3806 // Thread-safety: See comments in LayoutHasAltGr() below.
 3807 {
 3808     Get_active_window_keybd_layout // Defines the variable active_window_keybd_layout for use below.
 3809     return LayoutHasAltGr(active_window_keybd_layout) == CONDITION_TRUE; // i.e caller wants both CONDITION_FALSE and LAYOUT_UNDETERMINED to be considered non-AltGr.
 3810 }
 3811 
 3812 
 3813 
 3814 HMODULE LoadKeyboardLayoutModule(HKL aLayout)
 3815 // Loads a keyboard layout DLL and returns its handle.
 3816 // Activates the layout as a side-effect, but reverts it if !aSideEffectsOK.
 3817 {
 3818     HMODULE hmod = NULL;
 3819     // Unfortunately activating the layout seems to be the only way to retrieve it's name.
 3820     // This may have side-effects in general (such as the language selector flickering),
 3821     // but shouldn't have any in our case since we're only changing layouts for our thread,
 3822     // and only if some other window is active (because if our window was active, aLayout
 3823     // is already the current layout).
 3824     if (HKL old_layout = ActivateKeyboardLayout(aLayout, 0))
 3825     {
 3826         #define KEYBOARD_LAYOUTS_REG_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\")
 3827         const size_t prefix_length = _countof(KEYBOARD_LAYOUTS_REG_KEY) - 1;
 3828         TCHAR keyname[prefix_length + KL_NAMELENGTH];
 3829         _tcscpy(keyname, KEYBOARD_LAYOUTS_REG_KEY);
 3830         if (GetKeyboardLayoutName(keyname + prefix_length))
 3831         {
 3832             TCHAR layout_file[MAX_PATH]; // It's probably much smaller (like "KBDUSX.dll"), but who knows what whacky custom layouts exist?
 3833             if (ReadRegString(HKEY_LOCAL_MACHINE, keyname, _T("Layout File"), layout_file, _countof(layout_file)))
 3834             {
 3835                 hmod = LoadLibrary(layout_file);
 3836             }
 3837         }
 3838         if (aLayout != old_layout)
 3839             ActivateKeyboardLayout(old_layout, 0); // Nothing we can do if it fails.
 3840     }
 3841     return hmod;
 3842 }
 3843 
 3844 
 3845 
 3846 ResultType LayoutHasAltGrDirect(HKL aLayout)
 3847 // Loads and reads the keyboard layout DLL to determine if it has AltGr.
 3848 // Activates the layout as a side-effect, but reverts it if !aSideEffectsOK.
 3849 // This is fast enough that there's no need to cache these values on startup.
 3850 {
 3851     // This abbreviated definition is based on the actual definition in kbd.h (Windows DDK):
 3852     // Updated to use two separate struct definitions, since the pointers are qualified with
 3853     // KBD_LONG_POINTER, which is 64-bit when building for Wow64 (32-bit dll on 64-bit system).
 3854     typedef UINT64 KLP64;
 3855     typedef UINT KLP32;
 3856 
 3857     // Struct used on 64-bit systems (by both 32-bit and 64-bit programs):
 3858     struct KBDTABLES64 {
 3859         KLP64 pCharModifiers;
 3860         KLP64 pVkToWcharTable;
 3861         KLP64 pDeadKey;
 3862         KLP64 pKeyNames;
 3863         KLP64 pKeyNamesExt;
 3864         KLP64 pKeyNamesDead;
 3865         KLP64 pusVSCtoVK;
 3866         BYTE  bMaxVSCtoVK;
 3867         KLP64 pVSCtoVK_E0;
 3868         KLP64 pVSCtoVK_E1;
 3869         // This is the one we want:
 3870         DWORD fLocaleFlags;
 3871         // Struct definition truncated.
 3872     };
 3873 
 3874     // Struct used on 32-bit systems:
 3875     struct KBDTABLES32 {
 3876         KLP32 pCharModifiers;
 3877         KLP32 pVkToWcharTable;
 3878         KLP32 pDeadKey;
 3879         KLP32 pKeyNames;
 3880         KLP32 pKeyNamesExt;
 3881         KLP32 pKeyNamesDead;
 3882         KLP32 pusVSCtoVK;
 3883         BYTE  bMaxVSCtoVK;
 3884         KLP32 pVSCtoVK_E0;
 3885         KLP32 pVSCtoVK_E1;
 3886         // This is the one we want:
 3887         DWORD fLocaleFlags;
 3888         // Struct definition truncated.
 3889     };
 3890     
 3891     #define KLLF_ALTGR 0x0001 // Also defined in kbd.h.
 3892     typedef PVOID (* KbdLayerDescriptorType)();
 3893 
 3894     ResultType result = LAYOUT_UNDETERMINED;
 3895 
 3896     if (HMODULE hmod = LoadKeyboardLayoutModule(aLayout))
 3897     {
 3898         KbdLayerDescriptorType kbdLayerDescriptor = (KbdLayerDescriptorType)GetProcAddress(hmod, "KbdLayerDescriptor");
 3899         if (kbdLayerDescriptor)
 3900         {
 3901             PVOID kl = kbdLayerDescriptor();
 3902             DWORD flags = IsOS64Bit() ? ((KBDTABLES64 *)kl)->fLocaleFlags : ((KBDTABLES32 *)kl)->fLocaleFlags;
 3903             result = (flags & KLLF_ALTGR) ? CONDITION_TRUE : CONDITION_FALSE;
 3904         }
 3905         FreeLibrary(hmod);
 3906     }
 3907     return result;
 3908 }
 3909 
 3910 
 3911 
 3912 ResultType LayoutHasAltGr(HKL aLayout, ResultType aHasAltGr)
 3913 // Thread-safety: While not thoroughly thread-safe, due to the extreme simplicity of the cache array, even if
 3914 // a collision occurs it should be inconsequential.
 3915 // Caller must ensure that aLayout is a valid layout (special values like 0 aren't supported here).
 3916 // If aHasAltGr is not at its default of LAYOUT_UNDETERMINED, the specified layout's has_altgr property is
 3917 // updated to the new value, but only if it is currently undetermined (callers can rely on this).
 3918 {
 3919     // Layouts are cached for performance (to avoid the discovery loop later below).
 3920     int i;
 3921     for (i = 0; i < MAX_CACHED_LAYOUTS && sCachedLayout[i].hkl; ++i)
 3922         if (sCachedLayout[i].hkl == aLayout) // Match Found.
 3923         {
 3924             if (aHasAltGr != LAYOUT_UNDETERMINED && sCachedLayout[i].has_altgr == LAYOUT_UNDETERMINED) // Caller relies on this.
 3925                 sCachedLayout[i].has_altgr = aHasAltGr;
 3926             return sCachedLayout[i].has_altgr;
 3927         }
 3928 
 3929     // Since above didn't return, this layout isn't cached yet.  So create a new cache entry for it and
 3930     // determine whether this layout has an AltGr key.  If i<MAX_CACHED_LAYOUTS (which it almost always will be),
 3931     // there's room in the array for a new cache entry.  In the very unlikely event that there isn't room,
 3932     // overwrite an arbitrary item in the array.  An LRU/MRU algorithm (timestamp) isn't used because running out
 3933     // of slots seems too unlikely, and the consequences of running out are merely a slight degradation in performance.
 3934     CachedLayoutType &cl = sCachedLayout[(i < MAX_CACHED_LAYOUTS) ? i : MAX_CACHED_LAYOUTS-1];
 3935     if (aHasAltGr != LAYOUT_UNDETERMINED) // Caller determined it for us.  See top of function for explanation.
 3936     {
 3937         cl.hkl = aLayout;
 3938         return cl.has_altgr = aHasAltGr;
 3939     }
 3940 
 3941     // Otherwise, do AltGr detection on this newly cached layout so that we can return the AltGr state to caller.
 3942     // This detection is probably not 100% reliable because there may be some layouts (especially custom ones)
 3943     // that have an AltGr key yet none of its characters actually require AltGr to manifest.  A more reliable
 3944     // way to detect AltGr would be to simulate an RALT keystroke (maybe only an up event, not a down) and have
 3945     // a keyboard hook catch and block it.  If the layout has altgr, the hook would see a driver-generated LCtrl
 3946     // keystroke immediately prior to RAlt.
 3947     // Performance: This loop is quite fast. Doing this section 1000 times only takes about 160ms
 3948     // on a 2gHz system (0.16ms per call).  UPDATE: In theory, it can be 256 (that is, around WCHAR_MAX/UCHAR_MAX)
 3949     // times slower on Unicode builds, so an alternative method is used there.
 3950 #ifdef _UNICODE
 3951     // Read the AltGr value directly from the keyboard layout DLL.
 3952     // This method has been compared to the VkKeyScanEx method and another one using Send and hotkeys,
 3953     // and was found to have 100% accuracy for the 203 standard layouts on Windows 10, whereas the
 3954     // VkKeyScanEx method failed for two layouts:
 3955     //   - N'Ko has AltGr but does not appear to use it for anything.
 3956     //   - Ukrainian has AltGr but only uses it for one character, which is also assigned to a naked
 3957     //     VK (so VkKeyScanEx returns that one).  Likely the key in question is absent from some keyboards.
 3958     cl.has_altgr = LayoutHasAltGrDirect(aLayout);
 3959 #else
 3960     // Use the old VkKeyScanEx method on ANSI builds since it is faster and has smaller code size.
 3961     SHORT s;
 3962     for (cl.has_altgr = LAYOUT_UNDETERMINED, i = 32; i <= UorA(WCHAR_MAX,UCHAR_MAX); ++i) // Include Spacebar up through final ANSI character (i.e. include 255 but not 256).
 3963     {
 3964         s = VkKeyScanEx((TCHAR)i, aLayout);
 3965         // Check for presence of Ctrl+Alt but allow other modifiers like Shift to be present because
 3966         // I believe there are some layouts that manifest characters via Shift+AltGr.
 3967         if (s != -1 && (s & 0x600) == 0x600) // In this context, Ctrl+Alt means AltGr.
 3968         {
 3969             cl.has_altgr = CONDITION_TRUE;
 3970             break;
 3971         }
 3972     }
 3973 #endif
 3974     // If loop didn't break, leave cl.has_altgr as LAYOUT_UNDETERMINED because we can't be sure whether AltGr is
 3975     // present (see other comments for details).
 3976     cl.hkl = aLayout; // This is done here (immediately after has_altgr was set in the loop above) rather than earlier to minimize the consequences of not being fully thread-safe.
 3977     return cl.has_altgr;
 3978 }
 3979 
 3980 
 3981 
 3982 LPTSTR SCtoKeyName(sc_type aSC, LPTSTR aBuf, int aBufSize, bool aUseFallback)
 3983 // aBufSize is an int so that any negative values passed in from caller are not lost.
 3984 // Always produces a non-empty string.
 3985 {
 3986     for (int i = 0; i < g_key_to_sc_count; ++i)
 3987     {
 3988         if (g_key_to_sc[i].sc == aSC)
 3989         {
 3990             tcslcpy(aBuf, g_key_to_sc[i].key_name, aBufSize);
 3991             return aBuf;
 3992         }
 3993     }
 3994     // Since above didn't return, no match was found.  Use the default format for an unknown scan code:
 3995     if (aUseFallback)
 3996         sntprintf(aBuf, aBufSize, _T("sc%03X"), aSC);
 3997     else
 3998         *aBuf = '\0';
 3999     return aBuf;
 4000 }
 4001 
 4002 
 4003 
 4004 LPTSTR VKtoKeyName(vk_type aVK, LPTSTR aBuf, int aBufSize, bool aUseFallback)
 4005 // aBufSize is an int so that any negative values passed in from caller are not lost.
 4006 // Caller may omit aSC and it will be derived if needed.
 4007 {
 4008     for (int i = 0; i < g_key_to_vk_count; ++i)
 4009     {
 4010         if (g_key_to_vk[i].vk == aVK)
 4011         {
 4012             tcslcpy(aBuf, g_key_to_vk[i].key_name, aBufSize);
 4013             return aBuf;
 4014         }
 4015     }
 4016     // Since above didn't return, no match was found.  Try to map it to
 4017     // a character or use the default format for an unknown key code:
 4018     if (*aBuf = VKtoChar(aVK))
 4019         aBuf[1] = '\0';
 4020     else if (aUseFallback && aVK)
 4021         sntprintf(aBuf, aBufSize, _T("vk%02X"), aVK);
 4022     else
 4023         *aBuf = '\0';
 4024     return aBuf;
 4025 }
 4026 
 4027 
 4028 TCHAR VKtoChar(vk_type aVK, HKL aKeybdLayout)
 4029 // Given a VK code, returns the character that an unmodified keypress would produce
 4030 // on the given keyboard layout.  Defaults to the script's own layout if omitted.
 4031 // Using this rather than MapVirtualKey() fixes some inconsistency that used to
 4032 // exist between 'A'-'Z' and every other key.
 4033 {
 4034     if (!aKeybdLayout)
 4035         aKeybdLayout = GetKeyboardLayout(0);
 4036     
 4037     // MapVirtualKeyEx() always produces 'A'-'Z' for those keys regardless of keyboard layout,
 4038     // but for any other keys it produces the correct results, so we'll use it:
 4039     if (aVK > 'Z' || aVK < 'A')
 4040         return (TCHAR)MapVirtualKeyEx(aVK, MAPVK_VK_TO_CHAR, aKeybdLayout);
 4041 
 4042     // For any other keys, 
 4043     TCHAR ch[3], ch_not_used[2];
 4044     BYTE key_state[256];
 4045     ZeroMemory(key_state, sizeof(key_state));
 4046     TCHAR dead_char = 0;
 4047     int n;
 4048 
 4049     // If there's a pending dead-key char in aKeybdLayout's buffer, it would modify the result.
 4050     // We don't want that to happen, so as a workaround we pass a key-code which doesn't combine
 4051     // with any dead chars, and will therefore pull it out.  VK_DECIMAL is used because it is
 4052     // almost always valid; see http://www.siao2.com/2007/10/27/5717859.aspx
 4053     if (ToUnicodeOrAsciiEx(VK_DECIMAL, 0, key_state, ch, 0, aKeybdLayout) == 2)
 4054     {
 4055         // Save the char to be later re-injected.
 4056         dead_char = ch[0];
 4057     }
 4058     // Retrieve the character that corresponds to aVK, if any.
 4059     n = ToUnicodeOrAsciiEx(aVK, 0, key_state, ch, 0, aKeybdLayout);
 4060     if (n < 0) // aVK is a dead key, and we've just placed it into aKeybdLayout's buffer.
 4061     {
 4062         // Flush it out in the same manner as before (see above).
 4063         ToUnicodeOrAsciiEx(VK_DECIMAL, 0, key_state, ch_not_used, 0, aKeybdLayout);
 4064     }
 4065     if (dead_char)
 4066     {
 4067         // Re-inject the dead-key char so that user input is not interrupted.
 4068         // To do this, we need to find the right VK and modifier key combination:
 4069         modLR_type modLR;
 4070         vk_type dead_vk = CharToVKAndModifiers(dead_char, &modLR, aKeybdLayout);
 4071         if (dead_vk)
 4072         {
 4073             AdjustKeyState(key_state, modLR);
 4074             ToUnicodeOrAsciiEx(dead_vk, 0, key_state, ch_not_used, 0, aKeybdLayout);
 4075         }
 4076         //else: can't do it.
 4077     }
 4078     // ch[0] is set even for n < 0, but might not be for n == 0.
 4079     return n ? ch[0] : 0;
 4080 }
 4081 
 4082 
 4083 
 4084 sc_type TextToSC(LPTSTR aText, bool *aSpecifiedByNumber)
 4085 {
 4086     if (!*aText) return 0;
 4087     for (int i = 0; i < g_key_to_sc_count; ++i)
 4088         if (!_tcsicmp(g_key_to_sc[i].key_name, aText))
 4089             return g_key_to_sc[i].sc;
 4090     // Do this only after the above, in case any valid key names ever start with SC:
 4091     if (ctoupper(*aText) == 'S' && ctoupper(*(aText + 1)) == 'C')
 4092     {
 4093         LPTSTR endptr;
 4094         sc_type sc = (sc_type)_tcstol(aText + 2, &endptr, 16);  // Convert from hex.
 4095         if (*endptr)
 4096             return 0; // Fixed for v1.1.27: Disallow any invalid suffix so that hotkeys like a::scb() are not misinterpreted as remappings.
 4097         if (aSpecifiedByNumber)
 4098             *aSpecifiedByNumber = true; // Override caller-set default.
 4099         return sc;
 4100     }
 4101     return 0; // Indicate "not found".
 4102 }
 4103 
 4104 
 4105 
 4106 vk_type TextToVK(LPTSTR aText, modLR_type *pModifiersLR, bool aExcludeThoseHandledByScanCode, bool aAllowExplicitVK
 4107     , HKL aKeybdLayout)
 4108 // If modifiers_p is non-NULL, place the modifiers that are needed to realize the key in there.
 4109 // e.g. M is really +m (shift-m), # is really shift-3.
 4110 // HOWEVER, this function does not completely overwrite the contents of pModifiersLR; instead, it just
 4111 // adds the required modifiers into whatever is already there.
 4112 {
 4113     if (!*aText) return 0;
 4114 
 4115     // Don't trim() aText or modify it because that will mess up the caller who expects it to be unchanged.
 4116     // Instead, for now, just check it as-is.  The only extra whitespace that should exist, due to trimming
 4117     // of text during load, is that on either side of the COMPOSITE_DELIMITER (e.g. " then ").
 4118 
 4119     if (!aText[1]) // _tcslen(aText) == 1
 4120         return CharToVKAndModifiers(*aText, pModifiersLR, aKeybdLayout); // Making this a function simplifies things because it can do early return, etc.
 4121 
 4122     if (aAllowExplicitVK && ctoupper(aText[0]) == 'V' && ctoupper(aText[1]) == 'K')
 4123     {
 4124         LPTSTR endptr;
 4125         vk_type vk = (vk_type)_tcstol(aText + 2, &endptr, 16);  // Convert from hex.
 4126         return *endptr ? 0 : vk; // Fixed for v1.1.27: Disallow any invalid suffix so that hotkeys like a::vkb() are not misinterpreted as remappings.
 4127     }
 4128 
 4129     for (int i = 0; i < g_key_to_vk_count; ++i)
 4130         if (!_tcsicmp(g_key_to_vk[i].key_name, aText))
 4131             return g_key_to_vk[i].vk;
 4132 
 4133     if (aExcludeThoseHandledByScanCode)
 4134         return 0; // Zero is not a valid virtual key, so it should be a safe failure indicator.
 4135 
 4136     // Otherwise check if aText is the name of a key handled by scan code and if so, map that
 4137     // scan code to its corresponding virtual key:
 4138     sc_type sc = TextToSC(aText);
 4139     return sc ? sc_to_vk(sc) : 0;
 4140 }
 4141 
 4142 
 4143 
 4144 vk_type CharToVKAndModifiers(TCHAR aChar, modLR_type *pModifiersLR, HKL aKeybdLayout, bool aEnableAZFallback)
 4145 // If non-NULL, pModifiersLR contains the initial set of modifiers provided by the caller, to which
 4146 // we add any extra modifiers required to realize aChar.
 4147 {
 4148     // For v1.0.25.12, it seems best to avoid the many recent problems with linefeed (`n) being sent
 4149     // as Ctrl+Enter by changing it to always send a plain Enter, just like carriage return (`r).
 4150     if (aChar == '\n')
 4151         return VK_RETURN;
 4152 
 4153     // Otherwise:
 4154     SHORT mod_plus_vk = VkKeyScanEx(aChar, aKeybdLayout); // v1.0.44.03: Benchmark shows that VkKeyScanEx() is the same speed as VkKeyScan() when the layout has been pre-fetched.
 4155     vk_type vk = LOBYTE(mod_plus_vk);
 4156     char keyscan_modifiers = HIBYTE(mod_plus_vk);
 4157     if (keyscan_modifiers == -1 && vk == (UCHAR)-1) // No translation could be made.
 4158     {
 4159         if (  !(aEnableAZFallback && cisalpha(aChar))  )
 4160             return 0;
 4161         // v1.1.27.00: Use the A-Z fallback; assume the user means vk41-vk5A, since these letters
 4162         // are commonly used to describe keyboard shortcuts even when these vk codes are actually
 4163         // mapped to other characters.  Our callers should pass false for aEnableAZFallback if
 4164         // they require a strict printable character->keycode mapping, such as for sending text.
 4165         vk = (vk_type)ctoupper(aChar);
 4166         keyscan_modifiers = cisupper(aChar) ? 0x01 : 0; // It's debatable whether the user intends this to be Shift+letter; this at least makes `Send ^A` consistent across (most?) layouts.
 4167     }
 4168     if (keyscan_modifiers & 0x38) // "The Hankaku key is pressed" or either of the "Reserved" state bits (for instance, used by Neo2 keyboard layout).
 4169         // Callers expect failure in this case so that a fallback method can be used.
 4170         return 0;
 4171 
 4172     // For v1.0.35, pModifiersLR was changed to modLR vs. mod so that AltGr keys such as backslash and
 4173     // '{' are supported on layouts such as German when sending to apps such as Putty that are fussy about
 4174     // which ALT key is held down to produce the character.  The following section detects AltGr by the
 4175     // assuming that any character that requires both CTRL and ALT (with optional SHIFT) to be held
 4176     // down is in fact an AltGr key (I don't think there are any that aren't AltGr in this case, but
 4177     // confirmation would be nice).
 4178 
 4179     // The win docs for VkKeyScan() are a bit confusing, referring to flag "bits" when it should really
 4180     // say flag "values".  In addition, it seems that these flag values are incompatible with
 4181     // MOD_ALT, MOD_SHIFT, and MOD_CONTROL, so they must be translated:
 4182     if (pModifiersLR) // The caller wants this info added to the output param.
 4183     {
 4184         // Best not to reset this value because some callers want to retain what was in it before,
 4185         // merely merging these new values into it:
 4186         //*pModifiers = 0;
 4187         if ((keyscan_modifiers & 0x06) == 0x06) // 0x06 means "requires/includes AltGr".
 4188         {
 4189             // v1.0.35: The critical difference below is right vs. left ALT.  Must not include MOD_LCONTROL
 4190             // because simulating the RAlt keystroke on these keyboard layouts will automatically
 4191             // press LControl down.
 4192             *pModifiersLR |= MOD_RALT;
 4193         }
 4194         else // Do normal/default translation.
 4195         {
 4196             // v1.0.40: If caller-supplied modifiers already include the right-side key, no need to
 4197             // add the left-side key (avoids unnecessary keystrokes).
 4198             if (   (keyscan_modifiers & 0x02) && !(*pModifiersLR & (MOD_LCONTROL|MOD_RCONTROL))   )
 4199                 *pModifiersLR |= MOD_LCONTROL; // Must not be done if requires_altgr==true, see above.
 4200             if (   (keyscan_modifiers & 0x04) && !(*pModifiersLR & (MOD_LALT|MOD_RALT))   )
 4201                 *pModifiersLR |= MOD_LALT;
 4202         }
 4203         // v1.0.36.06: Done unconditionally because presence of AltGr should not preclude the presence of Shift.
 4204         // v1.0.40: If caller-supplied modifiers already contains MOD_RSHIFT, no need to add LSHIFT (avoids
 4205         // unnecessary keystrokes).
 4206         if (   (keyscan_modifiers & 0x01) && !(*pModifiersLR & (MOD_LSHIFT|MOD_RSHIFT))   )
 4207             *pModifiersLR |= MOD_LSHIFT;
 4208     }
 4209     return vk;
 4210 }
 4211 
 4212 
 4213 
 4214 bool TextToVKandSC(LPTSTR aText, vk_type &aVK, sc_type &aSC, modLR_type *pModifiersLR, HKL aKeybdLayout)
 4215 {
 4216     if (aVK = TextToVK(aText, pModifiersLR, true, true, aKeybdLayout))
 4217     {
 4218         aSC = 0; // Caller should call vk_to_sc(aVK) if needed.
 4219         return true;
 4220     }
 4221     if (aSC = TextToSC(aText))
 4222     {
 4223         // Leave aVK set to 0.  Caller should call sc_to_vk(aSC) if needed.
 4224         return true;
 4225     }
 4226     if (!_tcsnicmp(aText, _T("VK"), 2)) // Could be vkXXscXXX, which TextToVK() does not permit in v1.1.27+.
 4227     {
 4228         LPTSTR cp;
 4229         vk_type vk = (vk_type)_tcstoul(aText + 2, &cp, 16);
 4230         if (!_tcsnicmp(cp, _T("SC"), 2))
 4231         {
 4232             sc_type sc = (sc_type)_tcstoul(cp + 2, &cp, 16);
 4233             if (!*cp) // No invalid suffix.
 4234             {
 4235                 aVK = vk;
 4236                 aSC = sc;
 4237                 return true;
 4238             }
 4239         }
 4240         else // Invalid suffix.  *cp!=0 is implied as vkXX would be handled by TextToVK().
 4241             return false;
 4242     }
 4243     return false;
 4244 }
 4245 
 4246 
 4247 
 4248 vk_type TextToSpecial(LPTSTR aText, size_t aTextLength, KeyEventTypes &aEventType, modLR_type &aModifiersLR
 4249     , bool aUpdatePersistent)
 4250 // Returns vk for key-down, negative vk for key-up, or zero if no translation.
 4251 // We also update whatever's in *pModifiers and *pModifiersLR to reflect the type of key-action
 4252 // specified in <aText>.  This makes it so that {altdown}{esc}{altup} behaves the same as !{esc}.
 4253 // Note that things like LShiftDown are not supported because: 1) they are rarely needed; and 2)
 4254 // they can be down via "lshift down".
 4255 {
 4256     if (!tcslicmp(aText, _T("ALTDOWN"), aTextLength))
 4257     {
 4258         if (aUpdatePersistent)
 4259             if (!(aModifiersLR & (MOD_LALT | MOD_RALT))) // i.e. do nothing if either left or right is already present.
 4260                 aModifiersLR |= MOD_LALT; // If neither is down, use the left one because it's more compatible.
 4261         aEventType = KEYDOWN;
 4262         return VK_MENU;
 4263     }
 4264     if (!tcslicmp(aText, _T("ALTUP"), aTextLength))
 4265     {
 4266         // Unlike for Lwin/Rwin, it seems best to have these neutral keys (e.g. ALT vs. LALT or RALT)
 4267         // restore either or both of the ALT keys into the up position.  The user can use {LAlt Up}
 4268         // to be more specific and avoid this behavior:
 4269         if (aUpdatePersistent)
 4270             aModifiersLR &= ~(MOD_LALT | MOD_RALT);
 4271         aEventType = KEYUP;
 4272         return VK_MENU;
 4273     }
 4274     if (!tcslicmp(aText, _T("SHIFTDOWN"), aTextLength))
 4275     {
 4276         if (aUpdatePersistent)
 4277             if (!(aModifiersLR & (MOD_LSHIFT | MOD_RSHIFT))) // i.e. do nothing if either left or right is already present.
 4278                 aModifiersLR |= MOD_LSHIFT; // If neither is down, use the left one because it's more compatible.
 4279         aEventType = KEYDOWN;
 4280         return VK_SHIFT;
 4281     }
 4282     if (!tcslicmp(aText, _T("SHIFTUP"), aTextLength))
 4283     {
 4284         if (aUpdatePersistent)
 4285             aModifiersLR &= ~(MOD_LSHIFT | MOD_RSHIFT); // See "ALTUP" for explanation.
 4286         aEventType = KEYUP;
 4287         return VK_SHIFT;
 4288     }
 4289     if (!tcslicmp(aText, _T("CTRLDOWN"), aTextLength) || !tcslicmp(aText, _T("CONTROLDOWN"), aTextLength))
 4290     {
 4291         if (aUpdatePersistent)
 4292             if (!(aModifiersLR & (MOD_LCONTROL | MOD_RCONTROL))) // i.e. do nothing if either left or right is already present.
 4293                 aModifiersLR |= MOD_LCONTROL; // If neither is down, use the left one because it's more compatible.
 4294         aEventType = KEYDOWN;
 4295         return VK_CONTROL;
 4296     }
 4297     if (!tcslicmp(aText, _T("CTRLUP"), aTextLength) || !tcslicmp(aText, _T("CONTROLUP"), aTextLength))
 4298     {
 4299         if (aUpdatePersistent)
 4300             aModifiersLR &= ~(MOD_LCONTROL | MOD_RCONTROL); // See "ALTUP" for explanation.
 4301         aEventType = KEYUP;
 4302         return VK_CONTROL;
 4303     }
 4304     if (!tcslicmp(aText, _T("LWINDOWN"), aTextLength))
 4305     {
 4306         if (aUpdatePersistent)
 4307             aModifiersLR |= MOD_LWIN;
 4308         aEventType = KEYDOWN;
 4309         return VK_LWIN;
 4310     }
 4311     if (!tcslicmp(aText, _T("LWINUP"), aTextLength))
 4312     {
 4313         if (aUpdatePersistent)
 4314             aModifiersLR &= ~MOD_LWIN;
 4315         aEventType = KEYUP;
 4316         return VK_LWIN;
 4317     }
 4318     if (!tcslicmp(aText, _T("RWINDOWN"), aTextLength))
 4319     {
 4320         if (aUpdatePersistent)
 4321             aModifiersLR |= MOD_RWIN;
 4322         aEventType = KEYDOWN;
 4323         return VK_RWIN;
 4324     }
 4325     if (!tcslicmp(aText, _T("RWINUP"), aTextLength))
 4326     {
 4327         if (aUpdatePersistent)
 4328             aModifiersLR &= ~MOD_RWIN;
 4329         aEventType = KEYUP;
 4330         return VK_RWIN;
 4331     }
 4332     // Otherwise, leave aEventType unchanged and return zero to indicate failure:
 4333     return 0;
 4334 }
 4335 
 4336 
 4337 
 4338 #ifdef ENABLE_KEY_HISTORY_FILE
 4339 ResultType KeyHistoryToFile(LPTSTR aFilespec, char aType, bool aKeyUp, vk_type aVK, sc_type aSC)
 4340 {
 4341     static TCHAR sTargetFilespec[MAX_PATH] = _T("");
 4342     static FILE *fp = NULL;
 4343     static HWND last_foreground_window = NULL;
 4344     static DWORD last_tickcount = GetTickCount();
 4345 
 4346     if (!g_KeyHistory) // Since key history is disabled, keys are not being tracked by the hook, so there's nothing to log.
 4347         return OK;     // Files should not need to be closed since they would never have been opened in the first place.
 4348 
 4349     if (!aFilespec && !aVK && !aSC) // Caller is signaling to close the file if it's open.
 4350     {
 4351         if (fp)
 4352         {
 4353             fclose(fp);
 4354             fp = NULL;
 4355         }
 4356         return OK;
 4357     }
 4358 
 4359     if (aFilespec && *aFilespec && lstrcmpi(aFilespec, sTargetFilespec)) // Target filename has changed.
 4360     {
 4361         if (fp)
 4362         {
 4363             fclose(fp);
 4364             fp = NULL;  // To indicate to future calls to this function that it's closed.
 4365         }
 4366         tcslcpy(sTargetFilespec, aFilespec, _countof(sTargetFilespec));
 4367     }
 4368 
 4369     if (!aVK && !aSC) // Caller didn't want us to log anything this time.
 4370         return OK;
 4371     if (!*sTargetFilespec)
 4372         return OK; // No target filename has ever been specified, so don't even attempt to open the file.
 4373 
 4374     if (!aVK)
 4375         aVK = sc_to_vk(aSC);
 4376     else
 4377         if (!aSC)
 4378             aSC = vk_to_sc(aVK);
 4379 
 4380     TCHAR buf[2048] = _T(""), win_title[1024] = _T("<Init>"), key_name[128] = _T("");
 4381     HWND curr_foreground_window = GetForegroundWindow();
 4382     DWORD curr_tickcount = GetTickCount();
 4383     bool log_changed_window = (curr_foreground_window != last_foreground_window);
 4384     if (log_changed_window)
 4385     {
 4386         if (curr_foreground_window)
 4387             GetWindowText(curr_foreground_window, win_title, _countof(win_title));
 4388         else
 4389             tcslcpy(win_title, _T("<None>"), _countof(win_title));
 4390         last_foreground_window = curr_foreground_window;
 4391     }
 4392 
 4393     sntprintf(buf, _countof(buf), _T("%02X") _T("\t%03X") _T("\t%0.2f") _T("\t%c") _T("\t%c") _T("\t%s") _T("%s%s\n")
 4394         , aVK, aSC
 4395         , (float)(curr_tickcount - last_tickcount) / (float)1000
 4396         , aType
 4397         , aKeyUp ? 'u' : 'd'
 4398         , GetKeyName(aVK, aSC, key_name, sizeof(key_name))
 4399         , log_changed_window ? _T("\t") : _T("")
 4400         , log_changed_window ? win_title : _T("")
 4401         );
 4402     last_tickcount = curr_tickcount;
 4403     if (!fp)
 4404         if (   !(fp = _tfopen(sTargetFilespec, _T("a")))   )
 4405             return OK;
 4406     _fputts(buf, fp);
 4407     return OK;
 4408 }
 4409 #endif
 4410 
 4411 
 4412 
 4413 LPTSTR GetKeyName(vk_type aVK, sc_type aSC, LPTSTR aBuf, int aBufSize, LPTSTR aDefault)
 4414 // aBufSize is an int so that any negative values passed in from caller are not lost.
 4415 // Caller has ensured that aBuf isn't NULL.
 4416 {
 4417     if (aBufSize < 3)
 4418         return aBuf;
 4419 
 4420     *aBuf = '\0'; // Set default.
 4421     if (!aVK && !aSC)
 4422         return aBuf;
 4423 
 4424     if (!aVK)
 4425         aVK = sc_to_vk(aSC);
 4426     else
 4427         if (!aSC)
 4428             aSC = vk_to_sc(aVK);
 4429 
 4430     // Check SC first to properly differentiate between Home/NumpadHome, End/NumpadEnd, etc.
 4431     // v1.0.43: WheelDown/Up store the notch/turn count in SC, so don't consider that to be a valid SC.
 4432     if (aSC && !IS_WHEEL_VK(aVK))
 4433     {
 4434         if (*SCtoKeyName(aSC, aBuf, aBufSize, false))
 4435             return aBuf;
 4436         // Otherwise this key is probably one we can handle by VK.
 4437     }
 4438     if (*VKtoKeyName(aVK, aBuf, aBufSize, false))
 4439         return aBuf;
 4440     // Since this key is unrecognized, return the caller-supplied default value.
 4441     return aDefault;
 4442 }
 4443 
 4444 
 4445 
 4446 sc_type vk_to_sc(vk_type aVK, bool aReturnSecondary)
 4447 // For v1.0.37.03, vk_to_sc() was converted into a function rather than being an array because if the
 4448 // script's keyboard layout changes while it's running, the array would get out-of-date.
 4449 // If caller passes true for aReturnSecondary, the non-primary scan code will be returned for
 4450 // virtual keys that two scan codes (if there's only one scan code, callers rely on zero being returned).
 4451 {
 4452     // Try to minimize the number mappings done manually because MapVirtualKey is a more reliable
 4453     // way to get the mapping if user has non-standard or custom keyboard layout.
 4454 
 4455     sc_type sc = 0;
 4456 
 4457     // Yield a manual translation for virtual keys that MapVirtualKey() doesn't support or for which it
 4458     // doesn't yield consistent result.
 4459     switch (aVK)
 4460     {
 4461     // Win9x is probably the main reason the modifier keys were handled this way -- testing indicates
 4462     // that MapVirtualKey() returns the correct result even on Win2k.  However, since Alt & Ctrl are
 4463     // distinguished by the extended key flag which MapVirtualKey() doesn't include, they would need
 4464     // to be at least partially handled here anyway.
 4465     case VK_LSHIFT:   sc = SC_LSHIFT; break; // Modifiers are listed first for performance.
 4466     case VK_RSHIFT:   sc = SC_RSHIFT; break;
 4467     case VK_LCONTROL: sc = SC_LCONTROL; break;
 4468     case VK_RCONTROL: sc = SC_RCONTROL; break;
 4469     case VK_LMENU:    sc = SC_LALT; break;
 4470     case VK_RMENU:    sc = SC_RALT; break;
 4471     case VK_LWIN:     sc = SC_LWIN; break;
 4472     case VK_RWIN:     sc = SC_RWIN; break;
 4473 
 4474     case VK_PAUSE:    sc = SC_PAUSE; break; // Added in v1.1.26.01.
 4475 
 4476     // According to http://support.microsoft.com/default.aspx?scid=kb;en-us;72583 (broken link)
 4477     // most or all numeric keypad keys cannot be mapped reliably under any OS. The article is
 4478     // a little unclear about which direction, if any, that MapVirtualKey() does work in for
 4479     // the numpad keys, so for peace-of-mind map them all manually for now:
 4480     // UPDATE: MapVirtualKey() passes testing on 2k and 10, except for the extended keys
 4481     // (NumpadDiv and Numlock).
 4482     case VK_NUMPAD0:  sc = SC_NUMPAD0; break;
 4483     case VK_NUMPAD1:  sc = SC_NUMPAD1; break;
 4484     case VK_NUMPAD2:  sc = SC_NUMPAD2; break;
 4485     case VK_NUMPAD3:  sc = SC_NUMPAD3; break;
 4486     case VK_NUMPAD4:  sc = SC_NUMPAD4; break;
 4487     case VK_NUMPAD5:  sc = SC_NUMPAD5; break;
 4488     case VK_NUMPAD6:  sc = SC_NUMPAD6; break;
 4489     case VK_NUMPAD7:  sc = SC_NUMPAD7; break;
 4490     case VK_NUMPAD8:  sc = SC_NUMPAD8; break;
 4491     case VK_NUMPAD9:  sc = SC_NUMPAD9; break;
 4492     case VK_DECIMAL:  sc = SC_NUMPADDOT; break;
 4493     case VK_NUMLOCK:  sc = SC_NUMLOCK; break;
 4494     case VK_DIVIDE:   sc = SC_NUMPADDIV; break;
 4495     case VK_MULTIPLY: sc = SC_NUMPADMULT; break;
 4496     case VK_SUBTRACT: sc = SC_NUMPADSUB; break;
 4497     case VK_ADD:      sc = SC_NUMPADADD; break;
 4498 
 4499     // Added in v1.1.26.02 because MapVirtualKey returns the scan code for SysReq
 4500     // (which is what the key produces while Alt is held down):
 4501     case VK_SNAPSHOT: sc = SC_PRINTSCREEN; break;
 4502     }
 4503 
 4504     if (sc) // Above found a match.
 4505         return aReturnSecondary ? 0 : sc; // Callers rely on zero being returned for VKs that don't have secondary SCs.
 4506 
 4507     // Use the OS API's MapVirtualKey() to resolve any not manually done above:
 4508     if (   !(sc = MapVirtualKey(aVK, 0))   )
 4509         return 0; // Indicate "no mapping".
 4510 
 4511     // Turn on the extended flag for those that need it.
 4512     // Because MapVirtualKey can only accept (and return) naked scan codes (the low-order byte),
 4513     // handle extended scan codes that have a non-extended counterpart manually.
 4514     // Older comment: MapVirtualKey() should include 0xE0 in HIBYTE if key is extended, BUT IT DOESN'T.
 4515     // There doesn't appear to be any built-in function to determine whether a vk's scan code
 4516     // is extended or not.  See MSDN topic "keyboard input" for the below list.
 4517     // Note: NumpadEnter is probably the only extended key that doesn't have a unique VK of its own.
 4518     // So in that case, probably safest not to set the extended flag.  To send a true NumpadEnter,
 4519     // as well as a true NumPadDown and any other key that shares the same VK with another, the
 4520     // caller should specify the sc param to circumvent the need for KeyEvent() to use the below:
 4521     switch (aVK)
 4522     {
 4523     case VK_APPS:     // Application key on keyboards with LWIN/RWIN/Apps.  Not listed in MSDN as "extended"?
 4524     case VK_CANCEL:   // Ctrl-break
 4525     case VK_DIVIDE:   // NumpadDivide (slash)
 4526     case VK_NUMLOCK:
 4527     // Below are extended but were already handled and returned from higher above:
 4528     //case VK_LWIN:
 4529     //case VK_RWIN:
 4530     //case VK_RMENU:
 4531     //case VK_RCONTROL:
 4532     //case VK_RSHIFT: // WinXP needs this to be extended for keybd_event() to work properly.
 4533     // The rest are multimedia keys:
 4534     case VK_BROWSER_BACK:
 4535     case VK_BROWSER_FORWARD:
 4536     case VK_BROWSER_REFRESH:
 4537     case VK_BROWSER_STOP:
 4538     case VK_BROWSER_SEARCH:
 4539     case VK_BROWSER_FAVORITES:
 4540     case VK_BROWSER_HOME:
 4541     case VK_VOLUME_MUTE:
 4542     case VK_VOLUME_DOWN:
 4543     case VK_VOLUME_UP:
 4544     case VK_MEDIA_NEXT_TRACK:
 4545     case VK_MEDIA_PREV_TRACK:
 4546     case VK_MEDIA_STOP:
 4547     case VK_MEDIA_PLAY_PAUSE:
 4548     case VK_LAUNCH_MAIL:
 4549     case VK_LAUNCH_MEDIA_SELECT:
 4550     case VK_LAUNCH_APP1:
 4551     case VK_LAUNCH_APP2:
 4552         sc |= 0x0100;
 4553         break;
 4554 
 4555     // The following virtual keys have more than one physical key, and thus more than one scan code.
 4556     // If the caller passed true for aReturnSecondary, the extended version of the scan code will be
 4557     // returned (all of the following VKs have two SCs):
 4558     case VK_RETURN:
 4559     case VK_INSERT:
 4560     case VK_DELETE:
 4561     case VK_PRIOR: // PgUp
 4562     case VK_NEXT:  // PgDn
 4563     case VK_HOME:
 4564     case VK_END:
 4565     case VK_UP:
 4566     case VK_DOWN:
 4567     case VK_LEFT:
 4568     case VK_RIGHT:
 4569         return aReturnSecondary ? (sc | 0x0100) : sc; // Below relies on the fact that these cases return early.
 4570     }
 4571 
 4572     // Since above didn't return, if aReturnSecondary==true, return 0 to indicate "no secondary SC for this VK".
 4573     return aReturnSecondary ? 0 : sc; // Callers rely on zero being returned for VKs that don't have secondary SCs.
 4574 }
 4575 
 4576 
 4577 
 4578 vk_type sc_to_vk(sc_type aSC)
 4579 {
 4580     // These are mapped manually because MapVirtualKey() doesn't support them correctly, at least
 4581     // on some -- if not all -- OSs.  The main app also relies upon the values assigned below to
 4582     // determine which keys should be handled by scan code rather than vk:
 4583     switch (aSC)
 4584     {
 4585     // Some of the modifiers can be mapped with MapVirtualKey(), but the behaviour is not
 4586     // consistent for all modifiers across all OSes, so it seems best to handle them all here.
 4587     // For instance, LShift, LCtrl and LAlt can be mapped with MAPVK_VSC_TO_VK_EX, but RCtrl
 4588     // and RAlt must have 0x100 translated to 0xE000, which requires at least Windows Vista,
 4589     // while RShift only works as 0x36, not 0xE036, despite being an extended key.
 4590     case SC_LSHIFT:      return VK_LSHIFT; // Modifiers are listed first for performance.
 4591     case SC_RSHIFT:      return VK_RSHIFT;
 4592     case SC_LCONTROL:    return VK_LCONTROL;
 4593     case SC_RCONTROL:    return VK_RCONTROL;
 4594     case SC_LALT:        return VK_LMENU;
 4595     case SC_RALT:        return VK_RMENU;
 4596 
 4597     // These require explicit mapping on 2k/XP since (aSC & 0xFF) produces the wrong VK,
 4598     // but would work on Vista and later with 0x100 translated to 0xE000:
 4599     case SC_LWIN:        return VK_LWIN;
 4600     case SC_RWIN:        return VK_RWIN;
 4601 
 4602     case SC_NUMLOCK:     return VK_NUMLOCK; // Requires explicit mapping even on Windows 10.
 4603     case SC_NUMPADDIV:   return VK_DIVIDE; // Requires explicit mapping on 2k/XP (see above).
 4604 
 4605     // These are handled correctly by MapVirtualKey(), but are kept here to ensure consistency
 4606     // with the other Numpad keys (such as with unconventional custom keyboard layouts, in theory):
 4607     case SC_NUMPADENTER: return VK_RETURN; // Same VK as SC_ENTER, which is handled by MapVirtualKey().
 4608     case SC_NUMPADMULT:  return VK_MULTIPLY; // Only this key has this SC.
 4609     case SC_NUMPADSUB:   return VK_SUBTRACT; //
 4610     case SC_NUMPADADD:   return VK_ADD;      //
 4611 
 4612     // The following are ambiguous because the mapping depends on Numlock.  But be careful
 4613     // changing the value to the other choice because some callers rely upon the values
 4614     // assigned below to determine which keys should be handled by scan code rather than vk.
 4615     // For that reason, this is done manually even though testing indicates that both of the
 4616     // MapVirtualKey() calls below would produce this same result (which is what happens for
 4617     // extended keys such as SC_DELETE).
 4618     case SC_NUMPADDEL:   return VK_DELETE;
 4619     case SC_NUMPADCLEAR: return VK_CLEAR;
 4620     case SC_NUMPADINS:   return VK_INSERT;
 4621     case SC_NUMPADUP:    return VK_UP;
 4622     case SC_NUMPADDOWN:  return VK_DOWN;
 4623     case SC_NUMPADLEFT:  return VK_LEFT;
 4624     case SC_NUMPADRIGHT: return VK_RIGHT;
 4625     case SC_NUMPADHOME:  return VK_HOME;
 4626     case SC_NUMPADEND:   return VK_END;
 4627     case SC_NUMPADPGUP:  return VK_PRIOR;
 4628     case SC_NUMPADPGDN:  return VK_NEXT;
 4629 
 4630     // No callers currently need the following alternate virtual key mappings.  If it is ever needed,
 4631     // could have a new aReturnSecondary parameter that if true, causes these to be returned rather
 4632     // than the above:
 4633     //case SC_NUMPADDEL:   return VK_DECIMAL;
 4634     //case SC_NUMPADCLEAR: return VK_NUMPAD5; // Same key as Numpad5 on most keyboards?
 4635     //case SC_NUMPADINS:   return VK_NUMPAD0;
 4636     //case SC_NUMPADUP:    return VK_NUMPAD8;
 4637     //case SC_NUMPADDOWN:  return VK_NUMPAD2;
 4638     //case SC_NUMPADLEFT:  return VK_NUMPAD4;
 4639     //case SC_NUMPADRIGHT: return VK_NUMPAD6;
 4640     //case SC_NUMPADHOME:  return VK_NUMPAD7;
 4641     //case SC_NUMPADEND:   return VK_NUMPAD1;
 4642     //case SC_NUMPADPGUP:  return VK_NUMPAD9;
 4643     //case SC_NUMPADPGDN:  return VK_NUMPAD3;   
 4644 
 4645     case SC_APPSKEY:    return VK_APPS; // Added in v1.1.17.00.
 4646     case SC_PAUSE:      return VK_PAUSE; // Added in v1.1.26.01.
 4647     case SC_PRINTSCREEN: return VK_SNAPSHOT; // Added in v1.1.26.02 to ensure consistency with vk_to_sc() and fix Win2k/XP.
 4648     }
 4649 
 4650     if (aSC & 0x100) // Our extended-key flag.
 4651     {
 4652         // This section was added in v1.1.26.01 to fix multimedia keys such as Volume_Up.
 4653         // Passing the 0xE000 extended scan code prefix should work on Vista and up, though
 4654         // this appears to have not made it into the documentation at MSDN.  Details can be
 4655         // found in archives of Michael Kaplan's blog (the original blog has been taken down):
 4656         // https://web.archive.org/web/20070219075710/http://blogs.msdn.com/michkap/archive/2006/08/29/729476.aspx
 4657         if (UINT vk = MapVirtualKey(0xE000 | (aSC & 0xFF), MAPVK_VSC_TO_VK))
 4658             return vk;
 4659         // Since MapVirtualKey's support for 0xE000 isn't properly documented, assume that
 4660         // it might fail even on Vista or later.  Fall back to the old method in that case.
 4661         // Testing shows that it always returns 0 on XP.
 4662     }
 4663     // Use the OS API call to resolve any not manually set above.  This should correctly
 4664     // resolve even elements such as SC_INSERT, which is an extended scan code, because
 4665     // it passes in only the low-order byte which is SC_NUMPADINS.  In the case of SC_INSERT
 4666     // and similar ones, MapVirtualKey() will return the same vk for both, which is correct.
 4667     // Only pass the LOBYTE because even if the OS supports an extended scan code, aSC uses
 4668     // our non-standard 0x100 rather than the standard 0xE000 (see above).
 4669     return MapVirtualKey((BYTE)aSC, MAPVK_VSC_TO_VK);
 4670 }