context: /*
    KeePass Password Safe - The Open-Source Password Manager
    Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
  using System;
  using System.Text;
  using System.Security;
  using System.Runtime.InteropServices;
  using System.Windows.Forms;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Drawing.Imaging;
  using System.IO;
  using System.Diagnostics;
  
  using KeePass.UI;
  using KeePass.Util;
  
  using KeePassLib.Utility;
  
  namespace KeePass.Native
  {
  	internal static partial class NativeMethods
  	{
  		internal static string GetWindowText(IntPtr hWnd, bool bTrim)
  		{
  			int nLength = GetWindowTextLength(hWnd);
  			if(nLength <= 0) return string.Empty;
  
  			StringBuilder sb = new StringBuilder(nLength + 1);
  			GetWindowText(hWnd, sb, sb.Capacity);
  			string strWindow = sb.ToString();
  
  			return (bTrim ? strWindow.Trim() : strWindow);
  		}
  
  		/* internal static string GetWindowClassName(IntPtr hWnd)
  		{
  			try
  			{
  				StringBuilder sb = new StringBuilder(260);
  
  				if(GetClassName(hWnd, sb, 258) > 0)
  					return sb.ToString();
  				else { Debug.Assert(false); }
  
  				return string.Empty;
  			}
  			catch(Exception) { Debug.Assert(false); }
  
  			return null;
  		} */
  
  		internal static IntPtr GetForegroundWindowHandle()
  		{
  			if(!KeePassLib.Native.NativeLib.IsUnix())
  				return GetForegroundWindow(); // Windows API
  
  			try
  			{
  				return new IntPtr(int.Parse(RunXDoTool("getactivewindow")));
  			}
  			catch(Exception) { Debug.Assert(false); }
  			return IntPtr.Zero;
  		}
  
  		private static readonly char[] m_vWindowTrim = { '\r', '\n' };
  		internal static void GetForegroundWindowInfo(out IntPtr hWnd,
  			out string strWindowText, bool bTrimWindow)
  		{
  			hWnd = GetForegroundWindowHandle();
  
  			if(!KeePassLib.Native.NativeLib.IsUnix()) // Windows
  				strWindowText = GetWindowText(hWnd, bTrimWindow);
  			else // Unix
  			{
  				strWindowText = RunXDoTool("getactivewindow getwindowname");
  				if(!string.IsNullOrEmpty(strWindowText))
  				{
  					if(bTrimWindow) strWindowText = strWindowText.Trim();
  					else strWindowText = strWindowText.Trim(m_vWindowTrim);
  				}
  			}
  		}
  
  		internal static bool IsWindowEx(IntPtr hWnd)
  		{
  			if(!KeePassLib.Native.NativeLib.IsUnix()) // Windows
  				return IsWindow(hWnd);
  
  			return true;
  		}
  
  		internal static int GetWindowStyle(IntPtr hWnd)
  		{
  			return GetWindowLong(hWnd, GWL_STYLE);
  		}
  
  		internal static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
  		{
  			if(IntPtr.Size > 4) return GetClassLongPtr64(hWnd, nIndex);
  			return GetClassLongPtr32(hWnd, nIndex);
  		}
  
  		internal static bool SetForegroundWindowEx(IntPtr hWnd)
  		{
  			if(!KeePassLib.Native.NativeLib.IsUnix())
  				return SetForegroundWindow(hWnd);
  
  			return (RunXDoTool("windowactivate " +
  				hWnd.ToInt64().ToString()).Trim().Length == 0);
  		}
  
  		internal static bool EnsureForegroundWindow(IntPtr hWnd)
  		{
  			if(IsWindowEx(hWnd) == false) return false;
  
  			if(SetForegroundWindowEx(hWnd) == false)
  			{
  				Debug.Assert(false);
  				return false;
  			}
  
  			int nStartMS = Environment.TickCount;
  			while((Environment.TickCount - nStartMS) < 1000)
  			{
  				IntPtr h = GetForegroundWindowHandle();
  				if(h == hWnd) return true;
  
  				Application.DoEvents();
  			}
  
  			return false;
  		}
  
  		internal static bool LoseFocus(Form fCurrent)
  		{
  			if(KeePassLib.Native.NativeLib.IsUnix())
  				return LoseFocusUnix(fCurrent);
  
  			try
  			{
  				IntPtr hCurrentWnd = ((fCurrent != null) ? fCurrent.Handle : IntPtr.Zero);
  				IntPtr hWnd = GetWindow(hCurrentWnd, GW_HWNDNEXT);
  
  				while(true)
  				{
  					if(hWnd != hCurrentWnd)
  					{
  						int nStyle = GetWindowStyle(hWnd);
  						if(((nStyle & WS_VISIBLE) != 0) &&
  							(GetWindowTextLength(hWnd) > 0))
  						{
  							// Skip the taskbar window (required for Windows 7,
  							// when the target window is the only other window
  							// in the taskbar)
  							if(!IsTaskBar(hWnd)) break;
  						}
  					}
  
  					hWnd = GetWindow(hWnd, GW_HWNDNEXT);
  					if(hWnd == IntPtr.Zero) break;
  				}
  
  				if(hWnd == IntPtr.Zero) return false;
  
  				Debug.Assert(GetWindowText(hWnd, true) != "Start");
  				return EnsureForegroundWindow(hWnd);
  			}
  			catch(Exception) { Debug.Assert(false); }
  
  			return false;
  		}
  
  		internal static bool IsTaskBar(IntPtr hWnd)
  		{
  			Process p = null;
  			try
  			{
  				string strText = GetWindowText(hWnd, true);
  				if(strText == null) return false;
  				if(!strText.Equals("Start", StrUtil.CaseIgnoreCmp)) return false;
  
  				uint uProcessId;
  				NativeMethods.GetWindowThreadProcessId(hWnd, out uProcessId);
  
  				p = Process.GetProcessById((int)uProcessId);
  				string strExe = UrlUtil.GetFileName(p.MainModule.FileName).Trim();
  
  				return strExe.Equals("Explorer.exe", StrUtil.CaseIgnoreCmp);
  			}
  			catch(Exception) { Debug.Assert(false); }
  			finally
  			{
  				try { if(p != null) p.Dispose(); }
  				catch(Exception) { Debug.Assert(false); }
  			}
  
  			return false;
  		}
  
  		/* internal static bool IsMetroWindow(IntPtr hWnd)
  		{
  			if(hWnd == IntPtr.Zero) { Debug.Assert(false); return false; }
  			if(KeePassLib.Native.NativeLib.IsUnix() || !WinUtil.IsAtLeastWindows8)
  				return false;
  
  			try
  			{
  				uint uProcessId;
  				NativeMethods.GetWindowThreadProcessId(hWnd, out uProcessId);
  				if(uProcessId == 0) { Debug.Assert(false); return false; }
  
  				IntPtr h = NativeMethods.OpenProcess(NativeMethods.PROCESS_QUERY_INFORMATION,
  					false, uProcessId);
  				if(h == IntPtr.Zero) return false; // No assert
  
  				bool bRet = NativeMethods.IsImmersiveProcess(h);
  
  				NativeMethods.CloseHandle(h);
  				return bRet;
  			}
  			catch(Exception) { Debug.Assert(false); }
  
  			return false;
  		} */
  
  		public static bool IsInvalidHandleValue(IntPtr p)
  		{
  			long h = p.ToInt64();
  			if(h == -1) return true;
  			if(h == 0xFFFFFFFF) return true;
  
  			return false;
  		}
  
  		// Workaround for only partially visible list view items
  		/* public static void EnsureVisible(ListView lv, int nIndex, bool bPartialOK)
  		{
  			Debug.Assert(lv != null); if(lv == null) return;
  			Debug.Assert(nIndex >= 0); if(nIndex < 0) return;
  			Debug.Assert(nIndex < lv.Items.Count); if(nIndex >= lv.Items.Count) return;
  
  
gt: 			int nPartialOK = (bPartialOK ? 1 : 0);