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