Skip to content

[2.0-stable] Gated cherry-pick: MrmGetFilePathFromName S_OK fallback (#6603) - #6612

Merged
Scott Jones (Scottj1s) merged 3 commits into
release/2.0-stablefrom
user/scottj1s/mrm-fallback-2.0-cp
Jul 17, 2026
Merged

[2.0-stable] Gated cherry-pick: MrmGetFilePathFromName S_OK fallback (#6603)#6612
Scott Jones (Scottj1s) merged 3 commits into
release/2.0-stablefrom
user/scottj1s/mrm-fallback-2.0-cp

Conversation

@Scottj1s

Copy link
Copy Markdown
Member

Cherry-picks #6603 into release/2.0-stable, gated behind a RuntimeCompatibilityOptions containment check so apps can disable it.

Background

MrmGetFilePathFromName is documented to always succeed and return a best-effort path even when no PRI file exists. On release/2.0-stable it fails with ERROR_FILE_NOT_FOUND, which makes new ResourceManager() throw when there is no resources.pri (the XAML-island / no-PRI scenario — original issues #5814 / #5940, fixed on main by #6603).

Containment

Because this flips an HRESULT from a failure to S_OK, the change is contained under WINAPPSDK_CHANGEID_63048673:

  • Enabled (default): MrmGetFilePathFromName returns S_OK with a non-null best-effort path (the provided filename, else resources.pri) under the base directory (if set) otherwise the module directory.
  • Disabled (via RuntimeCompatibilityOptions / WindowsAppSDKDisabledChanges): behavior reverts byte-for-byte to current release/2.0-stable (ERROR_FILE_NOT_FOUND). Both terminal search passes jump to Final, skipping the DefaultFallback pass.

The gate is placed in MrmGetFilePathFromName itself, so it contains the public export's HRESULT flip for both ResourceManager and any direct external callers.

Changes

  • MRM.cpp — gate the reachable DefaultFallback pass + S_OK return on IsChangeEnabled<WINAPPSDK_CHANGEID_63048673>(). Adds #include <FrameworkUdk/Containment.h> + an inline #define for the change ID (following the existing 62382643 precedent in Helper.cpp). Preserves the module directory since the parent-folder search mutates exeDir in place.
  • MRM.vcxproj — link the FrameworkUdk Containment worker (targets import + EnsureNuGetPackageBuildImports).
  • MrmUnitTest.vcxproj — deploy Microsoft.Internal.FrameworkUdk.dll next to the test host (mrm.dll now imports it).
  • Helper.cpp (GetDefaultPriFile) — inside the existing 62382643 block, gate the sparse-packaged [modulename].pri fallback on actual file existence (CheckFile) so it still fires once MrmGetFilePathFromName returns S_OK. Correct whether 63048673 is enabled or disabled; preserves 62382643 behavior.
  • MrmTests.cpp — strengthen GetFilePath to assert the fallback path is under the module directory.
  • BypassTests.json — remove the now-passing UnitTest::BasicTest::GetFilePath and MrtCoreUnpackagedTests.TestClass.DefaultResourceManager entries so they gate again.

Note for release engineering

Per the ContainmentV2 model this PR only defines and gates the change ID. Associating 63048673 to a release group in RuntimeCompatibilityOptions.cpp's s_catalogGroupsProd[] is the separate branch-cut step (same as the existing 62382643).

Validation

Built MrtCore.sln native projects (x64 Debug) locally; MrmUnitTest 21/21 (change enabled by default, GetFilePath returns S_OK with a valid module-dir path). Disabled-path behavior is byte-equivalent to current release/2.0-stable by construction. The Helper.cpp logic is identical to #6603, validated 27/27 (incl. DefaultResourceManager) on main.

…/2.0-stable

Cherry-picks PR #6603 into release/2.0-stable, but gates the behavior change
behind a RuntimeCompatibilityOptions containment check so apps can disable it.

MrmGetFilePathFromName is documented to always succeed and return a best-effort
path even when no PRI file exists. On 2.0-stable it fails with
ERROR_FILE_NOT_FOUND, which makes `new ResourceManager()` throw when there is no
resources.pri (the XAML-island / no-PRI scenario).

Because this changes an HRESULT from a failure to S_OK, the change is contained
under WINAPPSDK_CHANGEID_63048673:
- Enabled (default): MrmGetFilePathFromName returns S_OK with a non-null
  best-effort path (the provided filename, else resources.pri) under the base
  directory (if set) otherwise the module directory.
- Disabled (via RuntimeCompatibilityOptions): behavior reverts byte-for-byte to
  the current 2.0-stable behavior (ERROR_FILE_NOT_FOUND). Both terminal search
  passes jump to Final, skipping the DefaultFallback pass.

Changes:
- MRM.cpp: gate the reachable DefaultFallback pass + S_OK return on
  IsChangeEnabled<WINAPPSDK_CHANGEID_63048673>(). Add #include
  <FrameworkUdk/Containment.h> and an inline #define for the change ID,
  following the existing 62382643 precedent in Helper.cpp. Preserve the module
  directory since the parent-folder search mutates exeDir in place.
- MRM.vcxproj: link the FrameworkUdk Containment worker (targets import +
  EnsureNuGetPackageBuildImports).
- MrmUnitTest.vcxproj: deploy Microsoft.Internal.FrameworkUdk.dll next to the
  test host (mrm.dll now imports it).
- Helper.cpp (GetDefaultPriFile): inside the existing 62382643 block, gate the
  sparse-packaged [modulename].pri fallback on actual file existence (CheckFile)
  so it still fires once MrmGetFilePathFromName returns S_OK. Correct whether
  63048673 is enabled or disabled; preserves 62382643 behavior.
- MrmTests.cpp: strengthen GetFilePath to assert the fallback path is under the
  module directory.
- BypassTests.json: remove the now-passing UnitTest::BasicTest::GetFilePath and
  MrtCoreUnpackagedTests.TestClass.DefaultResourceManager entries so they gate.

Note for release engineering: per the ContainmentV2 model this PR only defines
and gates the change ID; associating 63048673 to a release group in
RuntimeCompatibilityOptions.cpp's s_catalogGroupsProd[] is the separate
branch-cut step.

Verified locally (x64 Debug): MrmUnitTest 21/21 (change enabled by default).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Berrysoft

Copy link
Copy Markdown
Contributor

Hello, Scott Jones (@Scottj1s) ! Will you also backport it to 1.8? (Is 1.8 still under maintaince?) As far as I know, WinUI3 1.8+ is affected by this PR.

@Scottj1s

Scott Jones (Scottj1s) commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

Hello, Scott Jones (@Scottj1s) ! Will you also backport it to 1.8? (Is 1.8 still under maintaince?) As far as I know, WinUI3 1.8+ is affected by this PR.

Yes, I'll backport to 1.8 as well: #6617

…abled

Adds ContainmentDisabledTest::GetFilePathFallbackDisabled to MrmUnitTest. It
disables WINAPPSDK_CHANGEID_63048673 via the FrameworkUdk containment worker
(WinAppSdk::Containment::SetConfiguration) and verifies MrmGetFilePathFromName
reverts to the previous behavior: ERROR_FILE_NOT_FOUND (null path) for a
non-existent PRI file, instead of S_OK with a best-effort path.

The class uses IsolationLevel=Method so it runs in its own process. This is
required because IsChangeEnabled<>() caches its result in a process-lifetime
function-local static, so the disabled-state test must not share a process with
BasicTest::GetFilePath (which exercises the enabled default state).

MrmUnitTest.vcxproj: import the FrameworkUdk targets so the test can call the
Containment worker (mrm.dll already imports Microsoft.Internal.FrameworkUdk.dll,
deployed next to the test host).

Verified locally (x64 Debug): MrmUnitTest 22/22, including both the enabled
(GetFilePath) and disabled (GetFilePathFallbackDisabled) cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Scottj1s

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@Berrysoft

Copy link
Copy Markdown
Contributor

Scott Jones (@Scottj1s) I have a little question: after this PR merged, will the fix be enabled or disabled by default? If disabled by default, how to enable it explicitly? Or, is there a way to detect whether it is enabled?

@Scottj1s

Copy link
Copy Markdown
Member Author

Scott Jones (@Scottj1s) I have a little question: after this PR merged, will the fix be enabled or disabled by default? If disabled by default, how to enable it explicitly? Or, is there a way to detect whether it is enabled?

Yuyi Wang (@Berrysoft), All servicing fixes, including this one, are enabled by default. Disabling is an explicit action - e.g., see the GetFilePathFallbackDisabled test case.

@Scottj1s
Scott Jones (Scottj1s) merged commit 783728c into release/2.0-stable Jul 17, 2026
1 check passed
@Scottj1s
Scott Jones (Scottj1s) deleted the user/scottj1s/mrm-fallback-2.0-cp branch July 17, 2026 13:08
Scott Jones (Scottj1s) added a commit that referenced this pull request Jul 17, 2026
…6603) (#6617)

Ports the MrmGetFilePathFromName fix (main #6603, also cherry-picked to
release/2.0-stable in #6612) into release/1.8-stable, gated behind a
runtime-compatibility containment change so apps can disable it.

MrmGetFilePathFromName is documented to always succeed and return a best-effort
path even when no PRI file exists. On 1.8-stable it fails with
ERROR_FILE_NOT_FOUND, which makes `new ResourceManager()` throw when there is no
resources.pri (the XAML-island / no-PRI scenario - issue #5814).

1.8 uses the ContainmentV1 model where IsChangeEnabled requires a target patch
version, so the change ID macro bakes it in:
  #define WINAPPSDK_CHANGEID_63048673 63048673, WinAppSDK_1_8_11
- Enabled (runtime at/after 1.8.11, default): MrmGetFilePathFromName returns
  S_OK with a non-null best-effort path (the provided filename, else
  resources.pri) under the base directory (if set) otherwise the module
  directory.
- Disabled (via RuntimeCompatibilityOptions) or runtime pinned before 1.8.11:
  behavior reverts byte-for-byte to current 1.8-stable (ERROR_FILE_NOT_FOUND).
  Both terminal search passes jump to Final, skipping the DefaultFallback pass.

Changes:
- MRM.cpp: gate the reachable DefaultFallback pass + S_OK return on
  IsChangeEnabled<WINAPPSDK_CHANGEID_63048673>() (2-arg ContainmentV1 form).
  Add #include <FrameworkUdk/Containment.h> and the inline #define. Preserve the
  module directory since the parent-folder search mutates exeDir in place.
- MRM.vcxproj: link the FrameworkUdk Containment worker (targets import +
  EnsureNuGetPackageBuildImports).
- MrmUnitTest.vcxproj: link FrameworkUdk and deploy
  Microsoft.Internal.FrameworkUdk.dll next to the test host.
- MrmTests.cpp: strengthen GetFilePath to assert the fallback path is under the
  module directory; add ContainmentDisabledTest (IsolationLevel=Method) that
  disables 63048673 via SetConfiguration and verifies the pre-fix
  ERROR_FILE_NOT_FOUND behavior.
- BypassTests.json: remove the now-passing UnitTest::BasicTest::GetFilePath and
  MrtCoreUnpackagedTests.TestClass.DefaultResourceManager entries so they gate.

Helper.cpp is intentionally NOT changed: 1.8 has no sparse-packaged PRI fallback
block (that came later), so the S_OK result flows through GetDefaultPriFile
without adjustment.

Verified locally (x64 Debug): MrmUnitTest 22/22, including both the enabled
(GetFilePath) and disabled (GetFilePathFallbackDisabled) cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants