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 Z7_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 Z7_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 if (st.IsMultiVolMode)
337 {
338 s += "Volumes: ";
339 s.Add_UInt32(st.NumVolumes);
340 s.Add_LF();
341 }
342 *_so << endl;
343 *_so << s;
344 // *_so << endl;
345 }
346
347 return S_OK;
348 }
349
WriteSfx(const wchar_t * name,UInt64 size)350 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
351 {
352 if (_so)
353 {
354 *_so << "Write SFX: ";
355 *_so << name;
356 AString s (" : ");
357 PrintSize_bytes_Smart(s, size);
358 *_so << s << endl;
359 }
360 return S_OK;
361 }
362
363
DeletingAfterArchiving(const FString & path,bool)364 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
365 {
366 if (LogLevel > 0 && _so)
367 {
368 ClosePercents_for_so();
369
370 if (!DeleteMessageWasShown)
371 {
372 if (_so)
373 *_so << endl << ": Removing files after including to archive" << endl;
374 }
375
376 {
377 {
378 _tempA = "Removing";
379 _tempA.Add_Space();
380 *_so << _tempA;
381 _tempU = fs2us(path);
382 _so->Normalize_UString(_tempU);
383 _so->PrintUString(_tempU, _tempA);
384 *_so << endl;
385 if (NeedFlush)
386 _so->Flush();
387 }
388 }
389 }
390
391 if (!DeleteMessageWasShown)
392 {
393 if (NeedPercents())
394 {
395 _percent.ClearCurState();
396 }
397 DeleteMessageWasShown = true;
398 }
399 else
400 {
401 _percent.Files++;
402 }
403
404 if (NeedPercents())
405 {
406 // if (!FullLog)
407 {
408 _percent.Command = "Removing";
409 _percent.FileName = fs2us(path);
410 }
411 _percent.Print();
412 }
413
414 return S_OK;
415 }
416
417
FinishDeletingAfterArchiving()418 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
419 {
420 ClosePercents2();
421 if (_so && DeleteMessageWasShown)
422 *_so << endl;
423 return S_OK;
424 }
425
CheckBreak()426 HRESULT CUpdateCallbackConsole::CheckBreak()
427 {
428 return CheckBreak2();
429 }
430
431 /*
432 HRESULT CUpdateCallbackConsole::Finalize()
433 {
434 // MT_LOCK
435 return S_OK;
436 }
437 */
438
439
PrintToDoStat(CStdOutStream * _so,const CDirItemsStat2 & stat,const char * name)440 void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
441 {
442 AString s;
443 Print_DirItemsStat2(s, stat);
444 *_so << name << ": " << s << endl;
445 }
446
SetNumItems(const CArcToDoStat & stat)447 HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
448 {
449 if (_so)
450 {
451 ClosePercents_for_so();
452 if (!stat.DeleteData.IsEmpty())
453 {
454 *_so << endl;
455 PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
456 }
457 if (!stat.OldData.IsEmpty())
458 PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
459 // if (!stat.NewData.IsEmpty())
460 {
461 PrintToDoStat(_so, stat.NewData, "Add new data to archive");
462 }
463 *_so << endl;
464 }
465 return S_OK;
466 }
467
SetTotal(UInt64 size)468 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
469 {
470 MT_LOCK
471 if (NeedPercents())
472 {
473 _percent.Total = size;
474 _percent.Print();
475 }
476 return S_OK;
477 }
478
SetCompleted(const UInt64 * completeValue)479 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
480 {
481 MT_LOCK
482 if (completeValue)
483 {
484 if (NeedPercents())
485 {
486 _percent.Completed = *completeValue;
487 _percent.Print();
488 }
489 }
490 return CheckBreak2();
491 }
492
SetRatioInfo(const UInt64 *,const UInt64 *)493 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
494 {
495 return CheckBreak2();
496 }
497
PrintProgress(const wchar_t * name,bool isDir,const char * command,bool showInLog)498 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog)
499 {
500 MT_LOCK
501
502 bool show2 = (showInLog && _so);
503
504 if (show2)
505 {
506 ClosePercents_for_so();
507
508 _tempA = command;
509 if (name)
510 _tempA.Add_Space();
511 *_so << _tempA;
512
513 _tempU.Empty();
514 if (name)
515 {
516 _tempU = name;
517 if (isDir)
518 NWindows::NFile::NName::NormalizeDirPathPrefix(_tempU);
519 _so->Normalize_UString(_tempU);
520 }
521 _so->PrintUString(_tempU, _tempA);
522 *_so << endl;
523 if (NeedFlush)
524 _so->Flush();
525 }
526
527 if (NeedPercents())
528 {
529 if (PercentsNameLevel >= 1)
530 {
531 _percent.FileName.Empty();
532 _percent.Command.Empty();
533 if (PercentsNameLevel > 1 || !show2)
534 {
535 _percent.Command = command;
536 if (name)
537 _percent.FileName = name;
538 }
539 }
540 _percent.Print();
541 }
542
543 return CheckBreak2();
544 }
545
546
547 /*
548 void CCallbackConsoleBase::PrintInfoLine(const UString &s)
549 {
550 if (LogLevel < 1000)
551 return;
552
553 MT_LOCK
554
555 const bool show2 = (_so != NULL);
556
557 if (show2)
558 {
559 ClosePercents_for_so();
560 _so->PrintUString(s, _tempA);
561 *_so << endl;
562 if (NeedFlush)
563 _so->Flush();
564 }
565 }
566 */
567
GetStream(const wchar_t * name,bool isDir,bool isAnti,UInt32 mode)568 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode)
569 {
570 if (StdOutMode)
571 return S_OK;
572
573 if (!name || name[0] == 0)
574 name = kEmptyFileAlias;
575
576 unsigned requiredLevel = 1;
577
578 const char *s;
579 if (mode == NUpdateNotifyOp::kAdd ||
580 mode == NUpdateNotifyOp::kUpdate)
581 {
582 if (isAnti)
583 s = "Anti";
584 else if (mode == NUpdateNotifyOp::kAdd)
585 s = "+";
586 else
587 s = "U";
588 }
589 else
590 {
591 requiredLevel = 3;
592 if (mode == NUpdateNotifyOp::kAnalyze)
593 s = "A";
594 else
595 s = "Reading";
596 }
597
598 return PrintProgress(name, isDir, s, LogLevel >= requiredLevel);
599 }
600
OpenFileError(const FString & path,DWORD systemError)601 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
602 {
603 return OpenFileError_Base(path, systemError);
604 }
605
ReadingFileError(const FString & path,DWORD systemError)606 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
607 {
608 return ReadingFileError_Base(path, systemError);
609 }
610
SetOperationResult(Int32)611 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 /* opRes */)
612 {
613 MT_LOCK
614 _percent.Files++;
615 /*
616 if (opRes != NArchive::NUpdate::NOperationResult::kOK)
617 {
618 if (opRes == NArchive::NUpdate::NOperationResult::kError_FileChanged)
619 {
620 CommonError("Input file changed");
621 }
622 }
623 */
624 return S_OK;
625 }
626
627 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
628
ReportExtractResult(Int32 opRes,Int32 isEncrypted,const wchar_t * name)629 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
630 {
631 // if (StdOutMode) return S_OK;
632
633 if (opRes != NArchive::NExtract::NOperationResult::kOK)
634 {
635 ClosePercents2();
636
637 if (_se)
638 {
639 if (_so)
640 _so->Flush();
641
642 AString s;
643 SetExtractErrorMessage(opRes, isEncrypted, s);
644 *_se << s << " : " << endl;
645 _se->NormalizePrint_wstr(name);
646 *_se << endl << endl;
647 _se->Flush();
648 }
649 return S_OK;
650 }
651 return S_OK;
652 }
653
654
ReportUpdateOperation(UInt32 op,const wchar_t * name,bool isDir)655 HRESULT CUpdateCallbackConsole::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
656 {
657 // if (StdOutMode) return S_OK;
658
659 char temp[16];
660 const char *s;
661
662 unsigned requiredLevel = 1;
663
664 switch (op)
665 {
666 case NUpdateNotifyOp::kAdd: s = "+"; break;
667 case NUpdateNotifyOp::kUpdate: s = "U"; break;
668 case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
669 case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
670 case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
671 case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
672 case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
673 case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
674 case NUpdateNotifyOp::kInFileChanged: s = "Size of input file was changed:"; requiredLevel = 10; break;
675 // case NUpdateNotifyOp::kOpFinished: s = "Finished"; requiredLevel = 100; break;
676 default:
677 {
678 temp[0] = 'o';
679 temp[1] = 'p';
680 ConvertUInt64ToString(op, temp + 2);
681 s = temp;
682 }
683 }
684
685 return PrintProgress(name, isDir, s, LogLevel >= requiredLevel);
686 }
687
688 /*
689 HRESULT CUpdateCallbackConsole::SetPassword(const UString &
690 #ifndef Z7_NO_CRYPTO
691 password
692 #endif
693 )
694 {
695 #ifndef Z7_NO_CRYPTO
696 PasswordIsDefined = true;
697 Password = password;
698 #endif
699 return S_OK;
700 }
701 */
702
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)703 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
704 {
705 COM_TRY_BEGIN
706
707 *password = NULL;
708
709 #ifdef Z7_NO_CRYPTO
710
711 *passwordIsDefined = false;
712 return S_OK;
713
714 #else
715
716 if (!PasswordIsDefined)
717 {
718 if (AskPassword)
719 {
720 RINOK(GetPassword_HRESULT(_so, Password))
721 PasswordIsDefined = true;
722 }
723 }
724 *passwordIsDefined = BoolToInt(PasswordIsDefined);
725 return StringToBstr(Password, password);
726
727 #endif
728
729 COM_TRY_END
730 }
731
CryptoGetTextPassword(BSTR * password)732 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
733 {
734 COM_TRY_BEGIN
735
736 *password = NULL;
737
738 #ifdef Z7_NO_CRYPTO
739
740 return E_NOTIMPL;
741
742 #else
743
744 if (!PasswordIsDefined)
745 {
746 {
747 RINOK(GetPassword_HRESULT(_so, Password))
748 PasswordIsDefined = true;
749 }
750 }
751 return StringToBstr(Password, password);
752
753 #endif
754 COM_TRY_END
755 }
756
ShowDeleteFile(const wchar_t * name,bool isDir)757 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool isDir)
758 {
759 if (StdOutMode)
760 return S_OK;
761
762 if (LogLevel > 7)
763 {
764 if (!name || name[0] == 0)
765 name = kEmptyFileAlias;
766 return PrintProgress(name, isDir, "D", true);
767 }
768 return S_OK;
769 }
770
771 /*
772 void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU);
773
774 static void GetPropName(PROPID propID, UString &nameU)
775 {
776 AString nameA;
777 GetPropName(propID, NULL, nameA, nameU);
778 // if (!nameA.IsEmpty())
779 nameU = nameA;
780 }
781
782
783 static void AddPropNamePrefix(UString &s, PROPID propID)
784 {
785 UString name;
786 GetPropName(propID, name);
787 s += name;
788 s += " = ";
789 }
790
791 void CCallbackConsoleBase::PrintPropInfo(UString &s, PROPID propID, const PROPVARIANT *value)
792 {
793 AddPropNamePrefix(s, propID);
794 {
795 UString dest;
796 const int level = 9; // we show up to ns precision level
797 ConvertPropertyToString2(dest, *value, propID, level);
798 s += dest;
799 }
800 PrintInfoLine(s);
801 }
802
803 static void Add_IndexType_Index(UString &s, UInt32 indexType, UInt32 index)
804 {
805 if (indexType == NArchive::NEventIndexType::kArcProp)
806 {
807 }
808 else
809 {
810 if (indexType == NArchive::NEventIndexType::kBlockIndex)
811 {
812 s += "#";
813 }
814 else if (indexType == NArchive::NEventIndexType::kOutArcIndex)
815 {
816 }
817 else
818 {
819 s += "indexType_";
820 s.Add_UInt32(indexType);
821 s.Add_Space();
822 }
823 s.Add_UInt32(index);
824 }
825 s += ": ";
826 }
827
828 HRESULT CUpdateCallbackConsole::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)
829 {
830 UString s;
831 Add_IndexType_Index(s, indexType, index);
832 PrintPropInfo(s, propID, value);
833 return S_OK;
834 }
835
836 static inline char GetHex(Byte value)
837 {
838 return (char)((value < 10) ? ('0' + value) : ('a' + (value - 10)));
839 }
840
841 static void AddHexToString(UString &dest, const Byte *data, UInt32 size)
842 {
843 for (UInt32 i = 0; i < size; i++)
844 {
845 Byte b = data[i];
846 dest += GetHex((Byte)((b >> 4) & 0xF));
847 dest += GetHex((Byte)(b & 0xF));
848 }
849 }
850
851 void HashHexToString(char *dest, const Byte *data, UInt32 size);
852
853 HRESULT CUpdateCallbackConsole::ReportRawProp(UInt32 indexType, UInt32 index,
854 PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)
855 {
856 UString s;
857 propType = propType;
858 Add_IndexType_Index(s, indexType, index);
859 AddPropNamePrefix(s, propID);
860 if (propID == kpidChecksum)
861 {
862 char temp[k_HashCalc_DigestSize_Max + 8];
863 HashHexToString(temp, (const Byte *)data, dataSize);
864 s += temp;
865 }
866 else
867 AddHexToString(s, (const Byte *)data, dataSize);
868 PrintInfoLine(s);
869 return S_OK;
870 }
871
872 HRESULT CUpdateCallbackConsole::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)
873 {
874 UString s;
875 Add_IndexType_Index(s, indexType, index);
876 s += "finished";
877 if (opRes != NArchive::NUpdate::NOperationResult::kOK)
878 {
879 s += ": ";
880 s.Add_UInt32(opRes);
881 }
882 PrintInfoLine(s);
883 return S_OK;
884 }
885 */
886