winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ConfigurationSetSerializer_0_3.cpp (12456B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "ConfigurationSetSerializer_0_3.h"
      5 #include "ArgumentValidation.h"
      6 #include "ConfigurationSetParser_0_3.h"
      7 #include "ConfigurationSetUtilities.h"
      8 #include "ConfigurationEnvironment.h"
      9 #include <AppInstallerErrors.h>
     10 #include <AppInstallerStrings.h>
     11 
     12 using namespace AppInstaller::Utility;
     13 using namespace AppInstaller::YAML;
     14 using namespace winrt::Windows::Foundation;
     15 
     16 namespace winrt::Microsoft::Management::Configuration::implementation
     17 {
     18     namespace
     19     {
     20         Windows::Foundation::Collections::ValueSet GetWingetProcessorMetadataValueSet(Windows::Foundation::Collections::ValueSet& metadata)
     21         {
     22             Windows::Foundation::Collections::ValueSet result = nullptr;
     23             hstring processorMetadataKey = GetConfigurationFieldNameHString(ConfigurationField::ProcessorMetadata);
     24 
     25             if (metadata)
     26             {
     27                 Windows::Foundation::IInspectable processorMetadataObject = metadata.TryLookup(processorMetadataKey);
     28                 if (processorMetadataObject)
     29                 {
     30                     result = processorMetadataObject.try_as<Windows::Foundation::Collections::ValueSet>();
     31                     THROW_HR_IF(WINGET_CONFIG_ERROR_INVALID_FIELD_VALUE, !result);
     32                 }
     33             }
     34             else
     35             {
     36                 metadata = Collections::ValueSet{};
     37             }
     38 
     39             if (!result)
     40             {
     41                 result = Collections::ValueSet{};
     42                 metadata.Insert(processorMetadataKey, result);
     43             }
     44 
     45             return result;
     46         }
     47 
     48         Windows::Foundation::Collections::ValueSet CreateValueSetFromStringMap(const Windows::Foundation::Collections::IMap<hstring, hstring>& map)
     49         {
     50             Windows::Foundation::Collections::ValueSet result;
     51             if (map)
     52             {
     53                 for (const auto& item : map)
     54                 {
     55                     result.Insert(item.Key(), PropertyValue::CreateString(item.Value()));
     56                 }
     57             }
     58             return result;
     59         }
     60 
     61         void AddEnvironmentToMetadata(
     62             Windows::Foundation::Collections::ValueSet& metadata,
     63             SecurityContext context,
     64             hstring processor,
     65             Windows::Foundation::Collections::IMap<hstring, hstring> properties,
     66             SecurityContext defaultContext = SecurityContext::Current,
     67             hstring defaultProcessor = {},
     68             Windows::Foundation::Collections::IMap<hstring, hstring> defaultProperties = nullptr)
     69         {
     70             if (context != defaultContext)
     71             {
     72                 if (!metadata)
     73                 {
     74                     metadata = Collections::ValueSet{};
     75                 }
     76 
     77                 metadata.Insert(GetConfigurationFieldNameHString(ConfigurationField::SecurityContextMetadata), PropertyValue::CreateString(ToWString(context)));
     78             }
     79 
     80             Windows::Foundation::Collections::ValueSet processorValueSet{ nullptr };
     81 
     82             if (processor != defaultProcessor)
     83             {
     84                 if (!processorValueSet)
     85                 {
     86                     processorValueSet = GetWingetProcessorMetadataValueSet(metadata);
     87                 }
     88 
     89                 processorValueSet.Insert(GetConfigurationFieldNameHString(ConfigurationField::ProcessorIdentifierMetadata), PropertyValue::CreateString(processor));
     90             }
     91 
     92             if (!ConfigurationEnvironment::AreEqual(properties, defaultProperties))
     93             {
     94                 if (!processorValueSet)
     95                 {
     96                     processorValueSet = GetWingetProcessorMetadataValueSet(metadata);
     97                 }
     98 
     99                 processorValueSet.Insert(GetConfigurationFieldNameHString(ConfigurationField::ProcessorPropertiesMetadata), CreateValueSetFromStringMap(properties));
    100             }
    101         }
    102 
    103         void AddEnvironmentToMetadata(
    104             Windows::Foundation::Collections::ValueSet& metadata,
    105             const com_ptr<implementation::ConfigurationEnvironment>& environment)
    106         {
    107             if (environment)
    108             {
    109                 AddEnvironmentToMetadata(metadata, environment->Context(), environment->ProcessorIdentifier(), environment->ProcessorProperties());
    110             }
    111         }
    112 
    113         void AddEnvironmentToMetadata(
    114             Windows::Foundation::Collections::ValueSet& metadata,
    115             const Configuration::ConfigurationEnvironment& environment)
    116         {
    117             AddEnvironmentToMetadata(metadata,
    118                 environment.Context(), environment.ProcessorIdentifier(), environment.ProcessorProperties());
    119         }
    120     }
    121 
    122     hstring ConfigurationSetSerializer_0_3::Serialize(ConfigurationSet* configurationSet)
    123     {
    124         Emitter emitter;
    125 
    126         emitter << BeginMap;
    127 
    128         emitter << Key << GetConfigurationFieldName(ConfigurationField::Schema) << Value << ConvertToUTF8(configurationSet->SchemaUri().ToString());
    129 
    130         // Prepare an override if necessary
    131         Collections::ValueSet wingetMetadataOverride = nullptr;
    132         AddEnvironmentToMetadata(wingetMetadataOverride, configurationSet->EnvironmentInternal());
    133 
    134         WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Metadata, configurationSet->Metadata(),
    135             {
    136                 { ConfigurationField::WingetMetadataRoot, wingetMetadataOverride },
    137                 { ConfigurationField::SecurityContextMetadata, nullptr },
    138             });
    139 
    140         WriteYamlParameters(emitter, configurationSet->Parameters());
    141         WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Variables, configurationSet->Variables());
    142         WriteYamlConfigurationUnits(emitter, configurationSet->Units());
    143 
    144         emitter << EndMap;
    145 
    146         std::wostringstream result;
    147         result << GetSchemaVersionCommentPrefix() << static_cast<std::wstring_view>(configurationSet->SchemaVersion()) << L"\n" << ConvertToUTF16(emitter.str());
    148         return hstring{ std::move(result).str() };
    149     }
    150 
    151     std::string ConfigurationSetSerializer_0_3::SerializeMetadataWithEnvironment(const Windows::Foundation::Collections::ValueSet& metadata, const Configuration::ConfigurationEnvironment& environment)
    152     {
    153         Emitter emitter;
    154 
    155         Collections::ValueSet wingetMetadataOverride = nullptr;
    156         AddEnvironmentToMetadata(wingetMetadataOverride, environment);
    157 
    158         WriteYamlValueSet(emitter, metadata,
    159             {
    160                 { ConfigurationField::WingetMetadataRoot, wingetMetadataOverride },
    161                 { ConfigurationField::SecurityContextMetadata, nullptr },
    162             });
    163 
    164         return emitter.str();
    165     }
    166 
    167     void ConfigurationSetSerializer_0_3::WriteYamlParameters(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::IVector<Configuration::ConfigurationParameter>& values)
    168     {
    169         if (!values || values.Size() == 0)
    170         {
    171             return;
    172         }
    173 
    174         emitter << Key << GetConfigurationFieldName(ConfigurationField::Parameters);
    175 
    176         emitter << BeginMap;
    177 
    178         for (const Configuration::ConfigurationParameter& parameter : values)
    179         {
    180             emitter << Key << ConvertToUTF8(parameter.Name());
    181 
    182             emitter << BeginMap;
    183 
    184             auto type = parameter.Type();
    185 
    186             emitter << Key << GetConfigurationFieldName(ConfigurationField::Type) << Value << ToString(type, parameter.IsSecure());
    187             WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Metadata, parameter.Metadata());
    188             WriteYamlStringValueIfNotEmpty(emitter, ConfigurationField::Description, parameter.Description());
    189             WriteYamlValueIfNotEmpty(emitter, ConfigurationField::DefaultValue, parameter.DefaultValue());
    190 
    191             auto allowedValues = parameter.AllowedValues();
    192             if (allowedValues && allowedValues.Size() != 0)
    193             {
    194                 emitter << Key << GetConfigurationFieldName(ConfigurationField::AllowedValues);
    195 
    196                 emitter << BeginSeq;
    197 
    198                 for (const auto& value : allowedValues)
    199                 {
    200                     emitter << Value;
    201                     WriteYamlValue(emitter, value);
    202                 }
    203 
    204                 emitter << EndSeq;
    205             }
    206 
    207             if (IsLengthType(type))
    208             {
    209                 uint32_t minimumLength = parameter.MinimumLength();
    210                 if (minimumLength != 0)
    211                 {
    212                     emitter << Key << GetConfigurationFieldName(ConfigurationField::MinimumLength) << Value << static_cast<int64_t>(minimumLength);
    213                 }
    214 
    215                 uint32_t maximumLength = parameter.MaximumLength();
    216                 if (maximumLength != std::numeric_limits<uint32_t>::max())
    217                 {
    218                     emitter << Key << GetConfigurationFieldName(ConfigurationField::MaximumLength) << Value << static_cast<int64_t>(maximumLength);
    219                 }
    220             }
    221 
    222             if (IsComparableType(type))
    223             {
    224                 WriteYamlValueIfNotEmpty(emitter, ConfigurationField::MinimumValue, parameter.MinimumValue());
    225                 WriteYamlValueIfNotEmpty(emitter, ConfigurationField::MaximumValue, parameter.MaximumValue());
    226             }
    227 
    228             emitter << EndMap;
    229         }
    230 
    231         emitter << EndMap;
    232     }
    233 
    234     void ConfigurationSetSerializer_0_3::WriteYamlConfigurationUnits(
    235         AppInstaller::YAML::Emitter& emitter,
    236         const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& values)
    237     {
    238         emitter << Key << GetConfigurationFieldName(ConfigurationField::Resources);
    239 
    240         emitter << BeginSeq;
    241 
    242         for (const Configuration::ConfigurationUnit& unit : values)
    243         {
    244             emitter << BeginMap;
    245 
    246             hstring identifier = unit.Identifier();
    247             THROW_HR_IF(WINGET_CONFIG_ERROR_MISSING_FIELD, identifier.empty());
    248             emitter << Key << GetConfigurationFieldName(ConfigurationField::Name) << Value << ConvertToUTF8(identifier);
    249 
    250             hstring type = unit.Type();
    251             THROW_HR_IF(WINGET_CONFIG_ERROR_MISSING_FIELD, type.empty());
    252             emitter << Key << GetConfigurationFieldName(ConfigurationField::Type) << Value << ConvertToUTF8(type);
    253 
    254             // Prepare an override if necessary
    255             Collections::ValueSet wingetMetadataOverride = nullptr;
    256             Configuration::ConfigurationEnvironment unitEnvironment = unit.Environment();
    257             AddEnvironmentToMetadata(wingetMetadataOverride, unitEnvironment);
    258 
    259             WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Metadata, unit.Metadata(),
    260                 { { ConfigurationField::WingetMetadataRoot, wingetMetadataOverride } });
    261 
    262             auto dependencies = unit.Dependencies();
    263             if (dependencies && dependencies.Size() != 0)
    264             {
    265                 emitter << Key << GetConfigurationFieldName(ConfigurationField::DependsOn);
    266 
    267                 emitter << BeginSeq;
    268 
    269                 for (const auto& value : dependencies)
    270                 {
    271                     emitter << ConvertToUTF8(value);
    272                 }
    273 
    274                 emitter << EndSeq;
    275             }
    276 
    277             // If this unit is a group, write the units directly
    278             if (unit.IsGroup())
    279             {
    280                 auto groupUnits = unit.Units();
    281 
    282                 if (groupUnits.Size() != 0)
    283                 {
    284                     emitter << Key << GetConfigurationFieldName(ConfigurationField::Properties);
    285                     emitter << BeginMap;
    286 
    287                     // Write everything but the resources
    288                     WriteYamlValueSetValues(emitter, unit.Settings(),
    289                         { { ConfigurationField::Resources, nullptr } });
    290 
    291                     // Write the resources from the individual units
    292                     WriteYamlConfigurationUnits(emitter, groupUnits);
    293 
    294                     emitter << EndMap;
    295                 }
    296             }
    297             else
    298             {
    299                 WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Properties, unit.Settings());
    300             }
    301 
    302             emitter << EndMap;
    303         }
    304 
    305         emitter << EndSeq;
    306     }
    307 }