1 /*
2   KeePass Password Safe - The Open-Source Password Manager
3   Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 
20 using System;
21 using System.Collections.Generic;
22 using System.ComponentModel;
23 using System.Diagnostics;
24 using System.Drawing;
25 using System.Text;
26 using System.Windows.Forms;
27 
28 using KeePass.App;
29 using KeePass.UI;
30 using KeePass.Util;
31 
32 using KeePassLib;
33 using KeePassLib.Interfaces;
34 using KeePassLib.Utility;
35 
36 namespace KeePass.Forms
37 {
38 	public partial class StatusProgressForm : Form, IStatusLogger
39 	{
40 		private string m_strTitle = null;
41 		private bool m_bCanCancel = true;
42 		private bool m_bMarquee = false;
43 		private Form m_fOwner = null;
44 
45 		private volatile bool m_bCancelled = false;
46 		private bool m_bCanClose = true;
47 
48 		public bool UserCancelled
49 		{
50 			get { return m_bCancelled; }
51 		}
52 
ConstructEx(string strTitle, bool bCanCancel, bool bMarqueeProgress, Form fOwner, string strInitialOp)53 		public static StatusProgressForm ConstructEx(string strTitle,
54 			bool bCanCancel, bool bMarqueeProgress, Form fOwner,
55 			string strInitialOp)
56 		{
57 			StatusProgressForm dlg = new StatusProgressForm();
58 			dlg.InitEx(strTitle, bCanCancel, bMarqueeProgress, fOwner);
59 
60 			if(fOwner != null) dlg.Show(fOwner);
61 			else dlg.Show();
62 
63 			dlg.StartLogging(strInitialOp, false);
64 
65 			return dlg;
66 		}
67 
DestroyEx(StatusProgressForm dlg)68 		public static void DestroyEx(StatusProgressForm dlg)
69 		{
70 			if(dlg == null) { Debug.Assert(false); return; }
71 
72 			dlg.EndLogging();
73 			dlg.CloseEx();
74 			UIUtil.DestroyForm(dlg);
75 		}
76 
InitEx(string strTitle, bool bCanCancel, bool bMarqueeProgress, Form fOwner)77 		public void InitEx(string strTitle, bool bCanCancel, bool bMarqueeProgress,
78 			Form fOwner)
79 		{
80 			m_strTitle = strTitle; // May be null
81 			m_bCanCancel = bCanCancel;
82 			m_bMarquee = bMarqueeProgress;
83 			m_fOwner = fOwner;
84 		}
85 
StatusProgressForm()86 		public StatusProgressForm()
87 		{
88 			InitializeComponent();
89 			GlobalWindowManager.InitializeForm(this);
90 		}
91 
OnFormLoad(object sender, EventArgs e)92 		private void OnFormLoad(object sender, EventArgs e)
93 		{
94 			// Must work without a parent window
95 			Debug.Assert(this.StartPosition == FormStartPosition.CenterScreen);
96 
97 			GlobalWindowManager.AddWindow(this);
98 
99 			this.Icon = AppIcons.Default;
100 
101 			m_pbTotal.Minimum = 0;
102 			m_pbTotal.Maximum = 100;
103 			m_pbTotal.Value = 0;
104 
105 			try { if(m_bMarquee) m_pbTotal.Style = ProgressBarStyle.Marquee; }
106 			catch(Exception) { Debug.Assert(WinUtil.IsWindows9x || WinUtil.IsWindows2000); }
107 
108 			if(!string.IsNullOrEmpty(m_strTitle)) this.Text = m_strTitle;
109 			else this.Text = PwDefs.ShortProductName;
110 
111 			try { if(m_fOwner != null) this.Owner = m_fOwner; }
112 			catch(Exception) { Debug.Assert(false); } // Throws from other thread
113 
114 			if(!m_bCanCancel) m_btnCancel.Enabled = false;
115 		}
116 
OnBtnCancel(object sender, EventArgs e)117 		private void OnBtnCancel(object sender, EventArgs e)
118 		{
119 			this.DialogResult = DialogResult.None;
120 			DoCancel();
121 		}
122 
DoCancel()123 		private void DoCancel()
124 		{
125 			if(m_bCancelled) return;
126 			if(!m_bCanCancel) return;
127 
128 			m_bCancelled = true;
129 			m_btnCancel.Enabled = false;
130 		}
131 
Priv_SetProgressInternal(string strText, int nPercent)132 		public delegate void Priv_SetProgressInternal(string strText, int nPercent);
133 
SetProgressInternal(string strText, int nPercent)134 		private void SetProgressInternal(string strText, int nPercent)
135 		{
136 			Debug.Assert(!m_lblTotal.InvokeRequired);
137 			Debug.Assert(!m_pbTotal.InvokeRequired);
138 
139 			Debug.Assert(!m_lblTotal.AutoSize); // For RTL support
140 			if(strText != null) m_lblTotal.Text = strText;
141 
142 			if((nPercent >= 0) && (nPercent <= 100))
143 				m_pbTotal.Value = nPercent; // .NET compares with cached value
144 		}
145 
SetProgressGlobal(string strText, int nPercent)146 		private bool SetProgressGlobal(string strText, int nPercent)
147 		{
148 			if(this.InvokeRequired)
149 				this.Invoke(new Priv_SetProgressInternal(this.SetProgressInternal),
150 					strText, nPercent);
151 			else SetProgressInternal(strText, nPercent);
152 
153 			Application.DoEvents();
154 			return !m_bCancelled;
155 		}
156 
StartLogging(string strOperation, bool bWriteOperationToLog)157 		public void StartLogging(string strOperation, bool bWriteOperationToLog)
158 		{
159 			SetProgressGlobal(strOperation, -1);
160 			m_bCanClose = false;
161 
162 			if((m_fOwner != null) && (m_fOwner is MainForm))
163 				TaskbarList.SetProgressState(m_fOwner, TbpFlag.Indeterminate);
164 		}
165 
EndLogging()166 		public void EndLogging()
167 		{
168 			if((m_fOwner != null) && (m_fOwner is MainForm))
169 				TaskbarList.SetProgressState(m_fOwner, TbpFlag.NoProgress);
170 
171 			m_bCanClose = true;
172 		}
173 
SetProgress(uint uPercent)174 		public bool SetProgress(uint uPercent)
175 		{
176 			return SetProgressGlobal(null, (int)uPercent);
177 		}
178 
SetText(string strNewText, LogStatusType lsType)179 		public bool SetText(string strNewText, LogStatusType lsType)
180 		{
181 			return SetProgressGlobal(strNewText, -1);
182 		}
183 
ContinueWork()184 		public bool ContinueWork()
185 		{
186 			Application.DoEvents();
187 			return !m_bCancelled;
188 		}
189 
CloseEx()190 		internal void CloseEx()
191 		{
192 			Close();
193 
194 			if(MonoWorkarounds.IsRequired(1710))
195 				OnFormClosed(this, new FormClosedEventArgs(CloseReason.UserClosing));
196 		}
197 
OnFormClosed(object sender, FormClosedEventArgs e)198 		private void OnFormClosed(object sender, FormClosedEventArgs e)
199 		{
200 			GlobalWindowManager.RemoveWindow(this);
201 		}
202 
OnFormClosing(object sender, FormClosingEventArgs e)203 		private void OnFormClosing(object sender, FormClosingEventArgs e)
204 		{
205 			if(!m_bCanClose)
206 			{
207 				Debug.Assert(e.CloseReason == CloseReason.UserClosing);
208 				e.Cancel = true;
209 				DoCancel();
210 			}
211 		}
212 	}
213 }
214