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 *kEmptyFileAlias = L"[Content]"; 27 28 static const char *kOpenArchiveMessage = "Open archive: "; 29 static const char *kCreatingArchiveMessage = "Creating archive: "; 30 static const char *kUpdatingArchiveMessage = "Updating archive: "; 31 static const char *kScanningMessage = "Scanning the drive:"; 32 33 static const char *kError = "ERROR: "; 34 static const char *kWarning = "WARNING: "; 35 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 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 << name << endl; 147 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); 148 RINOK(res); 149 _se->Flush(); 150 } 151 } 152 153 return S_OK; 154 } 155 156 HRESULT CUpdateCallbackConsole::StartScanning() 157 { 158 if (_so) 159 *_so << kScanningMessage << endl; 160 _percent.Command = "Scan "; 161 return S_OK; 162 } 163 164 HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) 165 { 166 if (NeedPercents()) 167 { 168 _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; 169 _percent.Completed = st.GetTotalBytes(); 170 _percent.FileName = fs2us(path); 171 _percent.Print(); 172 } 173 174 return CheckBreak(); 175 } 176 177 void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning) 178 { 179 ClosePercents2(); 180 181 if (_se) 182 { 183 if (_so) 184 _so->Flush(); 185 186 *_se << endl << (isWarning ? kWarning : kError) 187 << NError::MyFormatMessage(systemError) 188 << endl << fs2us(path) << endl << endl; 189 _se->Flush(); 190 } 191 } 192 193 194 HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) 195 { 196 MT_LOCK 197 198 ScanErrors.AddError(path, systemError); 199 CommonError(path, systemError, true); 200 201 return S_OK; 202 } 203 204 HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError) 205 { 206 MT_LOCK 207 FailedFiles.AddError(path, systemError); 208 /* 209 if (systemError == ERROR_SHARING_VIOLATION) 210 { 211 */ 212 CommonError(path, systemError, true); 213 return S_FALSE; 214 /* 215 } 216 return systemError; 217 */ 218 } 219 220 HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError) 221 { 222 MT_LOCK 223 CommonError(path, systemError, false); 224 return HRESULT_FROM_WIN32(systemError); 225 } 226 227 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError) 228 { 229 return ScanError_Base(path, systemError); 230 } 231 232 233 static void PrintPropPair(AString &s, const char *name, UInt64 val) 234 { 235 char temp[32]; 236 ConvertUInt64ToString(val, temp); 237 s += name; 238 s += ": "; 239 s += temp; 240 } 241 242 void PrintSize_bytes_Smart(AString &s, UInt64 val); 243 void Print_DirItemsStat(AString &s, const CDirItemsStat &st); 244 245 HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) 246 { 247 if (NeedPercents()) 248 { 249 _percent.ClosePrint(true); 250 _percent.ClearCurState(); 251 } 252 253 if (_so) 254 { 255 AString s; 256 Print_DirItemsStat(s, st); 257 *_so << s << endl << endl; 258 } 259 return S_OK; 260 } 261 262 static const char *k_StdOut_ArcName = "StdOut"; 263 264 HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) 265 { 266 if (_so) 267 { 268 *_so << kOpenArchiveMessage; 269 if (name) 270 *_so << name; 271 else 272 *_so << k_StdOut_ArcName; 273 *_so << endl; 274 } 275 return S_OK; 276 } 277 278 HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) 279 { 280 if (_so) 281 { 282 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); 283 if (name != 0) 284 *_so << name; 285 else 286 *_so << k_StdOut_ArcName; 287 *_so << endl << endl; 288 } 289 return S_OK; 290 } 291 292 HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) 293 { 294 ClosePercents2(); 295 296 if (_so) 297 { 298 AString s; 299 // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); 300 PrintPropPair(s, "Files read from disk", _percent.Files); 301 s.Add_LF(); 302 s += "Archive size: "; 303 PrintSize_bytes_Smart(s, st.OutArcFileSize); 304 s.Add_LF(); 305 *_so << endl; 306 *_so << s; 307 // *_so << endl; 308 } 309 310 return S_OK; 311 } 312 313 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) 314 { 315 if (_so) 316 { 317 *_so << "Write SFX: "; 318 *_so << name; 319 AString s = " : "; 320 PrintSize_bytes_Smart(s, size); 321 *_so << s << endl; 322 } 323 return S_OK; 324 } 325 326 327 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) 328 { 329 if (LogLevel > 0 && _so) 330 { 331 ClosePercents_for_so(); 332 333 if (!DeleteMessageWasShown) 334 { 335 if (_so) 336 *_so << endl << ": Removing files after including to archive" << endl; 337 } 338 339 { 340 { 341 _tempA = "Removing"; 342 _tempA.Add_Space(); 343 *_so << _tempA; 344 _tempU = fs2us(path); 345 _so->PrintUString(_tempU, _tempA); 346 *_so << endl; 347 if (NeedFlush) 348 _so->Flush(); 349 } 350 } 351 } 352 353 if (!DeleteMessageWasShown) 354 { 355 if (NeedPercents()) 356 { 357 _percent.ClearCurState(); 358 } 359 DeleteMessageWasShown = true; 360 } 361 else 362 { 363 _percent.Files++; 364 } 365 366 if (NeedPercents()) 367 { 368 // if (!FullLog) 369 { 370 _percent.Command = "Removing"; 371 _percent.FileName = fs2us(path); 372 } 373 _percent.Print(); 374 } 375 376 return S_OK; 377 } 378 379 380 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving() 381 { 382 ClosePercents2(); 383 if (_so && DeleteMessageWasShown) 384 *_so << endl; 385 return S_OK; 386 } 387 388 HRESULT CUpdateCallbackConsole::CheckBreak() 389 { 390 return CheckBreak2(); 391 } 392 393 /* 394 HRESULT CUpdateCallbackConsole::Finalize() 395 { 396 // MT_LOCK 397 return S_OK; 398 } 399 */ 400 401 HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems) 402 { 403 if (_so) 404 { 405 ClosePercents_for_so(); 406 AString s; 407 PrintPropPair(s, "Items to compress", numItems); 408 *_so << s << endl << endl; 409 } 410 return S_OK; 411 } 412 413 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) 414 { 415 MT_LOCK 416 if (NeedPercents()) 417 { 418 _percent.Total = size; 419 _percent.Print(); 420 } 421 return S_OK; 422 } 423 424 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) 425 { 426 MT_LOCK 427 if (completeValue) 428 { 429 if (NeedPercents()) 430 { 431 _percent.Completed = *completeValue; 432 _percent.Print(); 433 } 434 } 435 return CheckBreak2(); 436 } 437 438 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) 439 { 440 return CheckBreak2(); 441 } 442 443 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog) 444 { 445 MT_LOCK 446 447 bool show2 = (showInLog && _so); 448 449 if (show2) 450 { 451 ClosePercents_for_so(); 452 453 _tempA = command; 454 if (name) 455 _tempA.Add_Space(); 456 *_so << _tempA; 457 458 _tempU.Empty(); 459 if (name) 460 _tempU = name; 461 _so->PrintUString(_tempU, _tempA); 462 *_so << endl; 463 if (NeedFlush) 464 _so->Flush(); 465 } 466 467 if (NeedPercents()) 468 { 469 if (PercentsNameLevel >= 1) 470 { 471 _percent.FileName.Empty(); 472 _percent.Command.Empty(); 473 if (PercentsNameLevel > 1 || !show2) 474 { 475 _percent.Command = command; 476 if (name) 477 _percent.FileName = name; 478 } 479 } 480 _percent.Print(); 481 } 482 483 return CheckBreak2(); 484 } 485 486 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode) 487 { 488 if (StdOutMode) 489 return S_OK; 490 491 if (!name || name[0] == 0) 492 name = kEmptyFileAlias; 493 494 unsigned requiredLevel = 1; 495 496 const char *s; 497 if (mode == NUpdateNotifyOp::kAdd || 498 mode == NUpdateNotifyOp::kUpdate) 499 { 500 if (isAnti) 501 s = "Anti"; 502 else if (mode == NUpdateNotifyOp::kAdd) 503 s = "+"; 504 else 505 s = "U"; 506 } 507 else 508 { 509 requiredLevel = 3; 510 if (mode == NUpdateNotifyOp::kAnalyze) 511 s = "A"; 512 else 513 s = "Reading"; 514 } 515 516 return PrintProgress(name, s, LogLevel >= requiredLevel); 517 } 518 519 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError) 520 { 521 return OpenFileError_Base(path, systemError); 522 } 523 524 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError) 525 { 526 return ReadingFileError_Base(path, systemError); 527 } 528 529 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32) 530 { 531 MT_LOCK 532 _percent.Files++; 533 return S_OK; 534 } 535 536 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); 537 538 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) 539 { 540 // if (StdOutMode) return S_OK; 541 542 if (opRes != NArchive::NExtract::NOperationResult::kOK) 543 { 544 ClosePercents2(); 545 546 if (_se) 547 { 548 if (_so) 549 _so->Flush(); 550 551 AString s; 552 SetExtractErrorMessage(opRes, isEncrypted, s); 553 *_se << s << " : " << endl << name << endl << endl; 554 _se->Flush(); 555 } 556 return S_OK; 557 } 558 return S_OK; 559 } 560 561 562 HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */) 563 { 564 // if (StdOutMode) return S_OK; 565 566 char temp[16]; 567 const char *s; 568 569 unsigned requiredLevel = 1; 570 571 switch (op) 572 { 573 case NUpdateNotifyOp::kAdd: s = "+"; break; 574 case NUpdateNotifyOp::kUpdate: s = "U"; break; 575 case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break; 576 case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break; 577 case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break; 578 case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; 579 case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; 580 case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; 581 default: 582 { 583 temp[0] = 'o'; 584 temp[1] = 'p'; 585 ConvertUInt64ToString(op, temp + 2); 586 s = temp; 587 } 588 } 589 590 return PrintProgress(name, s, LogLevel >= requiredLevel); 591 } 592 593 /* 594 HRESULT CUpdateCallbackConsole::SetPassword(const UString & 595 #ifndef _NO_CRYPTO 596 password 597 #endif 598 ) 599 { 600 #ifndef _NO_CRYPTO 601 PasswordIsDefined = true; 602 Password = password; 603 #endif 604 return S_OK; 605 } 606 */ 607 608 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) 609 { 610 COM_TRY_BEGIN 611 612 *password = NULL; 613 614 #ifdef _NO_CRYPTO 615 616 *passwordIsDefined = false; 617 return S_OK; 618 619 #else 620 621 if (!PasswordIsDefined) 622 { 623 if (AskPassword) 624 { 625 Password = GetPassword(_so); 626 PasswordIsDefined = true; 627 } 628 } 629 *passwordIsDefined = BoolToInt(PasswordIsDefined); 630 return StringToBstr(Password, password); 631 632 #endif 633 634 COM_TRY_END 635 } 636 637 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) 638 { 639 COM_TRY_BEGIN 640 641 *password = NULL; 642 643 #ifdef _NO_CRYPTO 644 645 return E_NOTIMPL; 646 647 #else 648 649 if (!PasswordIsDefined) 650 { 651 { 652 Password = GetPassword(_so); 653 PasswordIsDefined = true; 654 } 655 } 656 return StringToBstr(Password, password); 657 658 #endif 659 COM_TRY_END 660 } 661 662 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */) 663 { 664 if (StdOutMode) 665 return S_OK; 666 667 if (LogLevel > 7) 668 { 669 if (!name || name[0] == 0) 670 name = kEmptyFileAlias; 671 return PrintProgress(name, "D", true); 672 } 673 return S_OK; 674 } 675