Exports.cpp (24075B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "WinGetUtil.h" 5 6 #include <AppInstallerDownloader.h> 7 #include <AppInstallerFileLogger.h> 8 #include <AppInstallerLogging.h> 9 #include <AppInstallerStrings.h> 10 #include <AppInstallerTelemetry.h> 11 #include <Microsoft/SQLiteIndex.h> 12 #include <winget/ManifestYamlParser.h> 13 #include <winget/ThreadGlobals.h> 14 #include <winget/InstallerMetadataCollectionContext.h> 15 #include <PackageDependenciesValidation.h> 16 #include <public/winget/PackageDependenciesValidationUtil.h> 17 #include <ArpVersionValidation.h> 18 19 using namespace AppInstaller::Utility; 20 using namespace AppInstaller::Manifest; 21 using namespace AppInstaller::Repository; 22 using namespace AppInstaller::Repository::Metadata; 23 using namespace AppInstaller::Repository::Microsoft; 24 25 namespace 26 { 27 std::filesystem::path GetPathOrEmpty(WINGET_STRING potentiallyNullPath) 28 { 29 return potentiallyNullPath ? std::filesystem::path{ potentiallyNullPath } : std::filesystem::path{}; 30 } 31 32 SQLiteIndex::Property GetSQLiteIndexProperty(WinGetSQLiteIndexProperty property) 33 { 34 switch (property) 35 { 36 case WinGetSQLiteIndexProperty_PackageUpdateTrackingBaseTime: return SQLiteIndex::Property::PackageUpdateTrackingBaseTime; 37 case WinGetSQLiteIndexProperty_IntermediateFileOutputPath: return SQLiteIndex::Property::IntermediateFileOutputPath; 38 } 39 40 THROW_HR(E_INVALIDARG); 41 } 42 } 43 44 extern "C" 45 { 46 WINGET_UTIL_API WinGetLoggingInit(WINGET_STRING logPath) try 47 { 48 THROW_HR_IF(E_INVALIDARG, !logPath); 49 50 thread_local AppInstaller::ThreadLocalStorage::WingetThreadGlobals threadGlobals; 51 thread_local std::once_flag initLogging; 52 53 std::call_once(initLogging, []() { 54 std::unique_ptr<AppInstaller::ThreadLocalStorage::PreviousThreadGlobals> previous = threadGlobals.SetForCurrentThread(); 55 // Intentionally release to leave the local ThreadGlobals. 56 previous.release(); 57 // Enable all logs for now. 58 AppInstaller::Logging::Log().SetEnabledChannels(AppInstaller::Logging::Channel::All); 59 AppInstaller::Logging::Log().SetLevel(AppInstaller::Logging::Level::Verbose); 60 AppInstaller::Logging::EnableWilFailureTelemetry(); 61 }); 62 63 std::filesystem::path pathAsPath = logPath; 64 std::string loggerName = AppInstaller::Logging::FileLogger::GetNameForPath(pathAsPath); 65 66 if (!AppInstaller::Logging::Log().ContainsLogger(loggerName)) 67 { 68 // Let FileLogger use default file prefix 69 AppInstaller::Logging::FileLogger::Add(pathAsPath); 70 } 71 72 return S_OK; 73 } 74 CATCH_RETURN() 75 76 WINGET_UTIL_API WinGetLoggingTerm(WINGET_STRING logPath) try 77 { 78 if (logPath) 79 { 80 std::string loggerName = AppInstaller::Logging::FileLogger::GetNameForPath(logPath); 81 (void)AppInstaller::Logging::Log().RemoveLogger(loggerName); 82 } 83 else 84 { 85 AppInstaller::Logging::Log().RemoveAllLoggers(); 86 } 87 88 return S_OK; 89 } 90 CATCH_RETURN() 91 92 WINGET_UTIL_API WinGetSQLiteIndexCreate(WINGET_STRING filePath, UINT32 majorVersion, UINT32 minorVersion, WINGET_SQLITE_INDEX_HANDLE* index) try 93 { 94 THROW_HR_IF(E_INVALIDARG, !filePath); 95 THROW_HR_IF(E_INVALIDARG, !index); 96 THROW_HR_IF(E_INVALIDARG, !!*index); 97 98 std::string filePathUtf8 = ConvertToUTF8(filePath); 99 AppInstaller::SQLite::Version internalVersion{ majorVersion, minorVersion }; 100 101 std::unique_ptr<SQLiteIndex> result = std::make_unique<SQLiteIndex>(SQLiteIndex::CreateNew(filePathUtf8, internalVersion)); 102 103 *index = static_cast<WINGET_SQLITE_INDEX_HANDLE>(result.release()); 104 105 return S_OK; 106 } 107 CATCH_RETURN() 108 109 WINGET_UTIL_API WinGetSQLiteIndexOpen(WINGET_STRING filePath, WINGET_SQLITE_INDEX_HANDLE* index) try 110 { 111 THROW_HR_IF(E_INVALIDARG, !filePath); 112 THROW_HR_IF(E_INVALIDARG, !index); 113 THROW_HR_IF(E_INVALIDARG, !!*index); 114 115 std::string filePathUtf8 = ConvertToUTF8(filePath); 116 117 std::unique_ptr<SQLiteIndex> result = std::make_unique<SQLiteIndex>(SQLiteIndex::Open(filePathUtf8, SQLiteIndex::OpenDisposition::ReadWrite)); 118 119 *index = static_cast<WINGET_SQLITE_INDEX_HANDLE>(result.release()); 120 121 return S_OK; 122 } 123 CATCH_RETURN() 124 125 WINGET_UTIL_API WinGetSQLiteIndexClose(WINGET_SQLITE_INDEX_HANDLE index) try 126 { 127 std::unique_ptr<SQLiteIndex> toClose(reinterpret_cast<SQLiteIndex*>(index)); 128 129 return S_OK; 130 } 131 CATCH_RETURN() 132 133 WINGET_UTIL_API WinGetSQLiteIndexMigrate( 134 WINGET_SQLITE_INDEX_HANDLE index, 135 UINT32 majorVersion, 136 UINT32 minorVersion) try 137 { 138 THROW_HR_IF(E_INVALIDARG, !index); 139 140 return reinterpret_cast<SQLiteIndex*>(index)->MigrateTo({ majorVersion, minorVersion }) ? S_OK : HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); 141 } 142 CATCH_RETURN() 143 144 145 WINGET_UTIL_API WinGetSQLiteIndexSetProperty( 146 WINGET_SQLITE_INDEX_HANDLE index, 147 WinGetSQLiteIndexProperty property, 148 WINGET_STRING value) try 149 { 150 THROW_HR_IF(E_INVALIDARG, !index); 151 THROW_HR_IF(E_INVALIDARG, !value); 152 153 std::string valueUtf8 = ConvertToUTF8(value); 154 155 reinterpret_cast<SQLiteIndex*>(index)->SetProperty(GetSQLiteIndexProperty(property), valueUtf8); 156 157 return S_OK; 158 } 159 CATCH_RETURN() 160 161 WINGET_UTIL_API WinGetSQLiteIndexAddManifest( 162 WINGET_SQLITE_INDEX_HANDLE index, 163 WINGET_STRING manifestPath, WINGET_STRING relativePath) try 164 { 165 THROW_HR_IF(E_INVALIDARG, !index); 166 THROW_HR_IF(E_INVALIDARG, !manifestPath); 167 THROW_HR_IF(E_INVALIDARG, !relativePath); 168 169 reinterpret_cast<SQLiteIndex*>(index)->AddManifest(manifestPath, relativePath); 170 171 return S_OK; 172 } 173 CATCH_RETURN() 174 175 WINGET_UTIL_API WinGetSQLiteIndexUpdateManifest( 176 WINGET_SQLITE_INDEX_HANDLE index, 177 WINGET_STRING manifestPath, 178 WINGET_STRING relativePath, 179 BOOL* indexModified) try 180 { 181 THROW_HR_IF(E_INVALIDARG, !index); 182 THROW_HR_IF(E_INVALIDARG, !manifestPath); 183 THROW_HR_IF(E_INVALIDARG, !relativePath); 184 185 bool result = reinterpret_cast<SQLiteIndex*>(index)->UpdateManifest(manifestPath, relativePath); 186 if (indexModified) 187 { 188 *indexModified = (result ? TRUE : FALSE); 189 } 190 191 return S_OK; 192 } 193 CATCH_RETURN() 194 195 WINGET_UTIL_API WinGetSQLiteIndexAddOrUpdateManifest( 196 WINGET_SQLITE_INDEX_HANDLE index, 197 WINGET_STRING manifestPath, 198 WINGET_STRING relativePath, 199 BOOL* indexModified) try 200 { 201 THROW_HR_IF(E_INVALIDARG, !index); 202 THROW_HR_IF(E_INVALIDARG, !manifestPath); 203 THROW_HR_IF(E_INVALIDARG, !relativePath); 204 205 bool result = reinterpret_cast<SQLiteIndex*>(index)->AddOrUpdateManifest(manifestPath, relativePath); 206 if (indexModified) 207 { 208 *indexModified = (result ? TRUE : FALSE); 209 } 210 211 return S_OK; 212 } 213 CATCH_RETURN() 214 215 WINGET_UTIL_API WinGetSQLiteIndexRemoveManifest( 216 WINGET_SQLITE_INDEX_HANDLE index, 217 WINGET_STRING manifestPath, 218 WINGET_STRING relativePath) try 219 { 220 THROW_HR_IF(E_INVALIDARG, !index); 221 THROW_HR_IF(E_INVALIDARG, !manifestPath); 222 THROW_HR_IF(E_INVALIDARG, !relativePath); 223 224 reinterpret_cast<SQLiteIndex*>(index)->RemoveManifest(manifestPath, relativePath); 225 226 return S_OK; 227 } 228 CATCH_RETURN() 229 230 WINGET_UTIL_API WinGetSQLiteIndexPrepareForPackaging( 231 WINGET_SQLITE_INDEX_HANDLE index) try 232 { 233 THROW_HR_IF(E_INVALIDARG, !index); 234 235 reinterpret_cast<SQLiteIndex*>(index)->PrepareForPackaging(); 236 237 return S_OK; 238 } 239 CATCH_RETURN() 240 241 WINGET_UTIL_API WinGetSQLiteIndexCheckConsistency( 242 WINGET_SQLITE_INDEX_HANDLE index, 243 BOOL* succeeded) try 244 { 245 THROW_HR_IF(E_INVALIDARG, !index); 246 THROW_HR_IF(E_INVALIDARG, !succeeded); 247 248 auto sqliteIndex = reinterpret_cast<SQLiteIndex*>(index); 249 bool result = sqliteIndex->CheckConsistency(true); 250 251 *succeeded = (result ? TRUE : FALSE); 252 253 return S_OK; 254 } 255 CATCH_RETURN() 256 257 WINGET_UTIL_API WinGetValidateManifest( 258 WINGET_STRING manifestPath, 259 BOOL* succeeded, 260 WINGET_STRING_OUT* message) try 261 { 262 THROW_HR_IF(E_INVALIDARG, !manifestPath); 263 THROW_HR_IF(E_INVALIDARG, !succeeded); 264 265 try 266 { 267 ManifestValidateOption validateOption; 268 validateOption.FullValidation = true; 269 validateOption.ThrowOnWarning = true; 270 271 (void)YamlParser::CreateFromPath(manifestPath, validateOption); 272 273 *succeeded = TRUE; 274 } 275 catch (const ManifestException& e) 276 { 277 *succeeded = e.IsWarningOnly(); 278 if (message) 279 { 280 *message = ::SysAllocString(ConvertToUTF16(e.GetManifestErrorMessage()).c_str()); 281 } 282 } 283 284 return S_OK; 285 } 286 CATCH_RETURN() 287 288 WINGET_UTIL_API WinGetValidateManifestV2( 289 WINGET_STRING inputPath, 290 BOOL* succeeded, 291 WINGET_STRING_OUT* message, 292 WINGET_STRING mergedManifestPath, 293 WinGetValidateManifestOption option) try 294 { 295 THROW_HR_IF(E_INVALIDARG, !inputPath); 296 THROW_HR_IF(E_INVALIDARG, !succeeded); 297 298 try 299 { 300 ManifestValidateOption validateOption; 301 validateOption.FullValidation = true; 302 validateOption.ThrowOnWarning = true; 303 validateOption.SchemaValidationOnly = WI_IsFlagSet(option, WinGetValidateManifestOption::SchemaValidationOnly); 304 validateOption.ErrorOnVerifiedPublisherFields = WI_IsFlagSet(option, WinGetValidateManifestOption::ErrorOnVerifiedPublisherFields); 305 validateOption.InstallerValidation = WI_IsFlagSet(option, WinGetValidateManifestOption::InstallerValidations); 306 307 (void)YamlParser::CreateFromPath(inputPath, validateOption, mergedManifestPath ? mergedManifestPath : L""); 308 309 *succeeded = TRUE; 310 } 311 catch (const ManifestException& e) 312 { 313 *succeeded = e.IsWarningOnly(); 314 if (message) 315 { 316 *message = ::SysAllocString(ConvertToUTF16(e.GetManifestErrorMessage()).c_str()); 317 } 318 } 319 320 return S_OK; 321 } 322 CATCH_RETURN() 323 324 WINGET_UTIL_API WinGetCreateManifest( 325 WINGET_STRING inputPath, 326 BOOL* succeeded, 327 WINGET_MANIFEST_HANDLE* manifest, 328 WINGET_STRING_OUT* message, 329 WINGET_STRING mergedManifestPath, 330 WinGetCreateManifestOption option) try 331 { 332 THROW_HR_IF(E_INVALIDARG, !inputPath); 333 THROW_HR_IF(E_INVALIDARG, !succeeded); 334 THROW_HR_IF(E_INVALIDARG, !!*manifest); 335 // ErrorOnVerifiedPublisherFields can only be used with SchemaAndSemanticValidation 336 THROW_HR_IF(E_INVALIDARG, (WI_IsFlagSet(option, WinGetCreateManifestOption::ReturnErrorOnVerifiedPublisherFields) && WI_IsFlagClear(option, WinGetCreateManifestOption::SchemaAndSemanticValidation))); 337 338 *succeeded = false; 339 *manifest = nullptr; 340 341 try 342 { 343 ManifestValidateOption validateOption; 344 345 if (WI_IsFlagSet(option, WinGetCreateManifestOption::SchemaValidation) || WI_IsFlagSet(option, WinGetCreateManifestOption::SchemaAndSemanticValidation)) 346 { 347 validateOption.FullValidation = true; 348 validateOption.ThrowOnWarning = true; 349 validateOption.SchemaValidationOnly = WI_IsFlagClear(option, WinGetCreateManifestOption::SchemaAndSemanticValidation); 350 validateOption.ErrorOnVerifiedPublisherFields = WI_IsFlagSet(option, WinGetCreateManifestOption::ReturnErrorOnVerifiedPublisherFields); 351 } 352 353 if (WI_IsFlagSet(option, WinGetCreateManifestOption::AllowShadowManifest)) 354 { 355 validateOption.AllowShadowManifest = true; 356 } 357 358 std::unique_ptr<Manifest> result = std::make_unique<Manifest>(YamlParser::CreateFromPath(inputPath, validateOption, mergedManifestPath ? mergedManifestPath : L"")); 359 360 *manifest = static_cast<WINGET_MANIFEST_HANDLE>(result.release()); 361 *succeeded = true; 362 } 363 catch (const ManifestException& e) 364 { 365 *succeeded = e.IsWarningOnly(); 366 if (*succeeded) 367 { 368 ManifestValidateOption validateOption; 369 if (WI_IsFlagSet(option, WinGetCreateManifestOption::AllowShadowManifest)) 370 { 371 validateOption.AllowShadowManifest = true; 372 } 373 374 std::unique_ptr<Manifest> result = std::make_unique<Manifest>(YamlParser::CreateFromPath(inputPath, validateOption)); 375 *manifest = static_cast<WINGET_MANIFEST_HANDLE>(result.release()); 376 } 377 if (message) 378 { 379 *message = ::SysAllocString(ConvertToUTF16(e.GetManifestErrorMessage()).c_str()); 380 } 381 } 382 383 return S_OK; 384 } 385 CATCH_RETURN() 386 387 WINGET_UTIL_API WinGetCloseManifest( 388 WINGET_MANIFEST_HANDLE manifest) try 389 { 390 THROW_HR_IF(E_INVALIDARG, !manifest); 391 392 std::unique_ptr<Manifest> toClose{ reinterpret_cast<Manifest*>(manifest) }; 393 394 return S_OK; 395 } 396 CATCH_RETURN() 397 398 WINGET_UTIL_API WinGetValidateManifestV3( 399 WINGET_MANIFEST_HANDLE manifest, 400 WINGET_SQLITE_INDEX_HANDLE index, 401 WinGetValidateManifestResult* result, 402 WINGET_STRING_OUT* message, 403 WinGetValidateManifestOptionV2 option, 404 WinGetValidateManifestOperationType operationType) try 405 { 406 THROW_HR_IF(E_INVALIDARG, !manifest); 407 THROW_HR_IF(E_INVALIDARG, !result); 408 // Index should be provided if DependenciesValidation or ArpVersionValidation is to be performed 409 THROW_HR_IF(E_INVALIDARG, !index && (WI_IsFlagSet(option, WinGetValidateManifestOptionV2::DependenciesValidation) || WI_IsFlagSet(option, WinGetValidateManifestOptionV2::ArpVersionValidation))); 410 THROW_HR_IF(E_INVALIDARG, option == WinGetValidateManifestOptionV2::None); 411 412 *result = WinGetValidateManifestResult::InternalError; 413 414 std::string validationMessage; 415 auto validationResult = WinGetValidateManifestResult::Success; 416 417 Manifest* manifestPtr = reinterpret_cast<Manifest*>(manifest); 418 SQLiteIndex* sqliteIndex = reinterpret_cast<SQLiteIndex*>(index); 419 420 if (WI_IsFlagSet(option, WinGetValidateManifestOptionV2::DependenciesValidation)) 421 { 422 try 423 { 424 if (operationType == WinGetValidateManifestOperationType::OperationTypeDelete) 425 { 426 PackageDependenciesValidation::VerifyDependenciesStructureForManifestDelete(sqliteIndex, *manifestPtr); 427 } 428 else 429 { 430 PackageDependenciesValidation::ValidateManifestDependencies(sqliteIndex, *manifestPtr); 431 } 432 } 433 catch (const ManifestException& e) 434 { 435 if (!e.IsWarningOnly()) 436 { 437 validationResult |= WinGetValidateManifestResult::DependenciesValidationFailure; 438 } 439 440 validationResult |= static_cast<WinGetValidateManifestResult>( AppInstaller::Manifest::GetDependenciesValidationResultFromException(e) ); 441 442 if (message) 443 { 444 validationMessage += e.GetManifestErrorMessage(); 445 } 446 } 447 } 448 449 if (WI_IsFlagSet(option, WinGetValidateManifestOptionV2::ArpVersionValidation)) 450 { 451 try 452 { 453 ValidateManifestArpVersion(sqliteIndex, *manifestPtr); 454 } 455 catch (const ManifestException& e) 456 { 457 WI_SetFlagIf(validationResult, WinGetValidateManifestResult::ArpVersionValidationFailure, !e.IsWarningOnly()); 458 if (message) 459 { 460 validationMessage += e.GetManifestErrorMessage(); 461 } 462 } 463 } 464 465 if (WI_IsFlagSet(option, WinGetValidateManifestOptionV2::InstallerValidation)) 466 { 467 try 468 { 469 auto errors = ValidateManifestInstallers(*manifestPtr); 470 if (errors.size() > 0) 471 { 472 // Throw the errors as ManifestExceptions to get processed errors and message. 473 THROW_EXCEPTION(ManifestException({ std::move(errors) })); 474 } 475 } 476 catch (const ManifestException& e) 477 { 478 WI_SetFlagIf(validationResult, WinGetValidateManifestResult::InstallerValidationFailure, !e.IsWarningOnly()); 479 if (message) 480 { 481 validationMessage += e.GetManifestErrorMessage(); 482 } 483 } 484 } 485 486 *result = validationResult; 487 if (message) 488 { 489 *message = ::SysAllocString(ConvertToUTF16(validationMessage).c_str()); 490 } 491 492 return S_OK; 493 } 494 CATCH_RETURN() 495 496 WINGET_UTIL_API WinGetValidateManifestDependencies( 497 WINGET_STRING inputPath, 498 BOOL* succeeded, 499 WINGET_STRING_OUT* message, 500 WINGET_SQLITE_INDEX_HANDLE index, 501 WinGetValidateManifestDependenciesOption validationOption) try 502 { 503 THROW_HR_IF(E_INVALIDARG, !inputPath); 504 THROW_HR_IF(E_INVALIDARG, !succeeded); 505 506 try 507 { 508 Manifest manifest = YamlParser::CreateFromPath(inputPath); 509 SQLiteIndex* sqliteIndex(reinterpret_cast<SQLiteIndex*>(index)); 510 511 switch (validationOption) 512 { 513 case WinGetValidateManifestDependenciesOption::DefaultValidation: 514 PackageDependenciesValidation::ValidateManifestDependencies(sqliteIndex, manifest); 515 break; 516 case WinGetValidateManifestDependenciesOption::ForDelete: 517 PackageDependenciesValidation::VerifyDependenciesStructureForManifestDelete(sqliteIndex, manifest); 518 break; 519 default: 520 THROW_HR(E_INVALIDARG); 521 } 522 523 *succeeded = TRUE; 524 } 525 catch (const ManifestException& e) 526 { 527 *succeeded = e.IsWarningOnly(); 528 if (message) 529 { 530 *message = ::SysAllocString(ConvertToUTF16(e.GetManifestErrorMessage()).c_str()); 531 } 532 } 533 534 return S_OK; 535 } 536 CATCH_RETURN() 537 538 WINGET_UTIL_API WinGetDownload( 539 WINGET_STRING url, 540 WINGET_STRING filePath, 541 BYTE* sha256Hash, 542 UINT32 sha256HashLength) try 543 { 544 THROW_HR_IF(E_INVALIDARG, !url); 545 THROW_HR_IF(E_INVALIDARG, !filePath); 546 547 bool computeHash = sha256Hash != nullptr && sha256HashLength != 0; 548 THROW_HR_IF(E_INVALIDARG, !computeHash && (sha256Hash != nullptr || sha256HashLength != 0)); 549 THROW_HR_IF(E_INVALIDARG, computeHash && sha256HashLength != 32); 550 551 AppInstaller::ProgressCallback callback; 552 auto downloadResult = Download(ConvertToUTF8(url), filePath, DownloadType::WinGetUtil, callback); 553 554 // At this point, if computeHash is set we have verified that the buffer is valid and 32 bytes. 555 if (computeHash) 556 { 557 const auto& hash = downloadResult.Sha256Hash; 558 559 // The SHA 256 hash length should always be 32 bytes. 560 THROW_HR_IF(E_UNEXPECTED, hash.size() != sha256HashLength); 561 std::copy(hash.begin(), hash.end(), sha256Hash); 562 } 563 564 return S_OK; 565 } 566 CATCH_RETURN() 567 568 WINGET_UTIL_API WinGetCompareVersions( 569 WINGET_STRING versionA, 570 WINGET_STRING versionB, 571 INT* comparisonResult) try 572 { 573 THROW_HR_IF(E_INVALIDARG, !versionA); 574 THROW_HR_IF(E_INVALIDARG, !versionB); 575 576 Version vA{ ConvertToUTF8(versionA) }; 577 Version vB{ ConvertToUTF8(versionB) }; 578 579 *comparisonResult = vA < vB ? -1 : (vA == vB ? 0 : 1); 580 581 return S_OK; 582 } 583 CATCH_RETURN() 584 585 WINGET_UTIL_API WinGetBeginInstallerMetadataCollection( 586 WINGET_STRING inputJSON, 587 WINGET_STRING logFilePath, 588 WinGetBeginInstallerMetadataCollectionOptions options, 589 WINGET_INSTALLER_METADATA_COLLECTION_HANDLE* collectionHandle) try 590 { 591 THROW_HR_IF(E_INVALIDARG, !inputJSON); 592 THROW_HR_IF(E_INVALIDARG, !collectionHandle); 593 THROW_HR_IF(E_INVALIDARG, !!*collectionHandle); 594 // Flags specifying what inputJSON means are mutually exclusive 595 THROW_HR_IF(E_INVALIDARG, !WI_IsClearOrSingleFlagSetInMask(options, 596 WinGetBeginInstallerMetadataCollectionOption_InputIsFilePath | WinGetBeginInstallerMetadataCollectionOption_InputIsURI)); 597 598 std::unique_ptr<InstallerMetadataCollectionContext> result; 599 600 if (WI_IsFlagSet(options, WinGetBeginInstallerMetadataCollectionOption_InputIsFilePath)) 601 { 602 result = InstallerMetadataCollectionContext::FromFile(inputJSON, GetPathOrEmpty(logFilePath)); 603 } 604 else if (WI_IsFlagSet(options, WinGetBeginInstallerMetadataCollectionOption_InputIsURI)) 605 { 606 result = InstallerMetadataCollectionContext::FromURI(inputJSON, GetPathOrEmpty(logFilePath)); 607 } 608 else 609 { 610 result = InstallerMetadataCollectionContext::FromJSON(inputJSON, GetPathOrEmpty(logFilePath)); 611 } 612 613 *collectionHandle = static_cast<WINGET_INSTALLER_METADATA_COLLECTION_HANDLE>(result.release()); 614 615 return S_OK; 616 } 617 CATCH_RETURN() 618 619 WINGET_UTIL_API WinGetCompleteInstallerMetadataCollection( 620 WINGET_INSTALLER_METADATA_COLLECTION_HANDLE collectionHandle, 621 WINGET_STRING outputFilePath, 622 WinGetCompleteInstallerMetadataCollectionOptions options) try 623 { 624 THROW_HR_IF(E_INVALIDARG, !collectionHandle); 625 626 // Since we always free the handle from calling this function, we can just store it in a unique_ptr from the start 627 std::unique_ptr<InstallerMetadataCollectionContext> context{ reinterpret_cast<InstallerMetadataCollectionContext*>(collectionHandle) }; 628 629 if (WI_IsFlagSet(options, WinGetCompleteInstallerMetadataCollectionOption_Abandon)) 630 { 631 return S_OK; 632 } 633 634 THROW_HR_IF(E_INVALIDARG, !outputFilePath); 635 636 context->Complete(outputFilePath); 637 638 return S_OK; 639 } 640 CATCH_RETURN() 641 642 WINGET_UTIL_API WinGetMergeInstallerMetadata( 643 WINGET_STRING inputJSON, 644 WINGET_STRING_OUT* outputJSON, 645 UINT32 maximumOutputSizeInBytes, 646 WINGET_STRING logFilePath, 647 WinGetMergeInstallerMetadataOptions) try 648 { 649 THROW_HR_IF(E_INVALIDARG, !inputJSON); 650 THROW_HR_IF(E_INVALIDARG, !outputJSON); 651 652 std::wstring merged = InstallerMetadataCollectionContext::Merge(inputJSON, maximumOutputSizeInBytes, GetPathOrEmpty(logFilePath)); 653 *outputJSON = ::SysAllocString(merged.c_str()); 654 655 return S_OK; 656 } 657 CATCH_RETURN() 658 }