Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
213fb1d
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 2, 2026
8b7643b
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 6, 2026
ee55e0e
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 9, 2026
b87f3d9
Merge branch 'release/2.0-experimental' into darc-release/2.0-experim…
v-arlysenko Jun 15, 2026
d570a23
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 17, 2026
fa67915
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 22, 2026
24c6f25
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 29, 2026
49e86f9
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jun 30, 2026
29aa8e4
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 1, 2026
f40a285
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 5, 2026
5612a29
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 9, 2026
b104e95
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 9, 2026
ca35527
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 13, 2026
e7f0cc7
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 16, 2026
355854f
Containment v2: drop obsolete patchVersion/WinAppSDK_Security templat…
agniuks Jul 20, 2026
a9638f9
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 20, 2026
75ec31c
Update dependencies from https://dev.azure.com/microsoft/LiftedIXP/_g…
dotnet-maestro[bot] Jul 21, 2026
bde5355
Containment v2: port RuntimeCompatibilityOptions foundation to releas…
agniuks Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev/ApplicationData/M.W.S.ApplicationData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <FrameworkUdk/Containment.h>

// 61684930: [2.0 servicing] WindowsAppSDK: Microsoft.Windows.Storage.ApplicationData.GetForUnpackaged()
#define WINAPPSDK_CHANGEID_61684930 61684930, WinAppSDK_2_1_5
#define WINAPPSDK_CHANGEID_61684930 61684930

static_assert(static_cast<int32_t>(winrt::Microsoft::Windows::Storage::ApplicationDataLocality::Local) == static_cast<int32_t>(winrt::Windows::Storage::ApplicationDataLocality::Local));
static_assert(static_cast<int32_t>(winrt::Microsoft::Windows::Storage::ApplicationDataLocality::LocalCache) == static_cast<int32_t>(winrt::Windows::Storage::ApplicationDataLocality::LocalCache));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <AppModel.Identity.IsPackagedProcess.h>

// Bug 62382643: Fix sparse-packaged apps unable to discover module-specific PRI files
#define WINAPPSDK_CHANGEID_62382643 62382643, WinAppSDK_2_1_5
#define WINAPPSDK_CHANGEID_62382643 62382643

