Commits

Patrick Schaller  committed bb0d3e5

Initial checkin for v2.10 of keepass

  • Participants

Comments (0)

Files changed (26)

+*.suo
+*.user
+[submodule "keepass_src"]
+	path = keepass_src
+	url = https://github.com/bibinou/keepass2.git

File KeepassTrueCryptMount.sln

+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeepassTrueCryptMount", "src\KeepassTrueCryptMount\KeepassTrueCryptMount.csproj", "{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamplePlugin", "src\SamplePlugin\SamplePlugin.csproj", "{4C1BB6F8-D2CD-49C2-9053-21705681356C}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Submodule keepass_src

+Subproject commit af5c56552e1f779d12b001e0c05fbca29d58d4ae

File src/KeepassTrueCryptMount/App.config

+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+  <appSettings>
+    <add key="truecrypt.executable" value="C:\Program Files\TrueCrypt\TrueCrypt.exe" />
+    <add key="truecrypt.menuitem.always.visible" value="true" />
+  </appSettings>
+</configuration>

File src/KeepassTrueCryptMount/AssemblySettingKeys.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace KeepassTrueCryptMount
+{
+    internal static class AssemblySettingKeys
+    {
+        public const string TrueCryptExecuteable = "truecrypt.executable";
+
+        public const string TrueCryptMenuItemAlwaysVisible = "truecrypt.menuitem.always.visible";
+    }
+}

File src/KeepassTrueCryptMount/AssemblySettings.cs

+using System.Collections;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Xml;
+
+namespace KeepassTrueCryptMount
+{
+    /// <summary>
+    /// A class for reading settings of an assembly file.
+    /// </summary>
+    /// <example>
+    /// AssemblySettings usage:
+    /// <para/>
+    /// If you know the keys you're after, the following is probably
+    /// the most convenient:
+    /// <code> 
+    /// AssemblySettings settings = new AssemblySettings();
+    /// string someSetting1 = settings["someKey1"];
+    /// string someSetting2 = settings["someKey2"];
+    /// </code>
+    /// <para/>
+    /// If you want to enumerate over the settings (or just as an
+    /// alternative approach), you can do this too:
+    /// <code>
+    /// IDictionary settings = AssemblySettings.GetConfig();
+    /// foreach (DictionaryEntry entry in settings)
+    /// {
+    ///     // Use entry.Key or entry.Value as desired...
+    /// }
+    /// </code>
+    /// In either of the above two scenarios, the calling assembly
+    /// (the one that called the constructor or GetConfig) is used
+    /// to determine what file to parse and what the name of the
+    /// settings collection element is.  For example, if the calling
+    /// assembly is c:\foo\bar\TestLib.dll, then the configuration file
+    /// that's parsed is c:\foo\bar\TestLib.dll.config, and the
+    /// configuration section that's parsed must be named &lt;assemblySettings&gt;.
+    /// <para/>
+    /// To retrieve the configuration information for an arbitrary assembly,
+    /// use the overloaded constructor or GetConfig method that takes an
+    /// Assembly reference as input.
+    /// <para/>
+    /// If your assembly is being automatically downloaded from a web
+    /// site by an "href-exe" (an application that's run directly from a link
+    /// on a web page), then the enclosed web.config shows the mechanism
+    /// for allowing the AssemblySettings library to download the
+    /// configuration files you're using for your assemblies (while not
+    /// allowing web.config itself to be downloaded).
+    /// <para/>
+    /// If the assembly you are trying to use this with is installed in, and loaded
+    /// from, the GAC then you'll need to place the config file in the GAC directory where
+    /// the assembly is installed.  On the first release of the CLR, this directory is
+    /// %windir%\assembly\gac\libName\verNum__pubKeyToken.  For example,
+    /// the assembly "SomeLib, Version=1.2.3.4, Culture=neutral, PublicKeyToken=abcd1234"
+    /// would be installed to the c:\winnt\assembly\gac\SomeLib\1.2.3.4__abcd1234 diretory
+    /// (assuming the OS is installed in c:\winnt).  For future versions of the CLR, this
+    /// directory scheme may change, so you'll need to check the <code>CodeBase</code> property
+    /// of a GAC-loaded assembly in the debugger to determine the correct directory location.
+    /// </example>
+    /// <remarks>
+    /// Author: Mike Woodring
+    /// http://www.bearcanyon.com
+    /// </remarks>
+    public class AssemblySettings
+    {
+        /// <summary>The dictionary of the key value pair settings.</summary>
+        private IDictionary settings;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblySettings"/> class.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public AssemblySettings()
+            : this(Assembly.GetCallingAssembly())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblySettings"/> class.
+        /// </summary>
+        /// <param name="asm">The assembly.</param>
+        public AssemblySettings(Assembly asm)
+        {
+            if (asm == null)
+            {
+                this.settings = new Dictionary<string, string>();
+            }
+            else
+            {
+                this.settings = GetConfig(asm);               
+            }
+        }
+
+        /// <summary>
+        /// Gets the value of the specified key.
+        /// </summary>
+        /// <param name="key">Key of the configuration parameter.</param>
+        /// <value>The value of the specified key.</value>
+        public string this[string key]
+        {
+            get
+            {
+                string settingValue = null;
+
+                if (this.settings != null)
+                {
+                    settingValue = this.settings[key] as string;
+                }
+
+                return settingValue ?? string.Empty;
+            }
+        }
+
+        /// <summary>
+        /// Gets the configuration of the current assembly.
+        /// </summary>
+        /// <returns>A dictionary containing the assembly settings.</returns>
+        public static IDictionary GetConfig()
+        {
+            return GetConfig(Assembly.GetCallingAssembly());
+        }
+
+        /// <summary>
+        /// Gets the configuration of the specified assembly.
+        /// </summary>
+        /// <param name="asm">An assembly.</param>
+        /// <returns>A dictionary containing the assembly settings.</returns>
+        public static IDictionary GetConfig(Assembly asm)
+        {
+            if (asm == null)
+            {
+                return new Dictionary<string, string>();
+            }
+
+            // Open and parse configuration file for specified
+            // assembly, returning collection to caller for future
+            // use outside of this class.
+            try
+            {
+                string cfgFile = asm.CodeBase + ".config";
+                const string NodeName = "appSettings";
+
+                XmlDocument doc = new XmlDocument();
+                doc.Load(new XmlTextReader(cfgFile));
+
+                XmlNodeList nodes = doc.GetElementsByTagName(NodeName);
+
+                foreach (XmlNode node in nodes)
+                {
+                    if (node.LocalName == NodeName)
+                    {
+                        var handler = new DictionarySectionHandler();
+                        return (IDictionary)handler.Create(null, null, node);
+                    }
+                }
+            }
+            catch
+            {
+            }
+
+            return new Dictionary<string, string>();
+        }
+    }
+}

File src/KeepassTrueCryptMount/ChangesDetector.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace KeepassTrueCryptMount
+{
+    public class ChangesDetector : IDisposable
+    {
+        public ChangesDetector()
+        {
+            
+        }
+
+        public void Dispose()
+        {
+            
+        }
+
+        public ChangesDetector Subscribe<TControl>(Expression<Func<TControl, EventHandler>> eventDefinition)
+        {
+            
+
+            return this;
+        }
+    }
+}

File src/KeepassTrueCryptMount/EntryStrings.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace KeepassTrueCryptMount
+{
+    internal static class EntryStrings
+    {
+        public const string Enabled = "truecrypt.enabled";
+
+        public const string DriveLetter = "truecrypt.drive";
+
+        public const string Volume = "truecrypt.container";
+
+        public const string Readonly = "truecrypt.option.readonly";
+
+        public const string Removable = "truecrypt.option.removable";
+
+        public const string Silent = "truecrypt.option.silent";
+
+        public const string Quit = "truecrypt.option.quit";
+
+        public const string Beep = "truecrypt.option.beep";
+
+        public const string Explorer = "truecrypt.option.explorer";
+
+        public const string MountWithoutDialog = "truecrypt.mount.without.dialog";
+
+        public const string AskForPassword = "truecrypt.option.askpassword";
+    }
+}

File src/KeepassTrueCryptMount/FormExtensions.cs

+using System;
+using System.Windows.Forms;
+
+namespace KeepassTrueCryptMount
+{
+    public static class FormExtensions
+    {
+        public static TForm WithStartPosition<TForm>(this TForm form, FormStartPosition startPosition)
+            where TForm : Form
+        {
+            if (form == null)
+            {
+                throw new ArgumentNullException("form", "Form must not null.");
+            }
+
+            form.StartPosition = startPosition;
+            return form;
+        }
+
+        public static TForm WithShowInTaskBar<TForm>(this TForm form, bool visible)
+            where TForm : Form
+        {
+            if (form == null)
+            {
+                throw new ArgumentNullException("form", "Form must not null.");
+            }
+
+            form.ShowInTaskbar = visible;
+            return form;
+        }
+    }
+}

File src/KeepassTrueCryptMount/KeepassTrueCryptMount.csproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{82CE2EA5-3D2F-44DF-A5D2-89DD2E911469}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>KeepassTrueCryptMount</RootNamespace>
+    <AssemblyName>KeepassTrueCryptMount</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="KeePass, Version=2.1.0.28189, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\libs\Keepass\KeePass.exe</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssemblySettingKeys.cs" />
+    <Compile Include="AssemblySettings.cs" />
+    <Compile Include="ChangesDetector.cs" />
+    <Compile Include="EntryStrings.cs" />
+    <Compile Include="FormExtensions.cs" />
+    <Compile Include="KeepassTrueCryptMountExt.cs" />
+    <Compile Include="LogicalDriveLetters.cs" />
+    <Compile Include="ProcessStartInfoExtensions.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="PwEntryExtension.cs" />
+    <Compile Include="Resource1.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resource1.resx</DependentUpon>
+    </Compile>
+    <Compile Include="TrueCryptMountForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="TrueCryptMountForm.Designer.cs">
+      <DependentUpon>TrueCryptMountForm.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resource1.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resource1.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="TrueCryptMountForm.resx">
+      <DependentUpon>TrueCryptMountForm.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Resources\B16x16_Folder_Yellow_Open.png" />
+    <Content Include="Resources\B48_TrueCrypt.png" />
+    <Content Include="Resources\TrueCryptError.png" />
+    <Content Include="Resources\TrueCryptNormal.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

File src/KeepassTrueCryptMount/KeepassTrueCryptMountExt.cs

+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using KeePass.Plugins;
+
+namespace KeepassTrueCryptMount
+{
+    public sealed class KeepassTrueCryptMountExt : Plugin
+    {
+        private IPluginHost application;
+        private ToolStripMenuItem trueCryptMenuItem;
+        private readonly string trueCryptExecutable;
+        private readonly bool trueCryptExecutableExists;
+        private readonly bool trueCryptMenuItemAlwaysVisible;
+
+        public KeepassTrueCryptMountExt()
+        {
+            var settings = AssemblySettings.GetConfig(this.GetType().Assembly);
+
+            // read the key of path of true crypt exe.
+            this.trueCryptExecutable = settings[AssemblySettingKeys.TrueCryptExecuteable] as string;
+
+            // analyze exe file exists.
+            this.trueCryptExecutableExists = File.Exists(this.trueCryptExecutable);
+
+            // read and parse menu item visibility.
+            bool.TryParse(
+                settings[AssemblySettingKeys.TrueCryptMenuItemAlwaysVisible] as string,
+                out trueCryptMenuItemAlwaysVisible);
+
+        }
+
+        public override Image SmallIcon
+        {
+            get
+            {
+                return this.trueCryptExecutableExists
+                    ? Resource1.TrueCryptNormal
+                    : Resource1.TrueCryptError;
+            }
+        }
+
+        public override bool Initialize(IPluginHost host)
+        {
+            this.application = host;
+
+            this.application.MainWindow.EntryContextMenu.Opened += this.OnEntryContextMenuOpened;
+            this.trueCryptMenuItem = new ToolStripMenuItem("Mount True Crypt volume");
+            this.trueCryptMenuItem.ShortcutKeys = Keys.Control | Keys.T;
+            this.trueCryptMenuItem.ShowShortcutKeys = true;
+            this.trueCryptMenuItem.Click += this.OnTrueCryptMenuItemClicked;
+            this.trueCryptMenuItem.Image = Resource1.TrueCryptNormal;
+            this.application.MainWindow.EntryContextMenu.Items.Insert(4, this.trueCryptMenuItem);
+
+            // in case of missing executeable, disable the menu item and load another overlay image.
+            if (!this.trueCryptExecutableExists)
+            {
+                this.trueCryptMenuItem.Enabled = false;
+                this.trueCryptMenuItem.Image = Resource1.TrueCryptError;
+            }
+
+            return true;
+        }
+        
+        public override void Terminate()
+        {
+            this.application.MainWindow.EntryContextMenu.Opened -= this.OnEntryContextMenuOpened;
+            this.application.MainWindow.EntryContextMenu.Items.Remove(this.trueCryptMenuItem);
+            this.trueCryptMenuItem.Click -= this.OnTrueCryptMenuItemClicked;
+            this.trueCryptMenuItem.Dispose();
+            base.Terminate();
+        }
+
+        private void OnEntryContextMenuOpened(object sender, EventArgs e)
+        {
+            var entry = this.application.MainWindow.GetSelectedEntry(false);
+
+            if (this.trueCryptMenuItemAlwaysVisible)
+            {
+                this.trueCryptMenuItem.Visible = true;
+                return;
+            }
+
+            if (entry != null)
+            {
+                var enabled = entry.Strings.GetSafe(EntryStrings.Enabled).ReadString();
+
+                if (bool.TrueString.Equals(enabled))
+                {
+                    this.trueCryptMenuItem.Visible = true;
+                }
+                else
+                {
+                    this.trueCryptMenuItem.Visible = false;
+                }
+            }
+            else
+            {
+                this.trueCryptMenuItem.Visible = false;
+            }
+        }
+
+        private void OnTrueCryptMenuItemClicked(object sender, EventArgs e)
+        {
+            var entry = this.application.MainWindow.GetSelectedEntry(false);
+
+            if (entry == null)
+            {
+                return;
+            }
+
+            bool hideDialog;
+            {
+                var hideDialogString = entry.Strings.GetSafe(EntryStrings.MountWithoutDialog);
+
+                if (!hideDialogString.IsEmpty)
+                {
+                    bool.TryParse(hideDialogString.ReadString(), out hideDialog);
+                }
+                else
+                {
+                    hideDialog = false;
+                }
+            }
+
+            if (!hideDialog)
+            {
+                var dialog = new TrueCryptMountForm()
+                    .WithShowInTaskBar(false)
+                    .WithStartPosition(FormStartPosition.CenterParent)
+                    .ReadFrom(entry);
+
+                var result = dialog.ShowDialog(this.application.MainWindow);
+
+                if (result == DialogResult.Cancel)
+                {
+                    // exit here, save nothing, mount nothing
+                    return;
+                }
+
+                // save settings
+                if (dialog.SaveWasClicked)
+                {
+                    dialog.WriteTo(entry);
+                    entry.Touch(true);
+                    this.application.Database.Modified = true;
+                    this.application.MainWindow.UpdateUI(false, null, false, null, false, null, true);
+                }
+            }
+        
+            // do mount...
+            new ProcessStartInfo(this.trueCryptExecutable)
+                .HideExecution()
+                .WithCommandLine(entry.ToTrueCryptArguments())
+                .Execute();
+        }
+    }
+}

File src/KeepassTrueCryptMount/LogicalDriveLetters.cs

+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace KeepassTrueCryptMount
+{
+    internal static class LogicalDriveLetters
+    {
+        static LogicalDriveLetters()
+        {
+            AllDriveLetters = new[]
+                                  {
+                                      "C:\\", "D:\\", "E:\\", "F:\\", "G:\\", "H:\\", "I:\\", "J:\\",
+                                      "L:\\", "M:\\", "N:\\", "O:\\", "P:\\", "Q:\\", "R:\\", "S:\\",
+                                      "T:\\", "U:\\", "V:\\", "W:\\", "X:\\", "Y:\\", "Z:\\",
+                                  };
+        }
+
+        /// <summary>
+        /// Gets all drive letters.
+        /// </summary>
+        /// <value>All drive letters.</value>
+        public static IEnumerable<string> AllDriveLetters
+        {
+            get; 
+            private set;
+        }
+
+        /// <summary>
+        /// Gets the free drive letters.
+        /// </summary>
+        /// <value>The free drive letters.</value>
+        public static IEnumerable<string> FreeDriveLetters
+        {
+            get
+            {
+                return AllDriveLetters.Except(DriveInfo.GetDrives().Select(di => di.Name));
+            }
+        }
+
+        /// <summary>
+        /// Ensures the specified string contains drive letter.
+        /// </summary>
+        /// <param name="letter">The drive letter containing string.</param>
+        /// <returns></returns>
+        public static string EnsureIsDrive(this string letter)
+        {
+            if (string.IsNullOrEmpty(letter))
+            {
+                return string.Empty;
+            }
+
+            var drive = letter[0] + ":\\";
+
+            if (AllDriveLetters.Contains(drive))
+            {
+                return drive;
+            }
+
+            return string.Empty;
+        }
+    }
+}

File src/KeepassTrueCryptMount/ProcessStartInfoExtensions.cs

+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace KeepassTrueCryptMount
+{
+    public static class ProcessStartInfoExtensions
+    {
+        public static void ExecuteAndWait(this ProcessStartInfo info)
+        {
+            if (info == null)
+            {
+                return;
+            }
+
+            var process = Process.Start(info);
+            
+            if (process != null)
+            {
+                process.WaitForExit();
+            }
+            else
+            {
+                Console.WriteLine("Process could not start.");
+            }
+        }
+
+        public static void Execute(this ProcessStartInfo info)
+        {
+            if (info == null)
+            {
+                return;
+            }
+
+            var process = Process.Start(info);
+
+            if (process != null)
+            {
+                process.Start();
+            }
+        }
+
+        public static ProcessStartInfo HideExecution(this ProcessStartInfo info)
+        {
+            info.WindowStyle = ProcessWindowStyle.Hidden;
+            info.CreateNoWindow = true;
+            info.UseShellExecute = false;
+
+            return info;
+        }
+
+        public static ProcessStartInfo WithCommandLine(this ProcessStartInfo info, string arguments)
+        {
+            info.Arguments = arguments;
+            return info;
+        }
+    }
+}

File src/KeepassTrueCryptMount/Properties/AssemblyInfo.cs

+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("KeepassTrueCryptMount")]
+[assembly: AssemblyDescription("Plugin to mount true crypt volumes")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Schaller Patrick home.inc")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © Schaller Patrick 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3286b2fb-1f93-4342-928f-c27a37d19abb")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.9.*")]
+[assembly: AssemblyFileVersion("2.0.9.0")]

