예제 #1
0
		private static SiStateEx InitSendKeys()
		{
			SiStateEx si = new SiStateEx();

			try
			{
				EnsureSameKeyboardLayout(si);

				// Do not use SendKeys.Flush here, use Application.DoEvents
				// instead; SendKeys.Flush might run into an infinite loop here
				// if a previous auto-type process failed with throwing an
				// exception (SendKeys.Flush is waiting in a loop for an internal
				// queue being empty, however the queue is never processed)
				Application.DoEvents();

				List<int> lMod = GetActiveKeyModifiers();
				ActivateKeyModifiers(lMod, false);
				SpecialReleaseModifiers(lMod);

				si.InputBlocked = NativeMethods.BlockInput(true);
			}
			catch(Exception) { Debug.Assert(false); }

			return si;
		}
예제 #2
0
        // private const ushort LangIDGerman = 0x0407;

        public static void SendKeysWait(string strKeys, bool bObfuscate)
        {
            SiStateEx si = InitSendKeys();

            bool bUnix = KeePassLib.Native.NativeLib.IsUnix();

            try
            {
                if (!bUnix)
                {
                    Debug.Assert(GetActiveKeyModifiers().Count == 0);
                }

                strKeys = ExtractGlobalDelay(strKeys, si);                 // Before TCATO splitting

                if (bObfuscate)
                {
                    try { SendObfuscated(strKeys, si); }
                    catch (Exception) { SendKeysWithSpecial(strKeys, si); }
                }
                else
                {
                    SendKeysWithSpecial(strKeys, si);
                }
            }
            catch
            {
                FinishSendKeys(si);
                throw;
            }

            FinishSendKeys(si);
        }
예제 #3
0
        /// <summary>
        /// This method searches for a <c>{DELAY=X}</c> placeholder,
        /// removes it from the sequence and sets the global delay in
        /// <paramref name="siState" /> to X.
        /// </summary>
        private static string ExtractGlobalDelay(string strSequence, SiStateEx siState)
        {
            if (string.IsNullOrEmpty(strSequence))
            {
                return(string.Empty);
            }

            const string strDefDelay = @"(\{[Dd][Ee][Ll][Aa][Yy]\s*=\s*)(\d+)(\})";
            Match        mDefDelay   = Regex.Match(strSequence, strDefDelay);

            if (mDefDelay.Success)
            {
                string strTime = mDefDelay.Groups[2].Value;
                strSequence = Regex.Replace(strSequence, strDefDelay, string.Empty);

                uint uTime;
                if (uint.TryParse(strTime, out uTime))
                {
                    siState.DefaultDelay = uTime;
                }
                else
                {
                    Debug.Assert(false);
                }
            }

            return(strSequence);
        }
예제 #4
0
        private static void FinishSendKeys(SiStateEx si)
        {
            if (KeePassLib.Native.NativeLib.IsUnix())
            {
                return;
            }

            try
            {
                // Do not restore original modifier keys here, otherwise
                // modifier keys are restored even when the user released
                // them while KeePass is auto-typing!
                // ActivateKeyModifiers(lRestore, true);

                if (si.InputBlocked)
                {
                    NativeMethods.BlockInput(false);                                 // Unblock
                }
                // if(si.ThreadInputAttached)
                //	NativeMethods.AttachThreadInput(si.ThisThreadID,
                //		si.TargetThreadID, false); // Detach

                if (si.OriginalKeyboardLayout != IntPtr.Zero)
                {
                    NativeMethods.ActivateKeyboardLayout(si.OriginalKeyboardLayout, 0);
                }

                Application.DoEvents();
            }
            catch (Exception) { Debug.Assert(false); }
        }
예제 #5
0
        private static void EnsureSameKeyboardLayout(SiStateEx si)
        {
            IntPtr hWndTarget = NativeMethods.GetForegroundWindow();

            uint uTargetProcessId;
            uint uTargetThreadId = NativeMethods.GetWindowThreadProcessId(hWndTarget,
                                                                          out uTargetProcessId);

            IntPtr hklSelf   = NativeMethods.GetKeyboardLayout(0);
            IntPtr hklTarget = NativeMethods.GetKeyboardLayout(uTargetThreadId);

            si.CurrentKeyboardLayout = hklSelf;

            if (hklSelf != hklTarget)
            {
                si.OriginalKeyboardLayout = NativeMethods.ActivateKeyboardLayout(
                    hklTarget, 0);
                si.CurrentKeyboardLayout = hklTarget;

                Debug.Assert(si.OriginalKeyboardLayout == hklSelf);
            }

            // ushort uLangID = (ushort)(si.CurrentKeyboardLayout.ToInt64() & 0xFFFF);
            // si.EnableCaretWorkaround = (uLangID == LangIDGerman);
        }
