Beispiel #1
0
        private void InitByProcessName(string strName)
        {
            if (g_vProcessNamesUni == null)
            {
                g_vProcessNamesUni = new string[] {
                    "PuTTY",
                    "KiTTY", "KiTTY_Portable", "KiTTY_NoTrans",
                    "KiTTY_NoHyperlink", "KiTTY_NoCompress",
                    "PuTTYjp",
                    // "mRemoteNG", // No effect
                    // "PuTTYNG", // No effect

                    // SuperPuTTY spawns PuTTY processes whose windows are
                    // displayed embedded in the SuperPuTTY window (without
                    // window borders), thus the definition "PuTTY" also
                    // fixes SuperPuTTY; no "SuperPuTTY" required
                    // "SuperPuTTY",

                    "MinTTY"                     // Cygwin window "~"
                }
            }
            ;
            foreach (string str in g_vProcessNamesUni)
            {
                if (ProcessNameMatches(strName, str))
                {
                    m_sm = SiSendMethod.UnicodePacket;
                    return;
                }
            }

            if (g_vProcessNamesKeyRAlt == null)
            {
                g_vProcessNamesKeyRAlt = new string[] {
                    "MSTSC",                     // Remote Desktop Connection client
                    "VirtualBox",                // Oracle VirtualBox <= 5
                    "VirtualBoxVM",              // Oracle VirtualBox >= 6
                    "VpxClient",                 // VMware vSphere client

                    // VMware Player;
                    // https://sourceforge.net/p/keepass/discussion/329221/thread/c94e0f096e/
                    "VMware-VMX", "VMware-AuthD", "VMPlayer", "VMware-Unity-Helper",

                    // VMware Remote Console;
                    // https://sourceforge.net/p/keepass/bugs/1588/
                    "VMRC",

                    // Dameware Mini Remote Control;
                    // https://sourceforge.net/p/keepass/bugs/1874/
                    "DWRCC"
                }
            }
            ;
            foreach (string str in g_vProcessNamesKeyRAlt)
            {
                if (ProcessNameMatches(strName, str))
                {
                    m_sm = SiSendMethod.KeyEvent;
                    m_bCharsRAltAsCtrlAlt = true;
                    return;
                }
            }
        }
        private bool TrySendCharByKeypresses(char ch, bool?bDown)
        {
            if (ch == char.MinValue)
            {
                Debug.Assert(false); return(false);
            }

            SiSendMethod sm = GetSendMethod(m_swiCurrent);

            if (sm == SiSendMethod.UnicodePacket)
            {
                return(false);
            }

            if (m_vForcedUniChars == null)
            {
                m_vForcedUniChars = new char[] {
                    // All of the following diacritics are spacing / non-combining

                    '\u005E',                     // Circumflex ^
                    '\u0060',                     // Grave accent
                    '\u00A8',                     // Diaeresis
                    '\u00AF',                     // Macron above, long
                    '\u00B0',                     // Degree (e.g. for Czech)
                    '\u00B4',                     // Acute accent
                    '\u00B8',                     // Cedilla

                    // E.g. for US-International;
                    // https://sourceforge.net/p/keepass/discussion/329220/thread/5708e5ef/
                    '\u0022',                    // Quotation mark
                    '\u0027',                    // Apostrophe
                    '\u007E'                     // Tilde

                    // Spacing Modifier Letters; see below
                    // '\u02C7', // Caron (e.g. for Canadian Multilingual)
                    // '\u02C9', // Macron above, modifier, short
                    // '\u02CD', // Macron below, modifier, short
                    // '\u02D8', // Breve
                    // '\u02D9', // Dot above
                    // '\u02DA', // Ring above
                    // '\u02DB', // Ogonek
                    // '\u02DC', // Small tilde
                    // '\u02DD', // Double acute accent
                }
            }
            ;
            if (sm != SiSendMethod.KeyEvent)            // If Unicode packets allowed
            {
                if (Array.IndexOf <char>(m_vForcedUniChars, ch) >= 0)
                {
                    return(false);
                }

                // U+02B0 to U+02FF are Spacing Modifier Letters;
                // https://www.unicode.org/charts/PDF/U02B0.pdf
                // https://en.wikipedia.org/wiki/Spacing_Modifier_Letters
                if ((ch >= '\u02B0') && (ch <= '\u02FF'))
                {
                    return(false);
                }
            }

            IntPtr hKL = m_swiCurrent.KeyboardLayout;
            ushort u   = NativeMethods.VkKeyScan3(ch, hKL);

            if (u == 0xFFFFU)
            {
                return(false);
            }

            int vKey = (int)(u & 0xFFU);

            Keys kMod  = Keys.None;
            int  nMods = 0;

            if ((u & 0x100U) != 0U)
            {
                ++nMods; kMod |= Keys.Shift;
            }
            if ((u & 0x200U) != 0U)
            {
                ++nMods; kMod |= Keys.Control;
            }
            if ((u & 0x400U) != 0U)
            {
                ++nMods; kMod |= Keys.Alt;
            }
            if ((u & 0x800U) != 0U)
            {
                return(false);                               // Hankaku unsupported
            }
            // Do not send a key combination that is registered as hot key;
            // https://sourceforge.net/p/keepass/bugs/1235/
            // Windows shortcut hot keys involve at least 2 modifiers
            if (nMods >= 2)
            {
                Keys kFull = (kMod | (Keys)vKey);
                if (HotKeyManager.IsHotKeyRegistered(kFull, true))
                {
                    return(false);
                }
            }

            bool bShift    = ((kMod & Keys.Shift) != Keys.None);
            bool bCtrl     = ((kMod & Keys.Control) != Keys.None);
            bool bAlt      = ((kMod & Keys.Alt) != Keys.None);
            bool bCapsLock = false;

            // Windows' GetKeyboardState function does not return the
            // current virtual key array (especially not after changing
            // them below), thus we build the array on our own
            byte[] pbState = new byte[256];
            if (bShift)
            {
                pbState[NativeMethods.VK_SHIFT]  = 0x80;
                pbState[NativeMethods.VK_LSHIFT] = 0x80;
            }
            if (bCtrl && bAlt)            // Use RAlt as Ctrl+Alt
            {
                pbState[NativeMethods.VK_CONTROL] = 0x80;
                pbState[NativeMethods.VK_MENU]    = 0x80;
                pbState[NativeMethods.VK_RMENU]   = 0x80;
            }
            else
            {
                if (bCtrl)
                {
                    pbState[NativeMethods.VK_CONTROL]  = 0x80;
                    pbState[NativeMethods.VK_LCONTROL] = 0x80;
                }
                if (bAlt)
                {
                    pbState[NativeMethods.VK_MENU]  = 0x80;
                    pbState[NativeMethods.VK_LMENU] = 0x80;
                }
            }
            pbState[NativeMethods.VK_NUMLOCK] = 0x01;             // Toggled

            // The keypress that VkKeyScan returns may require a specific
            // state of toggle keys, on which it provides no information;
            // thus we now check whether the keypress will really result
            // in the character that we expect;
            // https://sourceforge.net/p/keepass/bugs/1594/
            string strUni = NativeMethods.ToUnicode3(vKey, pbState, hKL);

            if ((strUni != null) && (strUni.Length == 0))
            {
            }                                                            // Dead key
            else if (string.IsNullOrEmpty(strUni) || (strUni[strUni.Length - 1] != ch))
            {
                // Among the keyboard layouts that were tested, the
                // Czech one was the only one where the translation
                // may fail (due to dependency on the Caps Lock state)
                Debug.Assert(NativeMethods.GetPrimaryLangID((ushort)(hKL.ToInt64() &
                                                                     0xFFFFL)) == NativeMethods.LANG_CZECH);

                // Test whether Caps Lock is required
                pbState[NativeMethods.VK_CAPITAL] = 0x01;
                strUni = NativeMethods.ToUnicode3(vKey, pbState, hKL);
                if ((strUni != null) && (strUni.Length == 0))
                {
                }                                                                // Dead key
                else if (string.IsNullOrEmpty(strUni) || (strUni[strUni.Length - 1] != ch))
                {
                    Debug.Assert(false);                     // An unknown key modifier is required
                    return(false);
                }

                bCapsLock = true;
            }

            if (bCapsLock)
            {
                SendKeyImpl(NativeMethods.VK_CAPITAL, null, null);
                Thread.Sleep(1);
                Application.DoEvents();
            }

            Keys kModDiff = (kMod & ~m_kModCur);

            if (kModDiff != Keys.None)
            {
                // Send RAlt for better AltGr compatibility;
                // https://sourceforge.net/p/keepass/bugs/1475/
                SetKeyModifierImplEx(kModDiff, true, true);
                Thread.Sleep(1);
                Application.DoEvents();
            }

            SendKeyImpl(vKey, null, bDown);

            if (kModDiff != Keys.None)
            {
                Thread.Sleep(1);
                Application.DoEvents();
                SetKeyModifierImplEx(kModDiff, false, true);
            }

            if (bCapsLock)
            {
                Thread.Sleep(1);
                Application.DoEvents();
                SendKeyImpl(NativeMethods.VK_CAPITAL, null, null);
            }

            return(true);
        }
