/// <summary>
		/// Raises the NeedsConfiguration event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnNeedsConfiguration(object sender, XmlConfigurationEventArgs e)
		{
			try
			{
				if (this.NeedsConfiguration != null)
					this.NeedsConfiguration(sender, e);
			}
			catch(System.Exception systemException)
			{
				System.Diagnostics.Trace.WriteLine(systemException);
			}
		}
		/// <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;

			Trace.WriteLineIf(verbose, "'Configuration Engine': 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))
			{	
				Trace.WriteLineIf(verbose, "'Configuration Engine': The path '" + path + "' exists.");

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

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

							/// prompt to see what we should do about this
							DialogResult result = ExceptionEngine.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:	
								Trace.WriteLineIf(verbose, "'Configuration Engine': Aborting attempt to read from the path '" + path + "' because of user intervention.");
								return false;					

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

							case DialogResult.Ignore:
								Trace.WriteLineIf(verbose, "'Configuration Engine': Ignoring attempt to read from the path '" + path + "' because of user intervention.");
								return true;
								//break;					
							};												
						}
						else
						{
							Trace.WriteLineIf(verbose, "'Configuration Engine': 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 (!ConfigurationEngine.ReadConfiguration(encryptionEngine, out configuration, path))
							{
								Trace.WriteLineIf(verbose, "'Configuration Engine': Failed to read the configuration, throwing last exception from the ConfigurationEngine.");
								throw ConfigurationEngine.LastException;
							}

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

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

							return true;
						}
					}
				}
				catch(System.Exception systemException)
				{
					Trace.WriteLineIf(verbose, "'Configuration Engine': An unexpected exception was encountered while reading the configuration, dumping exception.");
					System.Diagnostics.Trace.WriteLine(systemException);
					Trace.WriteLineIf(verbose, "'Configuration Engine': 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 = ExceptionEngine.DisplayException(
						null,					
						"Exception encountered - Unable to read from file",
						MessageBoxIcon.Error,
						MessageBoxButtons.AbortRetryIgnore,
						systemException,
						"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:	
						Trace.WriteLineIf(verbose, "'Configuration Engine': Aborting attempt to read from the path '" + path + "' because of user intervention.");
						return false;					

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

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

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

				Trace.WriteLineIf(verbose, "'Configuration Engine': Checking for formatting callback for the configuration named '" + name + "'.");

				if (handler != null)
				{
					Trace.WriteLineIf(verbose, "'Configuration Engine': 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(System.Exception systemException)
					{
						Trace.WriteLineIf(verbose, "'Configuration Engine': An unexpected exception was encountered while reading the configuration named '" + name + "', dumping exception.");
						System.Diagnostics.Trace.WriteLine(systemException);
					}
				}
			}
									
			Trace.WriteLineIf(verbose, "'Configuration Engine': 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>
		/// Writes the data for the window we are listening to, to the appropriate category in the specified configuration
		/// </summary>
		private void WriteWindowData()
		{
			try
			{
				XmlConfigurationEventArgs e = new XmlConfigurationEventArgs(null, XmlConfigurationElementActions.None);
				this.OnNeedsConfiguration(this, e);
				if (e.Element == null)
					return;

				// retrive the configuration where this listener will read and write 
				XmlConfiguration configuration = e.Element;
				if (configuration != null)
				{
					XmlConfigurationCategory category = configuration.Categories[_path, true];
					if (category != null)
					{
						XmlConfigurationOption option = null;

						if ((option = category.Options["Size"]) == null)
						{
							option = category.Options["Size", true, _size];
							option.Description = "The size of the window (Width & Height)";
							option.Category = "Layout";
							option.ShouldSerializeValue = true;
						}
						option.Value = _size;
						
						if ((option = category.Options["Location"]) == null)
						{
							option = category.Options["Location", true, _location];
							option.Description = "The location of the top left corner of the window (Left & Top)";
							option.Category = "Layout";
							option.ShouldSerializeValue = true;
						}
						option.Value = _location;

						if ((option = category.Options["WindowState"]) == null)
						{
							option = category.Options["WindowState", true, _state];
							option.Description = "The state of the window (Normal, Maximized, or Minimized)";
							option.Category = "Layout";
//							option.ShouldSerializeValue = true;
						}
						option.Value = _state;						
					}
				}
			}
			catch(System.Exception systemException)
			{
				System.Diagnostics.Trace.WriteLine(systemException);
			}
		}		
		/// <summary>
		/// Reads the window data from the configuration
		/// </summary>
		private void ReadWindowData()
		{			
			try
			{
				XmlConfigurationEventArgs e = new XmlConfigurationEventArgs(null, XmlConfigurationElementActions.None);
				this.OnNeedsConfiguration(this, e);
				if (e.Element == null)
					return;

				// retrive the configuration where this listener will read and write 
				XmlConfiguration configuration = e.Element;
				if (configuration != null)
				{
					XmlConfigurationCategory category = configuration.Categories[_path, false];
					if (category != null)
					{
						XmlConfigurationOption option = null;

						if ((option = category.Options["Size"]) != null)
							_size = (Size)option.Value;

						if ((option = category.Options["Location"]) != null)
							_location = (Point)option.Value;

						if ((option = category.Options["WindowState"]) != null)
							_state = (FormWindowState)option.Value;
					}
				}
			}
			catch(System.Exception systemException)
			{
				System.Diagnostics.Trace.WriteLine(systemException);
			}			
		}
		/// <summary>
		/// Occurs when a window position listener needs a configuration to read/write to/from
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnListenerNeedsConfiguration(object sender, XmlConfigurationEventArgs e)
		{
			/// save everything to the local user configuration
			e.Element = SnapInHostingEngine.GetExecutingInstance().LocalUserConfiguration;
		}
		/// <summary>
		/// Formats a configuration for use as the local user's configuration
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void OnFormatLocalUserConfiguration(object sender, XmlConfigurationEventArgs e)
		{
			e.Element = SnapInHostingEngine.DefaultLocalUserConfigurationFormat;
		}
		/// <summary>
		/// Formats a configuration for use as the hosting engine's configuration
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void OnFormatInstallationEngineConfiguration(object sender, XmlConfigurationEventArgs e)
		{
			e.Element = InstallationEngine.DefaultConfigurationFormat;
		}