예제 #6
0
        private static SiStateEx InitSendKeys()
        {
            SiStateEx si = new SiStateEx();

            try
            {
                EnsureSameKeyboardLayout(si);

                // Do not use SendKeys.Flush here, use Application.DoEvents
                // instead; SendKeys.Flush might run into an infinite loop here
                // if a previous auto-type process failed with throwing an
                // exception (SendKeys.Flush is waiting in a loop for an internal
                // queue being empty, however the queue is never processed)
                Application.DoEvents();

                List <int> lMod = GetActiveKeyModifiers();
                ActivateKeyModifiers(lMod, false);
                SpecialReleaseModifiers(lMod);

                si.InputBlocked = NativeMethods.BlockInput(true);
            }
            catch (Exception) { Debug.Assert(false); }

            return(si);
        }
예제 #7
0
        // private const ushort LangIDGerman = 0x0407;

        public static void SendKeysWait(string strKeys, bool bObfuscate)
        {
            if (KeePassLib.Native.NativeLib.IsUnix())
            {
                try { OSSendKeys(strKeys); }
                catch (Exception) { Debug.Assert(false); }
                return;
            }

            SiStateEx si = InitSendKeys();

            try
            {
                Debug.Assert(GetActiveKeyModifiers().Count == 0);

                if (bObfuscate)
                {
                    try { SendObfuscated(strKeys, si); }
                    catch (Exception) { SendKeysWithSpecial(strKeys, si); }
                }
                else
                {
                    SendKeysWithSpecial(strKeys, si);
                }
            }
            catch
            {
                FinishSendKeys(si);
                throw;
            }

            FinishSendKeys(si);
        }
예제 #8
0
        private static bool ValidateTargetWindow(SiStateEx siState)
        {
            if (siState.Cancelled)
            {
                return(false);
            }

            if (!Program.Config.Integration.AutoTypeCancelOnWindowChange)
            {
                return(true);
            }
            if (KeePassLib.Native.NativeLib.IsUnix())
            {
                return(true);
            }

            bool bValid = true;

            try
            {
                IntPtr h = NativeMethods.GetForegroundWindowHandle();
                if (h != siState.TargetHWnd)
                {
                    siState.Cancelled = true;
                    bValid            = false;
                }
            }
            catch (Exception) { Debug.Assert(false); }

            return(bValid);
        }
예제 #9
0
        private static void SendKeysWithSpecial(string strSequence, SiStateEx siState)
        {
            Debug.Assert(strSequence != null);
            if (string.IsNullOrEmpty(strSequence))
            {
                return;
            }

            strSequence = ApplyGlobalDelay(strSequence, siState);

            while (true)
            {
                int nDelayStart = strSequence.IndexOf("{DELAY ", StrUtil.CaseIgnoreCmp);
                if (nDelayStart >= 0)
                {
                    int nDelayEnd = strSequence.IndexOf('}', nDelayStart);
                    if (nDelayEnd >= 0)
                    {
                        uint   uDelay;
                        string strDelay = strSequence.Substring(nDelayStart + 7,
                                                                nDelayEnd - (nDelayStart + 7));
                        if (uint.TryParse(strDelay, out uDelay))
                        {
                            string strFirstPart = strSequence.Substring(0,
                                                                        nDelayStart);
                            string strSecondPart = strSequence.Substring(
                                nDelayEnd + 1);

                            if (!string.IsNullOrEmpty(strFirstPart))
                            {
                                OSSendKeys(strFirstPart);
                            }
                            SendKeys.Flush();
                            Thread.Sleep((int)uDelay);

                            strSequence = strSecondPart;
                        }
                        else
                        {
                            Debug.Assert(false); break;
                        }
                    }
                    else
                    {
                        Debug.Assert(false); break;
                    }
                }
                else
                {
                    break;
                }
            }

            if (!string.IsNullOrEmpty(strSequence))
            {
                OSSendKeys(strSequence);
            }
        }
