/// <summary>
        /// Writes a configuration to a path using the specified encryption engine. Takes windows security into account and checks for write access before trying to write to the path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="configuration"></param>
        /// <param name="encryptionEngine"></param>
        /// <returns></returns>
        public static bool WriteConfiguration(bool verbose, string path, XmlConfiguration configuration, FileEncryptionEngine encryptionEngine)
        {
            try
            {
                Log.WriteLineIf(verbose, "Checking to see if the path '" + path + "' exists.");

                /// if the file exists, we need to try and read it
                if (System.IO.File.Exists(path))
                {
                    Log.WriteLineIf(verbose, "The path '" + path + "' exists.");

                    /// but first see if we have permissions to read it
                    using (SecurityAccessRight right = new SecurityAccessRight(path))
                    {
                        Log.WriteLineIf(verbose, "Checking to see if the path '" + path + "' has write access.");

                        /// if we don't have rights to the file						
                        if (!right.AssertWriteAccess())
                        {
                            Log.WriteLineIf(verbose, "The path '" + path + "' does not have write access.");
                            Log.WriteLineIf(verbose, "Prompting for user intervention for the path '" + path + "'.");

                            if (verbose)
                            {
                                /// prompt to see what we should do about this
                                DialogResult result = ExceptionUtilities.DisplayException(
                                    null,
                                    "Write access denied - Unable to write to file",
                                    MessageBoxIcon.Error,
                                    MessageBoxButtons.AbortRetryIgnore,
                                    null,
                                    "Write access has been denied for the file '" + path + "'.",
                                    "Ignoring this exception may result in a loss of data if any options in this file were changed.");

                                switch (result)
                                {
                                    case DialogResult.Abort:
                                        Log.WriteLineIf(verbose, "Aborting attempt to write to the path '" + path + "' because of user intervention.");
                                        return false;

                                    case DialogResult.Retry:
                                        Log.WriteLineIf(verbose, "Retrying attempt to write to the path '" + path + "' because of user intervention.");
                                        return WriteConfiguration(verbose, path, configuration, encryptionEngine);

                                    case DialogResult.Ignore:
                                        Log.WriteLineIf(verbose, "Ignoring attempt to write to the path '" + path + "' because of user intervention.");
                                        return true;
                                    //break;					
                                };
                            }
                            else
                            {
                                /// it failed, but we're not in verbose mode so who cares?
                                return true;
                            }
                        }
                        else
                        {
                            Log.WriteLineIf(verbose, "The path '" + path + "' has write access, preparing to write the configuration.");

                            /// rights to write to the file
                            /// ask the configuration engine to write our configuration file for us into our configuration 
                            if (!WriteConfiguration(encryptionEngine, configuration, path))
                            {
                                Log.WriteLineIf(verbose, "Failed to write the configuration, throwing exception from the last operation.");
                                throw _lastException;
                            }

                            /// ensure that the configuration has no changes visible
                            if (configuration != null)
                            {
                                Log.WriteLineIf(verbose, "Succeeded in writing the configuration, accepting changes .");
                                configuration.AcceptChanges();
                            }

                            return true;
                        }
                    }
                }
                else
                {
                    Log.WriteLineIf(verbose, "The path '" + path + "' does not exist, preparing to write the configuration for the first time.");

                    /// ask the configuration engine to write our configuration file for us into our configuration 
                    if (!WriteConfiguration(encryptionEngine, configuration, path))
                    {
                        Log.WriteLineIf(verbose, "Failed to write the configuration, throwing exception from the last operation.");
                        throw _lastException;
                    }

                    /// ensure that the configuration has no changes visible
                    if (configuration != null)
                    {
                        Log.WriteLineIf(verbose, "Succeeded in writing the configuration, accepting changes .");
                        configuration.AcceptChanges();
                    }

                    return true;
                }
            }
            catch (Exception ex)
            {
                Log.WriteLineIf(verbose, "An unexpected exception was encountered while writing the configuration, dumping exception.");
                Log.WriteLine(ex);
                Log.WriteLineIf(verbose, "Prompting for user intervention for the path '" + path + "'.");

                if (verbose)
                {
                    /// failed for some reason writing the file
                    /// prompt to see what we should do about this
                    DialogResult result = ExceptionUtilities.DisplayException(
                        null,
                        "Exception encountered - Unable to write to file",
                        MessageBoxIcon.Error,
                        MessageBoxButtons.AbortRetryIgnore,
                        ex,
                        "An exception was encountered while trying to write to the file '" + path + "'.",
                        "Ignoring this exception may result in a loss of data if any options in this file were changed");

                    switch (result)
                    {
                        case DialogResult.Abort:
                            Log.WriteLineIf(verbose, "Aborting attempt to write to the path '" + path + "' because of user intervention.");
                            return false;

                        case DialogResult.Retry:
                            Log.WriteLineIf(verbose, "Retrying attempt to write to the path '" + path + "' because of user intervention.");
                            return WriteConfiguration(verbose, path, configuration, encryptionEngine);

                        case DialogResult.Ignore:
                            Log.WriteLineIf(verbose, "Ignoring attempt to write to the path '" + path + "' because of user intervention.");
                            return true;
                    };
                }
            }
            return true;
        }
        /// <summary>
        /// Reads or creates an XmlConfiguration from a name, path, and/or a handler function to provide structure to a new configuration.
        /// </summary>
        /// <param name="name">The name that will be given to the configuration</param>
        /// <param name="path">The path to the file where the configuration is stored</param>
        /// <param name="configuration">The configuration that will be returned after creation or reading has finished</param>
        /// <param name="encryptionEngine">The encryption engine to use when reading the file</param>
        /// <param name="handler">The event handler to call if structure is needed for a new configuration</param>
        /// <returns>True if a configuration was created or read</returns>
        public static bool ReadOrCreateConfiguration(
            bool verbose,
            string name,
            string path,
            out XmlConfiguration configuration,
            FileEncryptionEngine encryptionEngine,
            XmlConfigurationEventHandler handler)
        {
            configuration = null;

            Log.WriteLineIf(verbose, "Checking to see if the path '" + path + "' exists.");

            /// if the file exists, we need to try and read it
            if (System.IO.File.Exists(path))
            {
                Log.WriteLineIf(verbose, "The path '" + path + "' exists.");

                try
                {
                    /// but first see if we have permissions to read it
                    using (SecurityAccessRight right = new SecurityAccessRight(path))
                    {
                        Log.WriteLineIf(verbose, "Checking to see if the path '" + path + "' has read access.");

                        /// if we don't have rights to the file
                        if (!right.AssertReadAccess())
                        {
                            Log.WriteLineIf(verbose, "The path '" + path + "' does not have write access.");
                            Log.WriteLineIf(verbose, "Prompting for user intervention for the path '" + path + "'.");

                            /// prompt to see what we should do about this
                            DialogResult result = ExceptionUtilities.DisplayException(
                                null,
                                "Read access denied - Unable to read from file",
                                MessageBoxIcon.Error,
                                MessageBoxButtons.AbortRetryIgnore,
                                null,
                                "Read access has been denied for the '" + name + "'.",
                                "Ignoring this exception will result in a default set of options to be loaded in the '" + name + "' for this application instance.",
                                "If the file has write access enabled, it will be overwritten with the loaded options when the application exits.",
                                "WARNING: Aborting this operation will exit the application!");

                            switch (result)
                            {
                                case DialogResult.Abort:
                                    Log.WriteLineIf(verbose, "Aborting attempt to read from the path '" + path + "' because of user intervention.");
                                    return false;

                                case DialogResult.Retry:
                                    Log.WriteLineIf(verbose, "Retrying attempt to read from the path '" + path + "' because of user intervention.");
                                    return ReadOrCreateConfiguration(verbose, name, path, out configuration, encryptionEngine, handler);

                                case DialogResult.Ignore:
                                    Log.WriteLineIf(verbose, "Ignoring attempt to read from the path '" + path + "' because of user intervention.");
                                    return true;
                                //break;					
                            };
                        }
                        else
                        {
                            Log.WriteLineIf(verbose, "The path '" + path + "' has read access, preparing to read the configuration.");

                            /// rights to read the file
                            /// ask the configuration engine to read our configuration file for us into our configuration 
                            if (!ReadConfiguration(encryptionEngine, out configuration, path))
                            {
                                Log.WriteLineIf(verbose, "Failed to write the configuration, throwing exception from the last operation.");
                                throw _lastException;
                            }

                            /// let the configuration know where it lives							
                            //							configuration.Path = path;

                            /// ensure that the configuration has no changes visible
                            if (configuration != null)
                            {
                                Log.WriteLineIf(verbose, "Succeeded in reading the configuration, accepting changes .");
                                configuration.AcceptChanges();
                            }

                            return true;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteLineIf(verbose, "An unexpected exception was encountered while reading the configuration, dumping exception.");
                    Log.WriteLine(ex);
                    Log.WriteLineIf(verbose, "Prompting for user intervention for the path '" + path + "'.");

                    /// failed for some reason reading the file
                    /// prompt to see what we should do about this
                    DialogResult result = ExceptionUtilities.DisplayException(
                        null,
                        "Exception encountered - Unable to read from file",
                        MessageBoxIcon.Error,
                        MessageBoxButtons.AbortRetryIgnore,
                        ex,
                        "An exception was encountered while trying to read '" + name + "'.",
                        "Ignoring this exception will result in a default set of options to be loaded in the '" + name + "' for this application instance.",
                        "If the file has write access enabled, it will be overwritten with the loaded options when the application exits.",
                        "WARNING: Aborting this operation will exit the application!");

                    switch (result)
                    {
                        case DialogResult.Abort:
                            Log.WriteLineIf(verbose, "Aborting attempt to read from the path '" + path + "' because of user intervention.");
                            return false;

                        case DialogResult.Retry:
                            Log.WriteLineIf(verbose, "Retrying attempt to read from the path '" + path + "' because of user intervention.");
                            return ReadOrCreateConfiguration(verbose, name, path, out configuration, encryptionEngine, handler);

                        case DialogResult.Ignore:
                            Log.WriteLineIf(verbose, "Ignoring attempt to read from the path '" + path + "' because of user intervention.");
                            break;
                    };
                }
            }
            else
            {
                Log.WriteLineIf(verbose, "The path '" + path + "' does not exist.");
            }

            /// if for some reason the configuration hasn't been loaded yet
            if (configuration == null)
            {
                Log.WriteLineIf(verbose, "Creating new configuration named '" + name + "'.");
                configuration = new XmlConfiguration();
                configuration.ElementName = name;

                Log.WriteLineIf(verbose, "Checking for formatting callback for the configuration named '" + name + "'.");

                if (handler != null)
                {
                    Log.WriteLineIf(verbose, "Formatting callback found for the configuration named '" + name + "', calling formatting callback to apply structure to the configuration.");
                    try
                    {
                        XmlConfigurationEventArgs e = new XmlConfigurationEventArgs(configuration, XmlConfigurationElementActions.None);
                        handler(null, e);
                        configuration = e.Element;
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLineIf(verbose, "An unexpected exception was encountered while reading the configuration named '" + name + "', dumping exception.");
                        Log.WriteLine(ex);
                    }
                }
            }

            Log.WriteLineIf(verbose, "Setting the path for the configuration named '" + name + "' and accepting changes to the configuration.");

            /// let the configuration know where it lives
            configuration.Path = path;

            /// ensure that the configuration has no changes visible
            configuration.AcceptChanges();

            return true;
        }     
		/// <summary>
		/// Displays a warning if any of the current configurations do not have sufficient security access permissions for write access on the local computer for the current user
		/// </summary>
		public void DisplayWarningIfLocalFilePermissionsAreInsufficient()
		{
			if (_selectedConfigurations == null)
				return;

			try
			{
				bool anyAreDeniedWriteAccess = false;
				foreach(XmlConfiguration configuration in _selectedConfigurations)
				{						
					string path = configuration.Path;
					if (path != null && path != string.Empty)
					{
						if (System.IO.File.Exists(path))
						{
							using(SecurityAccessRight right = new SecurityAccessRight(path))
							{
								bool noWrite = right.AssertWriteAccess();
								if (!noWrite)
									anyAreDeniedWriteAccess = true;	
							}
						}
						else
						{
							string dir = System.IO.Path.GetDirectoryName(path);
							using(SecurityAccessRight right = new SecurityAccessRight(dir))
							{
								bool noWrite = right.AssertWriteAccess();
								if (!noWrite)
									anyAreDeniedWriteAccess = true;
							}								
						}
					}
				}

				if (anyAreDeniedWriteAccess)
				{
					ExceptionUtilities.DisplayException(
						this,
						"Security restriction detected - Write access is denied to one or more configuration files",
						MessageBoxIcon.Information,
						MessageBoxButtons.OK,
						null,
						"One or more of the configuration files that store the options you are about to configure, has been denied write access for the current user '" + System.Environment.UserName + "'.",
						"You may continue and make changes to the options as normal, however some options may not be saved when the appliation exits.",
						"Please contact your system administrator for questions regarding Windows security and access rights.");
				}
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);
			}
		}