ArchiveUpdateCallback.cs 30 KB

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