예제 #10
0
        private static void SendKeysWithSpecial(string strSequence, SiStateEx siState)
        {
            Debug.Assert(strSequence != null);
            if (string.IsNullOrEmpty(strSequence))
            {
                return;
            }

            strSequence = ExtractGlobalDelay(strSequence, siState);             // Update
            strSequence = ApplyGlobalDelay(strSequence, siState);
            List <string> v = SplitSpecialSequence(strSequence);

            foreach (string strPart in v)
            {
                string strParam = GetParamIfSpecial(strPart, SkcDelay);
                if (strParam != null)                // Might be empty (invalid parameter)
                {
                    uint uDelay;
                    if (uint.TryParse(strParam, out uDelay))
                    {
                        if (uDelay == 0)
                        {
                            uDelay = 1;
                        }
                        if ((uDelay <= (uint)int.MaxValue) && !siState.Cancelled)
                        {
                            Thread.Sleep((int)uDelay);
                        }
                    }
                    continue;
                }

                strParam = GetParamIfSpecial(strPart, SkcVKey);
                if (strParam != null)                // Might be empty (invalid parameter)
                {
                    int vKey;
                    if (int.TryParse(strParam, out vKey) &&
                        !KeePassLib.Native.NativeLib.IsUnix())
                    {
                        SendVKeyNative(vKey, true);
                        SendVKeyNative(vKey, false);
                        Application.DoEvents();
                    }

                    continue;
                }

                OSSendKeys(strPart, siState);
                Application.DoEvents();                 // SendKeys.SendWait uses SendKeys.Flush

                if (siState.Cancelled)
                {
                    break;
                }
            }
        }
예제 #11
0
        private static void MixedTransfer(string strText, SiStateEx siState)
        {
            StringBuilder sbKeys = new StringBuilder();
            StringBuilder sbClip = new StringBuilder();

            // The string should be split randomly, but the same each
            // time this function is called. Otherwise an attacker could
            // get information by observing different splittings each
            // time auto-type is performed. Therefore, compute the random
            // seed based on the string to be auto-typed.
            Random r = new Random(GetRandomSeed(strText));

            foreach (char ch in strText)
            {
                if (r.Next(0, 2) == 0)
                {
                    sbClip.Append(ch);
                    sbKeys.Append(@"{RIGHT}");
                }
                else
                {
                    sbKeys.Append(ch);
                }
            }

            string strClip = sbClip.ToString();
            string strKeys = sbKeys.ToString();

            if (strClip.Length > 0)
            {
                StringBuilder sbNav = new StringBuilder();
                sbNav.Append(@"^v");
                for (int iLeft = 0; iLeft < strClip.Length; ++iLeft)
                {
                    sbNav.Append(@"{LEFT}");
                }

                strKeys = sbNav.ToString() + strKeys;
            }

            if (strClip.Length > 0)
            {
                ClipboardUtil.Copy(strClip, false, false, null, null, IntPtr.Zero);
            }
            else
            {
                ClipboardUtil.Clear();
            }

            if (strKeys.Length > 0)
            {
                SendKeysWithSpecial(strKeys, siState);
            }

            ClipboardUtil.Clear();
        }
예제 #12
0
        private static void SendObfuscated(string strKeys, SiStateEx siState)
        {
            Debug.Assert(strKeys != null);
            if (strKeys == null)
            {
                throw new ArgumentNullException("strKeys");
            }
            if (strKeys.Length == 0)
            {
                return;
            }

            ClipboardEventChainBlocker cev = new ClipboardEventChainBlocker();
            ClipboardContents          cnt = new ClipboardContents(true, true);
            Exception excpInner            = null;

            char[] vSpecial = new char[] { '{', '}', '(', ')', '+', '^', '%',
                                           ' ', '\t', '\r', '\n' };

            try
            {
                List <string> vParts = SplitKeySequence(strKeys);
                foreach (string strPart in vParts)
                {
                    if (string.IsNullOrEmpty(strPart))
                    {
                        continue;
                    }

                    if (strPart.IndexOfAny(vSpecial) >= 0)
                    {
                        SendKeysWithSpecial(strPart, siState);
                    }
                    else
                    {
                        MixedTransfer(strPart, siState);
                    }
                }
            }
            catch (Exception ex) { excpInner = ex; }

            cnt.SetData();
            cev.Release();

            if (excpInner != null)
            {
                throw excpInner;
            }
        }