bool IsResourceNotFound(HRESULT hr)
{
Expand Down
243 changes: 237 additions & 6 deletions dev/RuntimeCompatibilityOptions/RuntimeCompatibilityOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,193 @@
#include "Microsoft.Windows.ApplicationModel.WindowsAppRuntime.RuntimeCompatibilityOptions.g.cpp"
#include "AssemblyInfo.h"
#include <FrameworkUdk/Containment.h>
#include <algorithm>

namespace
{
// Per-release groups of WinAppSDK contained change IDs. Each group's
// releaseVersion is the patch release in which the contained change first
// shipped. RuntimeCompatibilityOptions::Apply() walks the active catalog at
// startup and pre-prunes (adds to the disabled list) any group whose
// releaseVersion is greater than the runtime's effective patch level.
//
// Release engineering: at branch cut, add a new release group to
// s_catalogGroupsProd below for any new WINAPPSDK_CHANGE_* IDs that landed
// in os.2020 FrameworkUdk Containment.h since the previous branch.
//
// Servicing engineers do NOT edit this file. They only add the
// #define WINAPPSDK_CHANGE_FOO id macro in their component source.
// Release engineering performs the catalog roll-up.
//
// The WinAppSDK_Security pseudo-version is reserved for security fixes -
// entries in a security group are catalog-tracked but are never
// auto-disabled by Apply's pre-prune walk because their releaseVersion (0)
// is never greater than any effective patch level.
//
// WinAppSDKReleaseVersion is defined locally here (rather than alongside
// FrameworkUdk's Containment.h enum) to break the per-release maintenance
// coupling between FrUdk and Foundation. It is named WinAppSDKReleaseVersion
// rather than WinAppSDKPatchVersion to avoid colliding with the legacy
// unscoped enum type name still exposed by older Containment.h headers
// (renamed there to WinAppSDKPatchVersionDeprecated in newer FrUdk
// revisions). The scoped enum keeps all release-version constants
// (WinAppSDK_Latest, WinAppSDK_Security, and per-release WinAppSDK_M_m_p
// values added by release engineering as the catalog grows) confined to
// this translation unit; no other component should reference them.
// WinAppSDKReleaseVersionFromValues mirrors the historical
// WinAppSDKPatchVersionFromValues encoding (major*1000000 + minor*1000 + patch)
// so the WindowsAppRuntimeVersion -> WinAppSDKReleaseVersion conversion
// is consistent with the encoding release engineering uses when adding
// new per-release enumerators below.
constexpr UINT32 WinAppSDKReleaseVersionFromValues(UINT32 major, UINT32 minor, UINT32 patch)
{
return (major * 1000000) + (minor * 1000) + patch;
}

enum class WinAppSDKReleaseVersion : UINT32
{
WinAppSDK_2_1_0 = WinAppSDKReleaseVersionFromValues(2, 1, 0),
WinAppSDK_2_1_5 = WinAppSDKReleaseVersionFromValues(2, 1, 5),
WinAppSDK_2_3_0 = WinAppSDKReleaseVersionFromValues(2, 3, 0),
WinAppSDK_Latest = 999999999,
WinAppSDK_Security = 0,
};

struct CatalogGroup
{
const UINT32* changes;
UINT32 count;
WinAppSDKReleaseVersion releaseVersion;
};

template <size_t N>
constexpr CatalogGroup MakeGroup(const UINT32(&arr)[N], WinAppSDKReleaseVersion v)
{
return { arr, static_cast<UINT32>(N), v };
}

// Test-only catalog. Activated by ContainmentTestInitialize(true). Holds
// two groups whose releaseVersion straddles the runtime's effective
// patch level under the default WinAppSDKRuntimeConfiguration (Apply
// resolves an unspecified patch level to WinAppSDKReleaseVersion::WinAppSDK_Latest).
// Together they exercise both branches of Apply's pre-prune walk and
// span the changeId value range so that std::sort (Apply) and
// std::binary_search (FrUdk worker) are probed at both ends:
//
// * s_enabled_changes_test is pinned at WinAppSDK_Latest - 1, so
// its releaseVersion is NOT greater than the effective patch level.
// Apply prunes the group OUT of disabledChanges; these IDs remain
// ENABLED at runtime. {1, 2, 3} = small-end IDs that must not
// appear in the final sorted disabledChanges set.
//
// * s_disabled_changes_test is pinned at WinAppSDK_Latest + 1, so
// its releaseVersion IS greater than the effective patch level.
// Apply preserves the group IN disabledChanges; these IDs are
// DISABLED at runtime. {0, 99999999} = smallest representable ID
// and a high-value sentinel; they must appear in the final sorted
// disabledChanges set.
//
// Unit tests call IsChangeEnabled<id>() (the 1-argument form) so the
// catalog pre-prune is the only mechanism that disables changes.
// Production callsites must not reference 0, 1, 2, 3, or 99999999.
constexpr UINT32 s_enabled_changes_test[] = { 1, 2, 3 };
constexpr UINT32 s_disabled_changes_test[] = { 0, 99999999 };
constexpr CatalogGroup s_catalogGroupsTest[] = {
MakeGroup(s_enabled_changes_test,
static_cast<WinAppSDKReleaseVersion>(static_cast<UINT32>(WinAppSDKReleaseVersion::WinAppSDK_Latest) - 1)),
MakeGroup(s_disabled_changes_test,
static_cast<WinAppSDKReleaseVersion>(static_cast<UINT32>(WinAppSDKReleaseVersion::WinAppSDK_Latest) + 1)),
};

// Production catalog for release/2.0-stable. Each per-release group
// collects the contained change IDs that first shipped in that patch
// release. Source of truth: os.2020 FrameworkUdk Containment.h
// (WINAPPSDK_CHANGEID_* macros) and WindowsAppSDK component callsites
// that #define WINAPPSDK_CHANGEID_* macros inline.
constexpr UINT32 s_changes_2_1_0[] = {
61760863, // os.2020: weak ref in implicit animation completion callback
62040515, // os.2020: see Containment.h for description
62147120, // os.2020: UniformGridLayout::GetItemsPerLine floor at 1u
};
constexpr UINT32 s_changes_2_1_5[] = {
61684930, // WindowsAppSDK: ApplicationData.GetForUnpackaged()
61854090, // os.2020: PopulateContactInFrame pen-overrides-touch crash
62134997, // os.2020: lifted DesktopChildSiteBridge smooth resize
62276145, // os.2020: ThemeSettings crash on shutdown off-thread
62382643, // WindowsAppSDK: MRT sparse-packaged module-specific PRI discovery
};
constexpr UINT32 s_changes_2_3_0[] = {
62393567, // CPopupRoot_ReplayPointerUpdateCrash
62406051, // XamlIslandRoot_UiaTeardownReentrancyCrash
62434240, // ModernCollectionBasePanel_StaleViewportAnchorRecycle
62434371, // Popup_RemoveChildIdempotentWhenClosing
62434372, // UIAWindow_PauseNewDispatchOnDisconnectProviders
62434373, // CascadingMenuHelper_DelayOpenTimerTickAfterUnload
62471884, // AcrylicBrush_InitializePropertyInMarkup
62542953, // Xaml_ReserveVectorSpace
62639407, // XamlUICommand_LightweightBindings
62644600, // Xaml_DefaultStyleOptimizations
62645877, // Xaml_ThemeResourceUseResourceKeys
62646974, // Xaml_FasterResourceDictionary
62659855, // Xaml_CachedTypeChecks
62673714, // Xaml_FasterXbfIntLoading
62676756, // Xaml_ActivationFactoryFastPaths
62676766, // XamlUICommand_SkipEmptyKeyboardAcceleratorBinding
62676773, // Xaml_ReduceThemeResourceLookupHashing
62688041, // RefreshRateInfo_RemovePowerNotification
62698635, // ApplicationData_GetForUnpackaged_LocalSettings
62724527, // CustomMetadataTypes_InvalidateUseAfterFree
62724733, // CPopup_OpenSetFocusReentrancy
62724906, // MediaPlayerPresenter_DeviceLostCrash
62725196, // HWBuildGlyphRunTextures_DeviceGuardScope
62725364, // FocusRectManager_FindFocusRectHostCrash
62726703, // Xaml_EagerDeviceRemovedEventRegistration
62738389, // XamlSettings_OptionalChangesApi
62755661, // UniversalBGTask_RunCrash
62759377, // Xaml_OptimizedCommandBarInitialization
62771256, // Flyout_SidePlacementFlipUpAlignmentFix
62774942, // LanguageModel_StructuredJsonOutput
62776273, // Xaml_OptimizedCommandBarFlyoutUpdateCommands
62779870, // XamlInit_GetMuxVersionCompileTime
62784965, // Xaml_IconNoGridOptimization
62786355, // UniformGridLayoutFlowLayout_OnItemsChangedNullLayoutStateCrash
62789076, // Xaml_DeferStylePropertySetters
62818033, // Xaml_LoadDeferredResourceOptimization
62833838, // Xaml_DeferContextFlyoutInit
62847209, // Xaml_DelayApplyStylesAfterCreationComplete
62849414, // Xaml_ReserveTrackerCollectionSpace
62865780, // WindowsML_ExecutionProviderEnumerationUpdate
62917618, // CompositionEngine_API
62927180, // WindowsServices_GetKeyboardModifiersStateRace
62934326, // VideoSuperResolution_HardwareDetection
};
constexpr CatalogGroup s_catalogGroupsProd[] = {
MakeGroup(s_changes_2_1_0, WinAppSDKReleaseVersion::WinAppSDK_2_1_0),
MakeGroup(s_changes_2_1_5, WinAppSDKReleaseVersion::WinAppSDK_2_1_5),
MakeGroup(s_changes_2_3_0, WinAppSDKReleaseVersion::WinAppSDK_2_3_0),
};
constexpr size_t s_catalogGroupsProdCount{ std::size(s_catalogGroupsProd) };

// Active catalog. ContainmentTestInitialize(bool) swaps these pointers
// between the production and test catalogs. Apply() reads them at runtime.
const CatalogGroup* s_catalogGroup{ s_catalogGroupsProd };
size_t s_catalogGroupCount{ s_catalogGroupsProdCount };
}

STDAPI ContainmentTestInitialize(bool enableTest) noexcept try
{
if (enableTest)
{
s_catalogGroup = s_catalogGroupsTest;
s_catalogGroupCount = std::size(s_catalogGroupsTest);
}
else
{
s_catalogGroup = s_catalogGroupsProd;
s_catalogGroupCount = s_catalogGroupsProdCount;
}
return S_OK;
} CATCH_RETURN();

namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation
{
Expand All @@ -28,26 +215,70 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
}
}

