context: //    This file is part of QTTabBar, a shell extension for Microsoft
  //    Windows Explorer.
  //    Copyright (C) 2007-2010  Quizo, Paul Accisano
  //
  //    QTTabBar 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 3 of the License, or
  //    (at your option) any later version.
  //
  //    QTTabBar 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 QTTabBar.  If not, see <http://www.gnu.org/licenses/>.
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Drawing;
  using System.Globalization;
  using System.IO;
  using System.Linq;
  using System.Reflection;
  using System.Resources;
  using System.Runtime.InteropServices;
  using System.Runtime.Serialization.Formatters.Binary;
  using System.Windows.Forms;
  using System.Xml;
  using System.Xml.Linq;
  using System.Text.RegularExpressions;
  using Microsoft.Win32;
  using QTPlugin;
  using QTTabBarLib.Interop;
  
  namespace QTTabBarLib {
      internal static class QTUtility {
          internal static readonly Version BetaRevision = new Version(0, 3);
          internal static readonly Version CurrentVersion = new Version(1, 5, 0, 0);
          internal const int FIRST_MOUSE_ONLY_ACTION = 1000;
          internal const int FLAG_KEYENABLED = 0x100000;
          internal const string IMAGEKEY_FOLDER = "folder";
          internal const string IMAGEKEY_MYNETWORK = "mynetwork";
          internal const string IMAGEKEY_NOEXT = "noext";
          internal const string IMAGEKEY_NOIMAGE = "noimage";
          internal const bool IS_DEV_VERSION = true;  // <----------------- Change me before releasing!
          internal static readonly bool IsRTL = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft;
          internal static readonly bool IsWin7 = Environment.OSVersion.Version >= new Version(6, 1);
          internal static readonly bool IsXP = Environment.OSVersion.Version.Major <= 5;
          internal static readonly string PATH_MYNETWORK = IsXP
                  ? "::{208D2C60-3AEA-1069-A2D7-08002B30309D}"
                  : "::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}";
          internal static readonly string PATH_SEARCHFOLDER = IsXP
                  ? "::{E17D4FC0-5564-11D1-83F2-00A0C90DC849}"
                  : "::{9343812E-1C37-4A49-A12E-4B2D810D956B}";
          internal const string REGUSER = RegConst.Root;
          internal static readonly char[] SEPARATOR_CHAR = new char[] { ';' };
          internal const string SEPARATOR_PATH_HASH_SESSION = "*?*?*";
          internal const bool NOW_DEBUGGING =
  #if DEBUG
              true;
  #else
              false;
  #endif
  
          
          // TODO: almost all of these need to be either sync'd or removed.
          // TODO: we should store actual TabItems, not just strings.
          internal static Dictionary<string, string> DisplayNameCacheDic = new Dictionary<string, string>();
          internal static bool fExplorerPrevented;
          internal static bool fRestoreFolderTree;
          internal static bool fSingleClick;
          internal static int iIconUnderLineVal;
          internal static ImageList ImageListGlobal;
          internal static Dictionary<string, byte[]> ITEMIDLIST_Dic_Session = new Dictionary<string, byte[]>();
          internal static List<string> NoCapturePathsList = new List<string>();
          internal static string[] ResMain;
          internal static string[] ResMisc;
          internal static bool RestoreFolderTree_Hide;
          internal static SolidBrush sbAlternate;
          internal static Font StartUpTabFont;
          internal static Dictionary<string, string[]> TextResourcesDic;
          internal static byte WindowAlpha = 0xff;
  
          static QTUtility() {
              // I'm tempted to just return for everything except "explorer"
              // Maybe I should...
              String processName = Process.GetCurrentProcess().ProcessName.ToLower();
              if(processName == "iexplore" || processName == "regasm" || processName == "gacutil") {
                  return;
              }
  
              // Register a callback for AssemblyResolve in order to load embedded assemblies.
              AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
                  String resourceName = "QTTabBarLib.Resources." + new AssemblyName(args.Name).Name + ".dll";
                  using(var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
                      if(stream == null) return null;
                      byte[] assemblyData = new byte[stream.Length];
                      stream.Read(assemblyData, 0, assemblyData.Length);
                      return Assembly.Load(assemblyData);
                  }
              };
  
              try {
                  // Load the config
                  ConfigManager.Initialize();
  
                  // Initialize the instance manager
                  InstanceManager.Initialize();
  
                  // Create and enable the API hooks
                  HookLibManager.Initialize();
  
                  // Create the global imagelist
                  ImageListGlobal = new ImageList { ColorDepth = ColorDepth.Depth32Bit };
                  ImageListGlobal.Images.Add("folder", GetIcon(string.Empty, false));
  
                  // Load groups/apps
                  GroupsManager.LoadGroups();
                  AppsManager.LoadApps();
  
                  if(Config.Lang.UseLangFile && File.Exists(Config.Lang.LangFile)) {
                      TextResourcesDic = ReadLanguageFile(Config.Lang.LangFile);
                  }
                  ValidateTextResources();
  
                  using(RegistryKey key = Registry.CurrentUser.CreateSubKey(RegConst.Root)) {
                      if(key != null) {
                          using(RegistryKey key2 = key.CreateSubKey("RecentlyClosed")) {
                              if(key2 != null) {
                                  List<string> collection = key2.GetValueNames()
                                          .Select(str4 => (string)key2.GetValue(str4)).ToList();
                                  StaticReg.ClosedTabHistoryList = new UniqueList<string>(collection, Config.Misc.TabHistoryCount);
                              }
                          }
                          using(RegistryKey key3 = key.CreateSubKey("RecentFiles")) {
                              if(key3 != null) {
                                  List<string> list2 = key3.GetValueNames().Select(str5 =>
                                          (string)key3.GetValue(str5)).ToList();
                                  StaticReg.ExecutedPathsList = new UniqueList<string>(list2, Config.Misc.FileHistoryCount);
                              }
                          }
                          RefreshLockedTabsList();
                          string str7 = (string)key.GetValue("NoCaptureAt", string.Empty);
                          if(str7.Length > 0) {
                              NoCapturePathsList = new List<string>(str7.Split(SEPARATOR_CHAR));
                          }
                          if(!byte.TryParse((string)key.GetValue("WindowAlpha", "255"), out WindowAlpha)) {
                              WindowAlpha = 0xff;
                          }
                      }
                  }
                  GetShellClickMode();
  
                  // Initialize plugins
                  PluginManager.Initialize();
              }
              catch(Exception exception) {
                  // TODO: Any errors here would be very serious.  Alert the user as such.
                  QTUtility2.MakeErrorLog(exception);
              }
          }
  
          public static object ByteArrayToObject(byte[] arrBytes) {
              using(MemoryStream memStream = new MemoryStream()) {
                  memStream.Write(arrBytes, 0, arrBytes.Length);
                  memStream.Seek(0, SeekOrigin.Begin);
                  return new BinaryFormatter().Deserialize(memStream);                
              }
          }
  
          private readonly static string[] strIconExt = new string[] { ".exe", ".lnk", ".ico", ".url", ".sln" };
          public static bool ExtHasIcon(string ext) {
              return strIconExt.Contains(ext);
          }
  
          private readonly static string[] strCompressedExt = new string[] { ".zip", ".lzh", ".cab" };
  
          public static bool ExtIsCompressed(string ext) {
              return strCompressedExt.Contains(ext);
          }
  
          public static void GetHiddenFileSettings(out bool fShowHidden, out bool fShowSystem) {
              const uint SSF_SHOWALLOBJECTS   = 0x00001;
              const uint SSF_SHOWSUPERHIDDEN  = 0x40000;
              SHELLSTATE ss = new SHELLSTATE();
              PInvoke.SHGetSetSettings(ref ss, SSF_SHOWALLOBJECTS | SSF_SHOWSUPERHIDDEN, false);
              fShowHidden = ss.fShowAllObjects != 0;
              fShowSystem = ss.fShowSuperHidden != 0;
          }
  
          public static Icon GetIcon(IntPtr pIDL) {
              SHFILEINFO psfi = new SHFILEINFO();
              if((IntPtr.Zero != PInvoke.SHGetFileInfo(pIDL, 0, ref psfi, Marshal.SizeOf(psfi), 0x109)) && (psfi.hIcon != IntPtr.Zero)) {
                  Icon icon = new Icon(Icon.FromHandle(psfi.hIcon), 0x10, 0x10);
                  PInvoke.DestroyIcon(psfi.hIcon);
                  return icon;
              }
              return Resources_Image.icoEmpty;
          }
  
          public static Icon GetIcon(string path, bool fExtension) {
              Icon icon;
              SHFILEINFO psfi = new SHFILEINFO();
              if(fExtension) {
                  if(path.Length == 0) {
                      path = ".*";
                  }
                  if((IntPtr.Zero != PInvoke.SHGetFileInfo("*" + path, 0x80, ref psfi, Marshal.SizeOf(psfi), 0x111)) && (psfi.hIcon != IntPtr.Zero)) {
                      icon = new Icon(Icon.FromHandle(psfi.hIcon), 0x10, 0x10);
                      PInvoke.DestroyIcon(psfi.hIcon);
                      return icon;
                  }
                  return Resources_Image.icoEmpty;
              }
              if(path.Length == 0) {
                  if((IntPtr.Zero != PInvoke.SHGetFileInfo("dummy", 0x10, ref psfi, Marshal.SizeOf(psfi), 0x111)) && (psfi.hIcon != IntPtr.Zero)) {
                      icon = new Icon(Icon.FromHandle(psfi.hIcon), 0x10, 0x10);
                      PInvoke.DestroyIcon(psfi.hIcon);
                      return icon;
                  }
                  return Resources_Image.icoEmpty;
              }
              if(!IsXP && path.StartsWith("::")) {
                  IntPtr pszPath = PInvoke.ILCreateFromPath(path);
                  if(pszPath != IntPtr.Zero) {
                      if((IntPtr.Zero != PInvoke.SHGetFileInfo(pszPath, 0, ref psfi, Marshal.SizeOf(psfi), 0x109)) && (psfi.hIcon != IntPtr.Zero)) {
                          icon = new Icon(Icon.FromHandle(psfi.hIcon), 0x10, 0x10);
                          PInvoke.DestroyIcon(psfi.hIcon);
                          PInvoke.CoTaskMemFree(pszPath);
                          return icon;
                      }
                      PInvoke.CoTaskMemFree(pszPath);
                  }
              }
              else if((IntPtr.Zero != PInvoke.SHGetFileInfo(path, 0, ref psfi, Marshal.SizeOf(psfi), 0x101)) && (psfi.hIcon != IntPtr.Zero)) {
                  icon = new Icon(Icon.FromHandle(psfi.hIcon), 0x10, 0x10);
                  PInvoke.DestroyIcon(psfi.hIcon);
                  return icon;
              }
              return Resources_Image.icoEmpty;
          }
  
          public static string GetImageKey(string path, string ext) {
              if(!string.IsNullOrEmpty(path)) {
                  if(QTUtility2.IsNetworkPath(path)) {
                      if(ext != null) {
                          ext = ext.ToLower();
                          if(ext.Length == 0) {
                              SetImageKey("noext", path);
                              return "noext";
                          }
                          if(!ImageListGlobal.Images.ContainsKey(ext)) {
                              ImageListGlobal.Images.Add(ext, GetIcon(ext, true));
                          }
                          return ext;
                      }
                      if(IsNetworkRootFolder(path)) {
                          SetImageKey(path, path);
                          return path;
                      }
                      SetImageKey("mynetwork", PATH_MYNETWORK);
                      return "mynetwork";
                  }
                  if(path.StartsWith("::")) {
                      SetImageKey(path, path);
                      return path;
                  }
                  if(ext != null) {
                      ext = ext.ToLower();
                      if(ext.Length == 0) {
                          SetImageKey("noext", path);
                          return "noext";
                      }
                      if(ExtHasIcon(ext)) {
                          SetImageKey(path, path);
                          return path;
                      }
                      SetImageKey(ext, path);
                      return ext;
                  }
                  if(path.Contains("*?*?*")) {
                      byte[] buffer;
                      if(ImageListGlobal.Images.ContainsKey(path)) {
                          return path;
                      }
                      if(ITEMIDLIST_Dic_Session.TryGetValue(path, out buffer)) {
                          using(IDLWrapper w = new IDLWrapper(buffer)) {
                              if(w.Available) {
                                  ImageListGlobal.Images.Add(path, GetIcon(w.PIDL));
                                  return path;
                              }
                          }
                      }
                      return "noimage";
                  }
                  if(QTUtility2.IsShellPathButNotFileSystem(path)) {
                      IDLWrapper wrapper;
                      if(ImageListGlobal.Images.ContainsKey(path)) {
                          return path;
                      }
                      if(IDLWrapper.TryGetCache(path, out wrapper)) {
                          using(wrapper) {
                              if(wrapper.Available) {
                                  ImageListGlobal.Images.Add(path, GetIcon(wrapper.PIDL));
                                  return path;
                              }
                          }
                      }
                      return "noimage";
                  }
                  if(path.StartsWith("ftp://") || path.StartsWith("http://")) {
                      return "folder";
                  }
                  try {
                      DirectoryInfo info = new DirectoryInfo(path);
                      if(info.Exists) {
                          FileAttributes attributes = info.Attributes;
                          if(((attributes & FileAttributes.System) != 0) || ((attributes & FileAttributes.ReadOnly) != 0)) {
                              SetImageKey(path, path);
                              return path;
                          }
                          return "folder";
                      }
                      if(File.Exists(path)) {
                          ext = Path.GetExtension(path).ToLower();
                          if(ext.Length == 0) {
                              SetImageKey("noext", path);
                              return "noext";
                          }
                          if(ExtHasIcon(ext)) {
                              SetImageKey(path, path);
                              return path;
                          }
                          SetImageKey(ext, path);
                          return ext;
                      }
                      if(path.ToLower().Contains(@".zip\")) {
                          return "folder";
                      }
                  }
                  catch {
                  }
              }
              return "noimage";
          }
  
          public static DateTime GetLinkerTimestamp() {
              string filePath = System.Reflection.Assembly.GetCallingAssembly().Location;
              const int c_PeHeaderOffset = 60;
              const int c_LinkerTimestampOffset = 8;
              byte[] buf = new byte[2048];
              Stream stream = null;
  
              try {
                  stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                  stream.Read(buf, 0, 2048);
              }
              finally {
                  if(stream != null) {
                      stream.Close();
                  }
              }
  
              int offset = BitConverter.ToInt32(buf, c_PeHeaderOffset);
              int secondsSince1970 = BitConverter.ToInt32(buf, offset + c_LinkerTimestampOffset);
              DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
              dt = dt.AddSeconds(secondsSince1970);
              dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
              return dt;
          }
  
          public static IEnumerable<KeyValuePair<string, string>> GetResourceStrings(this ResourceManager res) {
              var dict = res.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
              var e = dict.GetEnumerator();
              while(e.MoveNext()) {
                  yield return new KeyValuePair<string, string>((string)e.Key, (string)e.Value);
              }
          }
  
          public static T[] GetSettingValue<T>(T[] inputValues, T[] defaultValues, bool fClone) {
              if((inputValues == null) || (inputValues.Length == 0)) {
                  if(!fClone) {
                      return defaultValues;
                  }
                  return (T[])defaultValues.Clone();
              }
              int length = defaultValues.Length;
              int num2 = inputValues.Length;
              T[] localArray = new T[length];
              for(int i = 0; i < length; i++) {
  
gt:                 if(i < num2) {