예제 #13
0
        private static SiStateEx InitSendKeys()
        {
            SiStateEx si = new SiStateEx();

            if (KeePassLib.Native.NativeLib.IsUnix())
            {
                si.DefaultDelay /= 3;                 // Starting external program takes time
                return(si);
            }

            try
            {
                si.TargetHWnd   = NativeMethods.GetForegroundWindowHandle();
                si.ThisThreadID = NativeMethods.GetCurrentThreadId();
                uint uTargetProcessID;
                si.TargetThreadID = NativeMethods.GetWindowThreadProcessId(
                    si.TargetHWnd, out uTargetProcessID);
                si.TargetProcessID = uTargetProcessID;

                EnsureSameKeyboardLayout(si);

                // Do not use SendKeys.Flush here, use Application.DoEvents
                // instead; SendKeys.Flush might run into an infinite loop here
                // if a previous auto-type process failed with throwing an
                // exception (SendKeys.Flush is waiting in a loop for an internal
                // queue being empty, however the queue is never processed)
                Application.DoEvents();

                // if(si.ThisThreadID != si.TargetThreadID)
                // {
                //	si.ThreadInputAttached = NativeMethods.AttachThreadInput(
                //		si.ThisThreadID, si.TargetThreadID, true);
                //	Debug.Assert(si.ThreadInputAttached);
                // }
                // else { Debug.Assert(false); }

                List <int> lMod = GetActiveKeyModifiers();
                ActivateKeyModifiers(lMod, false);
                SpecialReleaseModifiers(lMod);

                Debug.Assert(GetActiveKeyModifiers().Count == 0);

                si.InputBlocked = NativeMethods.BlockInput(true);
            }
            catch (Exception) { Debug.Assert(false); }

            return(si);
        }
예제 #14
0
        private static void OSSendKeys(string strSequence, SiStateEx siState)
        {
            if (!ValidateTargetWindow(siState))
            {
                return;
            }

            if (!KeePassLib.Native.NativeLib.IsUnix())
            {
                OSSendKeysWindows(strSequence);
            }
            else             // Unix
            {
                OSSendKeysUnix(strSequence);
            }
        }
예제 #15
0
        private static void EnsureSameKeyboardLayout(SiStateEx si)
        {
            IntPtr hklSelf = NativeMethods.GetKeyboardLayout(0);
            IntPtr hklTarget = NativeMethods.GetKeyboardLayout(si.TargetThreadID);

            si.CurrentKeyboardLayout = hklSelf;

            if(hklSelf != hklTarget)
            {
                si.OriginalKeyboardLayout = NativeMethods.ActivateKeyboardLayout(
                    hklTarget, 0);
                si.CurrentKeyboardLayout = hklTarget;

                Debug.Assert(si.OriginalKeyboardLayout == hklSelf);
            }

            // ushort uLangID = (ushort)(si.CurrentKeyboardLayout.ToInt64() & 0xFFFF);
            // si.EnableCaretWorkaround = (uLangID == LangIDGerman);
        }
예제 #16
0
        private static string ApplyGlobalDelay(string strSequence, SiStateEx siState)
        {
            if (string.IsNullOrEmpty(strSequence))
            {
                return(string.Empty);
            }

            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|([\+\^%]\(.+?\))|[\+\^%].+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            if (siState.DefaultDelay > 0)
            {
                // const string strRx = @"(\{.+?\}+?|([\+\^%]\(.+?\))|([\+\^%]\{.+?\})|[\+\^%].+?|.+?)";
                const string strRx = @"(\{.+?\}+?|([\+\^%]+\(.+?\))|([\+\^%]+\{.+?\})|[\+\^%]+.+?|.+?)";
                strSequence = Regex.Replace(strSequence, strRx, @"{DELAY " +
                                            siState.DefaultDelay.ToString() + @"}$1");
            }

            return(strSequence);
        }
