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 }