private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                // Verify that _entriesProcessed matches _entries.Count
                // For Xar archives, when no file list is specified in the call IInArchive.Extract(null, uint.MaxValue, ...),
                // the "[TOC].xml" file is not extracted, so there is an exception for that.
                Debug.Assert(_entries == null || _extractMode != ExtractMode.ExtractToFile || _exception != null ||
                             (_entriesProcessed == _entries.Count - 1 && _archive.Format == ArchiveFormat.Xar) ||
                             _entriesProcessed == _entries.Count);

                if (_extractMode == ExtractMode.ExtractToFile)
                {
                    SetDirectoryAttributes();
                }

                if (disposing)
                {
                    // Dispose managed resources
                    if (_stream != null)
                    {
                        _stream.Dispose();
                    }
                }

                _stream           = null;
                _targetStream     = null;
                _entries          = null;
                _directoryEntries = null;
                _archive          = null;


                // Dispose unmanaged resources

                _disposed = true;
            }
        }
        public int SetOperationResult(OperationResult operationResult)
        {
            if (_stream != null)
            {
                _stream.Dispose();
                _stream = null;
            }

            if (_lastAskMode == AskMode.Skip)
            {
                Debug.Assert(!_entries.ContainsKey(_lastEntryIndex));
                return(HRESULT.S_OK);
            }

            _entriesProcessed++;
            _lastEntryIndexSet = false;
            Debug.Assert(_entriesProcessed <= _entries.Count);

            if (_lastFileSkipped)
            {
                _lastFileSkipped = false;

                ExistingFileSkippedEventArgs args = new ExistingFileSkippedEventArgs()
                {
                    CurrentEntry     = _entries[_lastEntryIndex],
                    ExistingFilePath = LastExtractedFilePath,
                    EntriesTotal     = _entries.Count,
                    EntriesProcessed = _entriesProcessed,
                };
                return(InvokeEventHandler(args, _archive.OnExistingFileSkipped, "SevenZipArchive.ExistingFileSkipped"));
            }

            if (_exception != null)
            {
                if (_exception is PasswordRequiredException)
                {
                    _exception = new PasswordRequiredException(
                        string.Format("The file '{0}' is encrypted, and requires a password to be decrypted.", LastEntryFileName),
                        LastEntryFileName, _exception.InnerException);
                }
                return(RaiseExtractionOrCheckFailedEvent(_exception));
            }

            int result = HRESULT.S_OK;

            switch (operationResult)
            {
            case OperationResult.OK:
                if (_extractMode == ExtractMode.ExtractToFile || _extractMode == ExtractMode.ExtractToStream)
                {
                    if (_extractMode == ExtractMode.ExtractToFile)
                    {
                        SetAttributes(LastExtractedFilePath, _entries[_lastEntryIndex]);
                    }

                    FileExtractedEventArgs args = new FileExtractedEventArgs()
                    {
                        CurrentEntry     = _entries[_lastEntryIndex],
                        TargetFilePath   = LastExtractedFilePath,
                        EntriesTotal     = _entries.Count,
                        EntriesProcessed = _entriesProcessed,
                    };
                    result = InvokeEventHandler(args, _archive.OnFileExtracted, "SevenZipArchive.FileExtracted");
                }
                else if (_extractMode == ExtractMode.IntegrityCheck)
                {
                    FileCheckedEventArgs args = new FileCheckedEventArgs()
                    {
                        CurrentEntry     = _entries[_lastEntryIndex],
                        EntriesTotal     = _entries.Count,
                        EntriesProcessed = _entriesProcessed,
                    };
                    result = InvokeEventHandler(args, _archive.OnFileChecked, "SevenZipArchive.FileChecked");
                }
                else
                {
                    result = HRESULT.S_OK;
                }
                break;

            case OperationResult.CRCError:
                _exception = new BadCrcException(string.Format(
                                                     "The {0} is corrupted. The CRC check has failed.",
                                                     (LastEntryFileName != null ? string.Format("file '{0}'", LastEntryFileName) : "archive")),
                                                 LastEntryFileName);
                result = RaiseExtractionOrCheckFailedEvent(_exception);
                break;

            case OperationResult.DataError:
                if (LastEntryFileName != null)
                {
                    _exception = new DataErrorException(string.Format(
                                                            "The file '{0}' is corrupted. A data error has occured.", LastEntryFileName), LastEntryFileName);
                    if (_isEncrypted)
                    {
                        _exception = new BadPasswordException(string.Format(
                                                                  "Incorrect password specified to decrypt the file '{0}'.", LastEntryFileName), LastEntryFileName, _exception);
                    }
                }
                else
                {
                    _exception = new DataErrorException("The archive is corrupted. A data error has occured.");
                }
                result = RaiseExtractionOrCheckFailedEvent(_exception);
                break;

            case OperationResult.UnSupportedMethod:
                _exception = new UnsupportedMethodException("An unsupported method error has occured.", LastEntryFileName);
                result     = RaiseExtractionOrCheckFailedEvent(_exception);
                break;
            }

            return(result);
        }
        public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
        {
            outStream          = null;
            _lastEntryIndex    = index;
            _lastEntryIndexSet = true;
            _lastAskMode       = askExtractMode;

            Debug.Assert(_stream == null);
            if (_stream != null)
            {
                _stream.Dispose();
                _stream = null;
            }

            if (_extractMode == ExtractMode.UnpackedSize)
            {
                return(HRESULT.E_ABORT);
            }
            else if (askExtractMode != AskMode.Extract)
            {
                if (askExtractMode == AskMode.Skip)
                {
                    Debug.Assert(!_entries.ContainsKey(index));
                }
                return(HRESULT.S_OK);
            }
            else if (!_entries.ContainsKey(index))
            {
                Debug.Fail("Unexpected case.");
                _stream   = new OutStreamWrapper(new DummyOutStream());
                outStream = _stream;
                return(HRESULT.S_OK);
            }

            Debug.Assert(_archive != null, "_archive was not set correctly. The wrong constructor may have been used.");

            if (_targetDirectory != null)
            {
                // Writing to file system

                Debug.Assert(_extractMode == ExtractMode.ExtractToFile, "Wrong constructor used.");
                Debug.Assert(_targetDirectory.IndexOfAny(Path.GetInvalidPathChars()) == -1);

                string filePath;
                if (AutoRenamePath(LastEntryFileName, out _lastExtractedFileName))
                {
                    filePath = LastExtractedFilePath;
                }
                else
                {
                    Debug.Assert(_exception == null || _exception is PasswordRequiredException);
                    if (!(_exception is PasswordRequiredException))
                    {
                        _exception = new SevenZipException(string.Format(
                                                               "The file '{0}' cannot be extracted because the path contains invalid characters or components.", LastEntryFileName));
                    }

                    _stream   = new OutStreamWrapper(new DummyOutStream());
                    outStream = _stream;
                    return(HRESULT.S_OK);
                }

                try
                {
                    string directory = _entries[index].IsDirectory ? filePath : Path.GetDirectoryName(filePath);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    if (_entries[index].IsDirectory)
                    {
                        Debug.Assert(_directoryEntries != null);
                        _directoryEntries[directory] = _entries[index];
                        _stream   = new OutStreamWrapper(new DummyOutStream());
                        outStream = _stream;
                        return(HRESULT.S_OK);
                    }
                    else
                    {
                        if (File.Exists(filePath))
                        {
                            FileExistsEventArgs fileExistsArgs = new FileExistsEventArgs()
                            {
                                Action          = ExtractOptionsToFileExistAction(_options),
                                TargetDirectory = _targetDirectory,
                                Entry           = _entries[_lastEntryIndex],
                            };

                            int result = InvokeEventHandler(fileExistsArgs, _archive.OnFileExists, "SevenZipArchive.FileExists");
                            if (result != HRESULT.S_OK)
                            {
                                return(result);
                            }

                            if (fileExistsArgs.Action == FileExistsAction.Throw)
                            {
                                Debug.Assert(_exception == null || _exception is PasswordRequiredException);
                                if (!(_exception is PasswordRequiredException))
                                {
                                    _exception = new SevenZipException(string.Format(
                                                                           "The file '{0}' cannot be extracted to '{1}' because a file with the same name already exists.",
                                                                           Path.GetFileName(LastExtractedFileName), directory));
                                }

                                _stream   = new OutStreamWrapper(new DummyOutStream());
                                outStream = _stream;
                                return(HRESULT.S_OK);
                            }
                            else if (fileExistsArgs.Action == FileExistsAction.Skip)
                            {
                                _lastFileSkipped = true;
                                _stream          = new OutStreamWrapper(new DummyOutStream());
                                outStream        = _stream;
                                return(HRESULT.S_OK);
                            }
                        }
                        _stream   = new OutStreamWrapper(File.Create(filePath));
                        outStream = _stream;
                        return(HRESULT.S_OK);
                    }
                }
                catch (Exception e)
                {
                    Debug.Assert(_exception == null || _exception is PasswordRequiredException);
                    if (!(_exception is PasswordRequiredException))
                    {
                        _exception = new SevenZipException(string.Format(
                                                               "An exception occured while extracting the file '{0}'.", LastEntryFileName), e);
                    }

                    _stream   = new OutStreamWrapper(new DummyOutStream());
                    outStream = _stream;
                    return(HRESULT.S_OK);
                }
            }
            else
            {
                // Writing to stream

                Debug.Assert(_extractMode == ExtractMode.ExtractToStream, "Wrong constructor used.");
                Debug.Assert(_targetStream != null);
                _stream   = new OutStreamWrapper(_targetStream, false);
                outStream = _stream;
                return(HRESULT.S_OK);
            }
        }