예제 #17
0
        private static string ApplyGlobalDelay(string strSequence, SiStateEx siState)
        {
            if (string.IsNullOrEmpty(strSequence))
            {
                return(string.Empty);
            }

            const string strDefDelay = @"(\{[Dd][Ee][Ll][Aa][Yy]\s*=\s*)(\d+)(\})";
            Match        mDefDelay   = Regex.Match(strSequence, strDefDelay);

            if (mDefDelay.Success)
            {
                string strTime = mDefDelay.Groups[2].Value;
                strSequence = Regex.Replace(strSequence, strDefDelay, string.Empty);

                uint uTime;
                if (uint.TryParse(strTime, out uTime))
                {
                    siState.DefaultDelay = uTime;
                }
                else
                {
                    Debug.Assert(false);
                }
            }

            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|([\+\^%]\(.+?\))|[\+\^%].+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            if (siState.DefaultDelay > 0)
            {
                // const string strRx = @"(\{.+?\}+?|([\+\^%]\(.+?\))|([\+\^%]\{.+?\})|[\+\^%].+?|.+?)";
                const string strRx = @"(\{.+?\}+?|([\+\^%]+\(.+?\))|([\+\^%]+\{.+?\})|[\+\^%]+.+?|.+?)";
                strSequence = Regex.Replace(strSequence, strRx, @"{DELAY " +
                                            siState.DefaultDelay.ToString() + @"}$1");
            }

            return(strSequence);
        }
예제 #18
0
        private static void FinishSendKeys(SiStateEx si)
        {
            try
            {
                // Do not restore original modifier keys here, otherwise
                // modifier keys are restored even when the user released
                // them while KeePass is auto-typing!
                // ActivateKeyModifiers(lRestore, true);

                if (si.InputBlocked)
                {
                    NativeMethods.BlockInput(false);                                 // Unblock
                }
                if (si.OriginalKeyboardLayout != IntPtr.Zero)
                {
                    NativeMethods.ActivateKeyboardLayout(si.OriginalKeyboardLayout, 0);
                }

                Application.DoEvents();
            }
            catch (Exception) { Debug.Assert(false); }
        }
예제 #19
0
        private static void EnsureSameKeyboardLayout(SiStateEx si)
        {
            IntPtr hklSelf   = NativeMethods.GetKeyboardLayout(0);
            IntPtr hklTarget = NativeMethods.GetKeyboardLayout(si.TargetThreadID);

            si.CurrentKeyboardLayout = hklSelf;

            if (!Program.Config.Integration.AutoTypeAdjustKeyboardLayout)
            {
                return;
            }

            if (hklSelf != hklTarget)
            {
                si.OriginalKeyboardLayout = NativeMethods.ActivateKeyboardLayout(
                    hklTarget, 0);
                si.CurrentKeyboardLayout = hklTarget;

                Debug.Assert(si.OriginalKeyboardLayout == hklSelf);
            }

            // ushort uLangID = (ushort)(si.CurrentKeyboardLayout.ToInt64() & 0xFFFF);
            // si.EnableCaretWorkaround = (uLangID == LangIDGerman);
        }
예제 #20
0
		private static string ApplyGlobalDelay(string strSequence, SiStateEx siState)
		{
			if(string.IsNullOrEmpty(strSequence)) return string.Empty;

			const string strDefDelay = @"(\{[Dd][Ee][Ll][Aa][Yy]\s*=\s*)(\d+)(\})";
			Match mDefDelay = Regex.Match(strSequence, strDefDelay);
			if(mDefDelay.Success)
			{
				string strTime = mDefDelay.Groups[2].Value;
				strSequence = Regex.Replace(strSequence, strDefDelay, string.Empty);

				uint uTime;
				if(uint.TryParse(strTime, out uTime)) siState.DefaultDelay = uTime;
				else { Debug.Assert(false); }
			}

			// strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|.+?)",
			//	@"{delay " + strTime + @"}$1");
			// strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|([\+\^%]\(.+?\))|[\+\^%].+?|.+?)",
			//	@"{delay " + strTime + @"}$1");
			if(siState.DefaultDelay > 0)
			{
				// const string strRx = @"(\{.+?\}+?|([\+\^%]\(.+?\))|([\+\^%]\{.+?\})|[\+\^%].+?|.+?)";
				const string strRx = @"(\{.+?\}+?|([\+\^%]+\(.+?\))|([\+\^%]+\{.+?\})|[\+\^%]+.+?|.+?)";
				strSequence = Regex.Replace(strSequence, strRx, @"{DELAY " +
					siState.DefaultDelay.ToString() + @"}$1");
			}

			return strSequence;
		}
