private static void Send(ISiEngine siEngine, List <SiEvent> l) { bool bHasClipOp = l.Exists(SendInputEx.IsClipboardOp); ClipboardEventChainBlocker cev = null; ClipboardContents cnt = null; if (bHasClipOp) { cev = new ClipboardEventChainBlocker(); cnt = new ClipboardContents(true, true); } try { SendPriv(siEngine, l); } finally { if (bHasClipOp) { ClipboardUtil.Clear(); cnt.SetData(); cev.Dispose(); } } }
private static void SendPriv(ISiEngine siEngine, List <SiEvent> l) { // For 2000 alphanumeric characters: // * KeePass 1.26: 0:31 min // * KeePass 2.24: 1:58 min // * New engine of KeePass 2.25 with default delay DD: // * DD = 1: 0:31 min // * DD = 31: 1:03 min // * DD = 32: 1:34 min // * DD = 33: 1:34 min // * DD = 43: 1:34 min // * DD = 46: 1:34 min // * DD = 47: 2:05 min // * DD = 49: 2:05 min // * DD = 59: 2:05 min uint uDefaultDelay = 33; // Slice boundary + 1 // Induced by SiEngineWin.TrySendCharByKeypresses uDefaultDelay += 2; int iDefOvr = Program.Config.Integration.AutoTypeInterKeyDelay; if (iDefOvr >= 0) { if (iDefOvr == 0) { iDefOvr = 1; // 1 ms is minimum } uDefaultDelay = (uint)iDefOvr; } bool bFirstInput = true; foreach (SiEvent si in l) { // Also delay key modifiers, as a workaround for applications // with broken time-dependent message processing; // https://sourceforge.net/p/keepass/bugs/1213/ if ((si.Type == SiEventType.Key) || (si.Type == SiEventType.Char) || (si.Type == SiEventType.KeyModifier)) { if (!bFirstInput) { siEngine.Delay(uDefaultDelay); } bFirstInput = false; } switch (si.Type) { case SiEventType.Key: siEngine.SendKey(si.VKey, si.ExtendedKey, si.Down); break; case SiEventType.KeyModifier: if (si.Down.HasValue) { siEngine.SetKeyModifier(si.KeyModifier, si.Down.Value); } else { Debug.Assert(false); } break; case SiEventType.Char: siEngine.SendChar(si.Char, si.Down); break; case SiEventType.Delay: siEngine.Delay(si.Delay); break; case SiEventType.SetDefaultDelay: uDefaultDelay = si.Delay; break; case SiEventType.ClipboardCopy: if (!string.IsNullOrEmpty(si.Text)) { ClipboardUtil.Copy(si.Text, false, false, null, null, IntPtr.Zero); } else if (si.Text != null) { ClipboardUtil.Clear(); } break; case SiEventType.AppActivate: AppActivate(si); break; case SiEventType.Beep: Beep(si); break; default: Debug.Assert(false); break; } // Extra delay after tabs if (((si.Type == SiEventType.Key) && (si.VKey == (int)Keys.Tab)) || ((si.Type == SiEventType.Char) && (si.Char == '\t'))) { if (uDefaultDelay < 100) { siEngine.Delay(uDefaultDelay); } } } }
private static void Send(ISiEngine siEngine, List<SiEvent> l) { bool bHasClipOp = l.Exists(SendInputEx.IsClipboardOp); ClipboardEventChainBlocker cev = null; ClipboardContents cnt = null; if(bHasClipOp) { cev = new ClipboardEventChainBlocker(); cnt = new ClipboardContents(true, true); } try { SendPriv(siEngine, l); } finally { if(bHasClipOp) { ClipboardUtil.Clear(); cnt.SetData(); cev.Release(); } } }
private static void SendPriv(ISiEngine siEngine, List<SiEvent> l) { // For 2000 alphanumeric characters: // * KeePass 1.26: 0:31 min // * KeePass 2.24: 1:58 min // * New engine of KeePass 2.25 with default delay DD: // * DD = 1: 0:31 min // * DD = 31: 1:03 min // * DD = 32: 1:34 min // * DD = 33: 1:34 min // * DD = 43: 1:34 min // * DD = 46: 1:34 min // * DD = 47: 2:05 min // * DD = 49: 2:05 min // * DD = 59: 2:05 min uint uDefaultDelay = 33; // Slice boundary + 1 // Induced by SiEngineWin.TrySendCharByKeypresses uDefaultDelay += 2; int iDefOvr = Program.Config.Integration.AutoTypeInterKeyDelay; if(iDefOvr >= 0) { if(iDefOvr == 0) iDefOvr = 1; // 1 ms is minimum uDefaultDelay = (uint)iDefOvr; } bool bFirstInput = true; foreach(SiEvent si in l) { // Also delay key modifiers, as a workaround for applications // with broken time-dependent message processing; // https://sourceforge.net/p/keepass/bugs/1213/ if((si.Type == SiEventType.Key) || (si.Type == SiEventType.Char) || (si.Type == SiEventType.KeyModifier)) { if(!bFirstInput) siEngine.Delay(uDefaultDelay); bFirstInput = false; } switch(si.Type) { case SiEventType.Key: siEngine.SendKey(si.VKey, si.ExtendedKey, si.Down); break; case SiEventType.KeyModifier: if(si.Down.HasValue) siEngine.SetKeyModifier(si.KeyModifier, si.Down.Value); else { Debug.Assert(false); } break; case SiEventType.Char: siEngine.SendChar(si.Char, si.Down); break; case SiEventType.Delay: siEngine.Delay(si.Delay); break; case SiEventType.SetDefaultDelay: uDefaultDelay = si.Delay; break; case SiEventType.ClipboardCopy: if(!string.IsNullOrEmpty(si.Text)) ClipboardUtil.Copy(si.Text, false, false, null, null, IntPtr.Zero); else if(si.Text != null) ClipboardUtil.Clear(); break; case SiEventType.AppActivate: AppActivate(si); break; default: Debug.Assert(false); break; } // Extra delay after tabs if(((si.Type == SiEventType.Key) && (si.VKey == (int)Keys.Tab)) || ((si.Type == SiEventType.Char) && (si.Char == '\t'))) { if(uDefaultDelay < 100) siEngine.Delay(uDefaultDelay); } } }
public static void SendKeysWait(string strKeys, bool bObfuscate) { if (strKeys == null) { Debug.Assert(false); return; } List <SiEvent> l = Parse(strKeys); if (l.Count == 0) { return; } if (bObfuscate) { SiObf.Obfuscate(l); } FixEventSeq(l); ISiEngine si = null; if (SendInputEx.CreateEngine != null) { SiEventArgs ea = new SiEventArgs(); SendInputEx.CreateEngine(null, ea); si = ea.Engine; } if (si == null) { if (NativeLib.IsUnix()) { si = new SiEngineUnix(); } else { si = new SiEngineWin(); } } bool bInter = Program.Config.Integration.AutoTypeAllowInterleaved; if (!bInter) { if (!g_csSending.TryEnter()) { return; } } Interlocked.Increment(ref g_cCurSending); try { si.Init(); Send(si, l); } finally { try { si.Release(); } catch (Exception) { Debug.Assert(false); } Interlocked.Decrement(ref g_cCurSending); if (!bInter) { g_csSending.Exit(); } } }