Beispiel #3
0
        private bool TrySendCharByKeypresses(char ch, bool?bDown, SiWindowInfo swi)
        {
            if (ch == char.MinValue)
            {
                Debug.Assert(false); return(false);
            }

            SiSendMethod sm = GetSendMethod(swi);

            if (sm == SiSendMethod.UnicodePacket)
            {
                return(false);
            }

            if (m_vForcedUniChars == null)
            {
                m_vForcedUniChars = new char[] {
                    // All of the following diacritics are spacing / non-combining

                    '\u00B4',                     // Acute accent
                    '\u02DD',                     // Double acute accent
                    '\u0060',                     // Grave accent
                    '\u02D8',                     // Breve
                    '\u00B8',                     // Cedilla
                    '\u005E',                     // Circumflex ^
                    '\u00A8',                     // Diaeresis
                    '\u02D9',                     // Dot above
                    '\u00AF',                     // Macron above, long
                    '\u02C9',                     // Macron above, modifier, short
                    '\u02CD',                     // Macron below, modifier, short
                    '\u02DB',                     // Ogonek

                    // E.g. for US-International;
                    // https://sourceforge.net/p/keepass/discussion/329220/thread/5708e5ef/
                    '\u0027',                    // Apostrophe
                    '\u0022',                    // Quotation mark
                    '\u007E'                     // Tilde
                }
            }
            ;
            if (sm != SiSendMethod.KeyEvent)            // If Unicode packets allowed
            {
                if (Array.IndexOf <char>(m_vForcedUniChars, ch) >= 0)
                {
                    return(false);
                }
            }

            IntPtr hKL = swi.KeyboardLayout;
            ushort u   = ((hKL == IntPtr.Zero) ? NativeMethods.VkKeyScan(ch) :
                          NativeMethods.VkKeyScanEx(ch, hKL));

            if (u == 0xFFFFU)
            {
                return(false);
            }

            int vKey = (int)(u & 0xFFU);

            Keys kMod  = Keys.None;
            int  nMods = 0;

            if ((u & 0x100U) != 0U)
            {
                ++nMods; kMod |= Keys.Shift;
            }
            if ((u & 0x200U) != 0U)
            {
                ++nMods; kMod |= Keys.Control;
            }
            if ((u & 0x400U) != 0U)
            {
                ++nMods; kMod |= Keys.Alt;
            }
            if ((u & 0x800U) != 0U)
            {
                return(false);                               // Hankaku unsupported
            }
            // Do not send a key combination that is registered as hot key;
            // https://sourceforge.net/p/keepass/bugs/1235/
            // Windows shortcut hot keys involve at least 2 modifiers
            if (nMods >= 2)
            {
                Keys kFull = (kMod | (Keys)vKey);
                if (HotKeyManager.IsHotKeyRegistered(kFull, true))
                {
                    return(false);
                }
            }

            Keys kModDiff = (kMod & ~m_kModCur);

            if (kModDiff != Keys.None)
            {
                // Send RAlt for better AltGr compatibility;
                // https://sourceforge.net/p/keepass/bugs/1475/
                SetKeyModifierImplEx(kModDiff, true, true);

                Thread.Sleep(1);
                Application.DoEvents();
            }

            SendKeyImpl(vKey, null, bDown);

            if (kModDiff != Keys.None)
            {
                Thread.Sleep(1);
                Application.DoEvents();

                SetKeyModifierImplEx(kModDiff, false, true);
            }

            return(true);
        }