예제 #21
0
		private static void FinishSendKeys(SiStateEx si)
		{
			try
			{
				// Do not restore original modifier keys here, otherwise
				// modifier keys are restored even when the user released
				// them while KeePass is auto-typing!
				// ActivateKeyModifiers(lRestore, true);

				if(si.InputBlocked) NativeMethods.BlockInput(false); // Unblock

				if(si.OriginalKeyboardLayout != IntPtr.Zero)
					NativeMethods.ActivateKeyboardLayout(si.OriginalKeyboardLayout, 0);

				Application.DoEvents();
			}
			catch(Exception) { Debug.Assert(false); }
		}
예제 #22
0
        private static void SendObfuscated(string strKeys, SiStateEx siState)
        {
            if(string.IsNullOrEmpty(strKeys)) return;

            ClipboardEventChainBlocker cev = new ClipboardEventChainBlocker();
            ClipboardContents cnt = new ClipboardContents(true, true);
            Exception excpInner = null;

            char[] vSpecial = new char[]{ '{', '}', '(', ')', '+', '^', '%',
                ' ', '\t', '\r', '\n' };

            try
            {
                List<string> vParts = SplitKeySequence(strKeys);
                foreach(string strPart in vParts)
                {
                    if(string.IsNullOrEmpty(strPart)) continue;

                    if(strPart.IndexOfAny(vSpecial) >= 0)
                        SendKeysWithSpecial(strPart, siState);
                    else MixedTransfer(strPart, siState);
                }
            }
            catch(Exception ex) { excpInner = ex; }

            cnt.SetData();
            cev.Release();

            if(excpInner != null) throw excpInner;
        }
예제 #23
0
        private static bool ValidateTargetWindow(SiStateEx siState)
        {
            if(siState.Cancelled) return false;

            if(!Program.Config.Integration.AutoTypeCancelOnWindowChange) return true;
            if(KeePassLib.Native.NativeLib.IsUnix()) return true;

            bool bValid = true;
            try
            {
                IntPtr h = NativeMethods.GetForegroundWindowHandle();
                if(h != siState.TargetHWnd)
                {
                    siState.Cancelled = true;
                    bValid = false;
                }
            }
            catch(Exception) { Debug.Assert(false); }

            return bValid;
        }
예제 #24
0
        private static void OSSendKeys(string strSequence, SiStateEx siState)
        {
            if(!ValidateTargetWindow(siState)) return;

            if(!KeePassLib.Native.NativeLib.IsUnix())
                OSSendKeysWindows(strSequence);
            else // Unix
                OSSendKeysUnix(strSequence);
        }
예제 #25
0
        private static void SendKeysWithSpecial(string strSequence, SiStateEx siState)
        {
            Debug.Assert(strSequence != null);
            if(string.IsNullOrEmpty(strSequence)) return;

            strSequence = ExtractGlobalDelay(strSequence, siState); // Update
            strSequence = ApplyGlobalDelay(strSequence, siState);
            List<string> v = SplitSpecialSequence(strSequence);

            foreach(string strPart in v)
            {
                string strParam = GetParamIfSpecial(strPart, SkcDelay);
                if(strParam != null) // Might be empty (invalid parameter)
                {
                    uint uDelay;
                    if(uint.TryParse(strParam, out uDelay))
                    {
                        if(uDelay == 0) uDelay = 1;
                        if((uDelay <= (uint)int.MaxValue) && !siState.Cancelled)
                            Thread.Sleep((int)uDelay);
                    }
                    continue;
                }

                strParam = GetParamIfSpecial(strPart, SkcVKey);
                if(strParam != null) // Might be empty (invalid parameter)
                {
                    int vKey;
                    if(int.TryParse(strParam, out vKey) &&
                        !KeePassLib.Native.NativeLib.IsUnix())
                    {
                        SendVKeyNative(vKey, true);
                        SendVKeyNative(vKey, false);
                        Application.DoEvents();
                    }

                    continue;
                }

                OSSendKeys(strPart, siState);
                Application.DoEvents(); // SendKeys.SendWait uses SendKeys.Flush

                if(siState.Cancelled) break;
            }
        }
