• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // UpdateCallbackConsole.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/IntToString.h"
6 
7 #include "../../../Windows/ErrorMsg.h"
8 
9 #ifndef _7ZIP_ST
10 #include "../../../Windows/Synchronization.h"
11 #endif
12 
13 #include "ConsoleClose.h"
14 #include "UserInputUtils.h"
15 #include "UpdateCallbackConsole.h"
16 
17 using namespace NWindows;
18 
19 #ifndef _7ZIP_ST
20 static NSynchronization::CCriticalSection g_CriticalSection;
21 #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
22 #else
23 #define MT_LOCK
24 #endif
25 
26 static const wchar_t * const kEmptyFileAlias = L"[Content]";
27 
28 static const char * const kOpenArchiveMessage = "Open archive: ";
29 static const char * const kCreatingArchiveMessage = "Creating archive: ";
30 static const char * const kUpdatingArchiveMessage = "Updating archive: ";
31 static const char * const kScanningMessage = "Scanning the drive:";
32 
33 static const char * const kError = "ERROR: ";
34 static const char * const kWarning = "WARNING: ";
35 
CheckBreak2()36 static HRESULT CheckBreak2()
37 {
38   return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
39 }
40 
41 HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
42 HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
43 
44 void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
45 
46 void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
47 
OpenResult(const CCodecs * codecs,const CArchiveLink & arcLink,const wchar_t * name,HRESULT result)48 HRESULT CUpdateCallbackConsole::OpenResult(
49     const CCodecs *codecs, const CArchiveLink &arcLink,
50     const wchar_t *name, HRESULT result)
51 {
52   ClosePercents2();
53 
54   FOR_VECTOR (level, arcLink.Arcs)
55   {
56     const CArc &arc = arcLink.Arcs[level];
57     const CArcErrorInfo &er = arc.ErrorInfo;
58 
59     UInt32 errorFlags = er.GetErrorFlags();
60 
61     if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
62     {
63       if (_se)
64       {
65         *_se << endl;
66         if (level != 0)
67           *_se << arc.Path << endl;
68       }
69 
70       if (errorFlags != 0)
71       {
72         if (_se)
73           PrintErrorFlags(*_se, "ERRORS:", errorFlags);
74       }
75 
76       if (!er.ErrorMessage.IsEmpty())
77       {
78         if (_se)
79           *_se << "ERRORS:" << endl << er.ErrorMessage << endl;
80       }
81 
82       if (_se)
83       {
84         *_se << endl;
85         _se->Flush();
86       }
87     }
88 
89     UInt32 warningFlags = er.GetWarningFlags();
90 
91     if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
92     {
93       if (_so)
94       {
95         *_so << endl;
96         if (level != 0)
97           *_so << arc.Path << endl;
98       }
99 
100       if (warningFlags != 0)
101       {
102         if (_so)
103           PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
104       }
105 
106       if (!er.WarningMessage.IsEmpty())
107       {
108         if (_so)
109           *_so << "WARNINGS:" << endl << er.WarningMessage << endl;
110       }
111 
112       if (_so)
113       {
114         *_so << endl;
115         if (NeedFlush)
116           _so->Flush();
117       }
118     }
119 
120 
121     if (er.ErrorFormatIndex >= 0)
122     {
123       if (_so)
124       {
125         Print_ErrorFormatIndex_Warning(_so, codecs, arc);
126         if (NeedFlush)
127           _so->Flush();
128       }
129     }
130   }
131 
132   if (result == S_OK)
133   {
134     if (_so)
135     {
136       RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
137       *_so << endl;
138     }
139   }
140   else
141   {
142     if (_so)
143       _so->Flush();
144     if (_se)
145     {
146       *_se << kError;
147       _se->NormalizePrint_wstr(name);
148       *_se << endl;
149       HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
150       RINOK(res);
151       _se->Flush();
152     }
153   }
154 
155   return S_OK;
156 }
157 
StartScanning()158 HRESULT CUpdateCallbackConsole::StartScanning()
159 {
160   if (_so)
161     *_so << kScanningMessage << endl;
162   _percent.Command = "Scan ";
163   return S_OK;
164 }
165 
ScanProgress(const CDirItemsStat & st,const FString & path,bool)166 HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
167 {
168   if (NeedPercents())
169   {
170     _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
171     _percent.Completed = st.GetTotalBytes();
172     _percent.FileName = fs2us(path);
173     _percent.Print();
174   }
175 
176   return CheckBreak();
177 }
178 
CommonError(const FString & path,DWORD systemError,bool isWarning)179 void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
180 {
181   ClosePercents2();
182 
183   if (_se)
184   {
185     if (_so)
186       _so->Flush();
187 
188     *_se << endl << (isWarning ? kWarning : kError)
189         << NError::MyFormatMessage(systemError)
190         << endl;
191     _se->NormalizePrint_UString(fs2us(path));
192     *_se << endl << endl;
193     _se->Flush();
194   }
195 }
196 
197 
ScanError_Base(const FString & path,DWORD systemError)198 HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
199 {
200   MT_LOCK
201 
202   ScanErrors.AddError(path, systemError);
203   CommonError(path, systemError, true);
204 
205   return S_OK;
206 }
207 
OpenFileError_Base(const FString & path,DWORD systemError)208 HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
209 {
210   MT_LOCK
211   FailedFiles.AddError(path, systemError);
212   /*
213   if (systemError == ERROR_SHARING_VIOLATION)
214   {
215   */
216     CommonError(path, systemError, true);
217     return S_FALSE;
218   /*
219   }
220   return systemError;
221   */
222 }
223 
ReadingFileError_Base(const FString & path,DWORD systemError)224 HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
225 {
226   MT_LOCK
227   CommonError(path, systemError, false);
228   return HRESULT_FROM_WIN32(systemError);
229 }
230 
ScanError(const FString & path,DWORD systemError)231 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
232 {
233   return ScanError_Base(path, systemError);
234 }
235 
236 
PrintPropPair(AString & s,const char * name,UInt64 val)237 static void PrintPropPair(AString &s, const char *name, UInt64 val)
238 {
239   char temp[32];
240   ConvertUInt64ToString(val, temp);
241   s += name;
242   s += ": ";
243   s += temp;
244 }
245 
246 void PrintSize_bytes_Smart(AString &s, UInt64 val);
247 void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
248 void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
249 
FinishScanning(const CDirItemsStat & st)250 HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
251 {
252   if (NeedPercents())
253   {
254     _percent.ClosePrint(true);
255     _percent.ClearCurState();
256   }
257 
258   if (_so)
259   {
260     AString s;
261     Print_DirItemsStat(s, st);
262     *_so << s << endl << endl;
263   }
264   return S_OK;
265 }
266 
267 static const char * const k_StdOut_ArcName = "StdOut";
268 
StartOpenArchive(const wchar_t * name)269 HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
270 {
271   if (_so)
272   {
273     *_so << kOpenArchiveMessage;
274     if (name)
275       *_so << name;
276     else
277       *_so << k_StdOut_ArcName;
278     *_so << endl;
279   }
280   return S_OK;
281 }
282 
StartArchive(const wchar_t * name,bool updating)283 HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
284 {
285   if (_so)
286   {
287     *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
288     if (name)
289       _so->NormalizePrint_wstr(name);
290     else
291       *_so << k_StdOut_ArcName;
292    *_so << endl << endl;
293   }
294   return S_OK;
295 }
296 
FinishArchive(const CFinishArchiveStat & st)297 HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
298 {
299   ClosePercents2();
300 
301   if (_so)
302   {
303     AString s;
304     // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
305     PrintPropPair(s, "Files read from disk", _percent.Files);
306     s.Add_LF();
307     s += "Archive size: ";
308     PrintSize_bytes_Smart(s, st.OutArcFileSize);
309     s.Add_LF();
310     *_so << endl;
311     *_so << s;
312     // *_so << endl;
313   }
314 
315   return S_OK;
316 }
317 
WriteSfx(const wchar_t * name,UInt64 size)318 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
319 {
320   if (_so)
321   {
322     *_so << "Write SFX: ";
323     *_so << name;
324     AString s (" : ");
325     PrintSize_bytes_Smart(s, size);
326     *_so << s << endl;
327   }
328   return S_OK;
329 }
330 
331 
DeletingAfterArchiving(const FString & path,bool)332 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
333 {
334   if (LogLevel > 0 && _so)
335   {
336     ClosePercents_for_so();
337 
338     if (!DeleteMessageWasShown)
339     {
340       if (_so)
341         *_so << endl << ": Removing files after including to archive" << endl;
342     }
343 
344     {
345       {
346         _tempA = "Removing";
347         _tempA.Add_Space();
348         *_so << _tempA;
349         _tempU = fs2us(path);
350         _so->Normalize_UString(_tempU);
351         _so->PrintUString(_tempU, _tempA);
352         *_so << endl;
353         if (NeedFlush)
354           _so->Flush();
355       }
356     }
357   }
358 
359   if (!DeleteMessageWasShown)
360   {
361     if (NeedPercents())
362     {
363       _percent.ClearCurState();
364     }
365     DeleteMessageWasShown = true;
366   }
367   else
368   {
369     _percent.Files++;
370   }
371 
372   if (NeedPercents())
373   {
374     // if (!FullLog)
375     {
376       _percent.Command = "Removing";
377       _percent.FileName = fs2us(path);
378     }
379     _percent.Print();
380   }
381 
382   return S_OK;
383 }
384 
385 
FinishDeletingAfterArchiving()386 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
387 {
388   ClosePercents2();
389   if (_so && DeleteMessageWasShown)
390     *_so << endl;
391   return S_OK;
392 }
393 
CheckBreak()394 HRESULT CUpdateCallbackConsole::CheckBreak()
395 {
396   return CheckBreak2();
397 }
398 
399 /*
400 HRESULT CUpdateCallbackConsole::Finalize()
401 {
402   // MT_LOCK
403   return S_OK;
404 }
405 */
406 
407 
PrintToDoStat(CStdOutStream * _so,const CDirItemsStat2 & stat,const char * name)408 void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
409 {
410   AString s;
411   Print_DirItemsStat2(s, stat);
412   *_so << name << ": " << s << endl;
413 }
414 
SetNumItems(const CArcToDoStat & stat)415 HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
416 {
417   if (_so)
418   {
419     ClosePercents_for_so();
420     if (!stat.DeleteData.IsEmpty())
421     {
422       *_so << endl;
423       PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
424     }
425     if (!stat.OldData.IsEmpty())
426       PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
427     // if (!stat.NewData.IsEmpty())
428     {
429       PrintToDoStat(_so, stat.NewData, "Add new data to archive");
430     }
431     *_so << endl;
432   }
433   return S_OK;
434 }
435 
SetTotal(UInt64 size)436 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
437 {
438   MT_LOCK
439   if (NeedPercents())
440   {
441     _percent.Total = size;
442     _percent.Print();
443   }
444   return S_OK;
445 }
446 
SetCompleted(const UInt64 * completeValue)447 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
448 {
449   MT_LOCK
450   if (completeValue)
451   {
452     if (NeedPercents())
453     {
454       _percent.Completed = *completeValue;
455       _percent.Print();
456     }
457   }
458   return CheckBreak2();
459 }
460 
SetRatioInfo(const UInt64 *,const UInt64 *)461 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
462 {
463   return CheckBreak2();
464 }
465 
PrintProgress(const wchar_t * name,const char * command,bool showInLog)466 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
467 {
468   MT_LOCK
469 
470   bool show2 = (showInLog && _so);
471 
472   if (show2)
473   {
474     ClosePercents_for_so();
475 
476     _tempA = command;
477     if (name)
478       _tempA.Add_Space();
479     *_so << _tempA;
480 
481     _tempU.Empty();
482     if (name)
483     {
484       _tempU = name;
485       _so->Normalize_UString(_tempU);
486     }
487     _so->PrintUString(_tempU, _tempA);
488     *_so << endl;
489     if (NeedFlush)
490       _so->Flush();
491   }
492 
493   if (NeedPercents())
494   {
495     if (PercentsNameLevel >= 1)
496     {
497       _percent.FileName.Empty();
498       _percent.Command.Empty();
499       if (PercentsNameLevel > 1 || !show2)
500       {
501         _percent.Command = command;
502         if (name)
503           _percent.FileName = name;
504       }
505     }
506     _percent.Print();
507   }
508 
509   return CheckBreak2();
510 }
511 
GetStream(const wchar_t * name,bool,bool isAnti,UInt32 mode)512 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
513 {
514   if (StdOutMode)
515     return S_OK;
516 
517   if (!name || name[0] == 0)
518     name = kEmptyFileAlias;
519 
520   unsigned requiredLevel = 1;
521 
522   const char *s;
523   if (mode == NUpdateNotifyOp::kAdd ||
524       mode == NUpdateNotifyOp::kUpdate)
525   {
526     if (isAnti)
527       s = "Anti";
528     else if (mode == NUpdateNotifyOp::kAdd)
529       s = "+";
530     else
531       s = "U";
532   }
533   else
534   {
535     requiredLevel = 3;
536     if (mode == NUpdateNotifyOp::kAnalyze)
537       s = "A";
538     else
539       s = "Reading";
540   }
541 
542   return PrintProgress(name, s, LogLevel >= requiredLevel);
543 }
544 
OpenFileError(const FString & path,DWORD systemError)545 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
546 {
547   return OpenFileError_Base(path, systemError);
548 }
549 
ReadingFileError(const FString & path,DWORD systemError)550 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
551 {
552   return ReadingFileError_Base(path, systemError);
553 }
554 
SetOperationResult(Int32)555 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
556 {
557   MT_LOCK
558   _percent.Files++;
559   return S_OK;
560 }
561 
562 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
563 
ReportExtractResult(Int32 opRes,Int32 isEncrypted,const wchar_t * name)564 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
565 {
566   // if (StdOutMode) return S_OK;
567 
568   if (opRes != NArchive::NExtract::NOperationResult::kOK)
569   {
570     ClosePercents2();
571 
572     if (_se)
573     {
574       if (_so)
575         _so->Flush();
576 
577       AString s;
578       SetExtractErrorMessage(opRes, isEncrypted, s);
579       *_se << s << " : " << endl;
580       _se->NormalizePrint_wstr(name);
581       *_se << endl << endl;
582       _se->Flush();
583     }
584     return S_OK;
585   }
586   return S_OK;
587 }
588 
589 
ReportUpdateOpeartion(UInt32 op,const wchar_t * name,bool)590 HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
591 {
592   // if (StdOutMode) return S_OK;
593 
594   char temp[16];
595   const char *s;
596 
597   unsigned requiredLevel = 1;
598 
599   switch (op)
600   {
601     case NUpdateNotifyOp::kAdd:       s = "+"; break;
602     case NUpdateNotifyOp::kUpdate:    s = "U"; break;
603     case NUpdateNotifyOp::kAnalyze:   s = "A"; requiredLevel = 3; break;
604     case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
605     case NUpdateNotifyOp::kRepack:    s = "R"; requiredLevel = 2; break;
606     case NUpdateNotifyOp::kSkip:      s = "."; requiredLevel = 2; break;
607     case NUpdateNotifyOp::kDelete:    s = "D"; requiredLevel = 3; break;
608     case NUpdateNotifyOp::kHeader:    s = "Header creation"; requiredLevel = 100; break;
609     default:
610     {
611       temp[0] = 'o';
612       temp[1] = 'p';
613       ConvertUInt64ToString(op, temp + 2);
614       s = temp;
615     }
616   }
617 
618   return PrintProgress(name, s, LogLevel >= requiredLevel);
619 }
620 
621 /*
622 HRESULT CUpdateCallbackConsole::SetPassword(const UString &
623     #ifndef _NO_CRYPTO
624     password
625     #endif
626     )
627 {
628   #ifndef _NO_CRYPTO
629   PasswordIsDefined = true;
630   Password = password;
631   #endif
632   return S_OK;
633 }
634 */
635 
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)636 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
637 {
638   COM_TRY_BEGIN
639 
640   *password = NULL;
641 
642   #ifdef _NO_CRYPTO
643 
644   *passwordIsDefined = false;
645   return S_OK;
646 
647   #else
648 
649   if (!PasswordIsDefined)
650   {
651     if (AskPassword)
652     {
653       RINOK(GetPassword_HRESULT(_so, Password));
654       PasswordIsDefined = true;
655     }
656   }
657   *passwordIsDefined = BoolToInt(PasswordIsDefined);
658   return StringToBstr(Password, password);
659 
660   #endif
661 
662   COM_TRY_END
663 }
664 
CryptoGetTextPassword(BSTR * password)665 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
666 {
667   COM_TRY_BEGIN
668 
669   *password = NULL;
670 
671   #ifdef _NO_CRYPTO
672 
673   return E_NOTIMPL;
674 
675   #else
676 
677   if (!PasswordIsDefined)
678   {
679     {
680       RINOK(GetPassword_HRESULT(_so, Password))
681       PasswordIsDefined = true;
682     }
683   }
684   return StringToBstr(Password, password);
685 
686   #endif
687   COM_TRY_END
688 }
689 
ShowDeleteFile(const wchar_t * name,bool)690 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
691 {
692   if (StdOutMode)
693     return S_OK;
694 
695   if (LogLevel > 7)
696   {
697     if (!name || name[0] == 0)
698       name = kEmptyFileAlias;
699     return PrintProgress(name, "D", true);
700   }
701   return S_OK;
702 }
703