private void CreateFci(long maxArchiveSize) { NativeMethods.FCI.CCAB ccab = new NativeMethods.FCI.CCAB(); if (maxArchiveSize > 0 && maxArchiveSize < ccab.cb) { ccab.cb = Math.Max( NativeMethods.FCI.MIN_DISK, (int)maxArchiveSize); } object maxFolderSizeOption = context.GetOption( "maxFolderSize", null); if (maxFolderSizeOption != null) { long maxFolderSize = Convert.ToInt64( maxFolderSizeOption, CultureInfo.InvariantCulture); if (maxFolderSize > 0 && maxFolderSize < ccab.cbFolderThresh) { ccab.cbFolderThresh = (int)maxFolderSize; } } maxCabBytes = ccab.cb; ccab.szCab = context.GetArchiveName(0); if (ccab.szCab == null) { throw new FileNotFoundException( "Cabinet name not provided by stream context."); } ccab.setID = (short)new Random().Next( Int16.MinValue, Int16.MaxValue + 1); CabNumbers[ccab.szCab] = 0; currentArchiveName = ccab.szCab; totalArchives = 1; CabStream = null; Erf.Clear(); fciHandle = NativeMethods.FCI.Create( ErfHandle.AddrOfPinnedObject(), fciFilePlacedHandler, fciAllocMemHandler, fciFreeMemHandler, fciOpenStreamHandler, fciReadStreamHandler, fciWriteStreamHandler, fciCloseStreamHandler, fciSeekStreamHandler, fciDeleteFileHandler, fciGetTempFileHandler, ccab, IntPtr.Zero); CheckError(false); }
protected override void Dispose(bool disposing) { try { if (disposing) { if (fciHandle != null) { fciHandle.Dispose(); fciHandle = null; } } } finally { base.Dispose(disposing); } }
public void Pack( IPackStreamContext streamContext, IEnumerable <string> files, long maxArchiveSize) { if (streamContext == null) { throw new ArgumentNullException("streamContext"); } if (files == null) { throw new ArgumentNullException("files"); } lock (this) { try { context = streamContext; ResetProgressData(); CreateFci(maxArchiveSize); foreach (string file in files) { FileAttributes attributes; DateTime lastWriteTime; Stream fileStream = context.OpenFileReadStream( file, out attributes, out lastWriteTime); if (fileStream != null) { totalFileBytes += fileStream.Length; totalFiles++; context.CloseFileReadStream(file, fileStream); } } long uncompressedBytesInFolder = 0; currentFileNumber = -1; foreach (string file in files) { FileAttributes attributes; DateTime lastWriteTime; Stream fileStream = context.OpenFileReadStream( file, out attributes, out lastWriteTime); if (fileStream == null) { continue; } if (fileStream.Length >= NativeMethods.FCI.MAX_FOLDER) { throw new NotSupportedException(String.Format( CultureInfo.InvariantCulture, "File {0} exceeds maximum file size " + "for cabinet format.", file)); } if (uncompressedBytesInFolder > 0) { // Automatically create a new folder if this file // won't fit in the current folder. bool nextFolder = uncompressedBytesInFolder + fileStream.Length >= NativeMethods.FCI.MAX_FOLDER; // Otherwise ask the client if it wants to // move to the next folder. if (!nextFolder) { object nextFolderOption = streamContext.GetOption( "nextFolder", new object[] { file, currentFolderNumber }); nextFolder = Convert.ToBoolean( nextFolderOption, CultureInfo.InvariantCulture); } if (nextFolder) { FlushFolder(); uncompressedBytesInFolder = 0; } } if (currentFolderTotalBytes > 0) { currentFolderTotalBytes = 0; currentFolderNumber++; uncompressedBytesInFolder = 0; } currentFileName = file; currentFileNumber++; currentFileTotalBytes = fileStream.Length; currentFileBytesProcessed = 0; OnProgress(ArchiveProgressType.StartFile); uncompressedBytesInFolder += fileStream.Length; AddFile( file, fileStream, attributes, lastWriteTime, false, CompressionLevel); } FlushFolder(); FlushCabinet(); } finally { if (CabStream != null) { context.CloseArchiveWriteStream( currentArchiveNumber, currentArchiveName, CabStream); CabStream = null; } if (FileStream != null) { context.CloseFileReadStream( currentFileName, FileStream); FileStream = null; } context = null; if (fciHandle != null) { fciHandle.Dispose(); fciHandle = null; } } } }