예제 #26
0
        private static SiStateEx InitSendKeys()
        {
            SiStateEx si = new SiStateEx();
            if(KeePassLib.Native.NativeLib.IsUnix())
            {
                si.DefaultDelay /= 2; // Starting external program takes time
                return si;
            }

            try
            {
                si.TargetHWnd = NativeMethods.GetForegroundWindowHandle();
                si.ThisThreadID = NativeMethods.GetCurrentThreadId();
                uint uTargetProcessID;
                si.TargetThreadID = NativeMethods.GetWindowThreadProcessId(
                    si.TargetHWnd, out uTargetProcessID);
                si.TargetProcessID = uTargetProcessID;

                EnsureSameKeyboardLayout(si);

                // Do not use SendKeys.Flush here, use Application.DoEvents
                // instead; SendKeys.Flush might run into an infinite loop here
                // if a previous auto-type process failed with throwing an
                // exception (SendKeys.Flush is waiting in a loop for an internal
                // queue being empty, however the queue is never processed)
                Application.DoEvents();

                // if(si.ThisThreadID != si.TargetThreadID)
                // {
                //	si.ThreadInputAttached = NativeMethods.AttachThreadInput(
                //		si.ThisThreadID, si.TargetThreadID, true);
                //	Debug.Assert(si.ThreadInputAttached);
                // }
                // else { Debug.Assert(false); }

                List<int> lMod = GetActiveKeyModifiers();
                ActivateKeyModifiers(lMod, false);
                SpecialReleaseModifiers(lMod);

                Debug.Assert(GetActiveKeyModifiers().Count == 0);

                si.InputBlocked = NativeMethods.BlockInput(true);
            }
            catch(Exception) { Debug.Assert(false); }

            return si;
        }
예제 #27
0
        private static void MixedTransfer(string strText, SiStateEx siState)
        {
            StringBuilder sbKeys = new StringBuilder();
            StringBuilder sbClip = new StringBuilder();

            // The string should be split randomly, but the same each
            // time this function is called. Otherwise an attacker could
            // get information by observing different splittings each
            // time auto-type is performed. Therefore, compute the random
            // seed based on the string to be auto-typed.
            Random r = new Random(GetRandomSeed(strText));

            foreach(char ch in strText)
            {
                if(r.Next(0, 2) == 0)
                {
                    sbClip.Append(ch);
                    sbKeys.Append(@"{RIGHT}");
                }
                else sbKeys.Append(ch);
            }

            string strClip = sbClip.ToString();
            string strKeys = sbKeys.ToString();

            if(strClip.Length > 0)
            {
                StringBuilder sbNav = new StringBuilder();
                sbNav.Append(@"^v");
                for(int iLeft = 0; iLeft < strClip.Length; ++iLeft)
                    sbNav.Append(@"{LEFT}");

                strKeys = sbNav.ToString() + strKeys;
            }

            if(strClip.Length > 0)
                ClipboardUtil.Copy(strClip, false, false, null, null, IntPtr.Zero);
            else ClipboardUtil.Clear();

            if(strKeys.Length > 0) SendKeysWithSpecial(strKeys, siState);

            ClipboardUtil.Clear();
        }
예제 #28
0
        private static void FinishSendKeys(SiStateEx si)
        {
            if(KeePassLib.Native.NativeLib.IsUnix()) return;

            try
            {
                // Do not restore original modifier keys here, otherwise
                // modifier keys are restored even when the user released
                // them while KeePass is auto-typing!
                // ActivateKeyModifiers(lRestore, true);

                if(si.InputBlocked) NativeMethods.BlockInput(false); // Unblock

                // if(si.ThreadInputAttached)
                //	NativeMethods.AttachThreadInput(si.ThisThreadID,
                //		si.TargetThreadID, false); // Detach

                if(si.OriginalKeyboardLayout != IntPtr.Zero)
                    NativeMethods.ActivateKeyboardLayout(si.OriginalKeyboardLayout, 0);

                Application.DoEvents();
            }
            catch(Exception) { Debug.Assert(false); }
        }
