/// <summary> /// Retrieves all information about the archive. /// </summary> /// <exception cref="SevenZip.SevenZipArchiveException"/> private void GetArchiveInfo(bool disposeStream) { if (_archive == null) { if (!ThrowException(null, new SevenZipArchiveException())) { return; } } else { IInStream archiveStream; using ((archiveStream = GetArchiveStream(disposeStream)) as IDisposable) { var openCallback = GetArchiveOpenCallback(); if (!_opened) { if (!OpenArchive(archiveStream, openCallback)) { return; } _opened = !disposeStream; } _filesCount = _archive.GetNumberOfItems(); _archiveFileData = new List<ArchiveFileInfo>((int)_filesCount); if (_filesCount != 0) { var data = new PropVariant(); try { #region Getting archive items data for (uint i = 0; i < _filesCount; i++) { try { var fileInfo = new ArchiveFileInfo { Index = (int)i }; _archive.GetProperty(i, ItemPropId.Path, ref data); fileInfo.FileName = NativeMethods.SafeCast(data, "[no name]"); _archive.GetProperty(i, ItemPropId.LastWriteTime, ref data); fileInfo.LastWriteTime = NativeMethods.SafeCast(data, DateTime.Now); _archive.GetProperty(i, ItemPropId.CreationTime, ref data); fileInfo.CreationTime = NativeMethods.SafeCast(data, DateTime.Now); _archive.GetProperty(i, ItemPropId.LastAccessTime, ref data); fileInfo.LastAccessTime = NativeMethods.SafeCast(data, DateTime.Now); _archive.GetProperty(i, ItemPropId.Size, ref data); fileInfo.Size = NativeMethods.SafeCast<ulong>(data, 0); if (fileInfo.Size == 0) { fileInfo.Size = NativeMethods.SafeCast<uint>(data, 0); } _archive.GetProperty(i, ItemPropId.Attributes, ref data); fileInfo.Attributes = NativeMethods.SafeCast<uint>(data, 0); _archive.GetProperty(i, ItemPropId.IsDirectory, ref data); fileInfo.IsDirectory = NativeMethods.SafeCast(data, false); _archive.GetProperty(i, ItemPropId.Encrypted, ref data); fileInfo.Encrypted = NativeMethods.SafeCast(data, false); _archive.GetProperty(i, ItemPropId.Crc, ref data); fileInfo.Crc = NativeMethods.SafeCast<uint>(data, 0); _archive.GetProperty(i, ItemPropId.Comment, ref data); fileInfo.Comment = NativeMethods.SafeCast(data, ""); _archiveFileData.Add(fileInfo); } catch (InvalidCastException) { ThrowException(null, new SevenZipArchiveException("probably archive is corrupted.")); } } #endregion #region Getting archive properties uint numProps = _archive.GetNumberOfArchiveProperties(); var archProps = new List<ArchiveProperty>((int)numProps); for (uint i = 0; i < numProps; i++) { string propName; ItemPropId propId; ushort varType; _archive.GetArchivePropertyInfo(i, out propName, out propId, out varType); _archive.GetArchiveProperty(propId, ref data); if (propId == ItemPropId.Solid) { _isSolid = NativeMethods.SafeCast(data, true); } // TODO Add more archive properties if (PropIdToName.PropIdNames.ContainsKey(propId)) { archProps.Add(new ArchiveProperty { Name = PropIdToName.PropIdNames[propId], Value = data.Object }); } else { Debug.WriteLine( "An unknown archive property encountered (code " + ((int)propId).ToString(CultureInfo.InvariantCulture) + ')'); } } _archiveProperties = new ReadOnlyCollection<ArchiveProperty>(archProps); if (!_isSolid.HasValue && _format == InArchiveFormat.Zip) { _isSolid = false; } if (!_isSolid.HasValue) { _isSolid = true; } #endregion } catch (Exception) { if (openCallback.ThrowException()) { throw; } } } } if (disposeStream) { _archive.Close(); _archiveStream = null; } _archiveFileInfoCollection = new ReadOnlyCollection<ArchiveFileInfo>(_archiveFileData); } }
public int GetProperty(ItemPropId propId, ref PropVariant value) { switch (propId) { case ItemPropId.Name: value.VarType = VarEnum.VT_BSTR; value.Value = Marshal.StringToBSTR(_fileInfo.FullName); break; case ItemPropId.IsDirectory: value.VarType = VarEnum.VT_BOOL; value.UInt64Value = (byte) (_fileInfo.Attributes & FileAttributes.Directory); break; case ItemPropId.Size: value.VarType = VarEnum.VT_UI8; value.UInt64Value = (UInt64) _fileInfo.Length; break; case ItemPropId.Attributes: value.VarType = VarEnum.VT_UI4; value.UInt32Value = (uint) _fileInfo.Attributes; break; case ItemPropId.CreationTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.CreationTime.ToFileTime(); break; case ItemPropId.LastAccessTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.LastAccessTime.ToFileTime(); break; case ItemPropId.LastWriteTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.LastWriteTime.ToFileTime(); break; } return 0; }
/// <summary> /// Determines whether the specified PropVariant is equal to the current PropVariant. /// </summary> /// <param name="afi">The PropVariant to compare with the current PropVariant.</param> /// <returns>true if the specified PropVariant is equal to the current PropVariant; otherwise, false.</returns> private bool Equals(PropVariant afi){ if (afi.VarType != VarType) return false; if (VarType != VarEnum.VT_BSTR) return afi.Int64Value == Int64Value; return afi.Value == Value; }
/// <summary> /// Sets the compression properties /// </summary> private void SetCompressionProperties() { switch (_archiveFormat) { case OutArchiveFormat.Tar: break; default: ISetProperties setter = CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null ? (ISetProperties)SevenZipLibraryManager.OutArchive( _archiveFormat, this) : (ISetProperties)SevenZipLibraryManager.InArchive( Formats.InForOutFormats[_archiveFormat], this); if (setter == null) { if (!ThrowException(null, new CompressionFailedException( "The specified archive format is unsupported."))) { return; } } if (_volumeSize > 0 && ArchiveFormat != OutArchiveFormat.SevenZip) { throw new CompressionFailedException("Unfortunately, the creation of multivolume non-7Zip archives is not implemented. It will be one day, though."); } if (CustomParameters.ContainsKey("x") || CustomParameters.ContainsKey("m")) { if ( !ThrowException(null, new CompressionFailedException( "The specified compression parameters are invalid."))) { return; } } var names = new List<IntPtr>(2 + CustomParameters.Count); var values = new List<PropVariant>(2 + CustomParameters.Count); #if !WINCE var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); sp.Demand(); #endif #region Initialize compression properties if (_compressionMethod == CompressionMethod.Default) { names.Add(Marshal.StringToBSTR("x")); values.Add(new PropVariant()); foreach (var pair in CustomParameters) { names.Add(Marshal.StringToBSTR(pair.Key)); var pv = new PropVariant(); if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d") { pv.VarType = VarEnum.VT_UI4; pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture); } else { pv.VarType = VarEnum.VT_BSTR; pv.Value = Marshal.StringToBSTR(pair.Value); } values.Add(pv); } } else { names.Add(Marshal.StringToBSTR("x")); names.Add(_archiveFormat == OutArchiveFormat.Zip ? Marshal.StringToBSTR("m") : Marshal.StringToBSTR("0")); values.Add(new PropVariant()); var pv = new PropVariant { VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR(Formats.MethodNames[_compressionMethod]) }; values.Add(pv); foreach (var pair in CustomParameters) { names.Add(Marshal.StringToBSTR(pair.Key)); pv = new PropVariant(); if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d") { pv.VarType = VarEnum.VT_UI4; pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture); } else { pv.VarType = VarEnum.VT_BSTR; pv.Value = Marshal.StringToBSTR(pair.Value); } values.Add(pv); } } #endregion #region Set compression level PropVariant clpv = values[0]; clpv.VarType = VarEnum.VT_UI4; switch (CompressionLevel) { case CompressionLevel.None: clpv.UInt32Value = 0; break; case CompressionLevel.Fast: clpv.UInt32Value = 1; break; case CompressionLevel.Low: clpv.UInt32Value = 3; break; case CompressionLevel.Normal: clpv.UInt32Value = 5; break; case CompressionLevel.High: clpv.UInt32Value = 7; break; case CompressionLevel.Ultra: clpv.UInt32Value = 9; break; } values[0] = clpv; #endregion #region Encrypt headers if (EncryptHeaders && _archiveFormat == OutArchiveFormat.SevenZip && !SwitchIsInCustomParameters("he")) { names.Add(Marshal.StringToBSTR("he")); var tmp = new PropVariant { VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR("on") }; values.Add(tmp); } #endregion #region Zip Encryption if (_archiveFormat == OutArchiveFormat.Zip && ZipEncryptionMethod != ZipEncryptionMethod.ZipCrypto && !SwitchIsInCustomParameters("em")) { names.Add(Marshal.StringToBSTR("em")); var tmp = new PropVariant { VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR( #if !WINCE Enum.GetName(typeof(ZipEncryptionMethod), ZipEncryptionMethod)) #else OpenNETCF.Enum2.GetName(typeof (ZipEncryptionMethod), ZipEncryptionMethod)) #endif }; values.Add(tmp); } #endregion var namesHandle = GCHandle.Alloc(names.ToArray(), GCHandleType.Pinned); var valuesHandle = GCHandle.Alloc(values.ToArray(), GCHandleType.Pinned); try { if (setter != null) //ReSharper setter.SetProperties(namesHandle.AddrOfPinnedObject(), valuesHandle.AddrOfPinnedObject(), names.Count); } finally { namesHandle.Free(); valuesHandle.Free(); } break; } }
public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) { index -= _indexOffset; try { switch (propID) { case ItemPropId.IsAnti: value.VarType = VarEnum.VT_BOOL; value.UInt64Value = 0; break; case ItemPropId.Path: #region Path value.VarType = VarEnum.VT_BSTR; string val = DefaultItemName; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_entries != null) { val = _entries[index]; } } else { if (_directoryStructure) { if (_rootLength > 0) { val = _files[index].FullName.Substring(_rootLength); } else { val = _files[index].FullName[0] + _files[index].FullName.Substring(2); } } else { val = _files[index].Name; } } } else { val = _updateData.FileNamesToModify[(int) index]; } value.Value = Marshal.StringToBSTR(val); #endregion break; case ItemPropId.IsDirectory: value.VarType = VarEnum.VT_BOOL; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { value.UInt64Value = 0; } else { value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0); } } else { value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory); } } else { value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int) index].IsDirectory); } break; case ItemPropId.Size: #region Size //zero 11-oct-2014 - this doesnt matter, we think it's only used for updating the progress indicator value.VarType = VarEnum.VT_UI8; //value.UInt64Value = unchecked((ulong)-1); break; value.VarType = VarEnum.VT_UI8; UInt64 size; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { size = _bytesCount > 0 ? (ulong) _bytesCount : 0; } else { size = (ulong) (_streams[index] == null? 0 : _streams[index].Length); } } else { size = (_files[index].Attributes & FileAttributes.Directory) == 0 ? (ulong) _files[index].Length : 0; } } else { size = _updateData.ArchiveFileData[(int) index].Size; } value.UInt64Value = size; #endregion break; case ItemPropId.Attributes: value.VarType = VarEnum.VT_UI4; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { value.UInt32Value = (uint)FileAttributes.Normal; } else { value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal); } } else { value.UInt32Value = (uint) _files[index].Attributes; } } else { value.UInt32Value = _updateData.ArchiveFileData[(int) index].Attributes; } break; #region Times case ItemPropId.CreationTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].CreationTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int) index].CreationTime.ToFileTime(); } break; case ItemPropId.LastAccessTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].LastAccessTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int) index].LastAccessTime.ToFileTime(); } break; case ItemPropId.LastWriteTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].LastWriteTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int) index].LastWriteTime.ToFileTime(); } break; #endregion case ItemPropId.Extension: #region Extension value.VarType = VarEnum.VT_BSTR; if (_updateData.Mode != InternalCompressionMode.Modify) { try { val = _files != null ? _files[index].Extension.Substring(1) : _entries == null ? "" : Path.GetExtension(_entries[index]); value.Value = Marshal.StringToBSTR(val); } catch (ArgumentException) { value.Value = Marshal.StringToBSTR(""); } } else { val = Path.GetExtension(_updateData.ArchiveFileData[(int) index].FileName); value.Value = Marshal.StringToBSTR(val); } #endregion break; } } catch (Exception e) { AddException(e); } return 0; }
/// <summary> /// Sets output stream for writing unpacked data /// </summary> /// <param name="index">Current file index</param> /// <param name="outStream">Output stream pointer</param> /// <param name="askExtractMode">Extraction mode</param> /// <returns>0 if OK</returns> public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode) { outStream = null; if (Canceled) { return(-1); } _currentIndex = (int)index; if (askExtractMode == AskMode.Extract) { var fileName = _directory; if (!_fileIndex.HasValue) { #region Extraction to a file if (_actualIndexes == null || _actualIndexes.Contains(index)) { var data = new PropVariant(); _archive.GetProperty(index, ItemPropId.Path, ref data); string entryName = NativeMethods.SafeCast(data, ""); #region Get entryName if (String.IsNullOrEmpty(entryName)) { if (_filesCount == 1) { var archName = Path.GetFileName(_extractor.FileName); archName = archName.Substring(0, archName.LastIndexOf('.')); if (!archName.EndsWith(".tar", StringComparison.OrdinalIgnoreCase)) { archName += ".tar"; } entryName = archName; } else { entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture); } } #endregion //ExtractionPath - TODO: Allow customization of where file is output to. if (outputFilenameMapping != null) { fileName = outputFilenameMapping.Invoke(_extractor.ArchiveFileData.FirstOrDefault(x => x.Index == index)); } else { fileName = Path.Combine(_directory, _directoryStructure ? entryName : Path.GetFileName(entryName)); } _archive.GetProperty(index, ItemPropId.IsDirectory, ref data); try { fileName = ValidateFileName(fileName); } catch (Exception e) { AddException(e); goto FileExtractionStartedLabel; } if (!NativeMethods.SafeCast(data, false)) { #region Branch _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data); var time = NativeMethods.SafeCast(data, DateTime.MinValue); if (File.Exists(fileName)) { var fnea = new FileOverwriteEventArgs(fileName); OnFileExists(fnea); if (fnea.Cancel) { Canceled = true; return(-1); } if (String.IsNullOrEmpty(fnea.FileName)) { outStream = _fakeStream; goto FileExtractionStartedLabel; } fileName = fnea.FileName; } try { if (File.Exists(fileName)) { //Ensure existing file is not read only FileAttributes attributes = File.GetAttributes(fileName); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { // Make the file RW attributes = attributes & ~FileAttributes.ReadOnly; File.SetAttributes(fileName, attributes); } } _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true); } catch (Exception e) { if (e is FileNotFoundException) { AddException( new IOException("The file \"" + fileName + "\" was not extracted due to the File.Create fail.")); } else { AddException(e); } outStream = _fakeStream; goto FileExtractionStartedLabel; } _fileStream.BytesWritten += IntEventArgsHandler; outStream = _fileStream; #endregion } else { #region Branch if (!Directory.Exists(fileName)) { try { Directory.CreateDirectory(fileName); } catch (Exception e) { AddException(e); } outStream = _fakeStream; } #endregion } } else { outStream = _fakeStream; } #endregion } else { #region Extraction to a stream if (index == _fileIndex) { outStream = _fileStream; _fileIndex = null; } else { outStream = _fakeStream; } #endregion } FileExtractionStartedLabel: _doneRate += 1.0f / _filesCount; var iea = new FileInfoEventArgs( _extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); OnFileExtractionStarted(iea); if (iea.Cancel) { if (!String.IsNullOrEmpty(fileName)) { _fileStream.Dispose(); if (File.Exists(fileName)) { try { File.Delete(fileName); } catch (Exception e) { AddException(e); } } } Canceled = true; return(-1); } } return(0); }
public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) { index -= _indexOffset; try { switch (propID) { case ItemPropId.IsAnti: value.VarType = VarEnum.VT_BOOL; value.UInt64Value = 0; break; case ItemPropId.Path: #region Path value.VarType = VarEnum.VT_BSTR; string val = DefaultItemName; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_entries != null) { val = _entries[index]; } } else { if (_directoryStructure) { if (_rootLength > 0) { val = _files[index].FullName.Substring(_rootLength); } else { val = _files[index].FullName[0] + _files[index].FullName.Substring(2); } } else { val = _files[index].Name; } } } else { val = _updateData.FileNamesToModify[(int)index]; } value.Value = Marshal.StringToBSTR(val); #endregion break; case ItemPropId.IsDirectory: value.VarType = VarEnum.VT_BOOL; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { value.UInt64Value = 0; } else { value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0); } } else { value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory); } } else { value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int)index].IsDirectory); } break; case ItemPropId.Size: #region Size value.VarType = VarEnum.VT_UI8; UInt64 size; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { size = _bytesCount > 0 ? (ulong)_bytesCount : 0; } else { size = (ulong)(_streams[index] == null? 0 : _streams[index].Length); } } else { size = (_files[index].Attributes & FileAttributes.Directory) == 0 ? (ulong)_files[index].Length : 0; } } else { size = _updateData.ArchiveFileData[(int)index].Size; } value.UInt64Value = size; #endregion break; case ItemPropId.Attributes: value.VarType = VarEnum.VT_UI4; if (_updateData.Mode != InternalCompressionMode.Modify) { if (_files == null) { if (_streams == null) { value.UInt32Value = (uint)FileAttributes.Normal; } else { value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal); } } else { value.UInt32Value = (uint)_files[index].Attributes; } } else { value.UInt32Value = _updateData.ArchiveFileData[(int)index].Attributes; } break; #region Times case ItemPropId.CreationTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].CreationTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int)index].CreationTime.ToFileTime(); } break; case ItemPropId.LastAccessTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].LastAccessTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int)index].LastAccessTime.ToFileTime(); } break; case ItemPropId.LastWriteTime: value.VarType = VarEnum.VT_FILETIME; if (_updateData.Mode != InternalCompressionMode.Modify) { value.Int64Value = _files == null ? DateTime.Now.ToFileTime() : _files[index].LastWriteTime.ToFileTime(); } else { value.Int64Value = _updateData.ArchiveFileData[(int)index].LastWriteTime.ToFileTime(); } break; #endregion case ItemPropId.Extension: #region Extension value.VarType = VarEnum.VT_BSTR; if (_updateData.Mode != InternalCompressionMode.Modify) { try { val = _files != null ? _files[index].Extension.Substring(1) : _entries == null ? "" : Path.GetExtension(_entries[index]); value.Value = Marshal.StringToBSTR(val); } catch (ArgumentException) { value.Value = Marshal.StringToBSTR(""); } } else { val = Path.GetExtension(_updateData.ArchiveFileData[(int)index].FileName); value.Value = Marshal.StringToBSTR(val); } #endregion break; } } catch (Exception e) { AddException(e); } return(0); }
/// <summary> /// Sets output stream for writing unpacked data /// </summary> /// <param name="index">Current file index</param> /// <param name="outStream">Output stream pointer</param> /// <param name="askExtractMode">Extraction mode</param> /// <returns>0 if OK</returns> public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode) { outStream = null; if (Canceled) { return(-1); } _currentIndex = (int)index; if (askExtractMode == AskMode.Extract) { var fileName = _directory; if (!_fileIndex.HasValue) { // Extraction to a file if (_actualIndexes == null || _actualIndexes.Contains(index)) { var data = new PropVariant(); _archive.GetProperty(index, ItemPropId.Path, ref data); var entryName = NativeMethods.SafeCast(data, ""); #region Get entryName if (string.IsNullOrEmpty(entryName)) { if (_filesCount == 1) { var archName = Path.GetFileName(_extractor.FileName); archName = archName.Substring(0, archName.LastIndexOf('.')); if (!archName.EndsWith(".tar", StringComparison.OrdinalIgnoreCase)) { archName += ".tar"; } entryName = archName; } else { entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture); } } #endregion try { fileName = Path.Combine(RemoveIllegalCharacters(_directory, true), RemoveIllegalCharacters(_directoryStructure ? entryName : Path.GetFileName(entryName))); if (string.IsNullOrEmpty(fileName)) { throw new SevenZipArchiveException("Some archive name is null or empty."); } } catch (Exception e) { AddException(e); outStream = _fakeStream; return(0); } _archive.GetProperty(index, ItemPropId.IsDirectory, ref data); if (!NativeMethods.SafeCast(data, false)) { _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data); var time = NativeMethods.SafeCast(data, DateTime.MinValue); if (File.Exists(fileName)) { var fnea = new FileOverwriteEventArgs(fileName); FileExists?.Invoke(this, fnea); if (fnea.Cancel) { Canceled = true; return(-1); } if (string.IsNullOrEmpty(fnea.FileName)) { outStream = _fakeStream; } else { fileName = fnea.FileName; } } _doneRate += 1.0f / _filesCount; var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); FileExtractionStarted?.Invoke(this, iea); if (iea.Cancel) { Canceled = true; return(-1); } if (iea.Skip) { outStream = _fakeStream; return(0); } CreateDirectory(fileName); try { _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true); } catch (Exception e) { AddException(e is FileNotFoundException ? new IOException($"The file \"{fileName}\" was not extracted due to the File.Create fail.") : e); outStream = _fakeStream; return(0); } _fileStream.BytesWritten += IntEventArgsHandler; outStream = _fileStream; } else { _doneRate += 1.0f / _filesCount; var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); FileExtractionStarted?.Invoke(this, iea); if (iea.Cancel) { Canceled = true; return(-1); } if (iea.Skip) { outStream = _fakeStream; return(0); } if (!Directory.Exists(fileName)) { try { Directory.CreateDirectory(fileName); } catch (Exception e) { AddException(e); } outStream = _fakeStream; } } } else { outStream = _fakeStream; } } else { // Extraction to a stream. if (index == _fileIndex) { outStream = _fileStream; _fileIndex = null; } else { outStream = _fakeStream; } } } return(0); }