ManifestCommon.cpp (40858B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "winget/ManifestCommon.h" 5 #include "winget/ManifestValidation.h" 6 7 namespace AppInstaller::Manifest 8 { 9 namespace 10 { 11 enum class CompatibilitySet 12 { 13 None, 14 Exe, 15 Msi, 16 Msix, 17 }; 18 19 CompatibilitySet GetCompatibilitySet(InstallerTypeEnum type) 20 { 21 switch (type) 22 { 23 case InstallerTypeEnum::Inno: 24 case InstallerTypeEnum::Nullsoft: 25 case InstallerTypeEnum::Exe: 26 case InstallerTypeEnum::Burn: 27 return CompatibilitySet::Exe; 28 case InstallerTypeEnum::Wix: 29 case InstallerTypeEnum::Msi: 30 return CompatibilitySet::Msi; 31 case InstallerTypeEnum::Msix: 32 case InstallerTypeEnum::MSStore: 33 return CompatibilitySet::Msix; 34 default: 35 return CompatibilitySet::None; 36 } 37 } 38 } 39 40 ManifestVer::ManifestVer(std::string_view version) 41 { 42 bool validationSuccess = true; 43 44 // Separate the extensions out 45 size_t hyphenPos = version.find_first_of('-'); 46 if (hyphenPos != std::string_view::npos) 47 { 48 // The first part is the main version 49 Assign(std::string{ version.substr(0, hyphenPos) }, "."); 50 51 // The second part is the extensions 52 hyphenPos += 1; 53 while (hyphenPos < version.length()) 54 { 55 size_t newPos = version.find_first_of('-', hyphenPos); 56 57 size_t length = (newPos == std::string::npos ? version.length() : newPos) - hyphenPos; 58 m_extensions.emplace_back(std::string{ version.substr(hyphenPos, length) }, "."); 59 60 hyphenPos += length + 1; 61 } 62 } 63 else 64 { 65 Assign(std::string{ version }, "."); 66 } 67 68 if (m_parts.size() > 3) 69 { 70 validationSuccess = false; 71 } 72 else 73 { 74 for (size_t i = 0; i < m_parts.size(); i++) 75 { 76 if (!m_parts[i].Other.empty()) 77 { 78 validationSuccess = false; 79 break; 80 } 81 } 82 83 for (const RawVersion& ext : m_extensions) 84 { 85 if (ext.GetParts().empty() || ext.GetParts()[0].Integer != 0) 86 { 87 validationSuccess = false; 88 break; 89 } 90 } 91 } 92 93 if (!validationSuccess) 94 { 95 std::vector<ValidationError> errors; 96 errors.emplace_back(ManifestError::InvalidFieldValue, "ManifestVersion", std::string{ version }); 97 THROW_EXCEPTION(ManifestException(std::move(errors))); 98 } 99 } 100 101 bool ManifestVer::HasExtension() const 102 { 103 return !m_extensions.empty(); 104 } 105 106 bool ManifestVer::HasExtension(std::string_view extension) const 107 { 108 for (const RawVersion& ext : m_extensions) 109 { 110 const auto& parts = ext.GetParts(); 111 if (!parts.empty() && parts[0].Integer == 0 && parts[0].Other == extension) 112 { 113 return true; 114 } 115 } 116 117 return false; 118 } 119 120 InstallerTypeEnum ConvertToInstallerTypeEnum(const std::string& in) 121 { 122 std::string inStrLower = Utility::ToLower(in); 123 InstallerTypeEnum result = InstallerTypeEnum::Unknown; 124 125 if (inStrLower == "inno") 126 { 127 result = InstallerTypeEnum::Inno; 128 } 129 else if (inStrLower == "wix") 130 { 131 result = InstallerTypeEnum::Wix; 132 } 133 else if (inStrLower == "msi") 134 { 135 result = InstallerTypeEnum::Msi; 136 } 137 else if (inStrLower == "nullsoft") 138 { 139 result = InstallerTypeEnum::Nullsoft; 140 } 141 else if (inStrLower == "zip") 142 { 143 result = InstallerTypeEnum::Zip; 144 } 145 else if (inStrLower == "appx" || inStrLower == "msix") 146 { 147 result = InstallerTypeEnum::Msix; 148 } 149 else if (inStrLower == "exe") 150 { 151 result = InstallerTypeEnum::Exe; 152 } 153 else if (inStrLower == "burn") 154 { 155 result = InstallerTypeEnum::Burn; 156 } 157 else if (inStrLower == "msstore") 158 { 159 result = InstallerTypeEnum::MSStore; 160 } 161 else if (inStrLower == "portable") 162 { 163 result = InstallerTypeEnum::Portable; 164 } 165 else if (inStrLower == "font") 166 { 167 result = InstallerTypeEnum::Font; 168 } 169 170 return result; 171 } 172 173 UpdateBehaviorEnum ConvertToUpdateBehaviorEnum(const std::string& in) 174 { 175 UpdateBehaviorEnum result = UpdateBehaviorEnum::Unknown; 176 177 if (Utility::CaseInsensitiveEquals(in, "install")) 178 { 179 result = UpdateBehaviorEnum::Install; 180 } 181 else if (Utility::CaseInsensitiveEquals(in, "uninstallprevious")) 182 { 183 result = UpdateBehaviorEnum::UninstallPrevious; 184 } 185 else if (Utility::CaseInsensitiveEquals(in, "deny")) 186 { 187 result = UpdateBehaviorEnum::Deny; 188 } 189 190 return result; 191 } 192 193 ScopeEnum ConvertToScopeEnum(std::string_view in) 194 { 195 ScopeEnum result = ScopeEnum::Unknown; 196 197 if (Utility::CaseInsensitiveEquals(in, "user")) 198 { 199 result = ScopeEnum::User; 200 } 201 else if (Utility::CaseInsensitiveEquals(in, "machine")) 202 { 203 result = ScopeEnum::Machine; 204 } 205 206 return result; 207 } 208 209 InstallModeEnum ConvertToInstallModeEnum(const std::string& in) 210 { 211 InstallModeEnum result = InstallModeEnum::Unknown; 212 213 if (Utility::CaseInsensitiveEquals(in, "interactive")) 214 { 215 result = InstallModeEnum::Interactive; 216 } 217 else if (Utility::CaseInsensitiveEquals(in, "silent")) 218 { 219 result = InstallModeEnum::Silent; 220 } 221 else if (Utility::CaseInsensitiveEquals(in, "silentWithProgress")) 222 { 223 result = InstallModeEnum::SilentWithProgress; 224 } 225 226 return result; 227 } 228 229 PlatformEnum ConvertToPlatformEnum(std::string_view in) 230 { 231 std::string inStrLower = Utility::ToLower(in); 232 233 if (inStrLower == "windows.desktop") 234 { 235 return PlatformEnum::Desktop; 236 } 237 else if (inStrLower == "windows.universal") 238 { 239 return PlatformEnum::Universal; 240 } 241 242 return PlatformEnum::Unknown; 243 } 244 245 PlatformEnum ConvertToPlatformEnumForMSStoreDownload(std::string_view in) 246 { 247 std::string inStrLower = Utility::ToLower(in); 248 249 if (inStrLower == "windows.desktop") 250 { 251 return PlatformEnum::Desktop; 252 } 253 else if (inStrLower == "windows.universal") 254 { 255 return PlatformEnum::Universal; 256 } 257 else if (inStrLower == "windows.iot") 258 { 259 return PlatformEnum::IoT; 260 } 261 else if (inStrLower == "windows.team") 262 { 263 return PlatformEnum::Team; 264 } 265 else if (inStrLower == "windows.holographic") 266 { 267 return PlatformEnum::Holographic; 268 } 269 270 return PlatformEnum::Unknown; 271 } 272 273 ElevationRequirementEnum ConvertToElevationRequirementEnum(const std::string& in) 274 { 275 ElevationRequirementEnum result = ElevationRequirementEnum::Unknown; 276 277 if (Utility::CaseInsensitiveEquals(in, "elevationRequired")) 278 { 279 result = ElevationRequirementEnum::ElevationRequired; 280 } 281 else if (Utility::CaseInsensitiveEquals(in, "elevationProhibited")) 282 { 283 result = ElevationRequirementEnum::ElevationProhibited; 284 } 285 else if (Utility::CaseInsensitiveEquals(in, "elevatesSelf")) 286 { 287 result = ElevationRequirementEnum::ElevatesSelf; 288 } 289 290 return result; 291 } 292 293 UnsupportedArgumentEnum ConvertToUnsupportedArgumentEnum(const std::string& in) 294 { 295 UnsupportedArgumentEnum result = UnsupportedArgumentEnum::Unknown; 296 297 if (Utility::CaseInsensitiveEquals(in, "log")) 298 { 299 result = UnsupportedArgumentEnum::Log; 300 } 301 else if (Utility::CaseInsensitiveEquals(in, "location")) 302 { 303 result = UnsupportedArgumentEnum::Location; 304 } 305 306 return result; 307 } 308 309 ManifestTypeEnum ConvertToManifestTypeEnum(const std::string& in) 310 { 311 if (in == "singleton") 312 { 313 return ManifestTypeEnum::Singleton; 314 } 315 else if (in == "version") 316 { 317 return ManifestTypeEnum::Version; 318 } 319 else if (in == "installer") 320 { 321 return ManifestTypeEnum::Installer; 322 } 323 else if (in == "defaultLocale") 324 { 325 return ManifestTypeEnum::DefaultLocale; 326 } 327 else if (in == "locale") 328 { 329 return ManifestTypeEnum::Locale; 330 } 331 else if (in == "merged") 332 { 333 return ManifestTypeEnum::Merged; 334 } 335 else if (in == "shadow") 336 { 337 return ManifestTypeEnum::Shadow; 338 } 339 else 340 { 341 THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported ManifestType: %hs", in.c_str()); 342 } 343 } 344 345 ExpectedReturnCodeEnum ConvertToExpectedReturnCodeEnum(const std::string& in) 346 { 347 std::string inStrLower = Utility::ToLower(in); 348 ExpectedReturnCodeEnum result = ExpectedReturnCodeEnum::Unknown; 349 350 if (inStrLower == "packageinuse") 351 { 352 result = ExpectedReturnCodeEnum::PackageInUse; 353 } 354 else if (inStrLower == "packageinusebyapplication") 355 { 356 result = ExpectedReturnCodeEnum::PackageInUseByApplication; 357 } 358 else if (inStrLower == "installinprogress") 359 { 360 result = ExpectedReturnCodeEnum::InstallInProgress; 361 } 362 else if (inStrLower == "fileinuse") 363 { 364 result = ExpectedReturnCodeEnum::FileInUse; 365 } 366 else if (inStrLower == "missingdependency") 367 { 368 result = ExpectedReturnCodeEnum::MissingDependency; 369 } 370 else if (inStrLower == "diskfull") 371 { 372 result = ExpectedReturnCodeEnum::DiskFull; 373 } 374 else if (inStrLower == "insufficientmemory") 375 { 376 result = ExpectedReturnCodeEnum::InsufficientMemory; 377 } 378 else if (inStrLower == "invalidparameter") 379 { 380 result = ExpectedReturnCodeEnum::InvalidParameter; 381 } 382 else if (inStrLower == "nonetwork") 383 { 384 result = ExpectedReturnCodeEnum::NoNetwork; 385 } 386 else if (inStrLower == "contactsupport") 387 { 388 result = ExpectedReturnCodeEnum::ContactSupport; 389 } 390 else if (inStrLower == "rebootrequiredtofinish") 391 { 392 result = ExpectedReturnCodeEnum::RebootRequiredToFinish; 393 } 394 else if (inStrLower == "rebootrequiredforinstall") 395 { 396 result = ExpectedReturnCodeEnum::RebootRequiredForInstall; 397 } 398 else if (inStrLower == "rebootinitiated") 399 { 400 result = ExpectedReturnCodeEnum::RebootInitiated; 401 } 402 else if (inStrLower == "cancelledbyuser") 403 { 404 result = ExpectedReturnCodeEnum::CancelledByUser; 405 } 406 else if (inStrLower == "alreadyinstalled") 407 { 408 result = ExpectedReturnCodeEnum::AlreadyInstalled; 409 } 410 else if (inStrLower == "downgrade") 411 { 412 result = ExpectedReturnCodeEnum::Downgrade; 413 } 414 else if (inStrLower == "blockedbypolicy") 415 { 416 result = ExpectedReturnCodeEnum::BlockedByPolicy; 417 } 418 else if (inStrLower == "systemnotsupported") 419 { 420 result = ExpectedReturnCodeEnum::SystemNotSupported; 421 } 422 else if (inStrLower == "custom") 423 { 424 result = ExpectedReturnCodeEnum::Custom; 425 } 426 427 return result; 428 } 429 430 InstalledFileTypeEnum ConvertToInstalledFileTypeEnum(const std::string& in) 431 { 432 std::string inStrLower = Utility::ToLower(in); 433 InstalledFileTypeEnum result = InstalledFileTypeEnum::Unknown; 434 435 if (inStrLower == "launch") 436 { 437 result = InstalledFileTypeEnum::Launch; 438 } 439 else if (inStrLower == "uninstall") 440 { 441 result = InstalledFileTypeEnum::Uninstall; 442 } 443 else if (inStrLower == "other") 444 { 445 result = InstalledFileTypeEnum::Other; 446 } 447 448 return result; 449 } 450 451 IconFileTypeEnum ConvertToIconFileTypeEnum(std::string_view in) 452 { 453 std::string inStrLower = Utility::ToLower(in); 454 IconFileTypeEnum result = IconFileTypeEnum::Unknown; 455 456 if (inStrLower == "jpeg") 457 { 458 result = IconFileTypeEnum::Jpeg; 459 } 460 else if (inStrLower == "png") 461 { 462 result = IconFileTypeEnum::Png; 463 } 464 else if (inStrLower == "ico") 465 { 466 result = IconFileTypeEnum::Ico; 467 } 468 469 return result; 470 } 471 472 IconThemeEnum ConvertToIconThemeEnum(std::string_view in) 473 { 474 std::string inStrLower = Utility::ToLower(in); 475 IconThemeEnum result = IconThemeEnum::Unknown; 476 477 if (inStrLower == "default") 478 { 479 result = IconThemeEnum::Default; 480 } 481 else if (inStrLower == "dark") 482 { 483 result = IconThemeEnum::Dark; 484 } 485 else if (inStrLower == "light") 486 { 487 result = IconThemeEnum::Light; 488 } 489 else if (inStrLower == "highcontrast") 490 { 491 result = IconThemeEnum::HighContrast; 492 } 493 494 return result; 495 } 496 497 IconResolutionEnum ConvertToIconResolutionEnum(std::string_view in) 498 { 499 std::string inStrLower = Utility::ToLower(in); 500 IconResolutionEnum result = IconResolutionEnum::Unknown; 501 502 if (inStrLower == "custom") 503 { 504 result = IconResolutionEnum::Custom; 505 } 506 else if (inStrLower == "16x16") 507 { 508 result = IconResolutionEnum::Square16; 509 } 510 else if (inStrLower == "20x20") 511 { 512 result = IconResolutionEnum::Square20; 513 } 514 else if (inStrLower == "24x24") 515 { 516 result = IconResolutionEnum::Square24; 517 } 518 else if (inStrLower == "30x30") 519 { 520 result = IconResolutionEnum::Square30; 521 } 522 else if (inStrLower == "32x32") 523 { 524 result = IconResolutionEnum::Square32; 525 } 526 else if (inStrLower == "36x36") 527 { 528 result = IconResolutionEnum::Square36; 529 } 530 else if (inStrLower == "40x40") 531 { 532 result = IconResolutionEnum::Square40; 533 } 534 else if (inStrLower == "48x48") 535 { 536 result = IconResolutionEnum::Square48; 537 } 538 else if (inStrLower == "60x60") 539 { 540 result = IconResolutionEnum::Square60; 541 } 542 else if (inStrLower == "64x64") 543 { 544 result = IconResolutionEnum::Square64; 545 } 546 else if (inStrLower == "72x72") 547 { 548 result = IconResolutionEnum::Square72; 549 } 550 else if (inStrLower == "80x80") 551 { 552 result = IconResolutionEnum::Square80; 553 } 554 else if (inStrLower == "96x96") 555 { 556 result = IconResolutionEnum::Square96; 557 } 558 else if (inStrLower == "256x256") 559 { 560 result = IconResolutionEnum::Square256; 561 } 562 563 return result; 564 } 565 566 std::string_view InstallerTypeToString(InstallerTypeEnum installerType) 567 { 568 switch (installerType) 569 { 570 case InstallerTypeEnum::Exe: 571 return "exe"sv; 572 case InstallerTypeEnum::Inno: 573 return "inno"sv; 574 case InstallerTypeEnum::Msi: 575 return "msi"sv; 576 case InstallerTypeEnum::Msix: 577 return "msix"sv; 578 case InstallerTypeEnum::Nullsoft: 579 return "nullsoft"sv; 580 case InstallerTypeEnum::Wix: 581 return "wix"sv; 582 case InstallerTypeEnum::Zip: 583 return "zip"sv; 584 case InstallerTypeEnum::Burn: 585 return "burn"sv; 586 case InstallerTypeEnum::MSStore: 587 return "msstore"sv; 588 case InstallerTypeEnum::Portable: 589 return "portable"sv; 590 case InstallerTypeEnum::Font: 591 return "font"sv; 592 } 593 594 return "unknown"sv; 595 } 596 597 std::string_view InstallerSwitchTypeToString(InstallerSwitchType installerSwitchType) 598 { 599 switch (installerSwitchType) 600 { 601 case InstallerSwitchType::Custom: 602 return "Custom"sv; 603 case InstallerSwitchType::Silent: 604 return "Silent"sv; 605 case InstallerSwitchType::SilentWithProgress: 606 return "SilentWithProgress"sv; 607 case InstallerSwitchType::Interactive: 608 return "Interactive"sv; 609 case InstallerSwitchType::Language: 610 return "Language"sv; 611 case InstallerSwitchType::Log: 612 return "Log"sv; 613 case InstallerSwitchType::InstallLocation: 614 return "InstallLocation"sv; 615 case InstallerSwitchType::Update: 616 return "Upgrade"sv; 617 case InstallerSwitchType::Repair: 618 return "Repair"sv; 619 } 620 621 return "Unknown"sv; 622 } 623 624 std::string_view ElevationRequirementToString(ElevationRequirementEnum elevationRequirement) 625 { 626 switch (elevationRequirement) 627 { 628 case ElevationRequirementEnum::ElevationRequired: 629 return "elevationRequired"sv; 630 case ElevationRequirementEnum::ElevationProhibited: 631 return "elevationProhibited"sv; 632 case ElevationRequirementEnum::ElevatesSelf: 633 return "elevatesSelf"sv; 634 } 635 636 return "unknown"sv; 637 } 638 639 std::string_view UnsupportedArgumentToString(UnsupportedArgumentEnum unsupportedArgument) 640 { 641 switch (unsupportedArgument) 642 { 643 case UnsupportedArgumentEnum::Log: 644 return "log"sv; 645 case UnsupportedArgumentEnum::Location: 646 return "location"sv; 647 } 648 649 return "unknown"sv; 650 } 651 652 std::string_view InstallModeToString(InstallModeEnum installMode) 653 { 654 switch (installMode) 655 { 656 case InstallModeEnum::Interactive: 657 return "interactive"sv; 658 case InstallModeEnum::Silent: 659 return "silent"sv; 660 case InstallModeEnum::SilentWithProgress: 661 return "silentWithProgress"sv; 662 } 663 664 return "unknown"sv; 665 } 666 667 std::string_view PlatformToString(PlatformEnum platform, bool shortString) 668 { 669 switch (platform) 670 { 671 case PlatformEnum::Desktop: 672 return shortString ? "Desktop" : "Windows.Desktop"sv; 673 case PlatformEnum::Universal: 674 return shortString ? "Universal" : "Windows.Universal"sv; 675 case PlatformEnum::IoT: 676 return shortString ? "IoT" : "Windows.IoT"sv; 677 case PlatformEnum::Holographic: 678 return shortString ? "Holographic" : "Windows.Holographic"sv; 679 case PlatformEnum::Team: 680 return shortString ? "Team" : "Windows.Team"sv; 681 } 682 683 return "Unknown"sv; 684 } 685 686 std::string_view UpdateBehaviorToString(UpdateBehaviorEnum updateBehavior) 687 { 688 switch (updateBehavior) 689 { 690 case UpdateBehaviorEnum::Install: 691 return "install"sv; 692 case UpdateBehaviorEnum::UninstallPrevious: 693 return "uninstallPrevious"sv; 694 case UpdateBehaviorEnum::Deny: 695 return "deny"sv; 696 } 697 698 return "unknown"sv; 699 } 700 701 std::string_view RepairBehaviorToString(RepairBehaviorEnum repairBehavior) 702 { 703 switch (repairBehavior) 704 { 705 case AppInstaller::Manifest::RepairBehaviorEnum::Modify: 706 return "modify"sv; 707 case AppInstaller::Manifest::RepairBehaviorEnum::Installer: 708 return "installer"sv; 709 case AppInstaller::Manifest::RepairBehaviorEnum::Uninstaller: 710 return "uninstaller"sv; 711 } 712 713 return "unknown"sv; 714 } 715 716 std::string_view ScopeToString(ScopeEnum scope) 717 { 718 switch (scope) 719 { 720 case ScopeEnum::User: 721 return "User"sv; 722 case ScopeEnum::Machine: 723 return "Machine"sv; 724 } 725 726 return "Unknown"sv; 727 } 728 729 std::string_view InstalledFileTypeToString(InstalledFileTypeEnum installedFileType) 730 { 731 switch (installedFileType) 732 { 733 case InstalledFileTypeEnum::Launch: 734 return "launch"sv; 735 case InstalledFileTypeEnum::Uninstall: 736 return "uninstall"sv; 737 case InstalledFileTypeEnum::Other: 738 return "other"sv; 739 } 740 741 return "unknown"sv; 742 } 743 744 std::string_view IconFileTypeToString(IconFileTypeEnum iconFileType) 745 { 746 switch (iconFileType) 747 { 748 case IconFileTypeEnum::Ico: 749 return "ico"sv; 750 case IconFileTypeEnum::Jpeg: 751 return "jpeg"sv; 752 case IconFileTypeEnum::Png: 753 return "png"sv; 754 } 755 756 return "unknown"sv; 757 } 758 759 std::string_view IconThemeToString(IconThemeEnum iconTheme) 760 { 761 switch (iconTheme) 762 { 763 case IconThemeEnum::Default: 764 return "default"sv; 765 case IconThemeEnum::Dark: 766 return "dark"sv; 767 case IconThemeEnum::Light: 768 return "light"sv; 769 case IconThemeEnum::HighContrast: 770 return "highContrast"sv; 771 } 772 773 return "unknown"sv; 774 } 775 776 std::string_view IconResolutionToString(IconResolutionEnum iconResolution) 777 { 778 switch (iconResolution) 779 { 780 case IconResolutionEnum::Custom: 781 return "custom"sv; 782 case IconResolutionEnum::Square16: 783 return "16x16"sv; 784 case IconResolutionEnum::Square20: 785 return "20x20"sv; 786 case IconResolutionEnum::Square24: 787 return "24x24"sv; 788 case IconResolutionEnum::Square30: 789 return "30x30"sv; 790 case IconResolutionEnum::Square32: 791 return "32x32"sv; 792 case IconResolutionEnum::Square36: 793 return "36x36"sv; 794 case IconResolutionEnum::Square40: 795 return "40x40"sv; 796 case IconResolutionEnum::Square48: 797 return "48x48"sv; 798 case IconResolutionEnum::Square60: 799 return "60x60"sv; 800 case IconResolutionEnum::Square64: 801 return "64x64"sv; 802 case IconResolutionEnum::Square72: 803 return "72x72"sv; 804 case IconResolutionEnum::Square80: 805 return "80x80"sv; 806 case IconResolutionEnum::Square96: 807 return "96x96"sv; 808 case IconResolutionEnum::Square256: 809 return "256x256"sv; 810 } 811 812 return "unknown"sv; 813 } 814 815 std::string_view ExpectedReturnCodeToString(ExpectedReturnCodeEnum expectedReturnCode) 816 { 817 switch (expectedReturnCode) 818 { 819 case ExpectedReturnCodeEnum::AlreadyInstalled: 820 return "alreadyInstalled"sv; 821 case ExpectedReturnCodeEnum::PackageInUse: 822 return "packageInUse"sv; 823 case ExpectedReturnCodeEnum::PackageInUseByApplication: 824 return "packageInUseByApplication"sv; 825 case ExpectedReturnCodeEnum::InstallInProgress: 826 return "installInProgress"sv; 827 case ExpectedReturnCodeEnum::FileInUse: 828 return "fileInUse"sv; 829 case ExpectedReturnCodeEnum::MissingDependency: 830 return "missingDependency"sv; 831 case ExpectedReturnCodeEnum::DiskFull: 832 return "diskFull"sv; 833 case ExpectedReturnCodeEnum::InsufficientMemory: 834 return "insufficientMemory"sv; 835 case ExpectedReturnCodeEnum::InvalidParameter: 836 return "invalidParameter"sv; 837 case ExpectedReturnCodeEnum::NoNetwork: 838 return "noNetwork"sv; 839 case ExpectedReturnCodeEnum::ContactSupport: 840 return "contactSupport"sv; 841 case ExpectedReturnCodeEnum::RebootRequiredToFinish: 842 return "rebootRequiredToFinish"sv; 843 case ExpectedReturnCodeEnum::RebootRequiredForInstall: 844 return "rebootRequiredForInstall"sv; 845 case ExpectedReturnCodeEnum::RebootInitiated: 846 return "rebootInitiated"sv; 847 case ExpectedReturnCodeEnum::CancelledByUser: 848 return "cancelledByUser"sv; 849 case ExpectedReturnCodeEnum::Downgrade: 850 return "downgrade"sv; 851 case ExpectedReturnCodeEnum::BlockedByPolicy: 852 return "blockedByPolicy"sv; 853 case ExpectedReturnCodeEnum::SystemNotSupported: 854 return "systemNotSupported"sv; 855 case ExpectedReturnCodeEnum::Custom: 856 return "custom"sv; 857 } 858 859 return "unknown"sv; 860 } 861 862 std::string_view ManifestTypeToString(ManifestTypeEnum manifestType) 863 { 864 switch (manifestType) 865 { 866 case ManifestTypeEnum::DefaultLocale: 867 return "defaultLocale"sv; 868 case ManifestTypeEnum::Installer: 869 return "installer"sv; 870 case ManifestTypeEnum::Locale: 871 return "locale"sv; 872 case ManifestTypeEnum::Merged: 873 return "merged"sv; 874 case ManifestTypeEnum::Singleton: 875 return "singleton"sv; 876 case ManifestTypeEnum::Version: 877 return "version"sv; 878 } 879 880 return "unknown"sv; 881 } 882 883 bool DoesInstallerTypeUsePackageFamilyName(InstallerTypeEnum installerType) 884 { 885 return (installerType == InstallerTypeEnum::Msix || installerType == InstallerTypeEnum::MSStore); 886 } 887 888 bool DoesInstallerTypeUseProductCode(InstallerTypeEnum installerType) 889 { 890 return ( 891 installerType == InstallerTypeEnum::Exe || 892 installerType == InstallerTypeEnum::Inno || 893 installerType == InstallerTypeEnum::Msi || 894 installerType == InstallerTypeEnum::Nullsoft || 895 installerType == InstallerTypeEnum::Wix || 896 installerType == InstallerTypeEnum::Burn || 897 installerType == InstallerTypeEnum::Portable 898 ); 899 } 900 901 bool DoesInstallerTypeWriteAppsAndFeaturesEntry(InstallerTypeEnum installerType) 902 { 903 return ( 904 installerType == InstallerTypeEnum::Exe || 905 installerType == InstallerTypeEnum::Inno || 906 installerType == InstallerTypeEnum::Msi || 907 installerType == InstallerTypeEnum::Nullsoft || 908 installerType == InstallerTypeEnum::Wix || 909 installerType == InstallerTypeEnum::Burn || 910 installerType == InstallerTypeEnum::Portable 911 ); 912 } 913 914 bool DoesInstallerTypeSupportArpVersionRange(InstallerTypeEnum installerType) 915 { 916 return ( 917 installerType == InstallerTypeEnum::Exe || 918 installerType == InstallerTypeEnum::Inno || 919 installerType == InstallerTypeEnum::Msi || 920 installerType == InstallerTypeEnum::Nullsoft || 921 installerType == InstallerTypeEnum::Wix || 922 installerType == InstallerTypeEnum::Burn 923 ); 924 } 925 926 bool DoesInstallerTypeIgnoreScopeFromManifest(InstallerTypeEnum installerType) 927 { 928 return 929 installerType == InstallerTypeEnum::Portable || 930 installerType == InstallerTypeEnum::Msix || 931 installerType == InstallerTypeEnum::MSStore; 932 } 933 934 bool DoesInstallerTypeRequireAdminForMachineScopeInstall(InstallerTypeEnum installerType) 935 { 936 return 937 installerType == InstallerTypeEnum::Portable || 938 installerType == InstallerTypeEnum::MSStore || 939 installerType == InstallerTypeEnum::Msix; 940 } 941 942 bool DoesInstallerTypeRequireRepairBehaviorForRepair(InstallerTypeEnum installerType) 943 { 944 return 945 installerType == InstallerTypeEnum::Burn || 946 installerType == InstallerTypeEnum::Inno || 947 installerType == InstallerTypeEnum::Nullsoft || 948 installerType == InstallerTypeEnum::Exe; 949 } 950 951 bool IsArchiveType(InstallerTypeEnum installerType) 952 { 953 return (installerType == InstallerTypeEnum::Zip); 954 } 955 956 bool IsPortableType(InstallerTypeEnum installerType) 957 { 958 return (installerType == InstallerTypeEnum::Portable); 959 } 960 961 bool IsNestedInstallerTypeSupported(InstallerTypeEnum nestedInstallerType) 962 { 963 return ( 964 nestedInstallerType == InstallerTypeEnum::Exe || 965 nestedInstallerType == InstallerTypeEnum::Inno || 966 nestedInstallerType == InstallerTypeEnum::Msi || 967 nestedInstallerType == InstallerTypeEnum::Nullsoft || 968 nestedInstallerType == InstallerTypeEnum::Wix || 969 nestedInstallerType == InstallerTypeEnum::Burn || 970 nestedInstallerType == InstallerTypeEnum::Portable || 971 nestedInstallerType == InstallerTypeEnum::Msix || 972 nestedInstallerType == InstallerTypeEnum::Font 973 ); 974 } 975 976 bool IsInstallerTypeCompatible(InstallerTypeEnum type1, InstallerTypeEnum type2) 977 { 978 // Unknown type cannot be compatible with any other 979 if (type1 == InstallerTypeEnum::Unknown || type2 == InstallerTypeEnum::Unknown) 980 { 981 return false; 982 } 983 984 // Not unknown, so must be compatible 985 if (type1 == type2) 986 { 987 return true; 988 } 989 990 CompatibilitySet set1 = GetCompatibilitySet(type1); 991 CompatibilitySet set2 = GetCompatibilitySet(type2); 992 993 // If either is none, they can't be compatible 994 if (set1 == CompatibilitySet::None || set2 == CompatibilitySet::None) 995 { 996 return false; 997 } 998 999 return set1 == set2; 1000 } 1001 1002 std::map<InstallerSwitchType, Utility::NormalizedString> GetDefaultKnownSwitches(InstallerTypeEnum installerType) 1003 { 1004 switch (installerType) 1005 { 1006 case InstallerTypeEnum::Burn: 1007 case InstallerTypeEnum::Wix: 1008 case InstallerTypeEnum::Msi: 1009 return 1010 { 1011 {InstallerSwitchType::Silent, ManifestInstaller::string_t("/quiet /norestart")}, 1012 {InstallerSwitchType::SilentWithProgress, ManifestInstaller::string_t("/passive /norestart")}, 1013 {InstallerSwitchType::Log, ManifestInstaller::string_t("/log \"" + std::string(ARG_TOKEN_LOGPATH) + "\"")}, 1014 {InstallerSwitchType::InstallLocation, ManifestInstaller::string_t("TARGETDIR=\"" + std::string(ARG_TOKEN_INSTALLPATH) + "\"")} 1015 }; 1016 case InstallerTypeEnum::Nullsoft: 1017 return 1018 { 1019 {InstallerSwitchType::Silent, ManifestInstaller::string_t("/S")}, 1020 {InstallerSwitchType::SilentWithProgress, ManifestInstaller::string_t("/S")}, 1021 {InstallerSwitchType::InstallLocation, ManifestInstaller::string_t("/D=" + std::string(ARG_TOKEN_INSTALLPATH))} 1022 }; 1023 case InstallerTypeEnum::Inno: 1024 return 1025 { 1026 {InstallerSwitchType::Silent, ManifestInstaller::string_t("/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART")}, 1027 {InstallerSwitchType::SilentWithProgress, ManifestInstaller::string_t("/SP- /SILENT /SUPPRESSMSGBOXES /NORESTART")}, 1028 {InstallerSwitchType::Log, ManifestInstaller::string_t("/LOG=\"" + std::string(ARG_TOKEN_LOGPATH) + "\"")}, 1029 {InstallerSwitchType::InstallLocation, ManifestInstaller::string_t("/DIR=\"" + std::string(ARG_TOKEN_INSTALLPATH) + "\"")} 1030 }; 1031 default: 1032 return {}; 1033 } 1034 } 1035 1036 RepairBehaviorEnum ConvertToRepairBehaviorEnum(std::string_view in) 1037 { 1038 std::string inStrLower = Utility::ToLower(in); 1039 RepairBehaviorEnum result = RepairBehaviorEnum::Unknown; 1040 1041 if (inStrLower == "installer") 1042 { 1043 result = RepairBehaviorEnum::Installer; 1044 } 1045 else if (inStrLower == "uninstaller") 1046 { 1047 result = RepairBehaviorEnum::Uninstaller; 1048 } 1049 else if (inStrLower == "modify") 1050 { 1051 result = RepairBehaviorEnum::Modify; 1052 } 1053 1054 return result; 1055 } 1056 1057 std::map<DWORD, ExpectedReturnCodeEnum> GetDefaultKnownReturnCodes(InstallerTypeEnum installerType) 1058 { 1059 switch (installerType) 1060 { 1061 case InstallerTypeEnum::Burn: 1062 case InstallerTypeEnum::Wix: 1063 case InstallerTypeEnum::Msi: 1064 // See https://docs.microsoft.com/windows/win32/msi/error-codes 1065 return 1066 { 1067 { ERROR_INSTALL_ALREADY_RUNNING, ExpectedReturnCodeEnum::InstallInProgress }, 1068 { ERROR_DISK_FULL, ExpectedReturnCodeEnum::DiskFull }, 1069 { ERROR_INSTALL_SERVICE_FAILURE, ExpectedReturnCodeEnum::ContactSupport }, 1070 { ERROR_SUCCESS_REBOOT_REQUIRED, ExpectedReturnCodeEnum::RebootRequiredToFinish }, 1071 { ERROR_SUCCESS_REBOOT_INITIATED, ExpectedReturnCodeEnum::RebootInitiated }, 1072 { ERROR_INSTALL_USEREXIT, ExpectedReturnCodeEnum::CancelledByUser }, 1073 { ERROR_PRODUCT_VERSION, ExpectedReturnCodeEnum::AlreadyInstalled }, 1074 { ERROR_INSTALL_REJECTED, ExpectedReturnCodeEnum::SystemNotSupported }, 1075 { ERROR_INSTALL_PACKAGE_REJECTED, ExpectedReturnCodeEnum::BlockedByPolicy }, 1076 { ERROR_INSTALL_TRANSFORM_REJECTED, ExpectedReturnCodeEnum::BlockedByPolicy }, 1077 { ERROR_PATCH_PACKAGE_REJECTED, ExpectedReturnCodeEnum::BlockedByPolicy }, 1078 { ERROR_PATCH_REMOVAL_DISALLOWED, ExpectedReturnCodeEnum::BlockedByPolicy }, 1079 { ERROR_INSTALL_REMOTE_DISALLOWED, ExpectedReturnCodeEnum::BlockedByPolicy }, 1080 { ERROR_INVALID_PARAMETER, ExpectedReturnCodeEnum::InvalidParameter }, 1081 { ERROR_INVALID_TABLE, ExpectedReturnCodeEnum::InvalidParameter }, 1082 { ERROR_INVALID_COMMAND_LINE, ExpectedReturnCodeEnum::InvalidParameter }, 1083 { ERROR_INVALID_PATCH_XML, ExpectedReturnCodeEnum::InvalidParameter }, 1084 { ERROR_INSTALL_LANGUAGE_UNSUPPORTED, ExpectedReturnCodeEnum::SystemNotSupported }, 1085 { ERROR_INSTALL_PLATFORM_UNSUPPORTED, ExpectedReturnCodeEnum::SystemNotSupported }, 1086 }; 1087 case InstallerTypeEnum::Inno: 1088 // See https://jrsoftware.org/ishelp/index.php?topic=setupexitcodes 1089 return 1090 { 1091 { 2, ExpectedReturnCodeEnum::CancelledByUser }, 1092 { 5, ExpectedReturnCodeEnum::CancelledByUser }, 1093 { 8, ExpectedReturnCodeEnum::RebootRequiredForInstall }, 1094 }; 1095 case InstallerTypeEnum::Msix: 1096 // See https://docs.microsoft.com/en-us/windows/win32/appxpkg/troubleshooting 1097 return 1098 { 1099 { HRESULT_FROM_WIN32(ERROR_INSTALL_PREREQUISITE_FAILED), ExpectedReturnCodeEnum::MissingDependency }, 1100 { HRESULT_FROM_WIN32(ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED), ExpectedReturnCodeEnum::MissingDependency }, 1101 { HRESULT_FROM_WIN32(ERROR_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE), ExpectedReturnCodeEnum::MissingDependency }, 1102 { HRESULT_FROM_WIN32(ERROR_INSTALL_OUT_OF_DISK_SPACE), ExpectedReturnCodeEnum::DiskFull }, 1103 { HRESULT_FROM_WIN32(ERROR_INSTALL_CANCEL), ExpectedReturnCodeEnum::CancelledByUser }, 1104 { HRESULT_FROM_WIN32(ERROR_PACKAGE_ALREADY_EXISTS), ExpectedReturnCodeEnum::AlreadyInstalled }, 1105 { HRESULT_FROM_WIN32(ERROR_INSTALL_PACKAGE_DOWNGRADE), ExpectedReturnCodeEnum::Downgrade }, 1106 { HRESULT_FROM_WIN32(ERROR_DEPLOYMENT_BLOCKED_BY_POLICY), ExpectedReturnCodeEnum::BlockedByPolicy}, 1107 { HRESULT_FROM_WIN32(ERROR_INSTALL_POLICY_FAILURE), ExpectedReturnCodeEnum::BlockedByPolicy}, 1108 { HRESULT_FROM_WIN32(ERROR_PACKAGES_IN_USE), ExpectedReturnCodeEnum::PackageInUse }, 1109 { HRESULT_FROM_WIN32(ERROR_INSTALL_WRONG_PROCESSOR_ARCHITECTURE), ExpectedReturnCodeEnum::SystemNotSupported }, 1110 { HRESULT_FROM_WIN32(ERROR_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM), ExpectedReturnCodeEnum::SystemNotSupported }, 1111 { HRESULT_FROM_WIN32(ERROR_DEPLOYMENT_OPTION_NOT_SUPPORTED), ExpectedReturnCodeEnum::SystemNotSupported }, 1112 { HRESULT_FROM_WIN32(ERROR_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST), ExpectedReturnCodeEnum::SystemNotSupported }, 1113 }; 1114 default: 1115 return {}; 1116 } 1117 } 1118 1119 void DependencyList::Add(const Dependency& newDependency) 1120 { 1121 Dependency* existingDependency = this->HasDependency(newDependency); 1122 1123 if (existingDependency != NULL) 1124 { 1125 if (newDependency.MinVersion > existingDependency->MinVersion) 1126 { 1127 existingDependency->MinVersion = newDependency.MinVersion; 1128 } 1129 } 1130 else 1131 { 1132 m_dependencies.push_back(newDependency); 1133 } 1134 } 1135 1136 void DependencyList::Add(const DependencyList& otherDependencyList) 1137 { 1138 for (const auto& dependency : otherDependencyList.m_dependencies) 1139 { 1140 this->Add(dependency); 1141 } 1142 } 1143 1144 bool DependencyList::HasAny() const { return !m_dependencies.empty(); } 1145 bool DependencyList::HasAnyOf(DependencyType type) const 1146 { 1147 for (const auto& dependency : m_dependencies) 1148 { 1149 if (dependency.Type == type) return true; 1150 }; 1151 return false; 1152 } 1153 1154 Dependency* DependencyList::HasDependency(const Dependency& dependencyToSearch) 1155 { 1156 for (auto& dependency : m_dependencies) 1157 { 1158 if (dependency.Type == dependencyToSearch.Type && ICUCaseInsensitiveEquals(dependency.Id(), dependencyToSearch.Id())) 1159 { 1160 return &dependency; 1161 } 1162 } 1163 return nullptr; 1164 } 1165 1166 // for testing purposes 1167 bool DependencyList::HasExactDependency(DependencyType type, const string_t& id, const string_t& minVersion) 1168 { 1169 for (const auto& dependency : m_dependencies) 1170 { 1171 if (dependency.Type == type && Utility::ICUCaseInsensitiveEquals(dependency.Id(), id)) 1172 { 1173 if (!minVersion.empty()) 1174 { 1175 return dependency.MinVersion == Utility::Version{ minVersion }; 1176 } 1177 else 1178 { 1179 return true; 1180 } 1181 } 1182 } 1183 return false; 1184 } 1185 1186 size_t DependencyList::Size() 1187 { 1188 return m_dependencies.size(); 1189 } 1190 1191 void DependencyList::ApplyToType(DependencyType type, std::function<void(const Dependency&)> func) const 1192 { 1193 for (const auto& dependency : m_dependencies) 1194 { 1195 if (dependency.Type == type) func(dependency); 1196 } 1197 } 1198 1199 void DependencyList::ApplyToAll(std::function<void(const Dependency&)> func) const 1200 { 1201 for (const auto& dependency : m_dependencies) 1202 { 1203 func(dependency); 1204 } 1205 } 1206 1207 bool DependencyList::Empty() const 1208 { 1209 return m_dependencies.empty(); 1210 } 1211 1212 void DependencyList::Clear() { m_dependencies.clear(); } 1213 }