// Apply the patch level which applies to the major.minor version, if any.
if (m_patchLevel1.Major == WINDOWSAPPSDK_RELEASE_MAJOR && m_patchLevel1.Minor == WINDOWSAPPSDK_RELEASE_MINOR)
// Resolve the effective patch level for catalog pre-prune. This is owned
// entirely by WinAppSDK now - when the 2.0 branch bumps to a FrUdk that
// exposes only WinAppSDKPatchVersionDeprecated, FrameworkUdk's
// Containment_GetChangeEnabled worker will no longer compare against any
// per-change patch version. The WASDK side is already prepared.
// A default-initialized WindowsAppRuntimeVersion is {0,0,0}; treat that as
// "not set" rather than as a request to pin to 0.0.0. (In production builds
// WINDOWSAPPSDK_RELEASE_MAJOR is > 0 so this case never arises; in dev builds
// the macro is 0/0 and the unset sentinel would otherwise spuriously match.)
WinAppSDKReleaseVersion runtimePatchLevel{ WinAppSDKReleaseVersion::WinAppSDK_Latest };
if (m_patchLevel1.Major == WINDOWSAPPSDK_RELEASE_MAJOR && m_patchLevel1.Minor == WINDOWSAPPSDK_RELEASE_MINOR
&& (m_patchLevel1.Major != 0 || m_patchLevel1.Minor != 0 || m_patchLevel1.Patch != 0))
{
// Apply patch level 1
config.patchVersion = (WinAppSDKPatchVersion)WinAppSDKPatchVersionFromValues(m_patchLevel1.Major, m_patchLevel1.Minor, m_patchLevel1.Patch);
runtimePatchLevel = static_cast<WinAppSDKReleaseVersion>(
WinAppSDKReleaseVersionFromValues(m_patchLevel1.Major, m_patchLevel1.Minor, m_patchLevel1.Patch));
}
else if (m_patchLevel2.Major == WINDOWSAPPSDK_RELEASE_MAJOR && m_patchLevel2.Minor == WINDOWSAPPSDK_RELEASE_MINOR)
else if (m_patchLevel2.Major == WINDOWSAPPSDK_RELEASE_MAJOR && m_patchLevel2.Minor == WINDOWSAPPSDK_RELEASE_MINOR
&& (m_patchLevel2.Major != 0 || m_patchLevel2.Minor != 0 || m_patchLevel2.Patch != 0))
{
// Apply patch level 2
config.patchVersion = (WinAppSDKPatchVersion)WinAppSDKPatchVersionFromValues(m_patchLevel2.Major, m_patchLevel2.Minor, m_patchLevel2.Patch);
runtimePatchLevel = static_cast<WinAppSDKReleaseVersion>(
WinAppSDKReleaseVersionFromValues(m_patchLevel2.Major, m_patchLevel2.Minor, m_patchLevel2.Patch));
}

