| OLD | NEW |
| (Empty) |
| 1 // Main.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 #include "Common/MyInitGuid.h" | |
| 6 | |
| 7 #include "Common/CommandLineParser.h" | |
| 8 #include "Common/MyException.h" | |
| 9 #include "Common/IntToString.h" | |
| 10 #include "Common/StdOutStream.h" | |
| 11 #include "Common/StringConvert.h" | |
| 12 #include "Common/StringToInt.h" | |
| 13 | |
| 14 #include "Windows/FileDir.h" | |
| 15 #include "Windows/FileName.h" | |
| 16 #include "Windows/Defs.h" | |
| 17 #include "Windows/Error.h" | |
| 18 #ifdef _WIN32 | |
| 19 #include "Windows/MemoryLock.h" | |
| 20 #endif | |
| 21 | |
| 22 #include "../../IPassword.h" | |
| 23 #include "../../ICoder.h" | |
| 24 #include "../Common/UpdateAction.h" | |
| 25 #include "../Common/Update.h" | |
| 26 #include "../Common/Extract.h" | |
| 27 #include "../Common/ArchiveCommandLine.h" | |
| 28 #include "../Common/ExitCode.h" | |
| 29 #ifdef EXTERNAL_CODECS | |
| 30 #include "../Common/LoadCodecs.h" | |
| 31 #endif | |
| 32 | |
| 33 #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" | |
| 34 | |
| 35 #include "List.h" | |
| 36 #include "OpenCallbackConsole.h" | |
| 37 #include "ExtractCallbackConsole.h" | |
| 38 #include "UpdateCallbackConsole.h" | |
| 39 | |
| 40 #include "../../MyVersion.h" | |
| 41 | |
| 42 #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) | |
| 43 extern "C" | |
| 44 { | |
| 45 #include "../../../../C/Alloc.h" | |
| 46 } | |
| 47 #endif | |
| 48 | |
| 49 using namespace NWindows; | |
| 50 using namespace NFile; | |
| 51 using namespace NCommandLineParser; | |
| 52 | |
| 53 HINSTANCE g_hInstance = 0; | |
| 54 extern CStdOutStream *g_StdStream; | |
| 55 | |
| 56 static const char *kCopyrightString = "\n7-Zip" | |
| 57 #ifndef EXTERNAL_CODECS | |
| 58 " (A)" | |
| 59 #endif | |
| 60 | |
| 61 #ifdef _WIN64 | |
| 62 " [64]" | |
| 63 #endif | |
| 64 | |
| 65 " " MY_VERSION_COPYRIGHT_DATE "\n"; | |
| 66 | |
| 67 static const char *kHelpString = | |
| 68 "\nUsage: 7z" | |
| 69 #ifdef _NO_CRYPTO | |
| 70 "r" | |
| 71 #else | |
| 72 #ifndef EXTERNAL_CODECS | |
| 73 "a" | |
| 74 #endif | |
| 75 #endif | |
| 76 " <command> [<switches>...] <archive_name> [<file_names>...]\n" | |
| 77 " [<@listfiles...>]\n" | |
| 78 "\n" | |
| 79 "<Commands>\n" | |
| 80 " a: Add files to archive\n" | |
| 81 " b: Benchmark\n" | |
| 82 " d: Delete files from archive\n" | |
| 83 " e: Extract files from archive (without using directory names)\n" | |
| 84 " l: List contents of archive\n" | |
| 85 // " l[a|t][f]: List contents of archive\n" | |
| 86 // " a - with Additional fields\n" | |
| 87 // " t - with all fields\n" | |
| 88 // " f - with Full pathnames\n" | |
| 89 " t: Test integrity of archive\n" | |
| 90 " u: Update files to archive\n" | |
| 91 " x: eXtract files with full paths\n" | |
| 92 "<Switches>\n" | |
| 93 " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" | |
| 94 " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" | |
| 95 " -bd: Disable percentage indicator\n" | |
| 96 " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" | |
| 97 " -m{Parameters}: set compression Method\n" | |
| 98 " -o{Directory}: set Output directory\n" | |
| 99 #ifndef _NO_CRYPTO | |
| 100 " -p{Password}: set Password\n" | |
| 101 #endif | |
| 102 " -r[-|0]: Recurse subdirectories\n" | |
| 103 " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" | |
| 104 " -sfx[{name}]: Create SFX archive\n" | |
| 105 " -si[{name}]: read data from stdin\n" | |
| 106 " -slt: show technical information for l (List) command\n" | |
| 107 " -so: write data to stdout\n" | |
| 108 " -ssc[-]: set sensitive case mode\n" | |
| 109 " -ssw: compress shared files\n" | |
| 110 " -t{Type}: Set type of archive\n" | |
| 111 " -v{Size}[b|k|m|g]: Create volumes\n" | |
| 112 " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" | |
| 113 " -w[{path}]: assign Work directory. Empty path means a temporary directory
\n" | |
| 114 " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" | |
| 115 " -y: assume Yes on all queries\n"; | |
| 116 | |
| 117 // --------------------------- | |
| 118 // exception messages | |
| 119 | |
| 120 static const char *kEverythingIsOk = "Everything is Ok"; | |
| 121 static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::
kUserError | |
| 122 static const char *kNoFormats = "7-Zip cannot find the code that works with arch
ives."; | |
| 123 | |
| 124 static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; | |
| 125 | |
| 126 static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExit
Code::EEnum code) | |
| 127 { | |
| 128 s << message << endl; | |
| 129 throw code; | |
| 130 } | |
| 131 | |
| 132 static void PrintHelpAndExit(CStdOutStream &s) // yyy | |
| 133 { | |
| 134 s << kHelpString; | |
| 135 ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); | |
| 136 } | |
| 137 | |
| 138 #ifndef _WIN32 | |
| 139 static void GetArguments(int numArguments, const char *arguments[], UStringVecto
r &parts) | |
| 140 { | |
| 141 parts.Clear(); | |
| 142 for(int i = 0; i < numArguments; i++) | |
| 143 { | |
| 144 UString s = MultiByteToUnicodeString(arguments[i]); | |
| 145 parts.Add(s); | |
| 146 } | |
| 147 } | |
| 148 #endif | |
| 149 | |
| 150 static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) | |
| 151 { | |
| 152 s << kCopyrightString; | |
| 153 // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\
n"; | |
| 154 if (needHelp) | |
| 155 s << kHelpString; | |
| 156 } | |
| 157 | |
| 158 #ifdef EXTERNAL_CODECS | |
| 159 static void PrintString(CStdOutStream &stdStream, const AString &s, int size) | |
| 160 { | |
| 161 int len = s.Length(); | |
| 162 stdStream << s; | |
| 163 for (int i = len; i < size; i++) | |
| 164 stdStream << ' '; | |
| 165 } | |
| 166 #endif | |
| 167 | |
| 168 static void PrintString(CStdOutStream &stdStream, const UString &s, int size) | |
| 169 { | |
| 170 int len = s.Length(); | |
| 171 stdStream << s; | |
| 172 for (int i = len; i < size; i++) | |
| 173 stdStream << ' '; | |
| 174 } | |
| 175 | |
| 176 static inline char GetHex(Byte value) | |
| 177 { | |
| 178 return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); | |
| 179 } | |
| 180 | |
| 181 const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; | |
| 182 | |
| 183 int Main2( | |
| 184 #ifndef _WIN32 | |
| 185 int numArguments, const char *arguments[] | |
| 186 #endif | |
| 187 ) | |
| 188 { | |
| 189 #ifdef _WIN32 | |
| 190 SetFileApisToOEM(); | |
| 191 #endif | |
| 192 | |
| 193 UStringVector commandStrings; | |
| 194 #ifdef _WIN32 | |
| 195 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); | |
| 196 #else | |
| 197 GetArguments(numArguments, arguments, commandStrings); | |
| 198 #endif | |
| 199 | |
| 200 if(commandStrings.Size() == 1) | |
| 201 { | |
| 202 ShowCopyrightAndHelp(g_StdOut, true); | |
| 203 return 0; | |
| 204 } | |
| 205 commandStrings.Delete(0); | |
| 206 | |
| 207 CArchiveCommandLineOptions options; | |
| 208 | |
| 209 CArchiveCommandLineParser parser; | |
| 210 | |
| 211 parser.Parse1(commandStrings, options); | |
| 212 | |
| 213 if(options.HelpMode) | |
| 214 { | |
| 215 ShowCopyrightAndHelp(g_StdOut, true); | |
| 216 return 0; | |
| 217 } | |
| 218 | |
| 219 #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) | |
| 220 if (options.LargePages) | |
| 221 { | |
| 222 SetLargePageSize(); | |
| 223 NSecurity::EnableLockMemoryPrivilege(); | |
| 224 } | |
| 225 #endif | |
| 226 | |
| 227 CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; | |
| 228 g_StdStream = &stdStream; | |
| 229 | |
| 230 if (options.EnableHeaders) | |
| 231 ShowCopyrightAndHelp(stdStream, false); | |
| 232 | |
| 233 parser.Parse2(options); | |
| 234 | |
| 235 CCodecs *codecs = new CCodecs; | |
| 236 CMyComPtr< | |
| 237 #ifdef EXTERNAL_CODECS | |
| 238 ICompressCodecsInfo | |
| 239 #else | |
| 240 IUnknown | |
| 241 #endif | |
| 242 > compressCodecsInfo = codecs; | |
| 243 HRESULT result = codecs->Load(); | |
| 244 if (result != S_OK) | |
| 245 throw CSystemException(result); | |
| 246 | |
| 247 bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); | |
| 248 | |
| 249 if (codecs->Formats.Size() == 0 && | |
| 250 (isExtractGroupCommand || | |
| 251 options.Command.CommandType == NCommandType::kList || | |
| 252 options.Command.IsFromUpdateGroup())) | |
| 253 throw kNoFormats; | |
| 254 | |
| 255 CIntVector formatIndices; | |
| 256 if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) | |
| 257 throw kUnsupportedArcTypeMessage; | |
| 258 | |
| 259 if (options.Command.CommandType == NCommandType::kInfo) | |
| 260 { | |
| 261 stdStream << endl << "Formats:" << endl; | |
| 262 int i; | |
| 263 for (i = 0; i < codecs->Formats.Size(); i++) | |
| 264 { | |
| 265 const CArcInfoEx &arc = codecs->Formats[i]; | |
| 266 #ifdef EXTERNAL_CODECS | |
| 267 if (arc.LibIndex >= 0) | |
| 268 { | |
| 269 char s[32]; | |
| 270 ConvertUInt64ToString(arc.LibIndex, s); | |
| 271 PrintString(stdStream, s, 2); | |
| 272 } | |
| 273 else | |
| 274 #endif | |
| 275 stdStream << " "; | |
| 276 stdStream << ' '; | |
| 277 stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); | |
| 278 stdStream << (char)(arc.KeepName ? 'K' : ' '); | |
| 279 stdStream << " "; | |
| 280 PrintString(stdStream, arc.Name, 6); | |
| 281 stdStream << " "; | |
| 282 UString s; | |
| 283 for (int t = 0; t < arc.Exts.Size(); t++) | |
| 284 { | |
| 285 const CArcExtInfo &ext = arc.Exts[t]; | |
| 286 s += ext.Ext; | |
| 287 if (!ext.AddExt.IsEmpty()) | |
| 288 { | |
| 289 s += L" ("; | |
| 290 s += ext.AddExt; | |
| 291 s += L')'; | |
| 292 } | |
| 293 s += L' '; | |
| 294 } | |
| 295 PrintString(stdStream, s, 14); | |
| 296 stdStream << " "; | |
| 297 const CByteBuffer &sig = arc.StartSignature; | |
| 298 for (size_t j = 0; j < sig.GetCapacity(); j++) | |
| 299 { | |
| 300 Byte b = sig[j]; | |
| 301 if (b > 0x20 && b < 0x80) | |
| 302 { | |
| 303 stdStream << (char)b; | |
| 304 } | |
| 305 else | |
| 306 { | |
| 307 stdStream << GetHex((Byte)((b >> 4) & 0xF)); | |
| 308 stdStream << GetHex((Byte)(b & 0xF)); | |
| 309 } | |
| 310 stdStream << ' '; | |
| 311 } | |
| 312 stdStream << endl; | |
| 313 } | |
| 314 stdStream << endl << "Codecs:" << endl; | |
| 315 | |
| 316 #ifdef EXTERNAL_CODECS | |
| 317 UInt32 numMethods; | |
| 318 if (codecs->GetNumberOfMethods(&numMethods) == S_OK) | |
| 319 for (UInt32 j = 0; j < numMethods; j++) | |
| 320 { | |
| 321 int libIndex = codecs->GetCodecLibIndex(j); | |
| 322 if (libIndex >= 0) | |
| 323 { | |
| 324 char s[32]; | |
| 325 ConvertUInt64ToString(libIndex, s); | |
| 326 PrintString(stdStream, s, 2); | |
| 327 } | |
| 328 else | |
| 329 stdStream << " "; | |
| 330 stdStream << ' '; | |
| 331 stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); | |
| 332 UInt64 id; | |
| 333 stdStream << " "; | |
| 334 HRESULT res = codecs->GetCodecId(j, id); | |
| 335 if (res != S_OK) | |
| 336 id = (UInt64)(Int64)-1; | |
| 337 char s[32]; | |
| 338 ConvertUInt64ToString(id, s, 16); | |
| 339 PrintString(stdStream, s, 8); | |
| 340 stdStream << " "; | |
| 341 PrintString(stdStream, codecs->GetCodecName(j), 11); | |
| 342 stdStream << endl; | |
| 343 /* | |
| 344 if (res != S_OK) | |
| 345 throw "incorrect Codec ID"; | |
| 346 */ | |
| 347 } | |
| 348 #endif | |
| 349 return S_OK; | |
| 350 } | |
| 351 else if (options.Command.CommandType == NCommandType::kBenchmark) | |
| 352 { | |
| 353 if (options.Method.CompareNoCase(L"CRC") == 0) | |
| 354 { | |
| 355 HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, option
s.NumThreads, options.DictionarySize); | |
| 356 if (res != S_OK) | |
| 357 { | |
| 358 if (res == S_FALSE) | |
| 359 { | |
| 360 stdStream << "\nCRC Error\n"; | |
| 361 return NExitCode::kFatalError; | |
| 362 } | |
| 363 throw CSystemException(res); | |
| 364 } | |
| 365 } | |
| 366 else | |
| 367 { | |
| 368 HRESULT res = LzmaBenchCon( | |
| 369 #ifdef EXTERNAL_LZMA | |
| 370 codecs, | |
| 371 #endif | |
| 372 (FILE *)stdStream, options.NumIterations, options.NumThreads, options.Di
ctionarySize); | |
| 373 if (res != S_OK) | |
| 374 { | |
| 375 if (res == S_FALSE) | |
| 376 { | |
| 377 stdStream << "\nDecoding Error\n"; | |
| 378 return NExitCode::kFatalError; | |
| 379 } | |
| 380 throw CSystemException(res); | |
| 381 } | |
| 382 } | |
| 383 } | |
| 384 else if (isExtractGroupCommand || options.Command.CommandType == NCommandType:
:kList) | |
| 385 { | |
| 386 if(isExtractGroupCommand) | |
| 387 { | |
| 388 CExtractCallbackConsole *ecs = new CExtractCallbackConsole; | |
| 389 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; | |
| 390 | |
| 391 ecs->OutStream = &stdStream; | |
| 392 | |
| 393 #ifndef _NO_CRYPTO | |
| 394 ecs->PasswordIsDefined = options.PasswordEnabled; | |
| 395 ecs->Password = options.Password; | |
| 396 #endif | |
| 397 | |
| 398 ecs->Init(); | |
| 399 | |
| 400 COpenCallbackConsole openCallback; | |
| 401 openCallback.OutStream = &stdStream; | |
| 402 | |
| 403 #ifndef _NO_CRYPTO | |
| 404 openCallback.PasswordIsDefined = options.PasswordEnabled; | |
| 405 openCallback.Password = options.Password; | |
| 406 #endif | |
| 407 | |
| 408 CExtractOptions eo; | |
| 409 eo.StdOutMode = options.StdOutMode; | |
| 410 eo.PathMode = options.Command.GetPathMode(); | |
| 411 eo.TestMode = options.Command.IsTestMode(); | |
| 412 eo.OverwriteMode = options.OverwriteMode; | |
| 413 eo.OutputDir = options.OutputDir; | |
| 414 eo.YesToAll = options.YesToAll; | |
| 415 #ifdef COMPRESS_MT | |
| 416 eo.Properties = options.ExtractProperties; | |
| 417 #endif | |
| 418 UString errorMessage; | |
| 419 CDecompressStat stat; | |
| 420 HRESULT result = DecompressArchives( | |
| 421 codecs, | |
| 422 formatIndices, | |
| 423 options.ArchivePathsSorted, | |
| 424 options.ArchivePathsFullSorted, | |
| 425 options.WildcardCensor.Pairs.Front().Head, | |
| 426 eo, &openCallback, ecs, errorMessage, stat); | |
| 427 if (!errorMessage.IsEmpty()) | |
| 428 { | |
| 429 stdStream << endl << "Error: " << errorMessage; | |
| 430 if (result == S_OK) | |
| 431 result = E_FAIL; | |
| 432 } | |
| 433 | |
| 434 stdStream << endl; | |
| 435 if (ecs->NumArchives > 1) | |
| 436 stdStream << "Archives: " << ecs->NumArchives << endl; | |
| 437 if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) | |
| 438 { | |
| 439 if (ecs->NumArchives > 1) | |
| 440 { | |
| 441 stdStream << endl; | |
| 442 if (ecs->NumArchiveErrors != 0) | |
| 443 stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; | |
| 444 if (ecs->NumFileErrors != 0) | |
| 445 stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; | |
| 446 } | |
| 447 if (result != S_OK) | |
| 448 throw CSystemException(result); | |
| 449 return NExitCode::kFatalError; | |
| 450 } | |
| 451 if (result != S_OK) | |
| 452 throw CSystemException(result); | |
| 453 if (stat.NumFolders != 0) | |
| 454 stdStream << "Folders: " << stat.NumFolders << endl; | |
| 455 if (stat.NumFiles != 1 || stat.NumFolders != 0) | |
| 456 stdStream << "Files: " << stat.NumFiles << endl; | |
| 457 stdStream | |
| 458 << "Size: " << stat.UnpackSize << endl | |
| 459 << "Compressed: " << stat.PackSize << endl; | |
| 460 } | |
| 461 else | |
| 462 { | |
| 463 UInt64 numErrors = 0; | |
| 464 HRESULT result = ListArchives( | |
| 465 codecs, | |
| 466 formatIndices, | |
| 467 options.ArchivePathsSorted, | |
| 468 options.ArchivePathsFullSorted, | |
| 469 options.WildcardCensor.Pairs.Front().Head, | |
| 470 options.EnableHeaders, | |
| 471 options.TechMode, | |
| 472 #ifndef _NO_CRYPTO | |
| 473 options.PasswordEnabled, | |
| 474 options.Password, | |
| 475 #endif | |
| 476 numErrors); | |
| 477 if (numErrors > 0) | |
| 478 { | |
| 479 g_StdOut << endl << "Errors: " << numErrors; | |
| 480 return NExitCode::kFatalError; | |
| 481 } | |
| 482 if (result != S_OK) | |
| 483 throw CSystemException(result); | |
| 484 } | |
| 485 } | |
| 486 else if(options.Command.IsFromUpdateGroup()) | |
| 487 { | |
| 488 UString workingDir; | |
| 489 | |
| 490 CUpdateOptions &uo = options.UpdateOptions; | |
| 491 if (uo.SfxMode && uo.SfxModule.IsEmpty()) | |
| 492 uo.SfxModule = kDefaultSfxModule; | |
| 493 | |
| 494 COpenCallbackConsole openCallback; | |
| 495 openCallback.OutStream = &stdStream; | |
| 496 | |
| 497 #ifndef _NO_CRYPTO | |
| 498 bool passwordIsDefined = | |
| 499 options.PasswordEnabled && !options.Password.IsEmpty(); | |
| 500 openCallback.PasswordIsDefined = passwordIsDefined; | |
| 501 openCallback.Password = options.Password; | |
| 502 #endif | |
| 503 | |
| 504 CUpdateCallbackConsole callback; | |
| 505 callback.EnablePercents = options.EnablePercents; | |
| 506 | |
| 507 #ifndef _NO_CRYPTO | |
| 508 callback.PasswordIsDefined = passwordIsDefined; | |
| 509 callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty()
; | |
| 510 callback.Password = options.Password; | |
| 511 #endif | |
| 512 callback.StdOutMode = uo.StdOutMode; | |
| 513 callback.Init(&stdStream); | |
| 514 | |
| 515 CUpdateErrorInfo errorInfo; | |
| 516 | |
| 517 if (!uo.Init(codecs, formatIndices, options.ArchiveName)) | |
| 518 throw kUnsupportedArcTypeMessage; | |
| 519 HRESULT result = UpdateArchive(codecs, | |
| 520 options.WildcardCensor, uo, | |
| 521 errorInfo, &openCallback, &callback); | |
| 522 | |
| 523 int exitCode = NExitCode::kSuccess; | |
| 524 if (callback.CantFindFiles.Size() > 0) | |
| 525 { | |
| 526 stdStream << endl; | |
| 527 stdStream << "WARNINGS for files:" << endl << endl; | |
| 528 int numErrors = callback.CantFindFiles.Size(); | |
| 529 for (int i = 0; i < numErrors; i++) | |
| 530 { | |
| 531 stdStream << callback.CantFindFiles[i] << " : "; | |
| 532 stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl
; | |
| 533 } | |
| 534 stdStream << "----------------" << endl; | |
| 535 stdStream << "WARNING: Cannot find " << numErrors << " file"; | |
| 536 if (numErrors > 1) | |
| 537 stdStream << "s"; | |
| 538 stdStream << endl; | |
| 539 exitCode = NExitCode::kWarning; | |
| 540 } | |
| 541 | |
| 542 if (result != S_OK) | |
| 543 { | |
| 544 UString message; | |
| 545 if (!errorInfo.Message.IsEmpty()) | |
| 546 { | |
| 547 message += errorInfo.Message; | |
| 548 message += L"\n"; | |
| 549 } | |
| 550 if (!errorInfo.FileName.IsEmpty()) | |
| 551 { | |
| 552 message += errorInfo.FileName; | |
| 553 message += L"\n"; | |
| 554 } | |
| 555 if (!errorInfo.FileName2.IsEmpty()) | |
| 556 { | |
| 557 message += errorInfo.FileName2; | |
| 558 message += L"\n"; | |
| 559 } | |
| 560 if (errorInfo.SystemError != 0) | |
| 561 { | |
| 562 message += NError::MyFormatMessageW(errorInfo.SystemError); | |
| 563 message += L"\n"; | |
| 564 } | |
| 565 if (!message.IsEmpty()) | |
| 566 stdStream << L"\nError:\n" << message; | |
| 567 throw CSystemException(result); | |
| 568 } | |
| 569 int numErrors = callback.FailedFiles.Size(); | |
| 570 if (numErrors == 0) | |
| 571 { | |
| 572 if (callback.CantFindFiles.Size() == 0) | |
| 573 stdStream << kEverythingIsOk << endl; | |
| 574 } | |
| 575 else | |
| 576 { | |
| 577 stdStream << endl; | |
| 578 stdStream << "WARNINGS for files:" << endl << endl; | |
| 579 for (int i = 0; i < numErrors; i++) | |
| 580 { | |
| 581 stdStream << callback.FailedFiles[i] << " : "; | |
| 582 stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; | |
| 583 } | |
| 584 stdStream << "----------------" << endl; | |
| 585 stdStream << "WARNING: Cannot open " << numErrors << " file"; | |
| 586 if (numErrors > 1) | |
| 587 stdStream << "s"; | |
| 588 stdStream << endl; | |
| 589 exitCode = NExitCode::kWarning; | |
| 590 } | |
| 591 return exitCode; | |
| 592 } | |
| 593 else | |
| 594 PrintHelpAndExit(stdStream); | |
| 595 return 0; | |
| 596 } | |
| OLD | NEW |