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