// Add the set of disabled changes
// Mirror the resolved patch level into the ABI-locked
// WinAppSDKRuntimeConfiguration::patchVersion field as an opaque UINT32
// cast. Containment_GetChangeEnabled does not read it for change
// filtering, but Containment_SetConfiguration uses it as part of the
// identity check that detects attempts to apply a divergent
// configuration twice from the same process.
config.patchVersion = static_cast<decltype(config.patchVersion)>(static_cast<UINT32>(runtimePatchLevel));

// Build the disabled-changes list from two sources:
// (1) The app's explicit DisabledChanges list (unchanged behavior).
// (2) Catalog pre-pruning: every change whose release is newer than the
// effective patch level is treated as disabled, so callsites see
// pre-change behavior on patch-pinned runtimes.
// Duplicates between (1) and (2) are harmless: the FrUdk worker treats
// disabledChanges as a sorted set and uses set-membership semantics.
std::vector<UINT32> disabledChanges;
for (auto changeId : m_disabledChanges)
{
// TODO: Telemetry! Log the changeId that was disabled.
// UINT32 is used internally for the changeId, so cast from the enum's Int32 to that.
disabledChanges.push_back(static_cast<UINT32>(changeId));
}

for (size_t g = 0; g < s_catalogGroupCount; ++g)
{
auto const& group = s_catalogGroup[g];
if (group.releaseVersion > runtimePatchLevel)
{
for (UINT32 i = 0; i < group.count; ++i)
{
disabledChanges.push_back(group.changes[i]);
}
}
}

