ArchiveUpdateCallback.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. /* This file is part of SevenZipSharp.
  2. SevenZipSharp is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU Lesser General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. SevenZipSharp is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU Lesser General Public License for more details.
  10. You should have received a copy of the GNU Lesser General Public License
  11. along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. using System;
  14. using System.Collections.Generic;
  15. using System.IO;
  16. using System.Runtime.InteropServices;
  17. #if MONO
  18. using SevenZip.Mono.COM;
  19. #endif
  20. namespace SevenZip
  21. {
  22. #if UNMANAGED
  23. #if COMPRESS
  24. /// <summary>
  25. /// Archive update callback to handle the process of packing files
  26. /// </summary>
  27. internal sealed class ArchiveUpdateCallback : CallbackBase, IArchiveUpdateCallback, ICryptoGetTextPassword2,
  28. IDisposable
  29. {
  30. #region Fields
  31. /// <summary>
  32. /// _files.Count if do not count directories
  33. /// </summary>
  34. private int _actualFilesCount;
  35. /// <summary>
  36. /// For Compressing event.
  37. /// </summary>
  38. private long _bytesCount;
  39. private long _bytesWritten;
  40. private long _bytesWrittenOld;
  41. private SevenZipCompressor _compressor;
  42. /// <summary>
  43. /// No directories.
  44. /// </summary>
  45. private bool _directoryStructure;
  46. /// <summary>
  47. /// Rate of the done work from [0, 1]
  48. /// </summary>
  49. private float _doneRate;
  50. /// <summary>
  51. /// The names of the archive entries
  52. /// </summary>
  53. private string[] _entries;
  54. /// <summary>
  55. /// Array of files to pack
  56. /// </summary>
  57. private FileInfo[] _files;
  58. private InStreamWrapper _fileStream;
  59. private uint _indexInArchive;
  60. private uint _indexOffset;
  61. /// <summary>
  62. /// Common root of file names length.
  63. /// </summary>
  64. private int _rootLength;
  65. /// <summary>
  66. /// Input streams to be compressed.
  67. /// </summary>
  68. private Stream[] _streams;
  69. private UpdateData _updateData;
  70. private List<InStreamWrapper> _wrappersToDispose;
  71. /// <summary>
  72. /// Gets or sets the default item name used in MemoryStream compression.
  73. /// </summary>
  74. public string DefaultItemName { private get; set; }
  75. /// <summary>
  76. /// Gets or sets the value indicating whether to compress as fast as possible, without calling events.
  77. /// </summary>
  78. public bool FastCompression { private get; set; }
  79. #if !WINCE
  80. private int _memoryPressure;
  81. #endif
  82. #endregion
  83. #region Constructors
  84. /// <summary>
  85. /// Initializes a new instance of the ArchiveUpdateCallback class
  86. /// </summary>
  87. /// <param name="files">Array of files to pack</param>
  88. /// <param name="rootLength">Common file names root length</param>
  89. /// <param name="compressor">The owner of the callback</param>
  90. /// <param name="updateData">The compression parameters.</param>
  91. /// <param name="directoryStructure">Preserve directory structure.</param>
  92. public ArchiveUpdateCallback(
  93. FileInfo[] files, int rootLength,
  94. SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  95. {
  96. Init(files, rootLength, compressor, updateData, directoryStructure);
  97. }
  98. /// <summary>
  99. /// Initializes a new instance of the ArchiveUpdateCallback class
  100. /// </summary>
  101. /// <param name="files">Array of files to pack</param>
  102. /// <param name="rootLength">Common file names root length</param>
  103. /// <param name="password">The archive password</param>
  104. /// <param name="compressor">The owner of the callback</param>
  105. /// <param name="updateData">The compression parameters.</param>
  106. /// <param name="directoryStructure">Preserve directory structure.</param>
  107. public ArchiveUpdateCallback(
  108. FileInfo[] files, int rootLength, string password,
  109. SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  110. : base(password)
  111. {
  112. Init(files, rootLength, compressor, updateData, directoryStructure);
  113. }
  114. /// <summary>
  115. /// Initializes a new instance of the ArchiveUpdateCallback class
  116. /// </summary>
  117. /// <param name="stream">The input stream</param>
  118. /// <param name="compressor">The owner of the callback</param>
  119. /// <param name="updateData">The compression parameters.</param>
  120. /// <param name="directoryStructure">Preserve directory structure.</param>
  121. public ArchiveUpdateCallback(
  122. Stream stream, SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  123. {
  124. Init(stream, compressor, updateData, directoryStructure);
  125. }
  126. /// <summary>
  127. /// Initializes a new instance of the ArchiveUpdateCallback class
  128. /// </summary>
  129. /// <param name="stream">The input stream</param>
  130. /// <param name="password">The archive password</param>
  131. /// <param name="compressor">The owner of the callback</param>
  132. /// <param name="updateData">The compression parameters.</param>
  133. /// <param name="directoryStructure">Preserve directory structure.</param>
  134. public ArchiveUpdateCallback(
  135. Stream stream, string password, SevenZipCompressor compressor, UpdateData updateData,
  136. bool directoryStructure)
  137. : base(password)
  138. {
  139. Init(stream, compressor, updateData, directoryStructure);
  140. }
  141. /// <summary>
  142. /// Initializes a new instance of the ArchiveUpdateCallback class
  143. /// </summary>
  144. /// <param name="streamDict">Dictionary&lt;file stream, name of the archive entry&gt;</param>
  145. /// <param name="compressor">The owner of the callback</param>
  146. /// <param name="updateData">The compression parameters.</param>
  147. /// <param name="directoryStructure">Preserve directory structure.</param>
  148. public ArchiveUpdateCallback(
  149. Dictionary<string, Stream> streamDict,
  150. SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  151. {
  152. Init(streamDict, compressor, updateData, directoryStructure);
  153. }
  154. /// <summary>
  155. /// Initializes a new instance of the ArchiveUpdateCallback class
  156. /// </summary>
  157. /// <param name="streamDict">Dictionary&lt;file stream, name of the archive entry&gt;</param>
  158. /// <param name="password">The archive password</param>
  159. /// <param name="compressor">The owner of the callback</param>
  160. /// <param name="updateData">The compression parameters.</param>
  161. /// <param name="directoryStructure">Preserve directory structure.</param>
  162. public ArchiveUpdateCallback(
  163. Dictionary<string, Stream> streamDict, string password,
  164. SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  165. : base(password)
  166. {
  167. Init(streamDict, compressor, updateData, directoryStructure);
  168. }
  169. private void CommonInit(SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  170. {
  171. _compressor = compressor;
  172. _indexInArchive = updateData.FilesCount;
  173. _indexOffset = updateData.Mode != InternalCompressionMode.Append ? 0 : _indexInArchive;
  174. if (_compressor.ArchiveFormat == OutArchiveFormat.Zip)
  175. {
  176. _wrappersToDispose = new List<InStreamWrapper>();
  177. }
  178. _updateData = updateData;
  179. _directoryStructure = directoryStructure;
  180. DefaultItemName = "default";
  181. }
  182. private void Init(
  183. FileInfo[] files, int rootLength, SevenZipCompressor compressor,
  184. UpdateData updateData, bool directoryStructure)
  185. {
  186. _files = files;
  187. _rootLength = rootLength;
  188. if (files != null)
  189. {
  190. foreach (var fi in files)
  191. {
  192. if (fi.Exists)
  193. {
  194. _bytesCount += fi.Length;
  195. if ((fi.Attributes & FileAttributes.Directory) == 0)
  196. {
  197. _actualFilesCount++;
  198. }
  199. }
  200. }
  201. }
  202. CommonInit(compressor, updateData, directoryStructure);
  203. }
  204. private void Init(
  205. Stream stream, SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  206. {
  207. _fileStream = new InStreamWrapper(stream, false);
  208. _fileStream.BytesRead += IntEventArgsHandler;
  209. _actualFilesCount = 1;
  210. try
  211. {
  212. _bytesCount = stream.Length;
  213. }
  214. catch (NotSupportedException)
  215. {
  216. _bytesCount = -1;
  217. }
  218. try
  219. {
  220. stream.Seek(0, SeekOrigin.Begin);
  221. }
  222. catch (NotSupportedException)
  223. {
  224. _bytesCount = -1;
  225. }
  226. CommonInit(compressor, updateData, directoryStructure);
  227. }
  228. private void Init(
  229. Dictionary<string, Stream> streamDict,
  230. SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure)
  231. {
  232. _streams = new Stream[streamDict.Count];
  233. streamDict.Values.CopyTo(_streams, 0);
  234. _entries = new string[streamDict.Count];
  235. streamDict.Keys.CopyTo(_entries, 0);
  236. _actualFilesCount = streamDict.Count;
  237. foreach (Stream str in _streams)
  238. {
  239. if (str != null)
  240. {
  241. _bytesCount += str.Length;
  242. }
  243. }
  244. CommonInit(compressor, updateData, directoryStructure);
  245. }
  246. #endregion
  247. /// <summary>
  248. /// Gets or sets the dictionary size.
  249. /// </summary>
  250. public float DictionarySize
  251. {
  252. set
  253. {
  254. #if !WINCE
  255. _memoryPressure = (int)(value * 1024 * 1024);
  256. GC.AddMemoryPressure(_memoryPressure);
  257. #endif
  258. }
  259. }
  260. /// <summary>
  261. /// Raises events for the GetStream method.
  262. /// </summary>
  263. /// <param name="index">The current item index.</param>
  264. /// <returns>True if not cancelled; otherwise, false.</returns>
  265. private bool EventsForGetStream(uint index)
  266. {
  267. if (!FastCompression)
  268. {
  269. if (_fileStream != null)
  270. {
  271. _fileStream.BytesRead += IntEventArgsHandler;
  272. }
  273. _doneRate += 1.0f / _actualFilesCount;
  274. var fiea = new FileNameEventArgs(_files != null? _files[index].Name : _entries[index],
  275. PercentDoneEventArgs.ProducePercentDone(_doneRate));
  276. OnFileCompression(fiea);
  277. if (fiea.Cancel)
  278. {
  279. Canceled = true;
  280. return false;
  281. }
  282. }
  283. return true;
  284. }
  285. #region Events
  286. /// <summary>
  287. /// Occurs when the next file is going to be packed.
  288. /// </summary>
  289. /// <remarks>Occurs when 7-zip engine requests for an input stream for the next file to pack it</remarks>
  290. public event EventHandler<FileNameEventArgs> FileCompressionStarted;
  291. /// <summary>
  292. /// Occurs when data are being compressed.
  293. /// </summary>
  294. public event EventHandler<ProgressEventArgs> Compressing;
  295. /// <summary>
  296. /// Occurs when the current file was compressed.
  297. /// </summary>
  298. public event EventHandler FileCompressionFinished;
  299. private void OnFileCompression(FileNameEventArgs e)
  300. {
  301. if (FileCompressionStarted != null)
  302. {
  303. FileCompressionStarted(this, e);
  304. }
  305. }
  306. private void OnCompressing(ProgressEventArgs e)
  307. {
  308. if (Compressing != null)
  309. {
  310. Compressing(this, e);
  311. }
  312. }
  313. private void OnFileCompressionFinished(EventArgs e)
  314. {
  315. if (FileCompressionFinished != null)
  316. {
  317. FileCompressionFinished(this, e);
  318. }
  319. }
  320. #endregion
  321. #region IArchiveUpdateCallback Members
  322. public void SetTotal(ulong total) {}
  323. public void SetCompleted(ref ulong completeValue) {}
  324. public int GetUpdateItemInfo(uint index, ref int newData, ref int newProperties, ref uint indexInArchive)
  325. {
  326. switch (_updateData.Mode)
  327. {
  328. case InternalCompressionMode.Create:
  329. newData = 1;
  330. newProperties = 1;
  331. indexInArchive = UInt32.MaxValue;
  332. break;
  333. case InternalCompressionMode.Append:
  334. if (index < _indexInArchive)
  335. {
  336. newData = 0;
  337. newProperties = 0;
  338. indexInArchive = index;
  339. }
  340. else
  341. {
  342. newData = 1;
  343. newProperties = 1;
  344. indexInArchive = UInt32.MaxValue;
  345. }
  346. break;
  347. case InternalCompressionMode.Modify:
  348. newData = 0;
  349. newProperties = Convert.ToInt32(_updateData.FileNamesToModify.ContainsKey((int)index)
  350. && _updateData.FileNamesToModify[(int)index] != null);
  351. if (_updateData.FileNamesToModify.ContainsKey((int)index)
  352. && _updateData.FileNamesToModify[(int)index] == null)
  353. {
  354. indexInArchive = (UInt32)_updateData.ArchiveFileData.Count;
  355. foreach (KeyValuePair<Int32, string> pairModification in _updateData.FileNamesToModify)
  356. if ((pairModification.Key <= index) && (pairModification.Value == null))
  357. {
  358. do
  359. {
  360. indexInArchive--;
  361. }
  362. while ((indexInArchive > 0) && _updateData.FileNamesToModify.ContainsKey((Int32)indexInArchive)
  363. && (_updateData.FileNamesToModify[(Int32)indexInArchive] == null));
  364. }
  365. }
  366. else
  367. {
  368. indexInArchive = index;
  369. }
  370. break;
  371. }
  372. return 0;
  373. }
  374. public int GetProperty(uint index, ItemPropId propID, ref PropVariant value)
  375. {
  376. index -= _indexOffset;
  377. try
  378. {
  379. switch (propID)
  380. {
  381. case ItemPropId.IsAnti:
  382. value.VarType = VarEnum.VT_BOOL;
  383. value.UInt64Value = 0;
  384. break;
  385. case ItemPropId.Path:
  386. #region Path
  387. value.VarType = VarEnum.VT_BSTR;
  388. string val = DefaultItemName;
  389. if (_updateData.Mode != InternalCompressionMode.Modify)
  390. {
  391. if (_files == null)
  392. {
  393. if (_entries != null)
  394. {
  395. val = _entries[index];
  396. }
  397. }
  398. else
  399. {
  400. if (_directoryStructure)
  401. {
  402. if (_rootLength > 0)
  403. {
  404. val = _files[index].FullName.Substring(_rootLength);
  405. }
  406. else
  407. {
  408. val = _files[index].FullName[0] + _files[index].FullName.Substring(2);
  409. }
  410. }
  411. else
  412. {
  413. val = _files[index].Name;
  414. }
  415. }
  416. }
  417. else
  418. {
  419. val = _updateData.FileNamesToModify[(int) index];
  420. }
  421. value.Value = Marshal.StringToBSTR(val);
  422. #endregion
  423. break;
  424. case ItemPropId.IsDirectory:
  425. value.VarType = VarEnum.VT_BOOL;
  426. if (_updateData.Mode != InternalCompressionMode.Modify)
  427. {
  428. if (_files == null)
  429. {
  430. if (_streams == null)
  431. {
  432. value.UInt64Value = 0;
  433. }
  434. else
  435. {
  436. value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0);
  437. }
  438. }
  439. else
  440. {
  441. value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory);
  442. }
  443. }
  444. else
  445. {
  446. value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int) index].IsDirectory);
  447. }
  448. break;
  449. case ItemPropId.Size:
  450. #region Size
  451. value.VarType = VarEnum.VT_UI8;
  452. UInt64 size;
  453. if (_updateData.Mode != InternalCompressionMode.Modify)
  454. {
  455. if (_files == null)
  456. {
  457. if (_streams == null)
  458. {
  459. size = _bytesCount > 0 ? (ulong) _bytesCount : 0;
  460. }
  461. else
  462. {
  463. size = (ulong) (_streams[index] == null? 0 : _streams[index].Length);
  464. }
  465. }
  466. else
  467. {
  468. size = (_files[index].Attributes & FileAttributes.Directory) == 0
  469. ? (ulong) _files[index].Length
  470. : 0;
  471. }
  472. }
  473. else
  474. {
  475. size = _updateData.ArchiveFileData[(int) index].Size;
  476. }
  477. value.UInt64Value = size;
  478. #endregion
  479. break;
  480. case ItemPropId.Attributes:
  481. value.VarType = VarEnum.VT_UI4;
  482. if (_updateData.Mode != InternalCompressionMode.Modify)
  483. {
  484. if (_files == null)
  485. {
  486. if (_streams == null)
  487. {
  488. value.UInt32Value = (uint)FileAttributes.Normal;
  489. }
  490. else
  491. {
  492. value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal);
  493. }
  494. }
  495. else
  496. {
  497. value.UInt32Value = (uint) _files[index].Attributes;
  498. }
  499. }
  500. else
  501. {
  502. value.UInt32Value = _updateData.ArchiveFileData[(int) index].Attributes;
  503. }
  504. break;
  505. #region Times
  506. case ItemPropId.CreationTime:
  507. value.VarType = VarEnum.VT_FILETIME;
  508. if (_updateData.Mode != InternalCompressionMode.Modify)
  509. {
  510. value.Int64Value = _files == null
  511. ? DateTime.Now.ToFileTime()
  512. : _files[index].CreationTime.ToFileTime();
  513. }
  514. else
  515. {
  516. value.Int64Value = _updateData.ArchiveFileData[(int) index].CreationTime.ToFileTime();
  517. }
  518. break;
  519. case ItemPropId.LastAccessTime:
  520. value.VarType = VarEnum.VT_FILETIME;
  521. if (_updateData.Mode != InternalCompressionMode.Modify)
  522. {
  523. value.Int64Value = _files == null
  524. ? DateTime.Now.ToFileTime()
  525. : _files[index].LastAccessTime.ToFileTime();
  526. }
  527. else
  528. {
  529. value.Int64Value = _updateData.ArchiveFileData[(int) index].LastAccessTime.ToFileTime();
  530. }
  531. break;
  532. case ItemPropId.LastWriteTime:
  533. value.VarType = VarEnum.VT_FILETIME;
  534. if (_updateData.Mode != InternalCompressionMode.Modify)
  535. {
  536. value.Int64Value = _files == null
  537. ? DateTime.Now.ToFileTime()
  538. : _files[index].LastWriteTime.ToFileTime();
  539. }
  540. else
  541. {
  542. value.Int64Value = _updateData.ArchiveFileData[(int) index].LastWriteTime.ToFileTime();
  543. }
  544. break;
  545. #endregion
  546. case ItemPropId.Extension:
  547. #region Extension
  548. value.VarType = VarEnum.VT_BSTR;
  549. if (_updateData.Mode != InternalCompressionMode.Modify)
  550. {
  551. try
  552. {
  553. val = _files != null
  554. ? _files[index].Extension.Substring(1)
  555. : _entries == null
  556. ? ""
  557. : Path.GetExtension(_entries[index]);
  558. value.Value = Marshal.StringToBSTR(val);
  559. }
  560. catch (ArgumentException)
  561. {
  562. value.Value = Marshal.StringToBSTR("");
  563. }
  564. }
  565. else
  566. {
  567. val = Path.GetExtension(_updateData.ArchiveFileData[(int) index].FileName);
  568. value.Value = Marshal.StringToBSTR(val);
  569. }
  570. #endregion
  571. break;
  572. }
  573. }
  574. catch (Exception e)
  575. {
  576. AddException(e);
  577. }
  578. return 0;
  579. }
  580. /// <summary>
  581. /// Gets the stream for 7-zip library.
  582. /// </summary>
  583. /// <param name="index">File index</param>
  584. /// <param name="inStream">Input file stream</param>
  585. /// <returns>Zero if Ok</returns>
  586. public int GetStream(uint index, out
  587. #if !MONO
  588. ISequentialInStream
  589. #else
  590. HandleRef
  591. #endif
  592. inStream)
  593. {
  594. index -= _indexOffset;
  595. if (_files != null)
  596. {
  597. _fileStream = null;
  598. try
  599. {
  600. if (File.Exists(_files[index].FullName))
  601. {
  602. _fileStream = new InStreamWrapper(
  603. new FileStream(_files[index].FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite),
  604. true);
  605. }
  606. }
  607. catch (Exception e)
  608. {
  609. AddException(e);
  610. inStream = null;
  611. return -1;
  612. }
  613. inStream = _fileStream;
  614. if (!EventsForGetStream(index))
  615. {
  616. return -1;
  617. }
  618. }
  619. else
  620. {
  621. if (_streams == null)
  622. {
  623. inStream = _fileStream;
  624. }
  625. else
  626. {
  627. _fileStream = new InStreamWrapper(_streams[index], true);
  628. inStream = _fileStream;
  629. if (!EventsForGetStream(index))
  630. {
  631. return -1;
  632. }
  633. }
  634. }
  635. return 0;
  636. }
  637. public long EnumProperties(IntPtr enumerator)
  638. {
  639. //Not implemented HRESULT
  640. return 0x80004001L;
  641. }
  642. public void SetOperationResult(OperationResult operationResult)
  643. {
  644. if (operationResult != OperationResult.Ok && ReportErrors)
  645. {
  646. switch (operationResult)
  647. {
  648. case OperationResult.CrcError:
  649. AddException(new ExtractionFailedException("File is corrupted. Crc check has failed."));
  650. break;
  651. case OperationResult.DataError:
  652. AddException(new ExtractionFailedException("File is corrupted. Data error has occured."));
  653. break;
  654. case OperationResult.UnsupportedMethod:
  655. AddException(new ExtractionFailedException("Unsupported method error has occured."));
  656. break;
  657. }
  658. }
  659. if (_fileStream != null)
  660. {
  661. _fileStream.BytesRead -= IntEventArgsHandler;
  662. //Specific Zip implementation - can not Dispose files for Zip.
  663. if (_compressor.ArchiveFormat != OutArchiveFormat.Zip)
  664. {
  665. try
  666. {
  667. _fileStream.Dispose();
  668. }
  669. catch (ObjectDisposedException) {}
  670. }
  671. else
  672. {
  673. _wrappersToDispose.Add(_fileStream);
  674. }
  675. _fileStream = null;
  676. GC.Collect();
  677. // Issue #6987
  678. //GC.WaitForPendingFinalizers();
  679. }
  680. OnFileCompressionFinished(EventArgs.Empty);
  681. }
  682. #endregion
  683. #region ICryptoGetTextPassword2 Members
  684. public int CryptoGetTextPassword2(ref int passwordIsDefined, out string password)
  685. {
  686. passwordIsDefined = String.IsNullOrEmpty(Password) ? 0 : 1;
  687. password = Password;
  688. return 0;
  689. }
  690. #endregion
  691. #region IDisposable Members
  692. public void Dispose()
  693. {
  694. #if !WINCE
  695. GC.RemoveMemoryPressure(_memoryPressure);
  696. #endif
  697. if (_fileStream != null)
  698. {
  699. try
  700. {
  701. _fileStream.Dispose();
  702. }
  703. catch (ObjectDisposedException) {}
  704. }
  705. if (_wrappersToDispose != null)
  706. {
  707. foreach (var wrapper in _wrappersToDispose)
  708. {
  709. try
  710. {
  711. wrapper.Dispose();
  712. }
  713. catch (ObjectDisposedException) {}
  714. }
  715. }
  716. GC.SuppressFinalize(this);
  717. }
  718. #endregion
  719. private void IntEventArgsHandler(object sender, IntEventArgs e)
  720. {
  721. lock (this)
  722. {
  723. var pold = (byte) ((_bytesWrittenOld*100)/_bytesCount);
  724. _bytesWritten += e.Value;
  725. byte pnow;
  726. if (_bytesCount < _bytesWritten) //Holy shit, this check for ZIP is golden
  727. {
  728. pnow = 100;
  729. }
  730. else
  731. {
  732. pnow = (byte)((_bytesWritten * 100) / _bytesCount);
  733. }
  734. if (pnow > pold)
  735. {
  736. _bytesWrittenOld = _bytesWritten;
  737. OnCompressing(new ProgressEventArgs(pnow, (byte) (pnow - pold)));
  738. }
  739. }
  740. }
  741. }
  742. #endif
  743. #endif
  744. }