예제 #29
0
        /// <summary>
        /// This method searches for a <c>{DELAY=X}</c> placeholder,
        /// removes it from the sequence and sets the global delay in
        /// <paramref name="siState" /> to X.
        /// </summary>
        private static string ExtractGlobalDelay(string strSequence, SiStateEx siState)
        {
            if(string.IsNullOrEmpty(strSequence)) return string.Empty;

            const string strDefDelay = @"(\{[Dd][Ee][Ll][Aa][Yy]\s*=\s*)(\d+)(\})";
            Match mDefDelay = Regex.Match(strSequence, strDefDelay);
            if(mDefDelay.Success)
            {
                string strTime = mDefDelay.Groups[2].Value;
                strSequence = Regex.Replace(strSequence, strDefDelay, string.Empty);

                uint uTime;
                if(uint.TryParse(strTime, out uTime)) siState.DefaultDelay = uTime;
                else { Debug.Assert(false); }
            }

            return strSequence;
        }
예제 #30
0
        private static string ApplyGlobalDelay(string strSequence, SiStateEx siState)
        {
            if(string.IsNullOrEmpty(strSequence)) return string.Empty;

            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            // strSequence = Regex.Replace(strSequence, @"(\{.+?\}+?|([\+\^%]\(.+?\))|[\+\^%].+?|.+?)",
            //	@"{delay " + strTime + @"}$1");
            if(siState.DefaultDelay > 0)
            {
                // const string strRx = @"(\{.+?\}+?|([\+\^%]\(.+?\))|([\+\^%]\{.+?\})|[\+\^%].+?|.+?)";
                const string strRx = @"(\{.+?\}+?|([\+\^%]+\(.+?\))|([\+\^%]+\{.+?\})|[\+\^%]+.+?|.+?)";
                strSequence = Regex.Replace(strSequence, strRx, @"{DELAY " +
                    siState.DefaultDelay.ToString() + @"}$1");
            }

            return strSequence;
        }
예제 #31
0
        private static bool ValidateTargetWindow(SiStateEx siState)
        {
            if(siState.Cancelled) return false;

            if(KeePassLib.Native.NativeLib.IsUnix()) return true;

            bool bChkWnd = Program.Config.Integration.AutoTypeCancelOnWindowChange;
            bool bChkTitle = Program.Config.Integration.AutoTypeCancelOnTitleChange;
            if(!bChkWnd && !bChkTitle) return true;

            bool bValid = true;
            try
            {
                IntPtr h;
                string strTitle;
                NativeMethods.GetForegroundWindowInfo(out h, out strTitle, false);

                if(bChkWnd && (h != siState.TargetHWnd))
                {
                    siState.Cancelled = true;
                    bValid = false;
                }

                if(bChkTitle && ((strTitle ?? string.Empty) != siState.TargetWindowTitle))
                {
                    siState.Cancelled = true;
                    bValid = false;
                }
            }
            catch(Exception) { Debug.Assert(false); }

            return bValid;
        }
예제 #32
0
		private static void SendKeysWithSpecial(string strSequence, SiStateEx siState)
		{
			Debug.Assert(strSequence != null);
			if(string.IsNullOrEmpty(strSequence)) return;

			strSequence = ApplyGlobalDelay(strSequence, siState);

			while(true)
			{
				int nDelayStart = strSequence.IndexOf("{DELAY ", StrUtil.CaseIgnoreCmp);
				if(nDelayStart >= 0)
				{
					int nDelayEnd = strSequence.IndexOf('}', nDelayStart);
					if(nDelayEnd >= 0)
					{
						uint uDelay;
						string strDelay = strSequence.Substring(nDelayStart + 7,
							nDelayEnd - (nDelayStart + 7));
						if(uint.TryParse(strDelay, out uDelay))
						{
							string strFirstPart = strSequence.Substring(0,
								nDelayStart);
							string strSecondPart = strSequence.Substring(
								nDelayEnd + 1);

							if(!string.IsNullOrEmpty(strFirstPart))
								OSSendKeys(strFirstPart);
							SendKeys.Flush();
							Thread.Sleep((int)uDelay);

							strSequence = strSecondPart;
						}
						else { Debug.Assert(false); break; }
					}
					else { Debug.Assert(false); break; }
				}
				else break;
			}

			if(!string.IsNullOrEmpty(strSequence)) OSSendKeys(strSequence);
		}