/// <summary>
			/// Add multiple files from the given folder, recursively.
			/// The filepaths are added relatively to the given folder path.
			/// </summary>
			public void AddFolder(
				DirectoryInfo folderPath,
				IZipEventSink eventSink,
				DeepMode deep,
				PathSaveMode pathSaveMode,
				string relativeRootPostfix )
			{
				DoAddFolder(
					folderPath,
					folderPath,
					eventSink,
					deep,
					pathSaveMode,
					relativeRootPostfix );
			}
			/// <summary>
			/// 
			/// </summary>
			private void DoAddFolder(
				DirectoryInfo baseFolderPath,
				DirectoryInfo currentFolderPath,
				IZipEventSink eventSink,
				DeepMode deep,
				PathSaveMode pathSaveMode,
				string relativeRootPostfix )
			{
				Debug.Assert(
					string.IsNullOrEmpty( relativeRootPostfix ) ||
					pathSaveMode == PathSaveMode.Relative );

				if ( eventSink == null ||
					eventSink.OnBeforeEnterFolder( this, currentFolderPath ) )
				{
					// All files.
					foreach ( FileInfo filePath
						in currentFolderPath.GetFiles() )
					{
						if ( eventSink == null ||
							eventSink.OnBeforeAddFile( this, filePath ) )
						{
							string pathSaveValue;
							switch ( pathSaveMode )
							{
								case PathSaveMode.Absolute:
									// Winzip always displays absolute paths with
									// the drive resp. server+share removed, so pack
									// it here in this way, too.
									pathSaveValue =
										PathHelper.SplitPath(
										filePath.FullName ).DirectoryAndNameWithExtension;
									break;
								case PathSaveMode.Relative:
									pathSaveValue =
										PathHelper.GetRelativePath(
										baseFolderPath.FullName,
										filePath.FullName );

									if ( !string.IsNullOrEmpty( relativeRootPostfix ) )
									{
										pathSaveValue = PathHelper.Combine(
											relativeRootPostfix,
											pathSaveValue );
									}
									break;
								case PathSaveMode.None:
									pathSaveValue = filePath.Name;
									break;
								default:
									Debug.Assert( false );
									pathSaveValue = filePath.Name;
									break;
							}

							using ( FileStream fs = new FileStream(
								filePath.FullName,
								FileMode.Open,
								FileAccess.Read,
								FileShare.Read ) )
							using ( BinaryReader r = new BinaryReader( fs ) )
							{
								byte[] buffer = new byte[fs.Length];
								fs.Read( buffer, 0, buffer.Length );

								AddBytes( buffer, pathSaveValue );
							}
						}
					}

					// --

					if ( deep == DeepMode.Deep )
					{
						// All folders.
						foreach ( DirectoryInfo folderPath in currentFolderPath.GetDirectories() )
						{
							DoAddFolder(
								baseFolderPath,
								folderPath,
								eventSink,
								deep,
								pathSaveMode,
								relativeRootPostfix );
						}
					}
				}
			}
			/// <summary>
			/// Add multiple files from the given folder, recursively.
			/// The filepaths are added relatively to the given folder path.
			/// </summary>
			public void AddFolder(
				DirectoryInfo folderPath,
				IZipEventSink eventSink,
				DeepMode deep,
				PathSaveMode pathSaveMode )
			{
				DoAddFolder(
					folderPath,
					folderPath,
					eventSink,
					deep,
					pathSaveMode,
					null );
			}