File src/KeepassTrueCryptMount/PwEntryExtension.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace KeepassTrueCryptMount
+{
+    internal static class PwEntryExtension
+    {
+        public static string ToTrueCryptArguments(this PwEntry entry)
+        {
+            var arguments = new StringBuilder();
+
+            // beep
+            {
+                var beepString = entry.Strings.GetSafe(EntryStrings.Beep).ReadString();
+                bool beep;
+                bool.TryParse(beepString, out beep);
+                if (beep)
+                {
+                    arguments.Append(" /beep ");
+                }
+            }
+
+            // readonly
+            {
+                var readonlyString = entry.Strings.GetSafe(EntryStrings.Readonly).ReadString();
+                bool readOnly;
+                bool.TryParse(readonlyString, out readOnly);
+                if (readOnly)
+                {
+                    arguments.Append(" /m ro ");
+                }
+            }
+
+            // removable
+            {
+                var removableString = entry.Strings.GetSafe(EntryStrings.Removable).ReadString();
+                bool removable;
+                bool.TryParse(removableString, out removable);
+                if (removable)
+                {
+                    arguments.Append(" /m rm ");
+                }
+            }
+
+            // explore
+            {
+                var exploreString = entry.Strings.GetSafe(EntryStrings.Explorer).ReadString();
+                bool explore;
+                bool.TryParse(exploreString, out explore);
+                if (explore)
+                {
+                    arguments.Append(" /explore ");
+                }
+            }
+
+            // silent
+            {
+                var silentString = entry.Strings.GetSafe(EntryStrings.Silent).ReadString();
+                bool silent;
+                bool.TryParse(silentString, out silent);
+                if (silent)
+                {
+                    arguments.Append(" /silent ");
+                }
+            }
+
+            // quit
+            {
+                var quitString = entry.Strings.GetSafe(EntryStrings.Quit).ReadString();
+                bool quit;
+                bool.TryParse(quitString, out quit);
+                if (quit)
+                {
+                    arguments.Append(" /q backgound ");
+                }
+            }
+
+            // drive letter
+            {
+                var driveString = entry.Strings.GetSafe(EntryStrings.DriveLetter).ReadString();
+                if (string.IsNullOrEmpty(driveString))
+                {
+                    arguments.Append(" /auto ");
+                }
+                else
+                {
+                    arguments.Append(" /letter ").Append(driveString[0]).Append(" ");
+                }
+            }
+
+            // container volume
+            {
+                var volumeString = entry.Strings.GetSafe(EntryStrings.Volume).ReadString();
+                arguments.Append(" /v ").Append(volumeString);
+            }
+
+            // ask for password or set password directly
+            {
+                var askForPasswordString = entry.Strings.GetSafe(EntryStrings.AskForPassword).ReadString();
+                bool askForPassword;
+                bool.TryParse(askForPasswordString, out askForPassword);
+
+                arguments.Append(" /p ");
+
+                if (!askForPassword)
+                {
+                    arguments.Append(entry.Strings.GetSafe("Password").ReadString());                    
+                }
+            }
+            
+            return arguments.ToString();
+        }
+    }
+}