// FrameworkUdk's Containment_GetChangeEnabled assumes disabledChanges is
// sorted ascending so it can use std::binary_search for O(log N) lookups.
std::sort(disabledChanges.begin(), disabledChanges.end());

config.disabledChanges = disabledChanges.data();
config.disabledChangesCount = static_cast<UINT32>(disabledChanges.size());

Expand Down
2 changes: 2 additions & 0 deletions dev/WindowsAppRuntime_DLL/WindowsAppRuntime.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ EXPORTS
WindowsAppRuntime_VersionInfo_MSIX_Main_PackageFamilyName_Get
WindowsAppRuntime_VersionInfo_TestInitialize

ContainmentTestInitialize

WindowsAppRuntime_EnsureIsLoaded
12 changes: 6 additions & 6 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,25 @@
-->
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.FrameworkUdk" Version="2.0.0-experimental-27200.1024.260527-1035.2">
<Dependency Name="Microsoft.FrameworkUdk" Version="2.1.0-experimental-27200.1040.260719-1733.2">
<Uri>https://dev.azure.com/microsoft/LiftedIXP/_git/DCPP</Uri>
<Sha>bcefb53ef31cde2d4d7e97760db1970335047aed</Sha>
<Sha>3fe865e9c77580e74858a5064b1f079a8cd3b8b5</Sha>
</Dependency>
<Dependency Name="Microsoft.WindowsAppSDK.AppLicensingInternal.TransportPackage" Version="2.0.0-experimental.20260403.0">
<Uri>https://dev.azure.com/microsoft/ProjectReunion/_git/WindowsAppSDKClosed</Uri>
<Sha>4c1df0de1a0025847b63017d0eefd6dc89d685f3</Sha>
</Dependency>
<Dependency Name="Microsoft.ProjectReunion.InteractiveExperiences.TransportPackage" Version="2.0.0-experimental-27200.1024.260527-1035.2">
<Dependency Name="Microsoft.ProjectReunion.InteractiveExperiences.TransportPackage" Version="2.1.0-experimental-27200.1040.260719-1733.2">
<Uri>https://dev.azure.com/microsoft/LiftedIXP/_git/DCPP</Uri>
<Sha>bcefb53ef31cde2d4d7e97760db1970335047aed</Sha>
<Sha>3fe865e9c77580e74858a5064b1f079a8cd3b8b5</Sha>
</Dependency>
<Dependency Name="Microsoft.WindowsAppSDK.Base" Version="2.0.5-experimental2">
<Uri>https://dev.azure.com/microsoft/ProjectReunion/_git/WindowsAppSDKAggregator</Uri>
<Sha>6f349c49ec4dfe60d424d12b3ab1091c06a1428f</Sha>
</Dependency>
<Dependency Name="Microsoft.WindowsAppSDK.InteractiveExperiences" Version="2.0.16-experimental">
<Dependency Name="Microsoft.WindowsAppSDK.InteractiveExperiences" Version="2.1.4-experimental">
<Uri>https://dev.azure.com/microsoft/LiftedIXP/_git/DCPP</Uri>
<Sha>bcefb53ef31cde2d4d7e97760db1970335047aed</Sha>
<Sha>3fe865e9c77580e74858a5064b1f079a8cd3b8b5</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
Expand Down
Loading