1 // ExtractCallbackConsole.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/IntToString.h"
6 #include "../../../Common/Wildcard.h"
7
8 #include "../../../Windows/FileDir.h"
9 #include "../../../Windows/FileFind.h"
10 #include "../../../Windows/TimeUtils.h"
11 #include "../../../Windows/ErrorMsg.h"
12 #include "../../../Windows/PropVariantConv.h"
13
14 #ifndef _7ZIP_ST
15 #include "../../../Windows/Synchronization.h"
16 #endif
17
18 #include "../../Common/FilePathAutoRename.h"
19
20 #include "../Common/ExtractingFilePath.h"
21
22 #include "ConsoleClose.h"
23 #include "ExtractCallbackConsole.h"
24 #include "UserInputUtils.h"
25
26 using namespace NWindows;
27 using namespace NFile;
28 using namespace NDir;
29
CheckBreak2()30 static HRESULT CheckBreak2()
31 {
32 return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
33 }
34
35 static const char * const kError = "ERROR: ";
36
37
StartScanning()38 void CExtractScanConsole::StartScanning()
39 {
40 if (NeedPercents())
41 _percent.Command = "Scan";
42 }
43
ScanProgress(const CDirItemsStat & st,const FString & path,bool)44 HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
45 {
46 if (NeedPercents())
47 {
48 _percent.Files = st.NumDirs + st.NumFiles;
49 _percent.Completed = st.GetTotalBytes();
50 _percent.FileName = fs2us(path);
51 _percent.Print();
52 }
53
54 return CheckBreak2();
55 }
56
ScanError(const FString & path,DWORD systemError)57 HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
58 {
59 // 22.00:
60 // ScanErrors.AddError(path, systemError);
61
62 ClosePercentsAndFlush();
63
64 if (_se)
65 {
66 *_se << endl << kError << NError::MyFormatMessage(systemError) << endl;
67 _se->NormalizePrint_UString(fs2us(path));
68 *_se << endl << endl;
69 _se->Flush();
70 }
71 return HRESULT_FROM_WIN32(systemError);
72
73 // 22.00: commented
74 // CommonError(path, systemError, true);
75 // return S_OK;
76 }
77
78
79 void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);
Print_UInt64_and_String(AString & s,UInt64 val,const char * name)80 void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
81 {
82 char temp[32];
83 ConvertUInt64ToString(val, temp);
84 s += temp;
85 s.Add_Space();
86 s += name;
87 }
88
89 void PrintSize_bytes_Smart(AString &s, UInt64 val);
PrintSize_bytes_Smart(AString & s,UInt64 val)90 void PrintSize_bytes_Smart(AString &s, UInt64 val)
91 {
92 Print_UInt64_and_String(s, val, "bytes");
93
94 if (val == 0)
95 return;
96
97 unsigned numBits = 10;
98 char c = 'K';
99 char temp[4] = { 'K', 'i', 'B', 0 };
100 if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
101 else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
102 temp[0] = c;
103 s += " (";
104 Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
105 s += ')';
106 }
107
PrintSize_bytes_Smart_comma(AString & s,UInt64 val)108 static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
109 {
110 if (val == (UInt64)(Int64)-1)
111 return;
112 s += ", ";
113 PrintSize_bytes_Smart(s, val);
114 }
115
116
117
118 void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
Print_DirItemsStat(AString & s,const CDirItemsStat & st)119 void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
120 {
121 if (st.NumDirs != 0)
122 {
123 Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders");
124 s += ", ";
125 }
126 Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
127 PrintSize_bytes_Smart_comma(s, st.FilesSize);
128 if (st.NumAltStreams != 0)
129 {
130 s.Add_LF();
131 Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
132 PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
133 }
134 }
135
136
137 void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
Print_DirItemsStat2(AString & s,const CDirItemsStat2 & st)138 void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
139 {
140 Print_DirItemsStat(s, (CDirItemsStat &)st);
141 bool needLF = true;
142 if (st.Anti_NumDirs != 0)
143 {
144 if (needLF)
145 s.Add_LF();
146 needLF = false;
147 Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
148 }
149 if (st.Anti_NumFiles != 0)
150 {
151 if (needLF)
152 s.Add_LF();
153 else
154 s += ", ";
155 needLF = false;
156 Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
157 }
158 if (st.Anti_NumAltStreams != 0)
159 {
160 if (needLF)
161 s.Add_LF();
162 else
163 s += ", ";
164 needLF = false;
165 Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
166 }
167 }
168
169
PrintStat(const CDirItemsStat & st)170 void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
171 {
172 if (_so)
173 {
174 AString s;
175 Print_DirItemsStat(s, st);
176 *_so << s << endl;
177 }
178 }
179
180
181
182
183
184
185
186 #ifndef _7ZIP_ST
187 static NSynchronization::CCriticalSection g_CriticalSection;
188 #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
189 #else
190 #define MT_LOCK
191 #endif
192
193
194 static const char * const kTestString = "T";
195 static const char * const kExtractString = "-";
196 static const char * const kSkipString = ".";
197 static const char * const kReadString = "H";
198
199 // static const char * const kCantAutoRename = "cannot create file with auto name\n";
200 // static const char * const kCantRenameFile = "cannot rename existing file\n";
201 // static const char * const kCantDeleteOutputFile = "cannot delete output file ";
202
203 static const char * const kMemoryExceptionMessage = "Can't allocate required memory!";
204
205 static const char * const kExtracting = "Extracting archive: ";
206 static const char * const kTesting = "Testing archive: ";
207
208 static const char * const kEverythingIsOk = "Everything is Ok";
209 static const char * const kNoFiles = "No files to process";
210
211 static const char * const kUnsupportedMethod = "Unsupported Method";
212 static const char * const kCrcFailed = "CRC Failed";
213 static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
214 static const char * const kDataError = "Data Error";
215 static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
216 static const char * const kUnavailableData = "Unavailable data";
217 static const char * const kUnexpectedEnd = "Unexpected end of data";
218 static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
219 static const char * const kIsNotArc = "Is not archive";
220 static const char * const kHeadersError = "Headers Error";
221 static const char * const kWrongPassword = "Wrong password";
222
223 static const char * const k_ErrorFlagsMessages[] =
224 {
225 "Is not archive"
226 , "Headers Error"
227 , "Headers Error in encrypted archive. Wrong password?"
228 , "Unavailable start of archive"
229 , "Unconfirmed start of archive"
230 , "Unexpected end of archive"
231 , "There are data after the end of archive"
232 , "Unsupported method"
233 , "Unsupported feature"
234 , "Data Error"
235 , "CRC Error"
236 };
237
SetTotal(UInt64 size)238 STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
239 {
240 MT_LOCK
241
242 if (NeedPercents())
243 {
244 _percent.Total = size;
245 _percent.Print();
246 }
247 return CheckBreak2();
248 }
249
SetCompleted(const UInt64 * completeValue)250 STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
251 {
252 MT_LOCK
253
254 if (NeedPercents())
255 {
256 if (completeValue)
257 _percent.Completed = *completeValue;
258 _percent.Print();
259 }
260 return CheckBreak2();
261 }
262
263 static const char * const kTab = " ";
264
PrintFileInfo(CStdOutStream * _so,const wchar_t * path,const FILETIME * ft,const UInt64 * size)265 static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
266 {
267 *_so << kTab << "Path: ";
268 _so->NormalizePrint_wstr(path);
269 *_so << endl;
270 if (size && *size != (UInt64)(Int64)-1)
271 {
272 AString s;
273 PrintSize_bytes_Smart(s, *size);
274 *_so << kTab << "Size: " << s << endl;
275 }
276 if (ft)
277 {
278 char temp[64];
279 if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))
280 *_so << kTab << "Modified: " << temp << endl;
281 }
282 }
283
AskOverwrite(const wchar_t * existName,const FILETIME * existTime,const UInt64 * existSize,const wchar_t * newName,const FILETIME * newTime,const UInt64 * newSize,Int32 * answer)284 STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
285 const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
286 const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
287 Int32 *answer)
288 {
289 MT_LOCK
290
291 RINOK(CheckBreak2());
292
293 ClosePercentsAndFlush();
294
295 if (_so)
296 {
297 *_so << endl << "Would you like to replace the existing file:\n";
298 PrintFileInfo(_so, existName, existTime, existSize);
299 *_so << "with the file from archive:\n";
300 PrintFileInfo(_so, newName, newTime, newSize);
301 }
302
303 NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);
304
305 switch (overwriteAnswer)
306 {
307 case NUserAnswerMode::kQuit: return E_ABORT;
308 case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break;
309 case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break;
310 case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
311 case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break;
312 case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
313 case NUserAnswerMode::kEof: return E_ABORT;
314 case NUserAnswerMode::kError: return E_FAIL;
315 default: return E_FAIL;
316 }
317
318 if (_so)
319 {
320 *_so << endl;
321 if (NeedFlush)
322 _so->Flush();
323 }
324
325 return CheckBreak2();
326 }
327
PrepareOperation(const wchar_t * name,Int32 isFolder,Int32 askExtractMode,const UInt64 * position)328 STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)
329 {
330 MT_LOCK
331
332 _currentName = name;
333
334 const char *s;
335 unsigned requiredLevel = 1;
336
337 switch (askExtractMode)
338 {
339 case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
340 case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
341 case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break;
342 case NArchive::NExtract::NAskMode::kReadExternal: s = kReadString; requiredLevel = 0; break;
343 default: s = "???"; requiredLevel = 2;
344 };
345
346 bool show2 = (LogLevel >= requiredLevel && _so);
347
348 if (show2)
349 {
350 ClosePercents_for_so();
351
352 _tempA = s;
353 if (name)
354 _tempA.Add_Space();
355 *_so << _tempA;
356
357 _tempU.Empty();
358 if (name)
359 {
360 _tempU = name;
361 _so->Normalize_UString(_tempU);
362 // 21.04
363 if (isFolder)
364 {
365 if (!_tempU.IsEmpty() && _tempU.Back() != WCHAR_PATH_SEPARATOR)
366 _tempU.Add_PathSepar();
367 }
368 }
369 _so->PrintUString(_tempU, _tempA);
370 if (position)
371 *_so << " <" << *position << ">";
372 *_so << endl;
373
374 if (NeedFlush)
375 _so->Flush();
376 }
377
378 if (NeedPercents())
379 {
380 if (PercentsNameLevel >= 1)
381 {
382 _percent.FileName.Empty();
383 _percent.Command.Empty();
384 if (PercentsNameLevel > 1 || !show2)
385 {
386 _percent.Command = s;
387 if (name)
388 _percent.FileName = name;
389 }
390 }
391 _percent.Print();
392 }
393
394 return CheckBreak2();
395 }
396
MessageError(const wchar_t * message)397 STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
398 {
399 MT_LOCK
400
401 RINOK(CheckBreak2());
402
403 NumFileErrors_in_Current++;
404 NumFileErrors++;
405
406 ClosePercentsAndFlush();
407 if (_se)
408 {
409 *_se << kError << message << endl;
410 _se->Flush();
411 }
412
413 return CheckBreak2();
414 }
415
416 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
SetExtractErrorMessage(Int32 opRes,Int32 encrypted,AString & dest)417 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
418 {
419 dest.Empty();
420 const char *s = NULL;
421
422 switch (opRes)
423 {
424 case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
425 s = kUnsupportedMethod;
426 break;
427 case NArchive::NExtract::NOperationResult::kCRCError:
428 s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
429 break;
430 case NArchive::NExtract::NOperationResult::kDataError:
431 s = (encrypted ? kDataErrorEncrypted : kDataError);
432 break;
433 case NArchive::NExtract::NOperationResult::kUnavailable:
434 s = kUnavailableData;
435 break;
436 case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
437 s = kUnexpectedEnd;
438 break;
439 case NArchive::NExtract::NOperationResult::kDataAfterEnd:
440 s = kDataAfterEnd;
441 break;
442 case NArchive::NExtract::NOperationResult::kIsNotArc:
443 s = kIsNotArc;
444 break;
445 case NArchive::NExtract::NOperationResult::kHeadersError:
446 s = kHeadersError;
447 break;
448 case NArchive::NExtract::NOperationResult::kWrongPassword:
449 s = kWrongPassword;
450 break;
451 }
452
453 dest += kError;
454 if (s)
455 dest += s;
456 else
457 {
458 dest += "Error #";
459 dest.Add_UInt32((UInt32)opRes);
460 }
461 }
462
SetOperationResult(Int32 opRes,Int32 encrypted)463 STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)
464 {
465 MT_LOCK
466
467 if (opRes == NArchive::NExtract::NOperationResult::kOK)
468 {
469 if (NeedPercents())
470 {
471 _percent.Command.Empty();
472 _percent.FileName.Empty();
473 _percent.Files++;
474 }
475 }
476 else
477 {
478 NumFileErrors_in_Current++;
479 NumFileErrors++;
480
481 if (_se)
482 {
483 ClosePercentsAndFlush();
484
485 AString s;
486 SetExtractErrorMessage(opRes, encrypted, s);
487
488 *_se << s;
489 if (!_currentName.IsEmpty())
490 {
491 *_se << " : ";
492 _se->NormalizePrint_UString(_currentName);
493 }
494 *_se << endl;
495 _se->Flush();
496 }
497 }
498
499 return CheckBreak2();
500 }
501
ReportExtractResult(Int32 opRes,Int32 encrypted,const wchar_t * name)502 STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
503 {
504 if (opRes != NArchive::NExtract::NOperationResult::kOK)
505 {
506 _currentName = name;
507 return SetOperationResult(opRes, encrypted);
508 }
509
510 return CheckBreak2();
511 }
512
513
514
515 #ifndef _NO_CRYPTO
516
SetPassword(const UString & password)517 HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
518 {
519 PasswordIsDefined = true;
520 Password = password;
521 return S_OK;
522 }
523
CryptoGetTextPassword(BSTR * password)524 STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
525 {
526 COM_TRY_BEGIN
527 MT_LOCK
528 return Open_CryptoGetTextPassword(password);
529 COM_TRY_END
530 }
531
532 #endif
533
BeforeOpen(const wchar_t * name,bool testMode)534 HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
535 {
536 RINOK(CheckBreak2());
537
538 NumTryArcs++;
539 ThereIsError_in_Current = false;
540 ThereIsWarning_in_Current = false;
541 NumFileErrors_in_Current = 0;
542
543 ClosePercents_for_so();
544 if (_so)
545 {
546 *_so << endl << (testMode ? kTesting : kExtracting);
547 _so->NormalizePrint_wstr(name);
548 *_so << endl;
549 }
550
551 if (NeedPercents())
552 _percent.Command = "Open";
553 return S_OK;
554 }
555
556 HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
557 HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
558
GetOpenArcErrorMessage(UInt32 errorFlags)559 static AString GetOpenArcErrorMessage(UInt32 errorFlags)
560 {
561 AString s;
562
563 for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
564 {
565 UInt32 f = (1 << i);
566 if ((errorFlags & f) == 0)
567 continue;
568 const char *m = k_ErrorFlagsMessages[i];
569 if (!s.IsEmpty())
570 s.Add_LF();
571 s += m;
572 errorFlags &= ~f;
573 }
574
575 if (errorFlags != 0)
576 {
577 char sz[16];
578 sz[0] = '0';
579 sz[1] = 'x';
580 ConvertUInt32ToHex(errorFlags, sz + 2);
581 if (!s.IsEmpty())
582 s.Add_LF();
583 s += sz;
584 }
585
586 return s;
587 }
588
589 void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
PrintErrorFlags(CStdOutStream & so,const char * s,UInt32 errorFlags)590 void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)
591 {
592 if (errorFlags == 0)
593 return;
594 so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;
595 }
596
Add_Messsage_Pre_ArcType(UString & s,const char * pre,const wchar_t * arcType)597 static void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)
598 {
599 s.Add_LF();
600 s += pre;
601 s += " as [";
602 s += arcType;
603 s += "] archive";
604 }
605
606 void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
Print_ErrorFormatIndex_Warning(CStdOutStream * _so,const CCodecs * codecs,const CArc & arc)607 void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
608 {
609 const CArcErrorInfo &er = arc.ErrorInfo;
610
611 *_so << "WARNING:\n";
612 _so->NormalizePrint_UString(arc.Path);
613 UString s;
614 if (arc.FormatIndex == er.ErrorFormatIndex)
615 {
616 s.Add_LF();
617 s += "The archive is open with offset";
618 }
619 else
620 {
621 Add_Messsage_Pre_ArcType(s, "Cannot open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex));
622 Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex));
623 }
624
625 *_so << s << endl << endl;
626 }
627
628
OpenResult(const CCodecs * codecs,const CArchiveLink & arcLink,const wchar_t * name,HRESULT result)629 HRESULT CExtractCallbackConsole::OpenResult(
630 const CCodecs *codecs, const CArchiveLink &arcLink,
631 const wchar_t *name, HRESULT result)
632 {
633 ClosePercents();
634
635 if (NeedPercents())
636 {
637 _percent.Files = 0;
638 _percent.Command.Empty();
639 _percent.FileName.Empty();
640 }
641
642
643 ClosePercentsAndFlush();
644
645 FOR_VECTOR (level, arcLink.Arcs)
646 {
647 const CArc &arc = arcLink.Arcs[level];
648 const CArcErrorInfo &er = arc.ErrorInfo;
649
650 UInt32 errorFlags = er.GetErrorFlags();
651
652 if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
653 {
654 if (_se)
655 {
656 *_se << endl;
657 if (level != 0)
658 {
659 _se->NormalizePrint_UString(arc.Path);
660 *_se << endl;
661 }
662 }
663
664 if (errorFlags != 0)
665 {
666 if (_se)
667 PrintErrorFlags(*_se, "ERRORS:", errorFlags);
668 NumOpenArcErrors++;
669 ThereIsError_in_Current = true;
670 }
671
672 if (!er.ErrorMessage.IsEmpty())
673 {
674 if (_se)
675 *_se << "ERRORS:" << endl << er.ErrorMessage << endl;
676 NumOpenArcErrors++;
677 ThereIsError_in_Current = true;
678 }
679
680 if (_se)
681 {
682 *_se << endl;
683 _se->Flush();
684 }
685 }
686
687 UInt32 warningFlags = er.GetWarningFlags();
688
689 if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
690 {
691 if (_so)
692 {
693 *_so << endl;
694 if (level != 0)
695 {
696 _so->NormalizePrint_UString(arc.Path);
697 *_so << endl;
698 }
699 }
700
701 if (warningFlags != 0)
702 {
703 if (_so)
704 PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
705 NumOpenArcWarnings++;
706 ThereIsWarning_in_Current = true;
707 }
708
709 if (!er.WarningMessage.IsEmpty())
710 {
711 if (_so)
712 *_so << "WARNINGS:" << endl << er.WarningMessage << endl;
713 NumOpenArcWarnings++;
714 ThereIsWarning_in_Current = true;
715 }
716
717 if (_so)
718 {
719 *_so << endl;
720 if (NeedFlush)
721 _so->Flush();
722 }
723 }
724
725
726 if (er.ErrorFormatIndex >= 0)
727 {
728 if (_so)
729 {
730 Print_ErrorFormatIndex_Warning(_so, codecs, arc);
731 if (NeedFlush)
732 _so->Flush();
733 }
734 ThereIsWarning_in_Current = true;
735 }
736 }
737
738 if (result == S_OK)
739 {
740 if (_so)
741 {
742 RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
743 *_so << endl;
744 }
745 }
746 else
747 {
748 NumCantOpenArcs++;
749 if (_so)
750 _so->Flush();
751 if (_se)
752 {
753 *_se << kError;
754 _se->NormalizePrint_wstr(name);
755 *_se << endl;
756 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
757 RINOK(res);
758 if (result == S_FALSE)
759 {
760 }
761 else
762 {
763 if (result == E_OUTOFMEMORY)
764 *_se << "Can't allocate required memory";
765 else
766 *_se << NError::MyFormatMessage(result);
767 *_se << endl;
768 }
769 _se->Flush();
770 }
771 }
772
773
774 return CheckBreak2();
775 }
776
ThereAreNoFiles()777 HRESULT CExtractCallbackConsole::ThereAreNoFiles()
778 {
779 ClosePercents_for_so();
780
781 if (_so)
782 {
783 *_so << endl << kNoFiles << endl;
784 if (NeedFlush)
785 _so->Flush();
786 }
787 return CheckBreak2();
788 }
789
ExtractResult(HRESULT result)790 HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
791 {
792 MT_LOCK
793
794 if (NeedPercents())
795 {
796 _percent.ClosePrint(true);
797 _percent.Command.Empty();
798 _percent.FileName.Empty();
799 }
800
801 if (_so)
802 _so->Flush();
803
804 if (result == S_OK)
805 {
806 if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)
807 {
808 if (ThereIsWarning_in_Current)
809 NumArcsWithWarnings++;
810 else
811 NumOkArcs++;
812 if (_so)
813 *_so << kEverythingIsOk << endl;
814 }
815 else
816 {
817 NumArcsWithError++;
818 if (_so)
819 {
820 *_so << endl;
821 if (NumFileErrors_in_Current != 0)
822 *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;
823 }
824 }
825 if (_so && NeedFlush)
826 _so->Flush();
827 }
828 else
829 {
830 NumArcsWithError++;
831 if (result == E_ABORT
832 || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
833 )
834 return result;
835
836 if (_se)
837 {
838 *_se << endl << kError;
839 if (result == E_OUTOFMEMORY)
840 *_se << kMemoryExceptionMessage;
841 else
842 *_se << NError::MyFormatMessage(result);
843 *_se << endl;
844 _se->Flush();
845 }
846 }
847
848 return CheckBreak2();
849 }
850