File src/KeepassTrueCryptMount/Resource1.Designer.cs

+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.3603
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace KeepassTrueCryptMount {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resource1 {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resource1() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KeepassTrueCryptMount.Resource1", typeof(Resource1).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap B16x16_Folder_Yellow_Open {
+            get {
+                object obj = ResourceManager.GetObject("B16x16_Folder_Yellow_Open", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap B48_TrueCrypt {
+            get {
+                object obj = ResourceManager.GetObject("B48_TrueCrypt", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TrueCryptError {
+            get {
+                object obj = ResourceManager.GetObject("TrueCryptError", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TrueCryptNormal {
+            get {
+                object obj = ResourceManager.GetObject("TrueCryptNormal", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}

File src/KeepassTrueCryptMount/Resource1.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="B16x16_Folder_Yellow_Open" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\b16x16_folder_yellow_open.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="B48_TrueCrypt" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\b48_truecrypt.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TrueCryptError" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\truecrypterror.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TrueCryptNormal" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\truecryptnormal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>

File src/KeepassTrueCryptMount/Resources/B16x16_Folder_Yellow_Open.png

Added
New image

File src/KeepassTrueCryptMount/Resources/B48_TrueCrypt.png

Added
New image

File src/KeepassTrueCryptMount/Resources/TrueCryptError.png

Added
New image

File src/KeepassTrueCryptMount/Resources/TrueCryptNormal.png

Added
New image

File src/KeepassTrueCryptMount/Resources/truecrypt.png

Added
New image

File src/KeepassTrueCryptMount/TrueCryptMountForm.Designer.cs

+namespace KeepassTrueCryptMount
+{
+    partial class TrueCryptMountForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.bannerPanel = new System.Windows.Forms.Panel();
+            this.m_lblSeparator = new System.Windows.Forms.Label();
+            this.m_btnCancel = new System.Windows.Forms.Button();
+            this.m_btnOK = new System.Windows.Forms.Button();
+            this.mountOptionsGroupBox = new System.Windows.Forms.GroupBox();
+            this.mountOptionsLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();
+            this.readonlyCheckBox = new System.Windows.Forms.CheckBox();
+            this.removableCheckBox = new System.Windows.Forms.CheckBox();
+            this.silentCheckBox = new System.Windows.Forms.CheckBox();
+            this.quitCheckBox = new System.Windows.Forms.CheckBox();
+            this.beepCheckBox = new System.Windows.Forms.CheckBox();
+            this.explorerCheckBox = new System.Windows.Forms.CheckBox();
+            this.volumeTextBox = new System.Windows.Forms.TextBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.button1 = new System.Windows.Forms.Button();
+            this.label2 = new System.Windows.Forms.Label();
+            this.driveComboBox = new System.Windows.Forms.ComboBox();
+            this.informationToolTip = new System.Windows.Forms.ToolTip(this.components);
+            this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
+            this.stateToolStripLabel = new System.Windows.Forms.ToolStripStatusLabel();
+            this.saveButton = new System.Windows.Forms.Button();
+            this.hideDialogCheckBox = new System.Windows.Forms.CheckBox();
+            this.askPasswordCheckBox = new System.Windows.Forms.CheckBox();
+            this.mountOptionsGroupBox.SuspendLayout();
+            this.mountOptionsLayoutPanel.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // bannerPanel
+            // 
+            this.bannerPanel.Dock = System.Windows.Forms.DockStyle.Top;
+            this.bannerPanel.Location = new System.Drawing.Point(0, 0);
+            this.bannerPanel.Name = "bannerPanel";
+            this.bannerPanel.Size = new System.Drawing.Size(480, 70);
+            this.bannerPanel.TabIndex = 0;
+            // 
+            // m_lblSeparator
+            // 
+            this.m_lblSeparator.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.m_lblSeparator.Location = new System.Drawing.Point(0, 279);
+            this.m_lblSeparator.Name = "m_lblSeparator";
+            this.m_lblSeparator.Size = new System.Drawing.Size(475, 2);
+            this.m_lblSeparator.TabIndex = 7;
+            // 
+            // m_btnCancel
+            // 
+            this.m_btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.m_btnCancel.Location = new System.Drawing.Point(388, 284);
+            this.m_btnCancel.Name = "m_btnCancel";
+            this.m_btnCancel.Size = new System.Drawing.Size(80, 23);
+            this.m_btnCancel.TabIndex = 6;
+            this.m_btnCancel.Text = "&Cancel";
+            this.m_btnCancel.UseVisualStyleBackColor = true;
+            // 
+            // m_btnOK
+            // 
+            this.m_btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
+            this.m_btnOK.Location = new System.Drawing.Point(302, 284);
+            this.m_btnOK.Name = "m_btnOK";
+            this.m_btnOK.Size = new System.Drawing.Size(80, 23);
+            this.m_btnOK.TabIndex = 5;
+            this.m_btnOK.Text = "&OK";
+            this.m_btnOK.UseVisualStyleBackColor = true;
+            // 
+            // mountOptionsGroupBox
+            // 
+            this.mountOptionsGroupBox.Controls.Add(this.mountOptionsLayoutPanel);
+            this.mountOptionsGroupBox.Location = new System.Drawing.Point(0, 190);
+            this.mountOptionsGroupBox.Name = "mountOptionsGroupBox";
+            this.mountOptionsGroupBox.Size = new System.Drawing.Size(468, 79);
+            this.mountOptionsGroupBox.TabIndex = 8;
+            this.mountOptionsGroupBox.TabStop = false;
+            this.mountOptionsGroupBox.Text = "Mount options";
+            // 
+            // mountOptionsLayoutPanel
+            // 
+            this.mountOptionsLayoutPanel.Controls.Add(this.readonlyCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.removableCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.silentCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.quitCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.beepCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.explorerCheckBox);
+            this.mountOptionsLayoutPanel.Controls.Add(this.askPasswordCheckBox);
+            this.mountOptionsLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.mountOptionsLayoutPanel.Location = new System.Drawing.Point(3, 16);
+            this.mountOptionsLayoutPanel.Name = "mountOptionsLayoutPanel";
+            this.mountOptionsLayoutPanel.Size = new System.Drawing.Size(462, 60);
+            this.mountOptionsLayoutPanel.TabIndex = 0;
+            // 
+            // readonlyCheckBox
+            // 
+            this.readonlyCheckBox.Location = new System.Drawing.Point(3, 3);
+            this.readonlyCheckBox.Name = "readonlyCheckBox";
+            this.readonlyCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.readonlyCheckBox.TabIndex = 0;
+            this.readonlyCheckBox.Text = "Readonly";
+            this.readonlyCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // removableCheckBox
+            // 
+            this.removableCheckBox.Location = new System.Drawing.Point(109, 3);
+            this.removableCheckBox.Name = "removableCheckBox";
+            this.removableCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.removableCheckBox.TabIndex = 1;
+            this.removableCheckBox.Text = "Removable";
+            this.removableCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // silentCheckBox
+            // 
+            this.silentCheckBox.Location = new System.Drawing.Point(215, 3);
+            this.silentCheckBox.Name = "silentCheckBox";
+            this.silentCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.silentCheckBox.TabIndex = 2;
+            this.silentCheckBox.Text = "Silent";
+            this.silentCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // quitCheckBox
+            // 
+            this.quitCheckBox.Location = new System.Drawing.Point(321, 3);
+            this.quitCheckBox.Name = "quitCheckBox";
+            this.quitCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.quitCheckBox.TabIndex = 4;
+            this.quitCheckBox.Text = "Quit";
+            this.quitCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // beepCheckBox
+            // 
+            this.beepCheckBox.Location = new System.Drawing.Point(3, 33);
+            this.beepCheckBox.Name = "beepCheckBox";
+            this.beepCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.beepCheckBox.TabIndex = 3;
+            this.beepCheckBox.Text = "Beep";
+            this.beepCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // explorerCheckBox
+            // 
+            this.explorerCheckBox.Location = new System.Drawing.Point(109, 33);
+            this.explorerCheckBox.Name = "explorerCheckBox";
+            this.explorerCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.explorerCheckBox.TabIndex = 5;
+            this.explorerCheckBox.Text = "Open Explorer";
+            this.explorerCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // volumeTextBox
+            // 
+            this.volumeTextBox.Location = new System.Drawing.Point(6, 105);
+            this.volumeTextBox.Name = "volumeTextBox";
+            this.volumeTextBox.Size = new System.Drawing.Size(421, 20);
+            this.volumeTextBox.TabIndex = 9;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(3, 89);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(161, 13);
+            this.label1.TabIndex = 10;
+            this.label1.Text = "Volume File | Partition | Harddrive";
+            // 
+            // button1
+            // 
+            this.button1.Image = global::KeepassTrueCryptMount.Resource1.B16x16_Folder_Yellow_Open;
+            this.button1.Location = new System.Drawing.Point(433, 103);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(35, 23);
+            this.button1.TabIndex = 11;
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.OnFileOpenDialogClicked);
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(3, 138);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(58, 13);
+            this.label2.TabIndex = 12;
+            this.label2.Text = "Drive letter";
+            // 
+            // driveComboBox
+            // 
+            this.driveComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.driveComboBox.FormattingEnabled = true;
+            this.driveComboBox.Location = new System.Drawing.Point(6, 154);
+            this.driveComboBox.Name = "driveComboBox";
+            this.driveComboBox.Size = new System.Drawing.Size(121, 21);
+            this.driveComboBox.TabIndex = 13;
+            // 
+            // informationToolTip
+            // 
+            this.informationToolTip.AutoPopDelay = 30000;
+            this.informationToolTip.InitialDelay = 500;
+            this.informationToolTip.IsBalloon = true;
+            this.informationToolTip.ReshowDelay = 1000;
+            this.informationToolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
+            this.informationToolTip.ToolTipTitle = "Helpful information";
+            // 
+            // toolStripStatusLabel1
+            // 
+            this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
+            this.toolStripStatusLabel1.Size = new System.Drawing.Size(42, 17);
+            this.toolStripStatusLabel1.Text = "Status:";
+            // 
+            // stateToolStripLabel
+            // 
+            this.stateToolStripLabel.Name = "stateToolStripLabel";
+            this.stateToolStripLabel.Size = new System.Drawing.Size(49, 17);
+            this.stateToolStripLabel.Text = "<State>";
+            // 
+            // saveButton
+            // 
+            this.saveButton.Location = new System.Drawing.Point(6, 284);
+            this.saveButton.Name = "saveButton";
+            this.saveButton.Size = new System.Drawing.Size(80, 23);
+            this.saveButton.TabIndex = 15;
+            this.saveButton.Text = "Save";
+            this.saveButton.UseVisualStyleBackColor = true;
+            // 
+            // hideDialogCheckBox
+            // 
+            this.hideDialogCheckBox.AutoSize = true;
+            this.hideDialogCheckBox.Location = new System.Drawing.Point(94, 288);
+            this.hideDialogCheckBox.Name = "hideDialogCheckBox";
+            this.hideDialogCheckBox.Size = new System.Drawing.Size(124, 17);
+            this.hideDialogCheckBox.TabIndex = 16;
+            this.hideDialogCheckBox.Text = "Hide dialog next time";
+            this.hideDialogCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // askPasswordCheckBox
+            // 
+            this.askPasswordCheckBox.Location = new System.Drawing.Point(215, 33);
+            this.askPasswordCheckBox.Name = "askPasswordCheckBox";
+            this.askPasswordCheckBox.Size = new System.Drawing.Size(100, 24);
+            this.askPasswordCheckBox.TabIndex = 6;
+            this.askPasswordCheckBox.Text = "Ask password";
+            this.askPasswordCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // TrueCryptMountForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(480, 314);
+            this.Controls.Add(this.hideDialogCheckBox);
+            this.Controls.Add(this.saveButton);
+            this.Controls.Add(this.driveComboBox);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.button1);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.volumeTextBox);
+            this.Controls.Add(this.mountOptionsGroupBox);
+            this.Controls.Add(this.m_lblSeparator);
+            this.Controls.Add(this.m_btnCancel);
+            this.Controls.Add(this.m_btnOK);
+            this.Controls.Add(this.bannerPanel);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "TrueCryptMountForm";
+            this.Text = "TrueCryptMountForm";
+            this.mountOptionsGroupBox.ResumeLayout(false);
+            this.mountOptionsLayoutPanel.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel bannerPanel;
+        private System.Windows.Forms.Label m_lblSeparator;
+        private System.Windows.Forms.Button m_btnCancel;
+        private System.Windows.Forms.Button m_btnOK;
+        private System.Windows.Forms.GroupBox mountOptionsGroupBox;
+        private System.Windows.Forms.FlowLayoutPanel mountOptionsLayoutPanel;
+        private System.Windows.Forms.CheckBox readonlyCheckBox;
+        private System.Windows.Forms.CheckBox removableCheckBox;
+        private System.Windows.Forms.TextBox volumeTextBox;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.ComboBox driveComboBox;
+        private System.Windows.Forms.ToolTip informationToolTip;
+        private System.Windows.Forms.CheckBox silentCheckBox;
+        private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
+        private System.Windows.Forms.ToolStripStatusLabel stateToolStripLabel;
+        private System.Windows.Forms.Button saveButton;
+        private System.Windows.Forms.CheckBox hideDialogCheckBox;
+        private System.Windows.Forms.CheckBox beepCheckBox;
+        private System.Windows.Forms.CheckBox quitCheckBox;
+        private System.Windows.Forms.CheckBox explorerCheckBox;
+        private System.Windows.Forms.CheckBox askPasswordCheckBox;
+    }
+}

File src/KeepassTrueCryptMount/TrueCryptMountForm.cs

+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+using KeePass.UI;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace KeepassTrueCryptMount
+{
+    public partial class TrueCryptMountForm : Form
+    {
+        public TrueCryptMountForm()
+        {
+            InitializeComponent();
+
+            this.driveComboBox.Items.AddRange(LogicalDriveLetters.FreeDriveLetters.ToArray());
+
+            var changesDetector = new ChangesDetector()
+                .Subscribe<TextBox>(t => t.TextChanged);
+        }
+
+        public string ContainerVolume
+        {
+            get { return this.volumeTextBox.Text; }
+        }
+
+        public string DriveLetter
+        {
+            get { return (string)this.driveComboBox.SelectedItem ?? string.Empty; }
+        }
+
+        public bool OptionReadOnly
+        {
+            get { return this.readonlyCheckBox.Checked; }
+            private set { this.readonlyCheckBox.Checked = value; }
+        }
+
+        public bool OptionRemovable
+        {
+            get { return this.removableCheckBox.Checked; }
+            private set { this.removableCheckBox.Checked = value; }
+        }
+
+        public bool OptionSilent
+        {
+            get { return this.silentCheckBox.Checked; }
+            private set { this.silentCheckBox.Checked = value; }
+        }
+
+        public bool HideForEntry
+        {
+            get { return this.hideDialogCheckBox.Checked; }
+        }
+
+        public bool SaveWasClicked { get; set; }
+
+        public TrueCryptMountForm ReadFrom(PwEntry entry)
+        {
+            // container
+            var containerString = entry.Strings.GetSafe(EntryStrings.Volume);
+            this.volumeTextBox.Text = containerString != null ? containerString.ReadString() : string.Empty;
+
+            // drive
+            var driveString = entry.Strings.GetSafe(EntryStrings.DriveLetter);
+            this.driveComboBox.SelectedItem = driveString != null ? driveString.ReadString().EnsureIsDrive() : string.Empty;
+
+            // silent
+            this.OptionSilent = false;
+            var silentString = entry.Strings.GetSafe(EntryStrings.Silent);
+            if (!silentString.IsEmpty)
+            {
+                bool silent;
+                bool.TryParse(silentString.ReadString(), out silent);
+                this.OptionSilent = silent;
+            }
+
+            // readonly
+            this.OptionReadOnly = false;
+            var readonlyString = entry.Strings.GetSafe(EntryStrings.Readonly);
+            if (!readonlyString.IsEmpty)
+            {
+                bool readOnly;
+                bool.TryParse(readonlyString.ReadString(), out readOnly);
+                this.OptionReadOnly = readOnly;
+            }
+
+            // removable
+            this.OptionRemovable = false;
+            var removableString = entry.Strings.GetSafe(EntryStrings.Removable);
+            if (!removableString.IsEmpty)
+            {
+                bool removable;
+                bool.TryParse(removableString.ReadString(), out removable);
+                this.OptionRemovable = removable;
+            }
+
+            // beep
+            this.beepCheckBox.Checked = false;
+            var beepString = entry.Strings.GetSafe(EntryStrings.Beep);
+            if (!beepString.IsEmpty)
+            {
+                bool beep;
+                bool.TryParse(beepString.ReadString(), out beep);
+                this.beepCheckBox.Checked = beep;
+            }
+
+            // explorer
+            this.explorerCheckBox.Checked = false;
+            var explorerString = entry.Strings.GetSafe(EntryStrings.Explorer);
+            if (!explorerString.IsEmpty)
+            {
+                bool explorer;
+                bool.TryParse(explorerString.ReadString(), out explorer);
+                this.explorerCheckBox.Checked = explorer;
+            }
+
+            // quit
+            this.quitCheckBox.Checked = false;
+            var quitString = entry.Strings.GetSafe(EntryStrings.Quit);
+            if (!quitString.IsEmpty)
+            {
+                bool quit;
+                bool.TryParse(quitString.ReadString(), out quit);
+                this.quitCheckBox.Checked = quit;
+            }
+
+            // ask for password
+            this.askPasswordCheckBox.Checked = false;
+            var askPasswordString = entry.Strings.GetSafe(EntryStrings.AskForPassword);
+            if (!askPasswordString.IsEmpty)
+            {
+                bool askPassword;
+                bool.TryParse(askPasswordString.ReadString(), out askPassword);
+                this.askPasswordCheckBox.Checked = askPassword;
+            }
+
+            return this;
+        }
+
+        public TrueCryptMountForm WriteTo(PwEntry entry)
+        {
+            entry.Strings.Set(EntryStrings.Volume, new ProtectedString(false, this.ContainerVolume));
+            entry.Strings.Set(EntryStrings.DriveLetter, new ProtectedString(false, this.DriveLetter));
+            entry.Strings.Set(EntryStrings.Enabled, new ProtectedString(false, true.ToString()));
+            entry.Strings.Set(EntryStrings.MountWithoutDialog, new ProtectedString(false, this.HideForEntry.ToString()));
+            entry.Strings.Set(EntryStrings.Silent, new ProtectedString(false, this.silentCheckBox.Checked.ToString()));
+            entry.Strings.Set(EntryStrings.Removable, new ProtectedString(false, this.removableCheckBox.Checked.ToString()));
+            entry.Strings.Set(EntryStrings.Readonly, new ProtectedString(false, this.readonlyCheckBox.Checked.ToString()));
+            entry.Strings.Set(EntryStrings.Beep, new ProtectedString(false, this.beepCheckBox.Checked.ToString()));
+            entry.Strings.Set(EntryStrings.Explorer, new ProtectedString(false, this.explorerCheckBox.Checked.ToString()));
+            entry.Strings.Set(EntryStrings.AskForPassword, new ProtectedString(false, this.askPasswordCheckBox.Checked.ToString()));
+
+            return this;
+        }
+
+        protected override void OnLoad(EventArgs e)
+        {
+            base.OnLoad(e);
+
+            this.Icon = Icon.FromHandle(Resource1.TrueCryptNormal.GetHicon());
+
+            this.bannerPanel.BackgroundImage = BannerFactory.CreateBanner(
+                this.bannerPanel.Width,
+                this.bannerPanel.Height,
+                BannerStyle.Default,
+                Resource1.B48_TrueCrypt,
+                "TrueCrypt mounting helper",
+                "Verify or edit the TrueCrypt mounting settings");
+
+            this.informationToolTip.SetToolTip(this.hideDialogCheckBox, string.Format("Sets option '{0}' = true{1}Only necessary for this entry.", EntryStrings.MountWithoutDialog, Environment.NewLine));
+
+            this.saveButton.Click += this.OnSaveClicked;
+
+            GlobalWindowManager.AddWindow(this);
+        }
+
+        protected override void OnFormClosed(FormClosedEventArgs e)
+        {
+            this.saveButton.Click -= this.OnSaveClicked;
+
+            GlobalWindowManager.RemoveWindow(this);
+
+            base.OnFormClosed(e);
+        }
+
+        protected void OnSaveClicked(object sender, EventArgs e)
+        {
+            this.SaveWasClicked = true;
+        }
+
+        private void OnFileOpenDialogClicked(object sender, EventArgs e)
+        {
+            var dialog = new OpenFileDialog();
+            dialog.Multiselect = false;
+            
+            if (dialog.ShowDialog(this) == DialogResult.OK && dialog.CheckFileExists)
+            {
+                this.volumeTextBox.Text = dialog.FileName;
+            }
+        }
+    }
+}

File src/KeepassTrueCryptMount/TrueCryptMountForm.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="informationToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>